From 314bba255aedf9ef905524efd0c7528378a3b7f4 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 22 Jun 2004 09:14:53 +0000 Subject: [PATCH] merged bugfixes from main brach --- ChangeLog | 41 ++++++++++++++++++++++++++ Filesystems | 68 ++++++++++++++++++++++++++++++++++++++++++++ configure.in | 12 +++++++- example/fusexmp.c | 1 - include/linux/fuse.h | 3 ++ kernel/dir.c | 17 +++++++---- kernel/file.c | 43 +++++++++++++++++++--------- kernel/fuse_i.h | 9 ++++-- kernel/inode.c | 45 ++++++++++++++++------------- lib/fuse.c | 6 ++-- util/fusermount.c | 6 ---- 11 files changed, 200 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 38bf17f..3d2098e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,44 @@ +2004-06-22 Miklos Szeredi + + * 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 + + * Check some limits so userspace won't get too big requests + +2004-04-05 Miklos Szeredi + + * Kill compile warning + +2004-03-02 Miklos Szeredi + + * Fix for uClinux (Christian Magnusson) + +2004-02-12 Miklos Szeredi + + * Remove MS_PERMISSION mount flag (that means something else now) + +2004-02-10 Miklos Szeredi + + * Added check for i_size_read/write functions to configure.in + (patch by Valient Gough) + +2004-02-06 Miklos Szeredi + + * 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 * Released 1.1 diff --git a/Filesystems b/Filesystems index d61d305..eecf82e 100644 --- a/Filesystems +++ b/Filesystems @@ -103,3 +103,71 @@ Description: linux apps. ============================================================================== +Name: C# bindings + +Author: Valient Gough + +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 + +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 + +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 + +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 + +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. + +============================================================================== diff --git a/configure.in b/configure.in index a5abe85..71878f8 100644 --- a/configure.in +++ b/configure.in @@ -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 ]) + CFLAGS="$old_cflags" + fi fi if test "$enable_lib" != "no"; then diff --git a/example/fusexmp.c b/example/fusexmp.c index 7af6c04..1a96ba5 100644 --- a/example/fusexmp.c +++ b/example/fusexmp.c @@ -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[]) diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 909c8b0..cb2cea9 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -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; diff --git a/kernel/dir.c b/kernel/dir.c index 739b677..988fc15 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -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); diff --git a/kernel/file.c b/kernel/file.c index 3e2208e..7d70bf1 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -16,7 +16,13 @@ #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 = { diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index cc386ac..b83f663 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -24,6 +24,11 @@ #define MODVERSIONS #include #endif +#include +#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 #include @@ -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) diff --git a/kernel/inode.c b/kernel/inode.c index f5c3a97..1dce924 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -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. @@ -23,6 +23,10 @@ #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, diff --git a/lib/fuse.c b/lib/fuse.c index f88653d..7aa1eca 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -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; } diff --git a/util/fusermount.c b/util/fusermount.c index d4fcebb..3d27219 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -35,10 +35,6 @@ #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; -- 2.30.2