diff -Naur linux-2.6.21/fs/fuse/control.c linux-2.6.21-magellan-r10/fs/fuse/control.c --- linux-2.6.21/fs/fuse/control.c 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21-magellan-r10/fs/fuse/control.c 2007-08-17 13:33:29.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -23,7 +23,7 @@ { struct fuse_conn *fc; mutex_lock(&fuse_mutex); - fc = file->f_path.dentry->d_inode->i_private; + fc = file->f_dentry->d_inode->i_private; if (fc) fc = fuse_conn_get(fc); mutex_unlock(&fuse_mutex); @@ -59,12 +59,12 @@ return simple_read_from_buffer(buf, len, ppos, tmp, size); } -static const struct file_operations fuse_ctl_abort_ops = { +static struct file_operations fuse_ctl_abort_ops = { .open = nonseekable_open, .write = fuse_conn_abort_write, }; -static const struct file_operations fuse_ctl_waiting_ops = { +static struct file_operations fuse_ctl_waiting_ops = { .open = nonseekable_open, .read = fuse_conn_waiting_read, }; @@ -74,7 +74,8 @@ const char *name, int mode, int nlink, const struct inode_operations *iop, - const struct file_operations *fop) + const struct file_operations *fop +) { struct dentry *dentry; struct inode *inode; diff -Naur linux-2.6.21/fs/fuse/dev.c linux-2.6.21-magellan-r10/fs/fuse/dev.c --- linux-2.6.21/fs/fuse/dev.c 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21-magellan-r10/fs/fuse/dev.c 2007-08-17 13:33:29.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -17,7 +17,9 @@ #include #include +#ifdef MODULE_ALIAS_MISCDEV MODULE_ALIAS_MISCDEV(FUSE_MINOR); +#endif static struct kmem_cache *fuse_req_cachep; @@ -212,7 +214,6 @@ * Called with fc->lock, unlocks it */ static void request_end(struct fuse_conn *fc, struct fuse_req *req) - __releases(fc->lock) { void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; req->end = NULL; @@ -482,6 +483,9 @@ { unsigned long offset; int err; +#ifdef DCACHE_BUG + struct vm_area_struct *vma; +#endif unlock_request(cs->fc, cs->req); fuse_copy_finish(cs); @@ -493,14 +497,22 @@ cs->nr_segs --; } down_read(¤t->mm->mmap_sem); +#ifndef DCACHE_BUG err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, &cs->pg, NULL); +#else + err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, + &cs->pg, &vma); +#endif up_read(¤t->mm->mmap_sem); if (err < 0) return err; BUG_ON(err != 1); offset = cs->addr % PAGE_SIZE; cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); +#ifdef DCACHE_BUG + flush_cache_page(vma, cs->addr, page_to_pfn(cs->pg)); +#endif cs->buf = cs->mapaddr + offset; cs->len = min(PAGE_SIZE - offset, cs->seglen); cs->seglen -= cs->len; @@ -641,7 +653,6 @@ */ static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req, const struct iovec *iov, unsigned long nr_segs) - __releases(fc->lock) { struct fuse_copy_state cs; struct fuse_in_header ih; @@ -680,15 +691,14 @@ * request_end(). Otherwise add it to the processing list, and set * the 'sent' flag. */ -static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, + unsigned long nr_segs, loff_t *off) { int err; struct fuse_req *req; struct fuse_in *in; struct fuse_copy_state cs; unsigned reqsize; - struct file *file = iocb->ki_filp; struct fuse_conn *fc = fuse_get_conn(file); if (!fc) return -EPERM; @@ -762,6 +772,12 @@ return err; } +static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + return fuse_dev_readv(iocb->ki_filp, iov, nr_segs, &pos); +} + /* Look up request on processing list by unique ID */ static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) { @@ -806,15 +822,15 @@ * it from the list and copy the rest of the buffer to the request. * The request is finished by calling request_end() */ -static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, + unsigned long nr_segs, loff_t *off) { int err; unsigned nbytes = iov_length(iov, nr_segs); struct fuse_req *req; struct fuse_out_header oh; struct fuse_copy_state cs; - struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp); + struct fuse_conn *fc = fuse_get_conn(file); if (!fc) return -EPERM; @@ -890,6 +906,12 @@ return err; } +static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + return fuse_dev_writev(iocb->ki_filp, iov, nr_segs, &pos); +} + static unsigned fuse_dev_poll(struct file *file, poll_table *wait) { unsigned mask = POLLOUT | POLLWRNORM; @@ -1021,7 +1043,7 @@ return fasync_helper(fd, file, on, &fc->fasync); } -const struct file_operations fuse_dev_operations = { +struct file_operations fuse_dev_operations = { .owner = THIS_MODULE, .llseek = no_llseek, .read = do_sync_read, diff -Naur linux-2.6.21/fs/fuse/dir.c linux-2.6.21-magellan-r10/fs/fuse/dir.c --- linux-2.6.21/fs/fuse/dir.c 2007-08-17 13:35:59.000000000 +0200 +++ linux-2.6.21-magellan-r10/fs/fuse/dir.c 2007-08-17 13:33:29.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -205,18 +205,19 @@ * Add a directory inode to a dentry, ensuring that no other dentry * refers to this inode. Called with fc->inst_mutex. */ -static int fuse_d_add_directory(struct dentry *entry, struct inode *inode) +static struct dentry *fuse_d_add_directory(struct dentry *entry, + struct inode *inode) { struct dentry *alias = d_find_alias(inode); - if (alias) { + if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { /* This tries to shrink the subtree below alias */ fuse_invalidate_entry(alias); dput(alias); if (!list_empty(&inode->i_dentry)) - return -EBUSY; - } - d_add(entry, inode); - return 0; + return ERR_PTR(-EBUSY); + } else + dput(alias); + return d_splice_alias(inode, entry); } static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, @@ -225,6 +226,7 @@ int err; struct fuse_entry_out outarg; struct inode *inode = NULL; + struct dentry *newent; struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_req *req; struct fuse_req *forget_req; @@ -265,23 +267,25 @@ if (inode && S_ISDIR(inode->i_mode)) { mutex_lock(&fc->inst_mutex); - err = fuse_d_add_directory(entry, inode); + newent = fuse_d_add_directory(entry, inode); mutex_unlock(&fc->inst_mutex); - if (err) { + if (IS_ERR(newent)) { iput(inode); - return ERR_PTR(err); + return newent; } } else - d_add(entry, inode); + newent = d_splice_alias(inode, entry); + entry = newent ? newent : entry; entry->d_op = &fuse_dentry_operations; if (!err) fuse_change_timeout(entry, &outarg); else fuse_invalidate_entry_cache(entry); - return NULL; + return newent; } +#ifdef HAVE_LOOKUP_INSTANTIATE_FILP /* * Synchronous release for the case when something goes wrong in CREATE_OPEN */ @@ -392,6 +396,7 @@ fuse_put_request(fc, forget_req); return err; } +#endif /* * Code shared between mknod, mkdir, symlink and link @@ -485,12 +490,14 @@ static int fuse_create(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { +#ifdef HAVE_LOOKUP_INSTANTIATE_FILP if (nd && (nd->flags & LOOKUP_OPEN)) { int err = fuse_create_open(dir, entry, mode, nd); if (err != -ENOSYS) return err; /* Fall back on mknod */ } +#endif return fuse_mknod(dir, entry, mode, 0); } @@ -821,6 +828,9 @@ if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) return -EACCES; +#ifndef LOOKUP_CHDIR +#define LOOKUP_CHDIR 0 +#endif if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) return fuse_access(inode, mask); return 0; @@ -857,7 +867,7 @@ int err; size_t nbytes; struct page *page; - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; @@ -973,11 +983,13 @@ arg->atime = iattr->ia_atime.tv_sec; arg->mtime = iattr->ia_mtime.tv_sec; } +#ifdef ATTR_FILE if (ivalid & ATTR_FILE) { struct fuse_file *ff = iattr->ia_file->private_data; arg->valid |= FATTR_FH; arg->fh = ff->fh; } +#endif } static void fuse_vmtruncate(struct inode *inode, loff_t offset) @@ -1040,6 +1052,9 @@ memset(&inarg, 0, sizeof(inarg)); iattr_to_fattr(attr, &inarg); + /* Defend against future expansion of ATTR_FILE use */ + if (S_ISDIR(inode->i_mode)) + inarg.valid &= ~FATTR_FH; req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; @@ -1074,6 +1089,8 @@ struct inode *inode = entry->d_inode; int err = fuse_revalidate(entry); if (!err) + /* FIXME: may want specialized function because of + st_blksize on block devices on 2.6.19+ */ generic_fillattr(inode, stat); return err; @@ -1243,7 +1260,7 @@ return err; } -static const struct inode_operations fuse_dir_inode_operations = { +static struct inode_operations fuse_dir_inode_operations = { .lookup = fuse_lookup, .mkdir = fuse_mkdir, .symlink = fuse_symlink, @@ -1262,7 +1279,7 @@ .removexattr = fuse_removexattr, }; -static const struct file_operations fuse_dir_operations = { +static struct file_operations fuse_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = fuse_readdir, @@ -1271,7 +1288,7 @@ .fsync = fuse_dir_fsync, }; -static const struct inode_operations fuse_common_inode_operations = { +static struct inode_operations fuse_common_inode_operations = { .setattr = fuse_setattr, .permission = fuse_permission, .getattr = fuse_getattr, @@ -1281,7 +1298,7 @@ .removexattr = fuse_removexattr, }; -static const struct inode_operations fuse_symlink_inode_operations = { +static struct inode_operations fuse_symlink_inode_operations = { .setattr = fuse_setattr, .follow_link = fuse_follow_link, .put_link = fuse_put_link, diff -Naur linux-2.6.21/fs/fuse/file.c linux-2.6.21-magellan-r10/fs/fuse/file.c --- linux-2.6.21/fs/fuse/file.c 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21-magellan-r10/fs/fuse/file.c 2007-08-17 13:33:29.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -11,8 +11,9 @@ #include #include #include +#include -static const struct file_operations fuse_direct_io_file_operations; +static struct file_operations fuse_direct_io_file_operations; static int fuse_send_open(struct inode *inode, struct file *file, int isdir, struct fuse_open_out *outargp) @@ -141,8 +142,8 @@ isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); /* Hold vfsmount and dentry until release is finished */ - req->vfsmount = mntget(file->f_path.mnt); - req->dentry = dget(file->f_path.dentry); + req->vfsmount = mntget(file->f_vfsmnt); + req->dentry = dget(file->f_dentry); request_send_background(fc, req); } @@ -184,7 +185,7 @@ static int fuse_flush(struct file *file, fl_owner_t id) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = file->private_data; struct fuse_req *req; @@ -370,21 +371,32 @@ struct fuse_req *req = data->req; struct inode *inode = data->inode; struct fuse_conn *fc = get_fuse_conn(inode); + int err; - if (req->num_pages && + if (req && req->num_pages && (req->num_pages == FUSE_MAX_PAGES_PER_REQ || (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || req->pages[req->num_pages - 1]->index + 1 != page->index)) { fuse_send_readpages(req, data->file, inode); + req = NULL; + } + if (!req) { + err = -EIO; + if (is_bad_inode(inode)) + goto out_unlock_page; + data->req = req = fuse_get_req(fc); - if (IS_ERR(req)) { - unlock_page(page); - return PTR_ERR(req); - } + err = PTR_ERR(req); + if (IS_ERR(req)) + goto out_unlock_page; } req->pages[req->num_pages] = page; req->num_pages ++; return 0; + + out_unlock_page: + unlock_page(page); + return err; } static int fuse_readpages(struct file *file, struct address_space *mapping, @@ -395,25 +407,17 @@ struct fuse_readpages_data data; int err; - err = -EIO; - if (is_bad_inode(inode)) - goto out; - data.file = file; data.inode = inode; - data.req = fuse_get_req(fc); - err = PTR_ERR(data.req); - if (IS_ERR(data.req)) - goto out; + data.req = NULL; err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); - if (!err) { + if (!err && data.req) { if (data.req->num_pages) fuse_send_readpages(data.req, file, inode); else fuse_put_request(fc, data.req); } -out: return err; } @@ -515,7 +519,8 @@ nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; - npages = min(max(npages, 1), FUSE_MAX_PAGES_PER_REQ); + npages = max(npages, 1); + npages = min(npages, FUSE_MAX_PAGES_PER_REQ); down_read(¤t->mm->mmap_sem); npages = get_user_pages(current, current->mm, user_addr, npages, write, 0, req->pages, NULL); @@ -531,7 +536,7 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int write) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); size_t nmax = write ? fc->max_write : fc->max_read; loff_t pos = *ppos; @@ -605,11 +610,13 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; ssize_t res; /* Don't allow parallel writes to the same file */ mutex_lock(&inode->i_mutex); - res = fuse_direct_io(file, buf, count, ppos, 1); + res = generic_write_checks(file, ppos, &count, 0); + if (!res) + res = fuse_direct_io(file, buf, count, ppos, 1); mutex_unlock(&inode->i_mutex); return res; } @@ -660,7 +667,7 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file, const struct file_lock *fl, int opcode, pid_t pid) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = file->private_data; struct fuse_lk_in *arg = &req->misc.lk_in; @@ -680,7 +687,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; struct fuse_lk_out outarg; @@ -705,7 +712,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; @@ -732,7 +739,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) { - struct inode *inode = file->f_path.dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); int err; @@ -788,7 +795,7 @@ return err ? 0 : outarg.block; } -static const struct file_operations fuse_file_operations = { +static struct file_operations fuse_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .aio_read = generic_file_aio_read, @@ -803,7 +810,7 @@ .sendfile = generic_file_sendfile, }; -static const struct file_operations fuse_direct_io_file_operations = { +static struct file_operations fuse_direct_io_file_operations = { .llseek = generic_file_llseek, .read = fuse_direct_read, .write = fuse_direct_write, @@ -815,7 +822,7 @@ /* no mmap and sendfile */ }; -static const struct address_space_operations fuse_file_aops = { +static struct address_space_operations fuse_file_aops = { .readpage = fuse_readpage, .prepare_write = fuse_prepare_write, .commit_write = fuse_commit_write, diff -Naur linux-2.6.21/fs/fuse/fuse_i.h linux-2.6.21-magellan-r10/fs/fuse/fuse_i.h --- linux-2.6.21/fs/fuse/fuse_i.h 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21-magellan-r10/fs/fuse/fuse_i.h 2007-08-17 13:33:29.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -15,6 +15,12 @@ #include #include #include +#ifndef FS_HAS_SUBTYPE +#define FS_HAS_SUBTYPE 0 +#endif +#ifndef FS_SAFE +#define FS_SAFE 0 +#endif /** Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 @@ -397,7 +403,7 @@ } /** Device operations */ -extern const struct file_operations fuse_dev_operations; +extern struct file_operations fuse_dev_operations; /** * Get a filled in inode diff -Naur linux-2.6.21/fs/fuse/inode.c linux-2.6.21-magellan-r10/fs/fuse/inode.c --- linux-2.6.21/fs/fuse/inode.c 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21-magellan-r10/fs/fuse/inode.c 2007-08-17 13:33:29.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -17,10 +17,13 @@ #include #include #include +#include MODULE_AUTHOR("Miklos Szeredi "); MODULE_DESCRIPTION("Filesystem in Userspace"); +#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); +#endif static struct kmem_cache *fuse_inode_cachep; struct list_head fuse_conn_list; @@ -28,6 +31,9 @@ #define FUSE_SUPER_MAGIC 0x65735546 +#ifndef MAX_LFS_FILESIZE +#define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) +#endif struct fuse_mount_data { int fd; unsigned rootmode; @@ -122,6 +128,9 @@ spin_lock(&fc->lock); i_size_write(inode, attr->size); spin_unlock(&fc->lock); +#ifdef HAVE_I_BLKSIZE + inode->i_blksize = PAGE_CACHE_SIZE; +#endif inode->i_blocks = attr->blocks; inode->i_atime.tv_sec = attr->atime; inode->i_atime.tv_nsec = attr->atimensec; @@ -200,11 +209,18 @@ return inode; } +#ifdef UMOUNT_BEGIN_VFSMOUNT static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags) { if (flags & MNT_FORCE) fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb)); } +#else +static void fuse_umount_begin(struct super_block *sb) +{ + fuse_abort_conn(get_fuse_conn_super(sb)); +} +#endif static void fuse_send_destroy(struct fuse_conn *fc) { @@ -311,6 +327,19 @@ d->max_read = ~0; d->blksize = 512; + /* + * For unprivileged mounts use current uid/gid. Still allow + * "user_id" and "group_id" options for compatibility, but + * only if they match these values. + */ + if (!capable(CAP_SYS_ADMIN)) { + d->user_id = current->uid; + d->user_id_present = 1; + d->group_id = current->gid; + d->group_id_present = 1; + + } + while ((p = strsep(&opt, ",")) != NULL) { int token; int value; @@ -339,6 +368,8 @@ case OPT_USER_ID: if (match_int(&args[0], &value)) return 0; + if (d->user_id_present && d->user_id != value) + return 0; d->user_id = value; d->user_id_present = 1; break; @@ -346,6 +377,8 @@ case OPT_GROUP_ID: if (match_int(&args[0], &value)) return 0; + if (d->group_id_present && d->group_id != value) + return 0; d->group_id = value; d->group_id_present = 1; break; @@ -448,11 +481,12 @@ return fuse_iget(sb, 1, 0, &attr); } -static const struct super_operations fuse_super_operations = { +static struct super_operations fuse_super_operations = { .alloc_inode = fuse_alloc_inode, .destroy_inode = fuse_destroy_inode, .read_inode = fuse_read_inode, .clear_inode = fuse_clear_inode, + .drop_inode = generic_delete_inode, .remount_fs = fuse_remount_fs, .put_super = fuse_put_super, .umount_begin = fuse_umount_begin, @@ -536,6 +570,10 @@ if (!parse_fuse_opt((char *) data, &d, is_bdev)) return -EINVAL; + /* This is a privileged option */ + if ((d.flags & FUSE_ALLOW_OTHER) && !capable(CAP_SYS_ADMIN)) + return -EPERM; + if (is_bdev) { #ifdef CONFIG_BLOCK if (!sb_set_blocksize(sb, d.blksize)) @@ -638,6 +676,7 @@ .name = "fuse", .get_sb = fuse_get_sb, .kill_sb = kill_anon_super, + .fs_flags = FS_HAS_SUBTYPE | FS_SAFE, }; #ifdef CONFIG_BLOCK @@ -654,7 +693,7 @@ .name = "fuseblk", .get_sb = fuse_get_sb_blk, .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, + .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, }; static inline int register_fuseblk(void) @@ -687,7 +726,7 @@ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) - inode_init_once(inode); + inode_init_once(inode); } static int __init fuse_fs_init(void) diff -Naur linux-2.6.21/include/linux/fuse.h linux-2.6.21-magellan-r10/include/linux/fuse.h --- linux-2.6.21/include/linux/fuse.h 2007-04-26 05:08:32.000000000 +0200 +++ linux-2.6.21-magellan-r10/include/linux/fuse.h 2007-08-17 12:00:33.000000000 +0200 @@ -1,6 +1,6 @@ /* FUSE: Filesystem in Userspace - Copyright (C) 2001-2006 Miklos Szeredi + Copyright (C) 2001-2007 Miklos Szeredi This program can be distributed under the terms of the GNU GPL. See the file COPYING. @@ -339,7 +339,7 @@ char name[0]; }; -#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name) +#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) #define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1)) #define FUSE_DIRENT_SIZE(d) \ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)