diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 1045da582b9b830e16aab0300917c8ace0a22fc3..3abf08f1b14a40dad085f38535857d4d8db5ff4b 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -142,15 +142,16 @@ see also dquot_operations section. --------------------------- file_system_type --------------------------- prototypes: - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + struct int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); locking rules: may block BKL get_sb yes yes kill_sb yes yes -->get_sb() returns error or a locked superblock (exclusive on ->s_umount). +->get_sb() returns error or 0 with locked superblock attached to the vfsmount +(exclusive on ->s_umount). ->kill_sb() takes a write-locked superblock, does all shutdown work on it, unlocks and drops the reference. diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 2f388460cbe72865be75b43b96f58e231b00e379..5531694059ab1678c1f206690b2d747bab1033f2 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -50,10 +50,11 @@ Turn your foo_read_super() into a function that would return 0 in case of success and negative number in case of error (-EINVAL unless you have more informative error value to report). Call it foo_fill_super(). Now declare -struct super_block foo_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +int foo_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, foo_fill_super, + mnt); } (or similar with s/bdev/nodev/ or s/bdev/single/, depending on the kind of diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 3a2e5520c1e3af38ea2ff91dc13a15d17f24aac0..dd7d0dcedc872f28bb32b02137b8aa898855ec4e 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -113,8 +113,8 @@ members are defined: struct file_system_type { const char *name; int fs_flags; - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + struct int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 077f21216b654cc433cb58c2104b11c7954b8b19..2359e2809f506e65e786f525735d5b1c6d0ec013 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -595,10 +595,11 @@ pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, } -static struct super_block * -pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) +static int +pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC); + return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt); } static struct file_system_type pfm_fs_type = { diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 1987697b23a0efeb19de551e99f133c32f841232..7b4572805db9973388267c3ae9d1cea61fea0ed7 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -436,11 +436,11 @@ spufs_fill_super(struct super_block *sb, void *data, int silent) return spufs_create_root(sb, data); } -static struct super_block * +static int spufs_get_sb(struct file_system_type *fstype, int flags, - const char *name, void *data) + const char *name, void *data, struct vfsmount *mnt) { - return get_sb_single(fstype, flags, data, spufs_fill_super); + return get_sb_single(fstype, flags, data, spufs_fill_super, mnt); } static struct file_system_type spufs_type = { diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 5ec2d49e9bb6ebae15bd88da1206e94d7f6eb860..e57d3c50f75f9a06100da442dcc096328bc21ed8 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -821,11 +821,12 @@ static void ib_uverbs_remove_one(struct ib_device *device) kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); } -static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) { return get_sb_pseudo(fs_type, "infinibandevent:", NULL, - INFINIBANDEVENTFS_MAGIC); + INFINIBANDEVENTFS_MAGIC, mnt); } static struct file_system_type uverbs_event_fs = { diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index e274120567e1d5068996efe74a0a4a41d3619321..63de3046aff30079415914aa4b55eb2d35e9b073 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -542,13 +542,14 @@ static int ipathfs_fill_super(struct super_block *sb, void *data, return ret; } -static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int ipathfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) { - ipath_super = get_sb_single(fs_type, flags, data, - ipathfs_fill_super); - return ipath_super; + int ret = get_sb_single(fs_type, flags, data, + ipathfs_fill_super, mnt); + if (ret >= 0) + ipath_super = mnt->mnt_sb; + return ret; } static void ipathfs_kill_super(struct super_block *s) diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 0a37aded4b54afa8990bc092bb02ca2e9d1b4180..9ea6bd0ddc35bdcb2fc532b00a84e0760829e136 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -121,10 +121,10 @@ capifs_fill_super(struct super_block *s, void *data, int silent) return -ENOMEM; } -static struct super_block *capifs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int capifs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, capifs_fill_super); + return get_sb_single(fs_type, flags, data, capifs_fill_super, mnt); } static struct file_system_type capifs_fs_type = { diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 26a230b6ff80dbee2d207a10d4625c44e64f02d4..4a35caff5d020e0e16d0f624e648ccb8cbf5b650 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -90,10 +90,11 @@ static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root); static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent); -static struct super_block *ibmasmfs_get_super(struct file_system_type *fst, - int flags, const char *name, void *data) +static int ibmasmfs_get_super(struct file_system_type *fst, + int flags, const char *name, void *data, + struct vfsmount *mnt) { - return get_sb_single(fst, flags, data, ibmasmfs_fill_super); + return get_sb_single(fst, flags, data, ibmasmfs_fill_super, mnt); } static struct super_operations ibmasmfs_s_ops = { diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index b62da9b0cbf025f7a93684cdbe6be6160dbe7159..71c2da277d6e6a398b13b8041195a41f540f409d 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -272,10 +272,10 @@ static int oprofilefs_fill_super(struct super_block * sb, void * data, int silen } -static struct super_block *oprofilefs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int oprofilefs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, oprofilefs_fill_super); + return get_sb_single(fs_type, flags, data, oprofilefs_fill_super, mnt); } diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 3cf945cc5b9ae1298fcc5fb7ad472a452f758c5f..95f5ad923b0f19188751c988ffc789b0af56d5e0 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -543,10 +543,10 @@ static void fs_remove_file (struct dentry *dentry) /* --------------------------------------------------------------------- */ -static struct super_block *usb_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int usb_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, usbfs_fill_super); + return get_sb_single(fs_type, flags, data, usbfs_fill_super, mnt); } static struct file_system_type usb_fs_type = { diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index aef0722b8f170104a898e2d556b6e67bba8418fb..3bdc5e3ba2346a588d518339de3bc31f5834520d 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -2070,11 +2070,11 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) } /* "mount -t gadgetfs path /dev/gadget" ends up here */ -static struct super_block * +static int gadgetfs_get_sb (struct file_system_type *t, int flags, - const char *path, void *opts) + const char *path, void *opts, struct vfsmount *mnt) { - return get_sb_single (t, flags, opts, gadgetfs_fill_super); + return get_sb_single (t, flags, opts, gadgetfs_fill_super, mnt); } static void diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 61c599b4a1e32de2f7053408e64657067450d58e..872943004e595de4772f7f44fa781360d19613f9 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -99,12 +99,13 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, * @flags: mount flags * @dev_name: device name that was mounted * @data: mount options + * @mnt: mountpoint record to be instantiated * */ -static struct super_block *v9fs_get_sb(struct file_system_type - *fs_type, int flags, - const char *dev_name, void *data) +static int v9fs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) { struct super_block *sb = NULL; struct v9fs_fcall *fcall = NULL; @@ -123,17 +124,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) - return ERR_PTR(-ENOMEM); + return -ENOMEM; if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); - sb = ERR_PTR(newfid); + retval = newfid; goto out_free_session; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); - if (IS_ERR(sb)) + if (IS_ERR(sb)) { + retval = PTR_ERR(sb); goto out_close_session; + } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); @@ -184,19 +187,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type goto put_back_sb; } - return sb; + return simple_set_mnt(mnt, sb); out_close_session: v9fs_session_close(v9ses); out_free_session: kfree(v9ses); - return sb; + return retval; put_back_sb: /* deactivate_super calls v9fs_kill_super which will frees the rest */ up_write(&sb->s_umount); deactivate_super(sb); - return ERR_PTR(retval); + return retval; } /** diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 252abda0d200cc6fc5e7531e99054e2a3e88eb17..1b58a9b7f6aa548d11caec601d73ac43dad144d4 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -470,10 +470,11 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) return -EINVAL; } -static struct super_block *adfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int adfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super, + mnt); } static struct file_system_type adfs_fs_type = { diff --git a/fs/affs/super.c b/fs/affs/super.c index 4d7e5b19e5cd20b99d76de5e53743dd9836704de..6a52e787540327910417a1de9834deda8c999e88 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -524,10 +524,11 @@ affs_statfs(struct super_block *sb, struct kstatfs *buf) return 0; } -static struct super_block *affs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int affs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super, + mnt); } static struct file_system_type affs_fs_type = { diff --git a/fs/afs/super.c b/fs/afs/super.c index 53c56e7231abf4e1bf8e88b0884dcd303f333b8a..82468df0ba540dd55bf68d863b40fee09862e4bb 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -38,9 +38,9 @@ struct afs_mount_params { static void afs_i_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags); -static struct super_block *afs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data); +static int afs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt); static struct inode *afs_alloc_inode(struct super_block *sb); @@ -294,10 +294,11 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent) * get an AFS superblock * - TODO: don't use get_sb_nodev(), but rather call sget() directly */ -static struct super_block *afs_get_sb(struct file_system_type *fs_type, - int flags, - const char *dev_name, - void *options) +static int afs_get_sb(struct file_system_type *fs_type, + int flags, + const char *dev_name, + void *options, + struct vfsmount *mnt) { struct afs_mount_params params; struct super_block *sb; @@ -311,7 +312,7 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type, ret = afscm_start(); if (ret < 0) { _leave(" = %d", ret); - return ERR_PTR(ret); + return ret; } /* parse the options */ @@ -348,18 +349,19 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type, goto error; } sb->s_flags |= MS_ACTIVE; + simple_set_mnt(mnt, sb); afs_put_volume(params.volume); afs_put_cell(params.default_cell); - _leave(" = %p", sb); - return sb; + _leave(" = 0 [%p]", 0, sb); + return 0; error: afs_put_volume(params.volume); afs_put_cell(params.default_cell); afscm_stop(); _leave(" = %d", ret); - return ERR_PTR(ret); + return ret; } /* end afs_get_sb() */ /*****************************************************************************/ diff --git a/fs/autofs/init.c b/fs/autofs/init.c index b977ece69f0c2893897c9e58a143a833f44f5341..aca12375240694975523badc164647cb10ca01c1 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c @@ -14,10 +14,10 @@ #include <linux/init.h> #include "autofs_i.h" -static struct super_block *autofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int autofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, autofs_fill_super); + return get_sb_nodev(fs_type, flags, data, autofs_fill_super, mnt); } static struct file_system_type autofs_fs_type = { diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c index acecec8578ce9e08d4e9998405ab4d74778d3be1..5d9193332bef1b9eac190d80fb0fa5f97ff28f8a 100644 --- a/fs/autofs4/init.c +++ b/fs/autofs4/init.c @@ -14,10 +14,10 @@ #include <linux/init.h> #include "autofs_i.h" -static struct super_block *autofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int autofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, autofs4_fill_super); + return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); } static struct file_system_type autofs_fs_type = { diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 68ebd10f345db87fc2d7cee847d16431168e257c..6ed07a5f10c6b3eaff3f17a5aae941d748190bef 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -899,11 +899,12 @@ befs_statfs(struct super_block *sb, struct kstatfs *buf) return 0; } -static struct super_block * +static int befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, - void *data) + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super, + mnt); } static struct file_system_type befs_fs_type = { diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 55a7a78332f8b45bd4960e112fe222cc0980cbbd..e7da03f63a5a3fb299256df3c336fd135c9ab2c2 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -410,10 +410,10 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) return -EINVAL; } -static struct super_block *bfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super, mnt); } static struct file_system_type bfs_fs_type = { diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 599f36fd0f6712669a759c996bd608872f588d13..07a4996cca3f76c03a1a6434decc88f0dacfdc42 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -739,10 +739,10 @@ static int bm_fill_super(struct super_block * sb, void * data, int silent) return err; } -static struct super_block *bm_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bm_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, bm_fill_super); + return get_sb_single(fs_type, flags, data, bm_fill_super, mnt); } static struct linux_binfmt misc_format = { diff --git a/fs/block_dev.c b/fs/block_dev.c index 44aaba202f78f87083605e11030d1b7613f2ccc0..028d9fb9c2d536dafad7563e36874c0e8c934d91 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -300,10 +300,10 @@ static struct super_operations bdev_sops = { .clear_inode = bdev_clear_inode, }; -static struct super_block *bd_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bd_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576); + return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt); } static struct file_system_type bd_type = { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c262d8874ce97b87cc6b8c137c44d230621d3d00..08b35801dfedef35442616a5d5d0f871fefdc239 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -460,9 +460,9 @@ struct super_operations cifs_super_ops = { .remount_fs = cifs_remount, }; -static struct super_block * +static int cifs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { int rc; struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); @@ -470,7 +470,7 @@ cifs_get_sb(struct file_system_type *fs_type, cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); if (IS_ERR(sb)) - return sb; + return PTR_ERR(sb); sb->s_flags = flags; @@ -478,10 +478,10 @@ cifs_get_sb(struct file_system_type *fs_type, if (rc) { up_write(&sb->s_umount); deactivate_super(sb); - return ERR_PTR(rc); + return rc; } sb->s_flags |= MS_ACTIVE; - return sb; + return simple_set_mnt(mnt, sb); } static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, diff --git a/fs/coda/inode.c b/fs/coda/inode.c index ada1a81df6bdb807af15b429823f54b89a634434..cba70201567dba7328a0d96c9efb4382954be9b7 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -307,10 +307,10 @@ static int coda_statfs(struct super_block *sb, struct kstatfs *buf) /* init_coda: used by filesystems.c to register coda */ -static struct super_block *coda_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int coda_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, coda_fill_super); + return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt); } struct file_system_type coda_fs_type = { diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index f920d30478e531a7a656548d9d9c7169a0cc99bf..94dab7bdd8518beef6528359ea178a1a6877b0d7 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -103,10 +103,10 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *configfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int configfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, configfs_fill_super); + return get_sb_single(fs_type, flags, data, configfs_fill_super, mnt); } static struct file_system_type configfs_fs_type = { diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 9efcc3a164e8ccb1278e4cbebd8dcd0ad0cefffd..37a91a153aa52ec3ed8db1ec277b7374ea5e3769 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -528,10 +528,11 @@ static struct super_operations cramfs_ops = { .statfs = cramfs_statfs, }; -static struct super_block *cramfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int cramfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super, + mnt); } static struct file_system_type cramfs_fs_type = { diff --git a/fs/dcache.c b/fs/dcache.c index 59dbc92c2079b88054c6f5852b5c7bd04cbd187c..313b54b2b8f2cb0f074fd122f7b929f67b60cee8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -687,46 +687,6 @@ void shrink_dcache_parent(struct dentry * parent) prune_dcache(found, parent->d_sb); } -/** - * shrink_dcache_anon - further prune the cache - * @head: head of d_hash list of dentries to prune - * - * Prune the dentries that are anonymous - * - * parsing d_hash list does not hlist_for_each_entry_rcu() as it - * done under dcache_lock. - * - */ -void shrink_dcache_anon(struct super_block *sb) -{ - struct hlist_node *lp; - struct hlist_head *head = &sb->s_anon; - int found; - do { - found = 0; - spin_lock(&dcache_lock); - hlist_for_each(lp, head) { - struct dentry *this = hlist_entry(lp, struct dentry, d_hash); - if (!list_empty(&this->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&this->d_lru); - } - - /* - * move only zero ref count dentries to the end - * of the unused list for prune_dcache - */ - if (!atomic_read(&this->d_count)) { - list_add_tail(&this->d_lru, &dentry_unused); - dentry_stat.nr_unused++; - found++; - } - } - spin_unlock(&dcache_lock); - prune_dcache(found, sb); - } while(found); -} - /* * Scan `nr' dentries and return the number which remain. * diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b55b4ea9a67675a92377ffeb4a12ab9542ed8ca6..440128ebef3b04ed4a90c0d247475f1a701b4c2c 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -111,11 +111,11 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent) return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); } -static struct super_block *debug_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int debug_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, debug_fill_super); + return get_sb_single(fs_type, flags, data, debug_fill_super, mnt); } static struct file_system_type debug_fs_type = { diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 52f5059c4f311532d7898f5053ae520ed9f217df..51a97f1327453fea92ac48dc1b74573cc0f8fb30 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2549,11 +2549,11 @@ static int devfs_fill_super(struct super_block *sb, void *data, int silent) return -EINVAL; } /* End Function devfs_fill_super */ -static struct super_block *devfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int devfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, devfs_fill_super); + return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt); } static struct file_system_type devfs_fs_type = { diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 14c5620b5cabc0384c935565c98dda8582cf7527..f7aef5bb584a7deb5736f556da5b9155b754a760 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -130,10 +130,10 @@ devpts_fill_super(struct super_block *s, void *data, int silent) return -ENOMEM; } -static struct super_block *devpts_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int devpts_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, devpts_fill_super); + return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); } static struct file_system_type devpts_fs_type = { diff --git a/fs/efs/super.c b/fs/efs/super.c index dff623e3ddbfec7ccca9ec87bfc3410041278e5b..1ba5e14f879fef26d111ac73513018af34b3554e 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -18,10 +18,10 @@ static int efs_statfs(struct super_block *s, struct kstatfs *buf); static int efs_fill_super(struct super_block *s, void *d, int silent); -static struct super_block *efs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int efs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt); } static struct file_system_type efs_fs_type = { diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 2695337d4d6444de725372d6250e082d3acbf8a4..08e7e6a555cacc71d17333bb8f9ae8510a0e00ea 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -268,9 +268,9 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, long timeout); static int eventpollfs_delete_dentry(struct dentry *dentry); static struct inode *ep_eventpoll_inode(void); -static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data); +static int eventpollfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt); /* * This semaphore is used to serialize ep_free() and eventpoll_release_file(). @@ -1595,11 +1595,12 @@ static struct inode *ep_eventpoll_inode(void) } -static struct super_block * +static int eventpollfs_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) + const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC); + return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC, + mnt); } diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7e30bae174edce379a67c212953a90c5912b1a20..a4dfffac5967d76942744914881d7c61bbd8e7c0 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1087,10 +1087,10 @@ static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) return 0; } -static struct super_block *ext2_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ext2_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt); } #ifdef CONFIG_QUOTA diff --git a/fs/ext3/super.c b/fs/ext3/super.c index f8a5266ea1ffed333fd8b9c92af9a4da14518eb4..657f8e73b62f296e02d5a6e25d7401dfcc1f854a 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2646,10 +2646,10 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type, #endif -static struct super_block *ext3_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ext3_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt); } static struct file_system_type ext3_fs_type = { diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index b44c916d24a187f84e78db662c564dd98b818a09..d76eeaafbde2ecffd0a820fc4df464abcbbffc09 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -241,10 +241,11 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) /* * The usual module blurb. */ -static struct super_block *vxfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int vxfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super, + mnt); } static struct file_system_type vxfs_fs_type = { diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 7627022446b27b0cd067006df2b818dc1b5d9bf5..c91f0a50aadb9c68cac9a67e2bb2a41567a19e4f 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -569,11 +569,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) return err; } -static struct super_block *fuse_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *raw_data) +static int fuse_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *raw_data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super); + return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt); } static struct file_system_type fuse_fs_type = { diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 1181d116117dc52f40b503190a03e28053517eaa..ee5b80a409e88faf920b7d021ba535f1081be043 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -413,10 +413,11 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) return res; } -static struct super_block *hfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super, mnt); } static struct file_system_type hfs_fs_type = { diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 7843f792a4b79494919338965bba8aa9dfdb27f4..0ed8b7e8e87fb97bc7934d3ae1cd3fe1771138f0 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -450,10 +450,12 @@ static void hfsplus_destroy_inode(struct inode *inode) #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) -static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hfsplus_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super, + mnt); } static struct file_system_type hfsplus_fs_type = { diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index bf0f8e16e4336db36e64f7b46bc253b283c18b7d..04035e08f5c1c7615c7a25930e1ab461f8f10c26 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -993,11 +993,11 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) return(err); } -static struct super_block *hostfs_read_sb(struct file_system_type *type, - int flags, const char *dev_name, - void *data) +static int hostfs_read_sb(struct file_system_type *type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); + return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt); } static struct file_system_type hostfs_type = { diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index d72d8c87c9962a5fa64afd25c86e0e605fd8ba12..3b25cf3e2e6576128f941e2b98ed76b685f396fd 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -662,10 +662,11 @@ bail2: brelse(bh0); return -EINVAL; } -static struct super_block *hpfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hpfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super, + mnt); } static struct file_system_type hpfs_fs_type = { diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 5e6363be246f6026bc45f340fc7aa83db5b5d5ef..ec43c22bc9c0f7181a375ed8057548adece3ca36 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -769,11 +769,11 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) return(err); } -static struct super_block *hppfs_read_super(struct file_system_type *type, - int flags, const char *dev_name, - void *data) +static int hppfs_read_super(struct file_system_type *type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return(get_sb_nodev(type, flags, data, hppfs_fill_super)); + return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt); } static struct file_system_type hppfs_type = { diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 3a5b4e9234550200b252f3ca2333d3343aafcb4e..4665c26171f72c042be6f2c25388a37c983419cf 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -723,10 +723,10 @@ void hugetlb_put_quota(struct address_space *mapping) } } -static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int hugetlbfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super); + return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt); } static struct file_system_type hugetlbfs_fs_type = { diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 9e9931e2badde80d57629c479b4f415fceb7953a..f2386442adeeeafad47132049aea39284fc07d98 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -672,11 +672,11 @@ asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) return ret; } -static struct super_block * +static int inotify_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) + const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA); + return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt); } static struct file_system_type inotify_fs_type = { diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 70adbb98bad1a486d44d364284dcab57615bbb41..17268da63a494c62bcef2ec0491738acc7d0d50a 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1399,10 +1399,11 @@ struct inode *isofs_iget(struct super_block *sb, return inode; } -static struct super_block *isofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int isofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, + mnt); } static struct file_system_type iso9660_fs_type = { diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 020cc097c539955b6771412b3d32d9ac291a0494..dd93a091ad67f0bccc9882a9f58907b58bfa2049 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -1785,10 +1785,11 @@ static struct super_operations jffs_ops = .remount_fs = jffs_remount, }; -static struct super_block *jffs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int jffs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super, + mnt); } static struct file_system_type jffs_fs_type = { diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9d0521451f5943964f6cd223d025f3561b580de7..2378a662c2561660e10a592937f771bf74d8241e 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -111,9 +111,10 @@ static int jffs2_sb_set(struct super_block *sb, void *data) return 0; } -static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data, struct mtd_info *mtd) +static int jffs2_get_sb_mtd(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct mtd_info *mtd, + struct vfsmount *mnt) { struct super_block *sb; struct jffs2_sb_info *c; @@ -121,19 +122,20 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) - return ERR_PTR(-ENOMEM); + return -ENOMEM; memset(c, 0, sizeof(*c)); c->mtd = mtd; sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); if (IS_ERR(sb)) - goto out_put; + goto out_error; if (sb->s_root) { /* New mountpoint for JFFS2 which is already mounted */ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name)); + ret = simple_set_mnt(mnt, sb); goto out_put; } @@ -161,44 +163,47 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, /* Failure case... */ up_write(&sb->s_umount); deactivate_super(sb); - return ERR_PTR(ret); + return ret; } sb->s_flags |= MS_ACTIVE; - return sb; + return simple_set_mnt(mnt, sb); +out_error: + ret = PTR_ERR(sb); out_put: kfree(c); put_mtd_device(mtd); - return sb; + return ret; } -static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data, int mtdnr) +static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, int mtdnr, + struct vfsmount *mnt) { struct mtd_info *mtd; mtd = get_mtd_device(NULL, mtdnr); if (!mtd) { D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); - return ERR_PTR(-EINVAL); + return -EINVAL; } - return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); + return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); } -static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int jffs2_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { int err; struct nameidata nd; int mtdnr; if (!dev_name) - return ERR_PTR(-EINVAL); + return -EINVAL; D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); @@ -220,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, mtd = get_mtd_device(NULL, mtdnr); if (mtd) { if (!strcmp(mtd->name, dev_name+4)) - return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); + return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); put_mtd_device(mtd); } } @@ -233,7 +238,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, if (!*endptr) { /* It was a valid number */ D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); + return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); } } } @@ -247,7 +252,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, err, nd.dentry->d_inode)); if (err) - return ERR_PTR(err); + return err; err = -EINVAL; @@ -269,11 +274,11 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, mtdnr = iminor(nd.dentry->d_inode); path_release(&nd); - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); + return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); out: path_release(&nd); - return ERR_PTR(err); + return err; } static void jffs2_put_super (struct super_block *sb) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index db6f41d6dd60f03fab4366a3cde1f0ac8f3de9cd..18a28137b90e41617c95ffac38238e9cbfb7a3bc 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -565,10 +565,11 @@ static void jfs_unlockfs(struct super_block *sb) } } -static struct super_block *jfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int jfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super, + mnt); } static int jfs_sync_fs(struct super_block *sb, int wait) diff --git a/fs/libfs.c b/fs/libfs.c index 7145ba7a48d06329de45384b3d3bda2c607cc1a1..7d70efa46da962b56851d2647a16ff161b613f71 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -196,9 +196,9 @@ struct inode_operations simple_dir_inode_operations = { * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that * will never be mountable) */ -struct super_block * -get_sb_pseudo(struct file_system_type *fs_type, char *name, - struct super_operations *ops, unsigned long magic) +int get_sb_pseudo(struct file_system_type *fs_type, char *name, + struct super_operations *ops, unsigned long magic, + struct vfsmount *mnt) { struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); static struct super_operations default_ops = {.statfs = simple_statfs}; @@ -207,7 +207,7 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name, struct qstr d_name = {.name = name, .len = strlen(name)}; if (IS_ERR(s)) - return s; + return PTR_ERR(s); s->s_flags = MS_NOUSER; s->s_maxbytes = ~0ULL; @@ -232,12 +232,12 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name, d_instantiate(dentry, root); s->s_root = dentry; s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); Enomem: up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 2dcccf1d1b7f7d2b72110e2d2be6b3a2f911b0b8..14f24dfbfe30f6dbc81129c52a15f439d0c1a6a6 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -559,10 +559,11 @@ void minix_truncate(struct inode * inode) V2_minix_truncate(inode); } -static struct super_block *minix_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int minix_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super, + mnt); } static struct file_system_type minix_fs_type = { diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 5b76ccd19e3fc25489af2d3ebc1addb587994c96..9e44158a7540d3c41e6324c89ea78ebfa68c016b 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -661,11 +661,12 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *msdos_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int msdos_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super, + mnt); } static struct file_system_type msdos_fs_type = { diff --git a/fs/namespace.c b/fs/namespace.c index bf478addb852b70c1ec036e33100f93031c5dc6b..c13072a5f1ee8bd1a57c9186de12a5a55c553d1b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -86,6 +86,15 @@ struct vfsmount *alloc_vfsmnt(const char *name) return mnt; } +int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) +{ + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sb->s_root); + return 0; +} + +EXPORT_SYMBOL(simple_set_mnt); + void free_vfsmnt(struct vfsmount *mnt) { kfree(mnt->mnt_devname); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index a1f3e972c6ef78bda1a18249a82aedb727f9a1cf..8db033fab3fdda6e28a8374bbd8df185a96f42af 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -957,10 +957,10 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) return result; } -static struct super_block *ncp_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ncp_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, ncp_fill_super); + return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt); } static struct file_system_type ncp_fs_type = { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d0b991a92327f32941a454865c6aed187523d52e..ff645a961bc83b0d74eae5be0b93860ec9ba1b29 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1690,8 +1690,8 @@ static int nfs_compare_super(struct super_block *sb, void *data) return !nfs_compare_fh(&old->fh, &server->fh); } -static struct super_block *nfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data) +static int nfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { int error; struct nfs_server *server = NULL; @@ -1699,14 +1699,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, struct nfs_fh *root; struct nfs_mount_data *data = raw_data; - s = ERR_PTR(-EINVAL); + error = -EINVAL; if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); - goto out_err; + goto out_err_noserver; } if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { dprintk("%s: bad mount version\n", __FUNCTION__); - goto out_err; + goto out_err_noserver; } switch (data->version) { case 1: @@ -1718,7 +1718,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, dprintk("%s: mount structure version %d does not support NFSv3\n", __FUNCTION__, data->version); - goto out_err; + goto out_err_noserver; } data->root.size = NFS2_FHSIZE; memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); @@ -1727,24 +1727,24 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, dprintk("%s: mount structure version %d does not support strong security\n", __FUNCTION__, data->version); - goto out_err; + goto out_err_noserver; } case 5: memset(data->context, 0, sizeof(data->context)); } #ifndef CONFIG_NFS_V3 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ - s = ERR_PTR(-EPROTONOSUPPORT); + error = -EPROTONOSUPPORT; if (data->flags & NFS_MOUNT_VER3) { dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); - goto out_err; + goto out_err_noserver; } #endif /* CONFIG_NFS_V3 */ - s = ERR_PTR(-ENOMEM); + error = -ENOMEM; server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) - goto out_err; + goto out_err_noserver; /* Zero out the NFS state stuff */ init_nfsv4_state(server); server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); @@ -1754,7 +1754,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, root->size = data->root.size; else root->size = NFS2_FHSIZE; - s = ERR_PTR(-EINVAL); + error = -EINVAL; if (root->size > sizeof(root->data)) { dprintk("%s: invalid root filehandle\n", __FUNCTION__); goto out_err; @@ -1770,15 +1770,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, } /* Fire up rpciod if not yet running */ - s = ERR_PTR(rpciod_up()); - if (IS_ERR(s)) { - dprintk("%s: couldn't start rpciod! Error = %ld\n", - __FUNCTION__, PTR_ERR(s)); + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); goto out_err; } s = sget(fs_type, nfs_compare_super, nfs_set_super, server); - if (IS_ERR(s) || s->s_root) + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_err_rpciod; + } + + if (s->s_root) goto out_rpciod_down; s->s_flags = flags; @@ -1787,15 +1792,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); + out_rpciod_down: rpciod_down(); + kfree(server); + return simple_set_mnt(mnt, s); + +out_err_rpciod: + rpciod_down(); out_err: kfree(server); - return s; +out_err_noserver: + return error; } static void nfs_kill_super(struct super_block *s) @@ -2032,8 +2044,8 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) return dst; } -static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data) +static int nfs4_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { int error; struct nfs_server *server; @@ -2043,16 +2055,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); - return ERR_PTR(-EINVAL); + return -EINVAL; } if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { dprintk("%s: bad mount version\n", __FUNCTION__); - return ERR_PTR(-EINVAL); + return -EINVAL; } server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) - return ERR_PTR(-ENOMEM); + return -ENOMEM; /* Zero out the NFS state stuff */ init_nfsv4_state(server); server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); @@ -2074,33 +2086,41 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, /* We now require that the mount process passes the remote address */ if (data->host_addrlen != sizeof(server->addr)) { - s = ERR_PTR(-EINVAL); + error = -EINVAL; goto out_free; } if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { - s = ERR_PTR(-EFAULT); + error = -EFAULT; goto out_free; } if (server->addr.sin_family != AF_INET || server->addr.sin_addr.s_addr == INADDR_ANY) { dprintk("%s: mount program didn't pass remote IP address!\n", __FUNCTION__); - s = ERR_PTR(-EINVAL); + error = -EINVAL; goto out_free; } /* Fire up rpciod if not yet running */ - s = ERR_PTR(rpciod_up()); - if (IS_ERR(s)) { - dprintk("%s: couldn't start rpciod! Error = %ld\n", - __FUNCTION__, PTR_ERR(s)); + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); goto out_free; } s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); - - if (IS_ERR(s) || s->s_root) + if (IS_ERR(s)) { + error = PTR_ERR(s); goto out_free; + } + + if (s->s_root) { + kfree(server->mnt_path); + kfree(server->hostname); + kfree(server); + return simple_set_mnt(mnt, s); + } s->s_flags = flags; @@ -2108,17 +2128,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); out_err: - s = (struct super_block *)p; + error = PTR_ERR(p); out_free: kfree(server->mnt_path); kfree(server->hostname); kfree(server); - return s; + return error; } static void nfs4_kill_super(struct super_block *sb) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3ef017b3b5bde5b0526832175208c2be8bde4490..a1810e6a93e562fe9f5bbf3ed44086bddbf151c4 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -494,10 +494,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) return simple_fill_super(sb, 0x6e667364, nfsd_files); } -static struct super_block *nfsd_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int nfsd_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, nfsd_fill_super); + return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt); } static struct file_system_type nfsd_fs_type = { diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 27833f6df49f561e50f304c1b92549043cdeac23..d5d5e969294f181637f6f1f1804e73bc3cc1a1e8 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -3093,10 +3093,11 @@ struct kmem_cache *ntfs_index_ctx_cache; /* Driver wide mutex. */ DEFINE_MUTEX(ntfs_lock); -static struct super_block *ntfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ntfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super, + mnt); } static struct file_system_type ntfs_fs_type = { diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 7e88e24b347117debdbf1eb0a3e3f60e27e6c553..7273d9fa6bab6dcecbc2bcee7311b6052db2511b 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -574,10 +574,10 @@ static struct inode_operations dlmfs_file_inode_operations = { .getattr = simple_getattr, }; -static struct super_block *dlmfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int dlmfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super); + return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt); } static struct file_system_type dlmfs_fs_type = { diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 949b3dac30f142127cefd25226d149c4c8bf465a..788b8b50dc4c33e646e90bfbb2fade9f2f591ae1 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -672,12 +672,14 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) return status; } -static struct super_block *ocfs2_get_sb(struct file_system_type *fs_type, - int flags, - const char *dev_name, - void *data) +static int ocfs2_get_sb(struct file_system_type *fs_type, + int flags, + const char *dev_name, + void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super, + mnt); } static struct file_system_type ocfs2_fs_type = { diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 0f14276a2e510de843ad4c6877c9aa5bd469ce0a..464e2bce02030618779cb39e6f751679d1b8f538 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -1054,10 +1054,10 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent) return -ENOMEM; } -static struct super_block *openprom_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int openprom_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, openprom_fill_super); + return get_sb_single(fs_type, flags, data, openprom_fill_super, mnt); } static struct file_system_type openprom_fs_type = { diff --git a/fs/pipe.c b/fs/pipe.c index 5acd8954aaa0a58a582e3910d1fb1eb50aa5f592..20352573e025f0fe2574b6ffb300c44fc3605fa9 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -979,12 +979,11 @@ int do_pipe(int *fd) * any operations on the root directory. However, we need a non-trivial * d_name - pipe: will go nicely and kill the special-casing in procfs. */ - -static struct super_block * -pipefs_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int pipefs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); + return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt); } static struct file_system_type pipe_fs_type = { diff --git a/fs/proc/root.c b/fs/proc/root.c index c3fd3611112f27f0b9379e35d00887d5f89f90d1..9995356ce73e573285ff2ed3623f04fc72fcbfcc 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -26,10 +26,10 @@ struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc struct proc_dir_entry *proc_sys_root; #endif -static struct super_block *proc_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int proc_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, proc_fill_super); + return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); } static struct file_system_type proc_fs_type = { diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 2ecd46f85e9f271a90e217d9ec8ba7f9b0911a75..e6cca5cd4b44154983c52ed233a8f0860c1cb6cc 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -561,10 +561,11 @@ static void destroy_inodecache(void) "qnx4_inode_cache: not all structures were freed\n"); } -static struct super_block *qnx4_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int qnx4_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super, + mnt); } static struct file_system_type qnx4_fs_type = { diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 14bd2246fb6d3403ad2dbe97c36a3988145a0026..b9677335cc8d8c146c92daaf4e81b308a11121e8 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -185,16 +185,17 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) return 0; } -struct super_block *ramfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +int ramfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, ramfs_fill_super); + return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, mnt); } -static struct super_block *rootfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int rootfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super); + return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, + mnt); } static struct file_system_type ramfs_fs_type = { diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index cae2abbc0c713933a4283f9e66f215ebd3ec57db..f3ff41d3398954bbf160c3bc6e5231833580b70b 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2249,11 +2249,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, #endif -static struct super_block *get_super_block(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int get_super_block(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super, + mnt); } static int __init init_reiserfs_fs(void) diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 9b9eda7b335c431803092dde7aa6fabea1fe8bdc..4d6cd66210620b0508462731b3e56358937a18ec 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -607,10 +607,11 @@ static struct super_operations romfs_ops = { .remount_fs = romfs_remount, }; -static struct super_block *romfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int romfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super, + mnt); } static struct file_system_type romfs_fs_type = { diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index fdeabc0a34f7c041db719baa85dfca8db2ccd6d1..4a37c2bbfa3f80bc0ffeebb438de05548ee1e4b9 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -782,10 +782,10 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr) return error; } -static struct super_block *smb_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int smb_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, smb_fill_super); + return get_sb_nodev(fs_type, flags, data, smb_fill_super, mnt); } static struct file_system_type smb_fs_type = { diff --git a/fs/super.c b/fs/super.c index 9d5c2add72286d531e26f0471b0e0148e5dbd6b6..324c2d232f542b4d5136e151eba58b943c30a47b 100644 --- a/fs/super.c +++ b/fs/super.c @@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb) if (root) { sb->s_root = NULL; shrink_dcache_parent(root); - shrink_dcache_anon(sb); + shrink_dcache_sb(sb); dput(root); fsync_super(sb); lock_super(sb); @@ -676,9 +676,10 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action) } } -struct super_block *get_sb_bdev(struct file_system_type *fs_type, +int get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, - int (*fill_super)(struct super_block *, void *, int)) + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt) { struct block_device *bdev; struct super_block *s; @@ -686,7 +687,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, bdev = open_bdev_excl(dev_name, flags, fs_type); if (IS_ERR(bdev)) - return (struct super_block *)bdev; + return PTR_ERR(bdev); /* * once the super is inserted into the list by sget, s_umount @@ -697,15 +698,17 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); mutex_unlock(&bdev->bd_mount_mutex); if (IS_ERR(s)) - goto out; + goto error_s; if (s->s_root) { if ((flags ^ s->s_flags) & MS_RDONLY) { up_write(&s->s_umount); deactivate_super(s); - s = ERR_PTR(-EBUSY); + error = -EBUSY; + goto error_bdev; } - goto out; + + close_bdev_excl(bdev); } else { char b[BDEVNAME_SIZE]; @@ -716,18 +719,21 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - s = ERR_PTR(error); - } else { - s->s_flags |= MS_ACTIVE; - bdev_uevent(bdev, KOBJ_MOUNT); + goto error; } + + s->s_flags |= MS_ACTIVE; + bdev_uevent(bdev, KOBJ_MOUNT); } - return s; + return simple_set_mnt(mnt, s); -out: +error_s: + error = PTR_ERR(s); +error_bdev: close_bdev_excl(bdev); - return s; +error: + return error; } EXPORT_SYMBOL(get_sb_bdev); @@ -744,15 +750,16 @@ void kill_block_super(struct super_block *sb) EXPORT_SYMBOL(kill_block_super); -struct super_block *get_sb_nodev(struct file_system_type *fs_type, +int get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)) + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt) { int error; struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); if (IS_ERR(s)) - return s; + return PTR_ERR(s); s->s_flags = flags; @@ -760,10 +767,10 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type, if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; - return s; + return simple_set_mnt(mnt, s); } EXPORT_SYMBOL(get_sb_nodev); @@ -773,94 +780,102 @@ static int compare_single(struct super_block *s, void *p) return 1; } -struct super_block *get_sb_single(struct file_system_type *fs_type, +int get_sb_single(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)) + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt) { struct super_block *s; int error; s = sget(fs_type, compare_single, set_anon_super, NULL); if (IS_ERR(s)) - return s; + return PTR_ERR(s); if (!s->s_root) { s->s_flags = flags; error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); - return ERR_PTR(error); + return error; } s->s_flags |= MS_ACTIVE; } do_remount_sb(s, flags, data, 0); - return s; + return simple_set_mnt(mnt, s); } EXPORT_SYMBOL(get_sb_single); struct vfsmount * -do_kern_mount(const char *fstype, int flags, const char *name, void *data) +vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { - struct file_system_type *type = get_fs_type(fstype); - struct super_block *sb = ERR_PTR(-ENOMEM); struct vfsmount *mnt; - int error; char *secdata = NULL; + int error; if (!type) return ERR_PTR(-ENODEV); + error = -ENOMEM; mnt = alloc_vfsmnt(name); if (!mnt) goto out; if (data) { secdata = alloc_secdata(); - if (!secdata) { - sb = ERR_PTR(-ENOMEM); + if (!secdata) goto out_mnt; - } error = security_sb_copy_data(type, data, secdata); - if (error) { - sb = ERR_PTR(error); + if (error) goto out_free_secdata; - } } - sb = type->get_sb(type, flags, name, data); - if (IS_ERR(sb)) + error = type->get_sb(type, flags, name, data, mnt); + if (error < 0) goto out_free_secdata; - error = security_sb_kern_mount(sb, secdata); + + error = security_sb_kern_mount(mnt->mnt_sb, secdata); if (error) goto out_sb; - mnt->mnt_sb = sb; - mnt->mnt_root = dget(sb->s_root); - mnt->mnt_mountpoint = sb->s_root; + + mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - up_write(&sb->s_umount); + up_write(&mnt->mnt_sb->s_umount); free_secdata(secdata); - put_filesystem(type); return mnt; out_sb: - up_write(&sb->s_umount); - deactivate_super(sb); - sb = ERR_PTR(error); + dput(mnt->mnt_root); + up_write(&mnt->mnt_sb->s_umount); + deactivate_super(mnt->mnt_sb); out_free_secdata: free_secdata(secdata); out_mnt: free_vfsmnt(mnt); out: + return ERR_PTR(error); +} + +EXPORT_SYMBOL_GPL(vfs_kern_mount); + +struct vfsmount * +do_kern_mount(const char *fstype, int flags, const char *name, void *data) +{ + struct file_system_type *type = get_fs_type(fstype); + struct vfsmount *mnt; + if (!type) + return ERR_PTR(-ENODEV); + mnt = vfs_kern_mount(type, flags, name, data); put_filesystem(type); - return (struct vfsmount *)sb; + return mnt; } EXPORT_SYMBOL_GPL(do_kern_mount); struct vfsmount *kern_mount(struct file_system_type *type) { - return do_kern_mount(type->name, 0, type->name, NULL); + return vfs_kern_mount(type, 0, type->name, NULL); } EXPORT_SYMBOL(kern_mount); diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index f1117e885bd6e95c7402c50c6d9b52a6b69f0b43..40190c4892715502b286c3e491c114af1c0b97bd 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -66,10 +66,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *sysfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sysfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sysfs_fill_super); + return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); } static struct file_system_type sysfs_fs_type = { diff --git a/fs/sysv/super.c b/fs/sysv/super.c index e92b991e6dda0fff10cb4ba5211a6b995a2ce153..876639b93321b42ac37336fa6a336ca6bb946a56 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c @@ -506,16 +506,17 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) /* Every kernel module contains stuff like this. */ -static struct super_block *sysv_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sysv_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super, + mnt); } -static struct super_block *v7_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int v7_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super, mnt); } static struct file_system_type sysv_fs_type = { diff --git a/fs/udf/super.c b/fs/udf/super.c index e45789fe38e8da1e69dec52c6c7c11be82cac855..2250774a831d89f61dc4bbb505e4e30f2ee01419 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -94,10 +94,10 @@ static unsigned int udf_count_free(struct super_block *); static int udf_statfs(struct super_block *, struct kstatfs *); /* UDF filesystem type */ -static struct super_block *udf_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int udf_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super, mnt); } static struct file_system_type udf_fstype = { diff --git a/fs/ufs/super.c b/fs/ufs/super.c index db98a4c71e630753c582945152f6061839dbd060..768fb8d9e67aa2c6a1867d83022df64ff0322388 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1311,10 +1311,10 @@ static ssize_t ufs_quota_write(struct super_block *sb, int type, #endif -static struct super_block *ufs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int ufs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt); } static struct file_system_type ufs_fs_type = { diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index a56cec3be5f09cf9be5e81d28065c6923962ec69..9a8f48bae95626b739b34867713fc2d7d367f649 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -1023,11 +1023,12 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *vfat_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int vfat_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super, + mnt); } static struct file_system_type vfat_fs_type = { diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index f2a0778536f4bb9e7d609c5c0f6a2b3b724f1ac6..d03c89a366550df8c65eaaa5d135b8bf581cdd99 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -853,14 +853,16 @@ xfs_fs_fill_super( return -error; } -STATIC struct super_block * +STATIC int xfs_fs_get_sb( struct file_system_type *fs_type, int flags, const char *dev_name, - void *data) + void *data, + struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super, + mnt); } STATIC struct super_operations xfs_super_operations = { diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 46d0e079735d19c01310df7200f058dd36af1401..0dd1610a94a940bdc38a12c0bd875c9159e55685 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -217,7 +217,6 @@ extern struct dentry * d_alloc_anon(struct inode *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); -extern void shrink_dcache_anon(struct super_block *); extern int d_invalidate(struct dentry *); /* only used at mount-time */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 73c7d6f04b31a657a9b7060ac43f5a256ce070f4..3e50dd24af875c6dcad5386fcfb6d7867b1dffed 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1269,23 +1269,26 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, struct file_system_type { const char *name; int fs_flags; - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct list_head fs_supers; }; -struct super_block *get_sb_bdev(struct file_system_type *fs_type, +extern int get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, - int (*fill_super)(struct super_block *, void *, int)); -struct super_block *get_sb_single(struct file_system_type *fs_type, + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt); +extern int get_sb_single(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)); -struct super_block *get_sb_nodev(struct file_system_type *fs_type, + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt); +extern int get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, - int (*fill_super)(struct super_block *, void *, int)); + int (*fill_super)(struct super_block *, void *, int), + struct vfsmount *mnt); void generic_shutdown_super(struct super_block *sb); void kill_block_super(struct super_block *sb); void kill_anon_super(struct super_block *sb); @@ -1296,8 +1299,10 @@ struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), void *data); -struct super_block *get_sb_pseudo(struct file_system_type *, char *, - struct super_operations *ops, unsigned long); +extern int get_sb_pseudo(struct file_system_type *, char *, + struct super_operations *ops, unsigned long, + struct vfsmount *mnt); +extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); int __put_super(struct super_block *sb); int __put_super_and_need_restart(struct super_block *sb); void unnamed_dev_init(void); diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 78ecfa28b1c286a3d5b5b8f22892ba18f6c26a46..00b340ba66127131b5f4a3790d649b1bc33c5256 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -2,8 +2,8 @@ #define _LINUX_RAMFS_H struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev); -struct super_block *ramfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data); +extern int ramfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt); #ifndef CONFIG_MMU extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 1511714a95851dc8af01ee2421907c5b0d23725c..0a2a24b6ebe40b3ff143ea0dfcaa5ae67ebba040 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -205,11 +205,11 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent) return 0; } -static struct super_block *mqueue_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int mqueue_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, mqueue_fill_super); + return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt); } static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index ab81fdd4572bb4b65dad432d69f58f222d3f1aee..77f45ffd5ea102499302233265c87b1b5d2ddc1a 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -392,11 +392,11 @@ static int cpuset_fill_super(struct super_block *sb, void *unused_data, return 0; } -static struct super_block *cpuset_get_sb(struct file_system_type *fs_type, - int flags, const char *unused_dev_name, - void *data) +static int cpuset_get_sb(struct file_system_type *fs_type, + int flags, const char *unused_dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, cpuset_fill_super); + return get_sb_single(fs_type, flags, data, cpuset_fill_super, mnt); } static struct file_system_type cpuset_fs_type = { diff --git a/kernel/futex.c b/kernel/futex.c index 5699c512057b087a14633b357a618d4528d4a032..e1a380c77a5a2ac947f4fceee190fa7518488f41 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1056,11 +1056,11 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, (unsigned long)uaddr2, val2, val3); } -static struct super_block * -futexfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int futexfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA); + return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt); } static struct file_system_type futex_fs_type = { diff --git a/mm/shmem.c b/mm/shmem.c index 1e43c8a865ba76924170f34471f32ad5a3cbdfdb..7617bb1c6bf78cd7789a40b2baa821e4fdb01837 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2233,10 +2233,10 @@ static struct vm_operations_struct shmem_vm_ops = { }; -static struct super_block *shmem_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int shmem_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_nodev(fs_type, flags, data, shmem_fill_super); + return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt); } static struct file_system_type tmpfs_fs_type = { diff --git a/net/socket.c b/net/socket.c index 02948b622bd2e938bfc6d02e44f2d13ae2b9f874..565f5e8d11913c797500a517c03835eee6e15ff9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -335,10 +335,11 @@ static struct super_operations sockfs_ops = { .statfs = simple_statfs, }; -static struct super_block *sockfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sockfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC); + return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC, + mnt); } static struct vfsmount *sock_mnt __read_mostly; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index cc673dd8433fd3653d66100e460acf7cdfac60ac..8241fa72680393c60675b3adb61e9981bf3e8193 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -815,11 +815,11 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) return -ENOMEM; } -static struct super_block * +static int rpc_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, rpc_fill_super); + return get_sb_single(fs_type, flags, data, rpc_fill_super, mnt); } static struct file_system_type rpc_pipe_fs_type = { diff --git a/security/inode.c b/security/inode.c index 0f77b0223662882ab548b8a27dfe16c2a4b94c08..e6fc29ac8564ac4f26c465c05e238e81049833c7 100644 --- a/security/inode.c +++ b/security/inode.c @@ -135,11 +135,11 @@ static int fill_super(struct super_block *sb, void *data, int silent) return simple_fill_super(sb, SECURITYFS_MAGIC, files); } -static struct super_block *get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, fill_super); + return get_sb_single(fs_type, flags, data, fill_super, mnt); } static struct file_system_type fs_type = { diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 2e73d3279f2dbd63d0e8a2e67a199410086353b3..7029bbc9bef8c1b897e4883bd8b9d587eb431eeb 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1345,10 +1345,11 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) goto out; } -static struct super_block *sel_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int sel_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, sel_fill_super); + return get_sb_single(fs_type, flags, data, sel_fill_super, mnt); } static struct file_system_type sel_fs_type = {