Jan Blunck
2009-Nov-02 10:04 UTC
[Ocfs2-devel] [PATCH 01/27] BKL: Push down BKL from do_new_mount() to the filesystems get_sb/fill_super operation
I've read through all the code formerly covered by the BKL inside do_kern_mount() and have satisfied myself that it doesn't need the BKL any more. do_kern_mount() is already called without the BKL when mounting the rootfs and in nfsctl. do_kern_mount() calls vfs_kern_mount(), which is called from various places without BKL: simple_pin_fs(), nfs_do_clone_mount() through nfs_follow_mountpoint(), afs_mntpt_do_automount() through afs_mntpt_follow_link(). Both later functions are actually the filesystems follow_link inode operation. vfs_kern_mount() is calling the specified get_sb function and lets the filesystem do its job by calling the given fill_super function. Therefore I think it is safe to push down the BKL from the VFS to the low-level filesystems get_sb/fill_super operation. Signed-off-by: Jan Blunck <jblunck at suse.de> Cc: Matthew Wilcox <matthew at wil.cx> --- fs/9p/vfs_super.c | 9 ++++++++- fs/adfs/super.c | 8 +++++++- fs/affs/super.c | 9 ++++++++- fs/afs/super.c | 5 +++++ fs/autofs4/inode.c | 4 ++++ fs/befs/linuxvfs.c | 4 ++++ fs/bfs/inode.c | 9 ++++++++- fs/binfmt_misc.c | 6 +++++- fs/btrfs/super.c | 8 +++++++- fs/cifs/cifsfs.c | 12 ++++++++++-- fs/coda/inode.c | 8 +++++++- fs/configfs/mount.c | 5 +++++ fs/cramfs/inode.c | 8 +++++++- fs/devpts/inode.c | 13 +++++++++++-- fs/ecryptfs/main.c | 3 +++ fs/efs/super.c | 10 ++++++++-- fs/exofs/super.c | 7 ++++++- fs/ext2/super.c | 10 ++++++++-- fs/ext3/super.c | 9 ++++++++- fs/ext4/super.c | 9 ++++++--- fs/fat/namei_msdos.c | 6 +++++- fs/fat/namei_vfat.c | 6 +++++- fs/freevxfs/vxfs_super.c | 7 ++++++- fs/fuse/control.c | 9 ++++++++- fs/fuse/inode.c | 5 +++++ fs/gfs2/ops_fstype.c | 9 +++++++++ fs/hfs/super.c | 8 +++++++- fs/hfsplus/super.c | 8 +++++++- fs/hostfs/hostfs_kern.c | 4 ++++ fs/hpfs/super.c | 8 +++++++- fs/hppfs/hppfs.c | 4 ++++ fs/hugetlbfs/inode.c | 12 ++++++++++-- fs/isofs/inode.c | 8 +++++++- fs/jffs2/super.c | 11 +++++++++-- fs/jfs/super.c | 14 ++++++++++++-- fs/libfs.c | 10 +++++++++- fs/minix/inode.c | 8 +++++++- fs/namespace.c | 2 -- fs/ncpfs/inode.c | 8 +++++++- fs/nfs/super.c | 19 +++++++++++++++++++ fs/nfsd/nfsctl.c | 7 ++++++- fs/nilfs2/super.c | 9 ++++++++- fs/ntfs/super.c | 5 +++++ fs/ocfs2/dlm/dlmfs.c | 8 +++++++- fs/ocfs2/super.c | 5 +++++ fs/omfs/inode.c | 7 ++++++- fs/openpromfs/inode.c | 4 ++++ fs/proc/root.c | 9 ++++++++- fs/qnx4/inode.c | 8 +++++++- fs/ramfs/inode.c | 5 +++++ fs/reiserfs/super.c | 4 ++++ fs/romfs/super.c | 9 ++++++++- fs/smbfs/inode.c | 5 +++++ fs/squashfs/super.c | 6 ++++++ fs/sysfs/mount.c | 6 ++++++ fs/sysv/super.c | 24 +++++++++++++++++++----- fs/ubifs/super.c | 5 +++++ fs/udf/super.c | 8 +++++++- fs/ufs/super.c | 5 +++++ fs/xfs/linux-2.6/xfs_super.c | 4 ++++ 60 files changed, 412 insertions(+), 53 deletions(-) diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 14a8644..4156a0c 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -106,11 +106,15 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, struct p9_fid *fid; int retval = 0; + lock_kernel(); + P9_DPRINTK(P9_DEBUG_VFS, " \n"); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); - if (!v9ses) + if (!v9ses) { + unlock_kernel(); return -ENOMEM; + } fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { @@ -155,6 +159,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); simple_set_mnt(mnt, sb); + unlock_kernel(); return 0; free_stat: @@ -167,12 +172,14 @@ clunk_fid: close_session: v9fs_session_close(v9ses); kfree(v9ses); + unlock_kernel(); return retval; release_sb: p9stat_free(st); kfree(st); deactivate_locked_super(sb); + unlock_kernel(); return retval; } diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 6910a98..e94f111 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -351,11 +351,15 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) struct adfs_sb_info *asb; struct inode *root; + lock_kernel(); + sb->s_flags |= MS_NODIRATIME; asb = kzalloc(sizeof(*asb), GFP_KERNEL); - if (!asb) + if (!asb) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = asb; /* set default options */ @@ -473,6 +477,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) goto error; } else sb->s_root->d_op = &adfs_dentry_operations; + unlock_kernel(); return 0; error_free_bh: @@ -480,6 +485,7 @@ error_free_bh: error: sb->s_fs_info = NULL; kfree(asb); + unlock_kernel(); return -EINVAL; } diff --git a/fs/affs/super.c b/fs/affs/super.c index 104fdcb..135f0d3 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -298,6 +298,8 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) u8 sig[4]; int ret = -EINVAL; + lock_kernel(); + save_mount_options(sb, data); pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options"); @@ -307,8 +309,10 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) sb->s_flags |= MS_NODIRATIME; sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; mutex_init(&sbi->s_bmlock); @@ -316,6 +320,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) &blocksize,&sbi->s_prefix, sbi->s_volume, &mount_flags)) { printk(KERN_ERR "AFFS: Error parsing options\n"); + unlock_kernel(); return -EINVAL; } /* N.B. after this point s_prefix must be released */ @@ -486,6 +491,7 @@ got_root: sb->s_root->d_op = &affs_dentry_operations; pr_debug("AFFS: s_flags=%lX\n",sb->s_flags); + unlock_kernel(); return 0; /* @@ -500,6 +506,7 @@ out_error_noinode: kfree(sbi->s_prefix); kfree(sbi); sb->s_fs_info = NULL; + unlock_kernel(); return ret; } diff --git a/fs/afs/super.c b/fs/afs/super.c index e1ea1c2..108fb3e 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -294,12 +294,15 @@ static int afs_fill_super(struct super_block *sb, void *data) struct inode *inode = NULL; int ret; + lock_kernel(); + _enter(""); /* allocate a superblock info record */ as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); if (!as) { _leave(" = -ENOMEM"); + unlock_kernel(); return -ENOMEM; } @@ -329,6 +332,7 @@ static int afs_fill_super(struct super_block *sb, void *data) sb->s_root = root; _leave(" = 0"); + unlock_kernel(); return 0; error_inode: @@ -342,6 +346,7 @@ error: sb->s_fs_info = NULL; _leave(" = %d", ret); + unlock_kernel(); return ret; } diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 69c8142..3adaba9 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -323,6 +323,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) struct autofs_sb_info *sbi; struct autofs_info *ino; + lock_kernel(); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) goto fail_unlock; @@ -418,6 +420,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) * Success! Install the root dentry now to indicate completion. */ s->s_root = root; + unlock_kernel(); return 0; /* @@ -439,6 +442,7 @@ fail_free: kfree(sbi); s->s_fs_info = NULL; fail_unlock: + unlock_kernel(); return -EINVAL; } diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 33baf27..f2aa193 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -759,6 +759,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent) const unsigned long sb_block = 0; const off_t x86_sb_off = 512; + lock_kernel(); + save_mount_options(sb, data); sb->s_fs_info = kmalloc(sizeof (*befs_sb), GFP_KERNEL); @@ -867,6 +869,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) befs_sb->nls = load_nls_default(); } + unlock_kernel(); return 0; /*****************/ unacquire_bh: @@ -877,6 +880,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) unacquire_none: sb->s_fs_info = NULL; + unlock_kernel(); return ret; } diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 6f60336..4bff506 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -356,9 +356,13 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) long ret = -EINVAL; unsigned long i_sblock, i_eblock, i_eoff, s_size; + lock_kernel(); + info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + if (!info) { + unlock_kernel(); return -ENOMEM; + } s->s_fs_info = info; sb_set_blocksize(s, BFS_BSIZE); @@ -463,6 +467,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) kfree(info->si_imap); kfree(info); s->s_fs_info = NULL; + unlock_kernel(); return -EIO; } @@ -484,12 +489,14 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) } dump_imap("read_super", s); mutex_init(&info->bfs_lock); + unlock_kernel(); return 0; out: brelse(bh); kfree(info); s->s_fs_info = NULL; + unlock_kernel(); return ret; } diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c4e8353..ca0e22d 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -695,9 +695,13 @@ static int bm_fill_super(struct super_block * sb, void * data, int silent) [3] = {"register", &bm_register_operations, S_IWUSR}, /* last one */ {""} }; - int err = simple_fill_super(sb, 0x42494e4d, bm_files); + int err; + + lock_kernel(); + err = simple_fill_super(sb, 0x42494e4d, bm_files); if (!err) sb->s_op = &s_ops; + unlock_kernel(); return err; } diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 752a546..e5cd2cf 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -480,13 +480,17 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, fmode_t mode = FMODE_READ; int error = 0; + lock_kernel(); + if (!(flags & MS_RDONLY)) mode |= FMODE_WRITE; error = btrfs_parse_early_options(data, mode, fs_type, &subvol_name, &fs_devices); - if (error) + if (error) { + unlock_kernel(); return error; + } error = btrfs_scan_one_device(dev_name, mode, fs_type, &fs_devices); if (error) @@ -555,6 +559,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, mnt->mnt_root = root; kfree(subvol_name); + unlock_kernel(); return 0; error_s: @@ -563,6 +568,7 @@ error_close_devices: btrfs_close_devices(fs_devices); error_free_subvol_name: kfree(subvol_name); + unlock_kernel(); return error; } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9a5e4f5..09ccb9d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -596,22 +596,30 @@ cifs_get_sb(struct file_system_type *fs_type, 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); + struct super_block *sb; + + lock_kernel(); + + sb = sget(fs_type, NULL, set_anon_super, NULL); cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); - if (IS_ERR(sb)) + if (IS_ERR(sb)) { + unlock_kernel(); return PTR_ERR(sb); + } sb->s_flags = flags; rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0); if (rc) { deactivate_locked_super(sb); + unlock_kernel(); return rc; } sb->s_flags |= MS_ACTIVE; simple_set_mnt(mnt, sb); + unlock_kernel(); return 0; } diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 830f51a..d081fc5 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -147,6 +147,8 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) int error; int idx; + lock_kernel(); + idx = get_device_index((struct coda_mount_data *) data); /* Ignore errors in data, for backward compatibility */ @@ -158,11 +160,13 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) vc = &coda_comms[idx]; if (!vc->vc_inuse) { printk("coda_read_super: No pseudo device\n"); + unlock_kernel(); return -EINVAL; } if ( vc->vc_sb ) { printk("coda_read_super: Device already mounted\n"); + unlock_kernel(); return -EBUSY; } @@ -196,7 +200,8 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) sb->s_root = d_alloc_root(root); if (!sb->s_root) goto error; - return 0; + unlock_kernel(); + return 0; error: if (root) @@ -204,6 +209,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent) if (vc) vc->vc_sb = NULL; + unlock_kernel(); return -EINVAL; } diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index 8421cea..5b2e06e 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -71,6 +71,8 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) struct inode *inode; struct dentry *root; + lock_kernel(); + sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = CONFIGFS_MAGIC; @@ -87,6 +89,7 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) inc_nlink(inode); } else { pr_debug("configfs: could not get root inode\n"); + unlock_kernel(); return -ENOMEM; } @@ -94,12 +97,14 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); iput(inode); + unlock_kernel(); return -ENOMEM; } config_group_init(&configfs_root_group); configfs_root_group.cg_item.ci_dentry = root; root->d_fsdata = &configfs_root; sb->s_root = root; + unlock_kernel(); return 0; } diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index dd3634e..13e696a 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -227,11 +227,15 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) struct cramfs_sb_info *sbi; struct inode *root; + lock_kernel(); + sb->s_flags |= MS_RDONLY; sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; /* Invalidate the read buffers on mount: think disk change.. */ @@ -308,10 +312,12 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) iput(root); goto out; } + unlock_kernel(); return 0; out: kfree(sbi); sb->s_fs_info = NULL; + unlock_kernel(); return -EINVAL; } diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index d5f8c96..e206eef 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -24,6 +24,7 @@ #include <linux/parser.h> #include <linux/fsnotify.h> #include <linux/seq_file.h> +#include <linux/smp_lock.h> /* just for lock_kernel() */ #define DEVPTS_DEFAULT_MODE 0600 /* @@ -363,17 +364,23 @@ static int devpts_get_sb(struct file_system_type *fs_type, struct pts_mount_opts opts; struct super_block *s; + lock_kernel(); + error = parse_mount_options(data, PARSE_MOUNT, &opts); - if (error) + if (error) { + unlock_kernel(); return error; + } if (opts.newinstance) s = sget(fs_type, NULL, set_anon_super, NULL); else s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); - if (IS_ERR(s)) + if (IS_ERR(s)) { + unlock_kernel(); return PTR_ERR(s); + } if (!s->s_root) { s->s_flags = flags; @@ -391,6 +398,7 @@ static int devpts_get_sb(struct file_system_type *fs_type, if (error) goto out_dput; + unlock_kernel(); return 0; out_dput: @@ -398,6 +406,7 @@ out_dput: out_undo_sget: deactivate_locked_super(s); + unlock_kernel(); return error; } diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index c6ac85d..fdc7bda 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -600,6 +600,8 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags, int rc; struct super_block *sb; + lock_kernel(); + rc = get_sb_nodev(fs_type, flags, raw_data, ecryptfs_fill_super, mnt); if (rc < 0) { printk(KERN_ERR "Getting sb failed; rc = [%d]\n", rc); @@ -621,6 +623,7 @@ out_abort: dput(sb->s_root); /* aka mnt->mnt_root, as set by get_sb_nodev() */ deactivate_locked_super(sb); out: + unlock_kernel(); return rc; } diff --git a/fs/efs/super.c b/fs/efs/super.c index f049428..0981141 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -249,9 +249,13 @@ static int efs_fill_super(struct super_block *s, void *d, int silent) struct inode *root; int ret = -EINVAL; - sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL); - if (!sb) + lock_kernel(); + + sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL); + if (!sb) { + unlock_kernel(); return -ENOMEM; + } s->s_fs_info = sb; s->s_magic = EFS_SUPER_MAGIC; @@ -319,12 +323,14 @@ static int efs_fill_super(struct super_block *s, void *d, int silent) goto out_no_fs; } + unlock_kernel(); return 0; out_no_fs_ul: out_no_fs: s->s_fs_info = NULL; kfree(sb); + unlock_kernel(); return ret; } diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 9f500de..ea045b8 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -297,9 +297,13 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) struct osd_obj_id obj; int ret; + lock_kernel(); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; /* use mount options to fill superblock */ @@ -399,6 +403,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) out: if (or) osd_end_request(or); + unlock_kernel(); return ret; free_sbi: diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 1a9ffee..5af1775 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -745,15 +745,18 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) __le32 features; int err; + lock_kernel(); + + err = -ENOMEM; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) - return -ENOMEM; + goto failed_unlock; sbi->s_blockgroup_lock kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); if (!sbi->s_blockgroup_lock) { kfree(sbi); - return -ENOMEM; + goto failed_unlock; } sb->s_fs_info = sbi; sbi->s_sb_block = sb_block; @@ -1063,6 +1066,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) ext2_warning(sb, __func__, "mounting ext3 filesystem as ext2"); ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); + unlock_kernel(); return 0; cantfind_ext2: @@ -1086,6 +1090,8 @@ failed_sbi: sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); kfree(sbi); +failed_unlock: + unlock_kernel(); return ret; } diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 7a520a8..38261a5 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1568,14 +1568,19 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) __le32 features; int err; + lock_kernel(); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sbi->s_blockgroup_lock kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); if (!sbi->s_blockgroup_lock) { kfree(sbi); + unlock_kernel(); return -ENOMEM; } sb->s_fs_info = sbi; @@ -1992,6 +1997,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) "writeback"); lock_kernel(); + unlock_kernel(); return 0; cantfind_ext3: @@ -2022,6 +2028,7 @@ out_fail: kfree(sbi->s_blockgroup_lock); kfree(sbi); lock_kernel(); + unlock_kernel(); return ret; } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 312211e..9db81d2 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2328,14 +2328,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) int err; unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; + lock_kernel(); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sbi->s_blockgroup_lock kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); if (!sbi->s_blockgroup_lock) { kfree(sbi); + unlock_kernel(); return -ENOMEM; } sb->s_fs_info = sbi; @@ -2913,7 +2918,6 @@ no_journal: ext4_msg(sb, KERN_INFO, "mounted filesystem with%s", descr); - lock_kernel(); return 0; cantfind_ext4: @@ -2959,7 +2963,6 @@ out_fail: sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); kfree(sbi); - lock_kernel(); return ret; } diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index bbc94ae..31dd072 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -662,12 +662,16 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent) { int res; + lock_kernel(); res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0); - if (res) + if (res) { + unlock_kernel(); return res; + } sb->s_flags |= MS_NOATIME; sb->s_root->d_op = &msdos_dentry_operations; + unlock_kernel(); return 0; } diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index f565f24..12961b8 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -1044,15 +1044,19 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent) { int res; + lock_kernel(); res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1); - if (res) + if (res) { + unlock_kernel(); return res; + } if (MSDOS_SB(sb)->options.name_check != 's') sb->s_root->d_op = &vfat_ci_dentry_ops; else sb->s_root->d_op = &vfat_dentry_ops; + unlock_kernel(); return 0; } diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 1e8af93..b8b7821 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -148,7 +148,7 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) * The superblock on success, else %NULL. * * Locking: - * We are under the bkl and @sbp->s_lock. + * We are under @sbp->s_lock. */ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) { @@ -159,11 +159,14 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) struct inode *root; int ret = -EINVAL; + lock_kernel(); + sbp->s_flags |= MS_RDONLY; infp = kzalloc(sizeof(*infp), GFP_KERNEL); if (!infp) { printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n"); + unlock_kernel(); return -ENOMEM; } @@ -236,6 +239,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out_free_ilist; } + unlock_kernel(); return 0; out_free_ilist: @@ -245,6 +249,7 @@ out_free_ilist: out: brelse(bp); kfree(infp); + unlock_kernel(); return ret; } diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 3773fd6..8d769f7 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/smp_lock.h> /* just for lock_kernel() */ #define FUSE_CTL_SUPER_MAGIC 0x65735543 @@ -297,9 +298,13 @@ static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent) struct fuse_conn *fc; int err; + lock_kernel(); + err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr); - if (err) + if (err) { + unlock_kernel(); return err; + } mutex_lock(&fuse_mutex); BUG_ON(fuse_control_sb); @@ -309,10 +314,12 @@ static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent) if (err) { fuse_control_sb = NULL; mutex_unlock(&fuse_mutex); + unlock_kernel(); return err; } } mutex_unlock(&fuse_mutex); + unlock_kernel(); return 0; } diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1a822ce..5690279 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -20,6 +20,7 @@ #include <linux/random.h> #include <linux/sched.h> #include <linux/exportfs.h> +#include <linux/smp_lock.h> /* Only for lock_kernel() */ MODULE_AUTHOR("Miklos Szeredi <miklos at szeredi.hu>"); MODULE_DESCRIPTION("Filesystem in Userspace"); @@ -919,6 +920,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) int err; int is_bdev = sb->s_bdev != NULL; + lock_kernel(); + err = -EINVAL; if (sb->s_flags & MS_MANDLOCK) goto err; @@ -1022,6 +1025,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) fuse_send_init(fc, init_req); + unlock_kernel(); return 0; err_unlock: @@ -1036,6 +1040,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) err_fput: fput(file); err: + unlock_kernel(); return err; } diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 52fb6c0..76415fe 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1120,9 +1120,12 @@ static int fill_super(struct super_block *sb, void *data, int silent) struct gfs2_holder mount_gh; int error; + lock_kernel(); + sdp = init_sbd(sb); if (!sdp) { printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); + unlock_kernel(); return -ENOMEM; } @@ -1211,6 +1214,7 @@ static int fill_super(struct super_block *sb, void *data, int silent) gfs2_glock_dq_uninit(&mount_gh); gfs2_online_uevent(sdp); + unlock_kernel(); return 0; fail_threads: @@ -1240,6 +1244,7 @@ fail: gfs2_delete_debugfs_file(sdp); kfree(sdp); sb->s_fs_info = NULL; + unlock_kernel(); return error; } @@ -1268,10 +1273,12 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, struct path path; int error; + lock_kernel(); error = kern_path(dev_name, LOOKUP_FOLLOW, &path); if (error) { printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", dev_name, error); + unlock_kernel(); return error; } s = sget(&gfs2_fs_type, test_meta_super, set_meta_super, @@ -1279,11 +1286,13 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, path_put(&path); if (IS_ERR(s)) { printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); + unlock_kernel(); return PTR_ERR(s); } sdp = s->s_fs_info; mnt->mnt_sb = s; mnt->mnt_root = dget(sdp->sd_master_dir); + unlock_kernel(); return 0; } diff --git a/fs/hfs/super.c b/fs/hfs/super.c index f7fcbe4..a2e19ff 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -381,9 +381,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) struct inode *root_inode; int res; + lock_kernel(); + sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; INIT_HLIST_HEAD(&sbi->rsrc_inodes); @@ -429,6 +433,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_root->d_op = &hfs_dentry_operations; /* everything's okay */ + unlock_kernel(); return 0; bail_iput: @@ -437,6 +442,7 @@ bail_no_root: printk(KERN_ERR "hfs: get root inode failed.\n"); bail: hfs_mdb_put(sb); + unlock_kernel(); return res; } diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 43022f3..824f57a 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -312,9 +312,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) struct nls_table *nls = NULL; int err = -EINVAL; + lock_kernel(); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; INIT_HLIST_HEAD(&sbi->rsrc_inodes); @@ -459,11 +463,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) out: unload_nls(sbi->nls); sbi->nls = nls; + unlock_kernel(); return 0; cleanup: hfsplus_put_super(sb); unload_nls(nls); + unlock_kernel(); return err; } diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 032604e..5eb2c26 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -968,6 +968,8 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) char *host_root_path, *req_root = d; int err; + lock_kernel(); + sb->s_blocksize = 1024; sb->s_blocksize_bits = 10; sb->s_magic = HOSTFS_SUPER_MAGIC; @@ -1016,6 +1018,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) goto out; } + unlock_kernel(); return 0; out_put: @@ -1023,6 +1026,7 @@ out_put: out_free: kfree(host_root_path); out: + unlock_kernel(); return err; } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index f2feaa0..a7b348a 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -477,11 +477,15 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) int o; + lock_kernel(); + save_mount_options(s, options); sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } s->s_fs_info = sbi; sbi->sb_bmp_dir = NULL; @@ -666,6 +670,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) root->i_blocks = 5; hpfs_brelse4(&qbh); } + unlock_kernel(); return 0; bail4: brelse(bh2); @@ -677,6 +682,7 @@ bail0: kfree(sbi->sb_cp_table); s->s_fs_info = NULL; kfree(sbi); + unlock_kernel(); return -EINVAL; } diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index a5089a6..6263973 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c @@ -712,6 +712,8 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) struct vfsmount *proc_mnt; int err = -ENOENT; + lock_kernel(); + proc_mnt = do_kern_mount("proc", 0, "proc", NULL); if (IS_ERR(proc_mnt)) goto out; @@ -731,6 +733,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) if (!sb->s_root) goto out_iput; + unlock_kernel(); return 0; out_iput: @@ -738,6 +741,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) out_mntput: mntput(proc_mnt); out: + unlock_kernel(); return(err); } diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 87a1258..53be2b9 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -32,6 +32,7 @@ #include <linux/security.h> #include <linux/ima.h> #include <linux/magic.h> +#include <linux/smp_lock.h> /* Only for lock_kernel() */ #include <asm/uaccess.h> @@ -824,6 +825,7 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) struct hugetlbfs_config config; struct hugetlbfs_sb_info *sbinfo; + lock_kernel(); save_mount_options(sb, data); config.nr_blocks = -1; /* No limit on size by default */ @@ -833,12 +835,16 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) config.mode = 0755; config.hstate = &default_hstate; ret = hugetlbfs_parse_options(data, &config); - if (ret) + if (ret) { + unlock_kernel(); return ret; + } sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL); - if (!sbinfo) + if (!sbinfo) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbinfo; sbinfo->hstate = config.hstate; spin_lock_init(&sbinfo->stat_lock); @@ -863,9 +869,11 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) goto out_free; } sb->s_root = root; + unlock_kernel(); return 0; out_free: kfree(sbinfo); + unlock_kernel(); return -ENOMEM; } diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 6b4dcd4..7c501d5 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -571,11 +571,15 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) int table, error = -EINVAL; unsigned int vol_desc_start; + lock_kernel(); + save_mount_options(s, data); sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } s->s_fs_info = sbi; if (!parse_options((char *)data, &opt)) @@ -895,6 +899,7 @@ root_found: kfree(opt.iocharset); + unlock_kernel(); return 0; /* @@ -934,6 +939,7 @@ out_freesbi: kfree(opt.iocharset); kfree(sbi); s->s_fs_info = NULL; + unlock_kernel(); return error; } diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9a80e8e..622bd51 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -148,14 +148,19 @@ static const struct super_operations jffs2_super_operations static int jffs2_fill_super(struct super_block *sb, void *data, int silent) { struct jffs2_sb_info *c; + int ret; + + lock_kernel(); D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():" " New superblock for device %d (\"%s\")\n", sb->s_mtd->index, sb->s_mtd->name)); c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) + if (!c) { + unlock_kernel(); return -ENOMEM; + } c->mtd = sb->s_mtd; c->os_priv = sb; @@ -177,7 +182,9 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_JFFS2_FS_POSIX_ACL sb->s_flags |= MS_POSIXACL; #endif - return jffs2_do_fill_super(sb, data, silent); + ret = jffs2_do_fill_super(sb, data, silent); + unlock_kernel(); + return ret; } static int jffs2_get_sb(struct file_system_type *fs_type, diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 2234c73..329d7b6 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -425,14 +425,20 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) s64 newLVSize = 0; int flag, ret = -EINVAL; + lock_kernel(); + jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags); - if (!new_valid_dev(sb->s_bdev->bd_dev)) + if (!new_valid_dev(sb->s_bdev->bd_dev)) { + unlock_kernel(); return -EOVERFLOW; + } sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; sbi->sb = sb; sbi->uid = sbi->gid = sbi->umask = -1; @@ -442,6 +448,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) if (!parse_options((char *) data, sb, &newLVSize, &flag)) { kfree(sbi); + unlock_kernel(); return -EINVAL; } sbi->flag = flag; @@ -452,6 +459,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) if (newLVSize) { printk(KERN_ERR "resize option for remount only\n"); + unlock_kernel(); return -EINVAL; } @@ -527,6 +535,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes); #endif sb->s_time_gran = 1; + unlock_kernel(); return 0; out_no_root: @@ -548,6 +557,7 @@ out_kfree: if (sbi->nls_tab) unload_nls(sbi->nls_tab); kfree(sbi); + unlock_kernel(); return ret; } diff --git a/fs/libfs.c b/fs/libfs.c index 219576c..3484040 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -11,6 +11,7 @@ #include <linux/exportfs.h> #include <linux/writeback.h> #include <linux/buffer_head.h> +#include <linux/smp_lock.h> /* Only for lock_kernel() */ #include <asm/uaccess.h> @@ -422,6 +423,8 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files struct dentry *dentry; int i; + lock_kernel(); + s->s_blocksize = PAGE_CACHE_SIZE; s->s_blocksize_bits = PAGE_CACHE_SHIFT; s->s_magic = magic; @@ -429,8 +432,10 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files s->s_time_gran = 1; inode = new_inode(s); - if (!inode) + if (!inode) { + unlock_kernel(); return -ENOMEM; + } /* * because the root inode is 1, the files array must not contain an * entry at index 1 @@ -444,6 +449,7 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files root = d_alloc_root(inode); if (!root) { iput(inode); + unlock_kernel(); return -ENOMEM; } for (i = 0; !files->name || files->name[0]; i++, files++) { @@ -469,10 +475,12 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files d_add(dentry, inode); } s->s_root = root; + unlock_kernel(); return 0; out: d_genocide(root); dput(root); + unlock_kernel(); return -ENOMEM; } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 74ea82d..b8aa0a6 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -147,9 +147,13 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) struct minix_sb_info *sbi; int ret = -EINVAL; + lock_kernel(); + sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } s->s_fs_info = sbi; BUILD_BUG_ON(32 != sizeof (struct minix_inode)); @@ -265,6 +269,7 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) else if (sbi->s_mount_state & MINIX_ERROR_FS) printk("MINIX-fs: mounting file system with errors, " "running fsck is recommended\n"); + unlock_kernel(); return 0; out_iput: @@ -314,6 +319,7 @@ out_bad_sb: out: s->s_fs_info = NULL; kfree(sbi); + unlock_kernel(); return ret; } diff --git a/fs/namespace.c b/fs/namespace.c index bdc3cb4..3f95497 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1647,9 +1647,7 @@ static int do_new_mount(struct path *path, char *type, int flags, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); mnt = do_kern_mount(type, flags, name, data); - unlock_kernel(); if (IS_ERR(mnt)) return PTR_ERR(mnt); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index cf98da1..a020d86 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -445,10 +445,14 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) #endif struct ncp_entry_info finfo; + lock_kernel(); + data.wdog_pid = NULL; server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); - if (!server) + if (!server) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = server; error = -EFAULT; @@ -695,6 +699,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) if (!sb->s_root) goto out_no_root; sb->s_root->d_op = &ncp_root_dentry_operations; + unlock_kernel(); return 0; out_no_root: @@ -729,6 +734,7 @@ out: put_pid(data.wdog_pid); sb->s_fs_info = NULL; kfree(server); + unlock_kernel(); return error; } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 90be551..1f97aad 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1877,6 +1877,8 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) options->version <= 6)))) return 0; + lock_kernel(); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -2184,6 +2186,7 @@ out: out_free_fh: kfree(mntfh); kfree(data); + unlock_kernel(); return error; out_err_nosb: @@ -2227,6 +2230,8 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, }; int error; + lock_kernel(); + dprintk("--> nfs_xdev_get_sb()\n"); /* create a new volume representation */ @@ -2281,17 +2286,20 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, security_sb_clone_mnt_opts(data->sb, s); dprintk("<-- nfs_xdev_get_sb() = 0\n"); + unlock_kernel(); return 0; out_err_nosb: nfs_free_server(server); out_err_noserver: dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); + unlock_kernel(); return error; error_splat_super: deactivate_locked_super(s); dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); + unlock_kernel(); return error; } @@ -2475,6 +2483,8 @@ static int nfs4_remote_get_sb(struct file_system_type *fs_type, }; int error = -ENOMEM; + lock_kernel(); + mntfh = kzalloc(sizeof(*mntfh), GFP_KERNEL); if (data == NULL || mntfh == NULL) goto out_free_fh; @@ -2534,6 +2544,7 @@ out: security_free_mnt_opts(&data->lsm_opts); out_free_fh: kfree(mntfh); + unlock_kernel(); return error; out_free: @@ -2794,6 +2805,8 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type, }; int error; + lock_kernel(); + dprintk("--> nfs4_referral_get_sb()\n"); /* create a new volume representation */ @@ -2847,17 +2860,20 @@ static int nfs4_remote_referral_get_sb(struct file_system_type *fs_type, security_sb_clone_mnt_opts(data->sb, s); dprintk("<-- nfs4_referral_get_sb() = 0\n"); + unlock_kernel(); return 0; out_err_nosb: nfs_free_server(server); out_err_noserver: dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); + unlock_kernel(); return error; error_splat_super: deactivate_locked_super(s); dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); + unlock_kernel(); return error; } @@ -2873,6 +2889,8 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, struct vfsmount *root_mnt; int error; + lock_kernel(); + dprintk("--> nfs4_referral_get_sb()\n"); export_path = data->mnt_path; @@ -2890,6 +2908,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, out: dprintk("<-- nfs4_referral_get_sb() = %d%s\n", error, error != 0 ? " [error]" : ""); + unlock_kernel(); return error; } diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 5c01fc1..dcaef52 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1347,7 +1347,12 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) #endif /* last one */ {""} }; - return simple_fill_super(sb, 0x6e667364, nfsd_files); + int ret; + + lock_kernel(); + ret = simple_fill_super(sb, 0x6e667364, nfsd_files); + unlock_kernel(); + return ret; } static int nfsd_get_sb(struct file_system_type *fs_type, diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 644e667..3448ec3 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -1059,9 +1059,13 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, struct the_nilfs *nilfs; int err, need_to_close = 1; + lock_kernel(); + sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); - if (IS_ERR(sd.bdev)) + if (IS_ERR(sd.bdev)) { + unlock_kernel(); return PTR_ERR(sd.bdev); + } /* * To get mount instance using sget() vfs-routine, NILFS needs @@ -1142,6 +1146,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, if (need_to_close) close_bdev_exclusive(sd.bdev, flags); simple_set_mnt(mnt, s); + unlock_kernel(); return 0; failed_unlock: @@ -1150,6 +1155,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, failed: close_bdev_exclusive(sd.bdev, flags); + unlock_kernel(); return err; cancel_new: @@ -1163,6 +1169,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, * We must finish all post-cleaning before this call; * put_nilfs() needs the block device. */ + unlock_kernel(); return err; } diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 80b0477..ab09c02 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -2723,6 +2723,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) struct inode *tmp_ino; int blocksize, result; + lock_kernel(); + /* * We do a pretty difficult piece of bootstrap by reading the * MFT (and other metadata) from disk into memory. We'll only @@ -2746,6 +2748,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) ntfs_error(sb, "Allocation of NTFS volume structure " "failed. Aborting mount..."); lockdep_on(); + unlock_kernel(); return -ENOMEM; } /* Initialize ntfs_volume structure. */ @@ -2933,6 +2936,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) sb->s_export_op = &ntfs_export_ops; lock_kernel(); lockdep_on(); + unlock_kernel(); return 0; } ntfs_error(sb, "Failed to allocate root directory."); @@ -3053,6 +3057,7 @@ err_out_now: kfree(vol); ntfs_debug("Failed, returning -EINVAL."); lockdep_on(); + unlock_kernel(); return -EINVAL; } diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 02bf178..58ce813 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -528,21 +528,27 @@ static int dlmfs_fill_super(struct super_block * sb, struct inode * inode; struct dentry * root; + lock_kernel(); + sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = DLMFS_MAGIC; sb->s_op = &dlmfs_ops; inode = dlmfs_get_root_inode(sb); - if (!inode) + if (!inode) { + unlock_kernel(); return -ENOMEM; + } root = d_alloc_root(inode); if (!root) { iput(inode); + unlock_kernel(); return -ENOMEM; } sb->s_root = root; + unlock_kernel(); return 0; } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index c0e48ae..fab815f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -986,6 +986,8 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) char nodestr[8]; struct ocfs2_blockcheck_stats stats; + lock_kernel(); + mlog_entry("%p, %p, %i", sb, data, silent); if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { @@ -1172,6 +1174,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) atomic_set(&osb->vol_state, VOLUME_DISABLED); wake_up(&osb->osb_mount_event); mlog_exit(status); + unlock_kernel(); return status; } } @@ -1186,6 +1189,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) ocfs2_orphan_scan_start(osb); mlog_exit(status); + unlock_kernel(); return status; read_super_error: @@ -1201,6 +1205,7 @@ read_super_error: } mlog_exit(status); + unlock_kernel(); return status; } diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index f3b7c15..ddfbb22 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c @@ -416,11 +416,15 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) sector_t start; int ret = -EINVAL; + lock_kernel(); + save_mount_options(sb, (char *) data); sbi = kzalloc(sizeof(struct omfs_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; @@ -525,6 +529,7 @@ out_brelse_bh2: out_brelse_bh: brelse(bh); end: + unlock_kernel(); return ret; } diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index ffcd04f..50dc4be 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -386,6 +386,8 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent) struct op_inode_info *oi; int ret; + lock_kernel(); + s->s_flags |= MS_NOATIME; s->s_blocksize = 1024; s->s_blocksize_bits = 10; @@ -405,6 +407,7 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent) s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto out_no_root_dentry; + unlock_kernel(); return 0; out_no_root_dentry: @@ -412,6 +415,7 @@ out_no_root_dentry: ret = -ENOMEM; out_no_root: printk("openprom_fill_super: get root inode failed\n"); + unlock_kernel(); return ret; } diff --git a/fs/proc/root.c b/fs/proc/root.c index b080b79..6384680 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -18,6 +18,7 @@ #include <linux/bitops.h> #include <linux/mount.h> #include <linux/pid_namespace.h> +#include <linux/smp_lock.h> /* For lock_kernel() only */ #include "internal.h" @@ -43,6 +44,8 @@ static int proc_get_sb(struct file_system_type *fs_type, struct pid_namespace *ns; struct proc_inode *ei; + lock_kernel(); + if (proc_mnt) { /* Seed the root directory with a pid so it doesn't need * to be special in base.c. I would do this earlier but @@ -60,14 +63,17 @@ static int proc_get_sb(struct file_system_type *fs_type, ns = current->nsproxy->pid_ns; sb = sget(fs_type, proc_test_super, proc_set_super, ns); - if (IS_ERR(sb)) + if (IS_ERR(sb)) { + unlock_kernel(); return PTR_ERR(sb); + } if (!sb->s_root) { sb->s_flags = flags; err = proc_fill_super(sb); if (err) { deactivate_locked_super(sb); + unlock_kernel(); return err; } @@ -83,6 +89,7 @@ static int proc_get_sb(struct file_system_type *fs_type, } simple_set_mnt(mnt, sb); + unlock_kernel(); return 0; } diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index d2cd179..18640ce 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -253,9 +253,13 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent) struct qnx4_sb_info *qs; int ret = -EINVAL; + lock_kernel(); + qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL); - if (!qs) + if (!qs) { + unlock_kernel(); return -ENOMEM; + } s->s_fs_info = qs; sb_set_blocksize(s, QNX4_BLOCK_SIZE); @@ -303,6 +307,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent) brelse(bh); + unlock_kernel(); return 0; outi: @@ -312,6 +317,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent) outnobh: kfree(qs); s->s_fs_info = NULL; + unlock_kernel(); return ret; } diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index a6090aa..9b3983f 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -35,6 +35,7 @@ #include <linux/sched.h> #include <linux/parser.h> #include <linux/magic.h> +#include <linux/smp_lock.h> /* Only for lock_kernel() */ #include <asm/uaccess.h> #include "internal.h" @@ -220,6 +221,8 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) struct dentry *root; int err; + lock_kernel(); + save_mount_options(sb, data); fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); @@ -253,11 +256,13 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) goto fail; } + unlock_kernel(); return 0; fail: kfree(fsi); sb->s_fs_info = NULL; iput(inode); + unlock_kernel(); return err; } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f0ad05f..f32bf62 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1608,6 +1608,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) char *qf_names[MAXQUOTAS] = {}; unsigned int qfmt = 0; + lock_kernel(); + save_mount_options(s, data); sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); @@ -1852,6 +1854,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) init_waitqueue_head(&(sbi->s_wait)); spin_lock_init(&sbi->bitmap_lock); + unlock_kernel(); return (0); error: @@ -1872,6 +1875,7 @@ error: kfree(sbi); s->s_fs_info = NULL; + unlock_kernel(); return errval; } diff --git a/fs/romfs/super.c b/fs/romfs/super.c index c117fa8..7342617 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c @@ -468,6 +468,8 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) size_t len; int ret; + lock_kernel(); + #ifdef CONFIG_BLOCK if (!sb->s_mtd) { sb_set_blocksize(sb, ROMBSIZE); @@ -484,8 +486,10 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) /* read the image superblock and check it */ rsb = kmalloc(512, GFP_KERNEL); - if (!rsb) + if (!rsb) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = (void *) 512; ret = romfs_dev_read(sb, 0, rsb, 512); @@ -535,15 +539,18 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) if (!sb->s_root) goto error_i; + unlock_kernel(); return 0; error_i: iput(root); error: + unlock_kernel(); return -EINVAL; error_rsb_inval: ret = -EINVAL; error_rsb: + unlock_kernel(); return ret; } diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 1c4c8f0..c3c9044 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -500,6 +500,8 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) void *mem; static int warn_count; + lock_kernel(); + if (warn_count < 5) { warn_count++; printk(KERN_EMERG "smbfs is deprecated and will be removed" @@ -615,6 +617,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) smb_new_dentry(sb->s_root); + unlock_kernel(); return 0; out_no_root: @@ -635,9 +638,11 @@ out_wrong_data: out_no_data: printk(KERN_ERR "smb_fill_super: missing data argument\n"); out_fail: + unlock_kernel(); return -EINVAL; out_no_server: printk(KERN_ERR "smb_fill_super: cannot allocate struct smb_sb_info\n"); + unlock_kernel(); return -ENOMEM; } diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 6c197ef..23cea83 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -78,11 +78,14 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) u64 lookup_table_start; int err; + lock_kernel(); + TRACE("Entered squashfs_fill_superblock\n"); sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL); if (sb->s_fs_info == NULL) { ERROR("Failed to allocate squashfs_sb_info\n"); + unlock_kernel(); return -ENOMEM; } msblk = sb->s_fs_info; @@ -286,6 +289,7 @@ allocate_root: TRACE("Leaving squashfs_fill_super\n"); kfree(sblk); + unlock_kernel(); return 0; failed_mount: @@ -299,12 +303,14 @@ failed_mount: kfree(sb->s_fs_info); sb->s_fs_info = NULL; kfree(sblk); + unlock_kernel(); return err; failure: kfree(msblk->stream.workspace); kfree(sb->s_fs_info); sb->s_fs_info = NULL; + unlock_kernel(); return -ENOMEM; } diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 4974995..2e5a870 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/magic.h> +#include <linux/smp_lock.h> /* Only for lock_kernel() */ #include "sysfs.h" @@ -45,6 +46,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) struct inode *inode; struct dentry *root; + lock_kernel(); + sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = SYSFS_MAGIC; @@ -58,6 +61,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) mutex_unlock(&sysfs_mutex); if (!inode) { pr_debug("sysfs: could not get root inode\n"); + unlock_kernel(); return -ENOMEM; } @@ -66,10 +70,12 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); iput(inode); + unlock_kernel(); return -ENOMEM; } root->d_fsdata = &sysfs_root; sb->s_root = root; + unlock_kernel(); return 0; } diff --git a/fs/sysv/super.c b/fs/sysv/super.c index 5a903da..145d949 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c @@ -357,7 +357,9 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) struct sysv_sb_info *sbi; unsigned long blocknr; int size = 0, i; - + + lock_kernel(); + BUILD_BUG_ON(1024 != sizeof (struct xenix_super_block)); BUILD_BUG_ON(512 != sizeof (struct sysv4_super_block)); BUILD_BUG_ON(512 != sizeof (struct sysv2_super_block)); @@ -365,8 +367,10 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) BUILD_BUG_ON(64 != sizeof (struct sysv_inode)); sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sbi->s_sb = sb; sbi->s_block_base = 0; @@ -409,8 +413,10 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) if (bh && bh1) { sbi->s_bh1 = bh1; sbi->s_bh2 = bh; - if (complete_read_super(sb, silent, size)) + if (complete_read_super(sb, silent, size)) { + unlock_kernel(); return 0; + } } brelse(bh1); @@ -419,6 +425,7 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent) printk("oldfs: cannot read superblock\n"); failed: kfree(sbi); + unlock_kernel(); return -EINVAL; Eunknown: @@ -442,14 +449,18 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) struct v7_super_block *v7sb; struct sysv_inode *v7i; + lock_kernel(); + if (440 != sizeof (struct v7_super_block)) panic("V7 FS: bad super-block size"); if (64 != sizeof (struct sysv_inode)) panic("sysv fs: bad i-node size"); sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sbi->s_sb = sb; sbi->s_block_base = 0; @@ -487,13 +498,16 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) sbi->s_bh1 = bh; sbi->s_bh2 = bh; - if (complete_read_super(sb, silent, 1)) + if (complete_read_super(sb, silent, 1)) { + unlock_kernel(); return 0; + } failed: brelse(bh2); brelse(bh); kfree(sbi); + unlock_kernel(); return -EINVAL; } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 333e181..04a0fc9 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2029,6 +2029,8 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, struct super_block *sb; int err; + lock_kernel(); + dbg_gen("name %s, flags %#x", name, flags); /* @@ -2040,6 +2042,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, if (IS_ERR(ubi)) { ubifs_err("cannot open \"%s\", error %d", name, (int)PTR_ERR(ubi)); + unlock_kernel(); return PTR_ERR(ubi); } ubi_get_volume_info(ubi, &vi); @@ -2077,12 +2080,14 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, ubi_close_volume(ubi); simple_set_mnt(mnt, sb); + unlock_kernel(); return 0; out_deact: deactivate_locked_super(sb); out_close: ubi_close_volume(ubi); + unlock_kernel(); return err; } diff --git a/fs/udf/super.c b/fs/udf/super.c index 9d1b8c2..fa6f8db 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1866,6 +1866,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) struct kernel_lb_addr rootdir, fileset; struct udf_sb_info *sbi; + lock_kernel(); + uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); uopt.uid = -1; uopt.gid = -1; @@ -1874,8 +1876,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) uopt.dmode = UDF_INVALID_MODE; sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); - if (!sbi) + if (!sbi) { + unlock_kernel(); return -ENOMEM; + } sb->s_fs_info = sbi; @@ -2021,6 +2025,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) goto error_out; } sb->s_maxbytes = MAX_LFS_FILESIZE; + unlock_kernel(); return 0; error_out: @@ -2041,6 +2046,7 @@ error_out: kfree(sbi); sb->s_fs_info = NULL; + unlock_kernel(); return -EINVAL; } diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 5faed79..31ad198 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -646,6 +646,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) unsigned maxsymlen; int ret = -EINVAL; + lock_kernel(); + uspi = NULL; ubh = NULL; flags = 0; @@ -1107,6 +1109,7 @@ magic_found: goto failed; UFSD("EXIT\n"); + unlock_kernel(); return 0; dalloc_failed: @@ -1118,10 +1121,12 @@ failed: kfree(sbi); sb->s_fs_info = NULL; UFSD("EXIT (FAILED)\n"); + unlock_kernel(); return ret; failed_nomem: UFSD("EXIT (NOMEM)\n"); + unlock_kernel(); return -ENOMEM; } diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 18a4b8e..7426166 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1412,6 +1412,8 @@ xfs_fs_fill_super( int flags = 0, error = ENOMEM; char *mtpt = NULL; + lock_kernel(); + mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL); if (!mp) goto out; @@ -1506,6 +1508,7 @@ xfs_fs_fill_super( kfree(mtpt); xfs_itrace_exit(XFS_I(sb->s_root->d_inode)); + unlock_kernel(); return 0; out_filestream_unmount: @@ -1522,6 +1525,7 @@ xfs_fs_fill_super( kfree(mtpt); kfree(mp); out: + unlock_kernel(); return -error; fail_vnrele: -- 1.6.4.2