merged bugfixes from main brach
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 22 Jun 2004 09:14:53 +0000 (09:14 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 22 Jun 2004 09:14:53 +0000 (09:14 +0000)
ChangeLog
Filesystems
configure.in
example/fusexmp.c
include/linux/fuse.h
kernel/dir.c
kernel/file.c
kernel/fuse_i.h
kernel/inode.c
lib/fuse.c
util/fusermount.c

index 38bf17fd219d54b35440d413d2653f9580ece301..3d2098ea52e08ec6d9c8103d948db6de2ea9a3e5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2004-06-22  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Add FS_BINARY_MOUNTDATA filesystem flag for kernels that define
+       it.  This fixes mount problems on recent 2.6 kernels with SELinux
+       enabled
+       
+       * Merge bugfixes from main branch (see below)
+       
+2004-04-09  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Check some limits so userspace won't get too big requests
+
+2004-04-05  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Kill compile warning
+
+2004-03-02  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Fix for uClinux (Christian Magnusson)
+
+2004-02-12  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Remove MS_PERMISSION mount flag (that means something else now)
+       
+2004-02-10  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Added check for i_size_read/write functions to configure.in
+       (patch by Valient Gough)
+
+2004-02-06  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * Fixed writing >= 2G files
+
+       * Check file size on open (with generic_file_open())
+
+       * Readpage calls flush_dcache_page() after storing data
+
+       * Use i_size_read/write for accessing inode->i_size
+
+       * Make loopback mount of a fuse file work
+       
 2004-02-04  Miklos Szeredi <mszeredi@inf.bme.hu>
 
        * Released 1.1
index d61d30589e20beec891998ab589a7748f38b1461..eecf82e70bc88a86a4267a0642fde4d6e307b1f1 100644 (file)
@@ -103,3 +103,71 @@ Description:
   linux apps.
 
 ==============================================================================
+Name: C# bindings
+
+Author: Valient Gough <vgough at pobox com>
+
+Homepage: http://pobox.com/~vgough/fuse-csharp.html
+
+Description:
+
+  It allows you to write a Linux filesystem in C#. It uses the FUSE
+  library to do the actual Linux filesystem integration, and adds an
+  interface to the Mono runtime.
+
+==============================================================================
+Name: LUFS bridge (alpha)
+
+Author: Miklos Szeredi <mszeredi at inf bme hu>
+
+Homepage: http://sourceforge.net/project/showfiles.php?group_id=21636&package_id=109154
+
+Description:
+
+  This is a modified LUFS daemon, which uses the FUSE kernel module.  It
+  is binary compatible with existing LUFS filesystems, so no
+  recompilation is needed.
+
+==============================================================================
+Name: btfs (Bluetooth FileSystemMapping)
+
+Author: Collin R. Mulliner <collin at betaversion net>
+
+Homepage: http://www.mulliner.org/bluetooth/btfs.php
+
+Description:
+
+  Btfs is a simple application to map some basic bluetooth functions
+  into the filesystem.  With btfs a simple ls DEVICES shows you all
+  bluetooth devices within range and cp somefile OPUSH/devicename sends
+  the given file to the device.
+
+==============================================================================
+Name: mcachefs
+
+Author: Michael Still <mikal at stillhq com>
+
+Homepage: http://lists.samba.org/archive/linux/2004-March/010211.html
+
+Description:
+
+  mcachefs is a simple caching filesystem for Linux using FUSE. It
+  works by copying the file that you asked for when the file is
+  opened, and then using that copy for all subsequent requests for the
+  file. This is really a fairly naive approach to caching, and will be
+  improved in the future.
+
+==============================================================================
+Name: Fusedav
+
+Author: Lennart Poettering <mzshfrqni (at) 0pointer (dot) de>
+
+Homepage: http://0pointer.de/lennart/projects/fusedav/
+
+Description:
+
+  fusedav is a Linux userspace file system driver for mounting WebDAV
+  shares.  It makes use of FUSE as userspace file system API and neon
+  as WebDAV API.
+
+==============================================================================
index a5abe8554e6702cc3ec239ab3e9379d0e97ec283..71878f83b09bbb351d0ab2e8bb68f0b1b6c17c19 100644 (file)
@@ -1,5 +1,5 @@
 AC_INIT(lib/fuse.c)
-AM_INIT_AUTOMAKE(fuse, 1.1)
+AM_INIT_AUTOMAKE(fuse, 1.2)
 AM_CONFIG_HEADER(include/config.h)
 
 AC_PROG_CC
@@ -60,6 +60,16 @@ if test "$enable_kernel_module" != "no"; then
        AC_SUBST(majver)
        AC_SUBST(kmoduledir)
        subdirs="$subdirs kernel"
+
+       if echo "$kernsrcver" | grep -q "^2.4"; then
+               old_cflags="$CFLAGS"
+               CFLAGS="-I${kernelsrc}/include -Wall -O2 -fno-strict-aliasing -D__KERNEL__"
+               AC_CHECK_DECL(i_size_read,
+                       AC_DEFINE(HAVE_I_SIZE_FUNC, 1,
+                               [Kernel has i_size_read() and i_size_write() functions]),,
+                       [#include <linux/fs.h>])
+               CFLAGS="$old_cflags"
+       fi
 fi
 
 if test "$enable_lib" != "no"; then
index 7af6c04181360b69d1946980322809680735dc64..1a96ba546ddd96a7b3dfdfd1fa71a91896fe92b9 100644 (file)
@@ -289,7 +289,6 @@ static struct fuse_operations xmp_oper = {
     .statfs    = xmp_statfs,
     .release   = xmp_release,
     .fsync     = xmp_fsync
-    
 };
 
 int main(int argc, char *argv[])
index 909c8b055ca9ffab3501380706d00734d40fcc27..cb2cea9746443420276634ab1644c450d7f3694a 100644 (file)
@@ -114,6 +114,9 @@ enum fuse_opcode {
 /* Conservative buffer size for the client */
 #define FUSE_MAX_IN 8192
 
+#define FUSE_NAME_MAX 1024
+#define FUSE_SYMLINK_MAX 4096
+
 struct fuse_lookup_out {
        unsigned long ino;
        struct fuse_attr attr;
index 739b677fa57fe3270bbff9a5bf8bdcd4975b4739..988fc15444d364b92c1039a24b4ee6cdf05ae5f7 100644 (file)
@@ -30,7 +30,7 @@ static struct dentry_operations fuse_dentry_operations;
 
 static void change_attributes(struct inode *inode, struct fuse_attr *attr)
 {
-       if(S_ISREG(inode->i_mode) && inode->i_size != attr->size) {
+       if(S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) {
 #ifdef KERNEL_2_6
                invalidate_inode_pages(inode->i_mapping);
 #else
@@ -42,7 +42,7 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr)
        inode->i_nlink   = attr->nlink;
        inode->i_uid     = attr->uid;
        inode->i_gid     = attr->gid;
-       inode->i_size    = attr->size;
+       i_size_write(inode, attr->size);
        inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks  = attr->blocks;
 #ifdef KERNEL_2_6
@@ -62,7 +62,7 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr)
 static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
 {
        inode->i_mode = attr->mode & S_IFMT;
-       inode->i_size = attr->size;
+       i_size_write(inode, attr->size);
        if(S_ISREG(inode->i_mode)) {
                inode->i_op = &fuse_file_inode_operations;
                fuse_init_file_inode(inode);
@@ -106,6 +106,9 @@ static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
 
+       if (entry->d_name.len > FUSE_NAME_MAX)
+               return -ENAMETOOLONG;
+
        in.h.opcode = FUSE_LOOKUP;
        in.h.ino = dir->i_ino;
        in.numargs = 1;
@@ -238,13 +241,17 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
        struct fuse_conn *fc = INO_FC(dir);
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
+       unsigned int len = strlen(link) + 1;
+       
+       if (len > FUSE_SYMLINK_MAX)
+               return -ENAMETOOLONG;
 
        in.h.opcode = FUSE_SYMLINK;
        in.h.ino = dir->i_ino;
        in.numargs = 2;
        in.args[0].size = entry->d_name.len + 1;
        in.args[0].value = entry->d_name.name;
-       in.args[1].size = strlen(link) + 1;
+       in.args[1].size = len;
        in.args[1].value = link;
        request_send(fc, &in, &out);
        if(out.h.error)
@@ -619,7 +626,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 
        if(!out.h.error) {
                if(attr->ia_valid & ATTR_SIZE &&
-                  outarg.attr.size < inode->i_size)
+                  outarg.attr.size < i_size_read(inode))
                        vmtruncate(inode, outarg.attr.size);
 
                change_attributes(inode, &outarg.attr);
index 3e2208e1aa7f8cef9d7081b5ae76f1106b19e2e7..7d70bf13a8a296b2e48f3d7dac6e6733235ed672 100644 (file)
 
 #ifndef KERNEL_2_6
 #define PageUptodate(page) Page_Uptodate(page)
+#ifndef filemap_fdatawrite
+#ifndef NO_MM
 #define filemap_fdatawrite filemap_fdatasync
+#else
+#define filemap_fdatawrite do {} while(0)
+#endif
+#endif
 #endif
 
 static int fuse_open(struct inode *inode, struct file *file)
@@ -25,6 +31,11 @@ static int fuse_open(struct inode *inode, struct file *file)
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_open_in inarg;
+       int err;
+
+       err = generic_file_open(inode, file);
+       if(err)
+               return err;
 
        /* If opening the root node, no lookup has been performed on
           it, so the attributes must be refreshed */
@@ -137,6 +148,7 @@ static int fuse_readpage(struct file *file, struct page *page)
                size_t outsize = out.args[0].size;
                if(outsize < PAGE_CACHE_SIZE) 
                        memset(buffer + outsize, 0, PAGE_CACHE_SIZE - outsize);
+               flush_dcache_page(page);
                SetPageUptodate(page);
        }
 
@@ -151,7 +163,7 @@ static int fuse_is_block_uptodate(struct address_space *mapping,
 {
        size_t index = bl_index << FUSE_BLOCK_PAGE_SHIFT;
        size_t end_index = ((bl_index + 1) << FUSE_BLOCK_PAGE_SHIFT) - 1;
-       size_t file_end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+       size_t file_end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
 
        if (end_index > file_end_index)
                end_index = file_end_index;
@@ -180,7 +192,7 @@ static int fuse_cache_block(struct address_space *mapping,
 {
        size_t start_index = bl_index << FUSE_BLOCK_PAGE_SHIFT;
        size_t end_index = ((bl_index + 1) << FUSE_BLOCK_PAGE_SHIFT) - 1;
-       size_t file_end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+       size_t file_end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
 
        int i;
 
@@ -200,6 +212,7 @@ static int fuse_cache_block(struct address_space *mapping,
                        buffer = kmap(page);
                        memcpy(buffer, bl_buf + i * PAGE_CACHE_SIZE,
                                        PAGE_CACHE_SIZE);
+                       flush_dcache_page(page);
                        SetPageUptodate(page);
                        kunmap(page);
                }
@@ -249,7 +262,7 @@ static void fuse_file_bigread(struct address_space *mapping,
 {
        size_t bl_index = pos >> FUSE_BLOCK_SHIFT;
        size_t bl_end_index = (pos + count) >> FUSE_BLOCK_SHIFT;
-       size_t bl_file_end_index = inode->i_size >> FUSE_BLOCK_SHIFT;
+       size_t bl_file_end_index = i_size_read(inode) >> FUSE_BLOCK_SHIFT;
        
        if (bl_end_index > bl_file_end_index)
                bl_end_index = bl_file_end_index;
@@ -316,13 +329,14 @@ static int write_buffer(struct inode *inode, struct page *page,
 static int get_write_count(struct inode *inode, struct page *page)
 {
        unsigned long end_index;
+       loff_t size = i_size_read(inode);
        int count;
        
-       end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+       end_index = size >> PAGE_CACHE_SHIFT;
        if(page->index < end_index)
                count = PAGE_CACHE_SIZE;
        else {
-               count = inode->i_size & (PAGE_CACHE_SIZE - 1);
+               count = size & (PAGE_CACHE_SIZE - 1);
                if(page->index > end_index || count == 0)
                        return 0;
        }
@@ -447,19 +461,22 @@ static int fuse_commit_write(struct file *file, struct page *page,
        err = write_buffer(inode, page, offset, to - offset);
        if(!err) {
                loff_t pos = (page->index << PAGE_CACHE_SHIFT) + to;
-               if(pos > inode->i_size)
-                       inode->i_size = pos;
+               if(pos > i_size_read(inode))
+                       i_size_write(inode, pos);
        }
        return err;
 }
 
 static struct file_operations fuse_file_operations = {
-       .open =         fuse_open,
-       .release =      fuse_release,
-       .fsync =        fuse_fsync,
-       .read =         fuse_file_read,
-       .write =        generic_file_write,
-       .mmap =         generic_file_mmap,
+       .read           = fuse_file_read,
+       .write          = generic_file_write,
+       .mmap           = generic_file_mmap,
+       .open           = fuse_open,
+       .release        = fuse_release,
+       .fsync          = fuse_fsync,
+#ifdef KERNEL_2_6
+       .sendfile       = generic_file_sendfile,
+#endif
 };
 
 static struct address_space_operations fuse_file_aops  = {
index cc386ac0cb6c0a24ccd2e2413d343a42681affd5..b83f6634e5a692b9df3c14daec83425c2c5247e5 100644 (file)
 #define MODVERSIONS
 #include <linux/modversions.h>
 #endif
+#include <config.h>
+#ifndef HAVE_I_SIZE_FUNC
+#define i_size_read(inode) ((inode)->i_size)
+#define i_size_write(inode, size) do { (inode)->i_size = size; } while(0)
+#endif
 #endif 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -147,9 +152,9 @@ struct fuse_req {
 };
 
 #ifdef KERNEL_2_6
-#define SB_FC(sb) ((struct fuse_conn *) (sb)->s_fs_info)
+#define SB_FC(sb) ((sb)->s_fs_info)
 #else
-#define SB_FC(sb) ((struct fuse_conn *) (sb)->u.generic_sbp)
+#define SB_FC(sb) ((sb)->u.generic_sbp)
 #endif
 #define INO_FC(inode) SB_FC((inode)->i_sb)
 #define DEV_FC(file) ((struct fuse_conn *) (file)->private_data)
index f5c3a97e1de746a18bebf7ef1b823a83668f3490..1dce924a0abe20aad8f1f9c7ba04532933a6f95a 100644 (file)
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001  Miklos Szeredi (mszeredi@inf.bme.hu)
+    Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
 #define kstatfs statfs
 #endif
 
+#ifndef FS_BINARY_MOUNTDATA
+#define FS_BINARY_MOUNTDATA 0
+#endif
+
 static void fuse_read_inode(struct inode *inode)
 {
        /* No op */
@@ -74,15 +78,15 @@ static void fuse_put_super(struct super_block *sb)
 
 static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
 {
-       stbuf->f_type    = FUSE_SUPER_MAGIC;
-       stbuf->f_bsize   = attr->block_size;
-       stbuf->f_blocks  = attr->blocks;
-       stbuf->f_bfree   = stbuf->f_bavail = attr->blocks_free;
-       stbuf->f_files   = attr->files;
-       stbuf->f_ffree   = attr->files_free;
+       stbuf->f_type    = FUSE_SUPER_MAGIC;
+       stbuf->f_bsize   = attr->block_size;
+       stbuf->f_blocks  = attr->blocks;
+       stbuf->f_bfree   = stbuf->f_bavail = attr->blocks_free;
+       stbuf->f_files   = attr->files;
+       stbuf->f_ffree   = attr->files_free;
        /* Is this field necessary?  Most filesystems ignore it...
        stbuf->f_fsid.val[0] = (FUSE_SUPER_MAGIC>>16)&0xffff;
-       stbuf->f_fsid.val[1] =  FUSE_SUPER_MAGIC     &0xffff; */
+       stbuf->f_fsid.val[1] =  FUSE_SUPER_MAGIC     &0xffff; */
        stbuf->f_namelen = attr->namelen;
 }
 
@@ -92,7 +96,7 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
        struct fuse_statfs_out outarg;
-        
+       
        in.numargs = 0;
        in.h.opcode = FUSE_STATFS;
        out.numargs = 1;
@@ -193,10 +197,11 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
        struct inode *root;
        struct fuse_mount_data *d = data;
 
-        sb->s_blocksize = PAGE_CACHE_SIZE;
-        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-        sb->s_magic = FUSE_SUPER_MAGIC;
-        sb->s_op = &fuse_super_operations;
+       sb->s_blocksize = PAGE_CACHE_SIZE;
+       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+       sb->s_magic = FUSE_SUPER_MAGIC;
+       sb->s_op = &fuse_super_operations;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
 #ifdef KERNEL_2_6
        sb->s_export_op = &fuse_export_operations;
 #endif
@@ -216,7 +221,7 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
        spin_unlock(&fuse_lock);
        
        /* fc is needed in fuse_init_file_inode which could be called
-           from get_root_inode */
+          from get_root_inode */
        SB_FC(sb) = fc;
 
        root = get_root_inode(sb, d->rootmode);
@@ -237,15 +242,15 @@ static struct super_block *fuse_get_sb(struct file_system_type *fs_type,
                                       int flags, const char *dev_name,
                                       void *raw_data)
 {
-        return get_sb_nodev(fs_type, flags, raw_data, fuse_read_super);
+       return get_sb_nodev(fs_type, flags, raw_data, fuse_read_super);
 }
 
 static struct file_system_type fuse_fs_type = {
-        .owner          = THIS_MODULE,
-        .name           = "fuse",
-        .get_sb         = fuse_get_sb,
-        .kill_sb        = kill_anon_super,
-        .fs_flags       = 0
+       .owner          = THIS_MODULE,
+       .name           = "fuse",
+       .get_sb         = fuse_get_sb,
+       .kill_sb        = kill_anon_super,
+       .fs_flags       = FS_BINARY_MOUNTDATA,
 };
 #else
 static struct super_block *fuse_read_super_compat(struct super_block *sb,
index f88653d19196e145a381081a302925ef04cfbed1..7aa1eca73a6976e856b16edccae49954b08d458b 100644 (file)
@@ -361,15 +361,15 @@ static int send_reply_raw(struct fuse *f, char *outbuf, size_t outsize)
         fflush(stdout);
     }
 
-    /* This needs to be done before the reply because otherwise the
-    scheduler can tricks with us, and only let the counter be increased
+    /* This needs to be done before the reply, otherwise the scheduler
+    could play tricks with us, and only let the counter be increased
     long after the operation is done */
     inc_avail(f);
 
     res = write(f->fd, outbuf, outsize);
     if(res == -1) {
         /* ENOENT means the operation was interrupted */
-        if(errno != ENOENT)
+        if(!f->exited && errno != ENOENT)
             perror("fuse: writing device");
         return -errno;
     }
index d4fcebba897f8fe4e58ee5c66375f305fa8bd9b4..3d27219affb8fb76c798621e0e19e3eb8bd14591 100644 (file)
 
 #define CHECK_PERMISSION 1
 
-#ifndef MS_PERMISSION
-#define MS_PERMISSION  128
-#endif
-
 #define FUSE_DEV "/proc/fs/fuse/dev"
 
 #define FUSE_MOUNTED_ENV        "_FUSE_MOUNTED"
@@ -305,8 +301,6 @@ static int do_mount(const char *dev, const char *mnt, const char *type,
         res = drop_privs();
         if(res == -1)
             return -1;
-
-        flags |= MS_PERMISSION;
     }
     
     data.version = FUSE_KERNEL_VERSION;