push BKL down into ->put_super
Move BKL into ->put_super from the only caller. A couple of
filesystems had trivial enough ->put_super (only kfree and NULLing of
s_fs_info + stuff in there) to not get any locking: coda, cramfs, efs,
hugetlbfs, omfs, qnx4, shmem, all others got the full treatment. Most
of them probably don't need it, but I'd rather sort that out individually.
Preferably after all the other BKL pushdowns in that area.
[AV: original used to move lock_super() down as well; these changes are
removed since we don't do lock_super() at all in generic_shutdown_super()
now]
[AV: fuse, btrfs and xfs are known to need no damn BKL, exempt]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index dd9becc..0ec5aaf 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -132,11 +132,15 @@
int i;
struct adfs_sb_info *asb = ADFS_SB(sb);
+ lock_kernel();
+
for (i = 0; i < asb->s_map_size; i++)
brelse(asb->s_map[i].dm_bh);
kfree(asb->s_map);
kfree(asb);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 63f5183..d738646 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -29,6 +29,8 @@
struct affs_sb_info *sbi = AFFS_SB(sb);
pr_debug("AFFS: put_super()\n");
+ lock_kernel();
+
if (!(sb->s_flags & MS_RDONLY)) {
AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(1);
secs_to_datestamp(get_seconds(),
@@ -42,7 +44,8 @@
affs_brelse(sbi->s_root_bh);
kfree(sbi);
sb->s_fs_info = NULL;
- return;
+
+ unlock_kernel();
}
static void
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 76828e5..ad0514d 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -440,8 +440,12 @@
_enter("");
+ lock_kernel();
+
afs_put_volume(as->volume);
+ unlock_kernel();
+
_leave("");
}
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 76afd0d..9367b62 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -737,6 +737,8 @@
static void
befs_put_super(struct super_block *sb)
{
+ lock_kernel();
+
kfree(BEFS_SB(sb)->mount_opts.iocharset);
BEFS_SB(sb)->mount_opts.iocharset = NULL;
@@ -747,7 +749,8 @@
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
- return;
+
+ unlock_kernel();
}
/* Allocate private field of the superblock, fill it.
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 4cf3d26..3a9a136 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -217,6 +217,8 @@
if (!info)
return;
+ lock_kernel();
+
if (s->s_dirt)
bfs_write_super(s);
@@ -225,6 +227,8 @@
kfree(info->si_imap);
kfree(info);
s->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 0a10a59..0d92114 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -204,6 +204,9 @@
cFYI(1, ("Empty cifs superblock info passed to unmount"));
return;
}
+
+ lock_kernel();
+
rc = cifs_umount(sb, cifs_sb);
if (rc)
cERROR(1, ("cifs_umount failed with return code %d", rc));
@@ -216,7 +219,8 @@
unload_nls(cifs_sb->local_nls);
kfree(cifs_sb);
- return;
+
+ unlock_kernel();
}
static int
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index fa4c7e7..12d6496 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -27,6 +27,7 @@
#include <linux/mount.h>
#include <linux/key.h>
#include <linux/seq_file.h>
+#include <linux/smp_lock.h>
#include <linux/file.h>
#include <linux/crypto.h>
#include "ecryptfs_kernel.h"
@@ -120,9 +121,13 @@
{
struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb);
+ lock_kernel();
+
ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat);
kmem_cache_free(ecryptfs_sb_info_cache, sb_info);
ecryptfs_set_superblock_private(sb, NULL);
+
+ unlock_kernel();
}
/**
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 3cdb761..cd1f8b1 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -258,6 +258,8 @@
int num_pend;
struct exofs_sb_info *sbi = sb->s_fs_info;
+ lock_kernel();
+
if (sb->s_dirt)
exofs_write_super(sb);
@@ -274,6 +276,8 @@
osduld_put_device(sbi->s_dev);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
/*
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 932a2bc..a44963d 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -114,6 +114,8 @@
int i;
struct ext2_sb_info *sbi = EXT2_SB(sb);
+ lock_kernel();
+
if (sb->s_dirt)
ext2_write_super(sb);
@@ -138,7 +140,7 @@
kfree(sbi->s_blockgroup_lock);
kfree(sbi);
- return;
+ unlock_kernel();
}
static struct kmem_cache * ext2_inode_cachep;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 1efd958..546b8d7 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -398,6 +398,8 @@
struct ext3_super_block *es = sbi->s_es;
int i, err;
+ lock_kernel();
+
ext3_xattr_put_super(sb);
err = journal_destroy(sbi->s_journal);
sbi->s_journal = NULL;
@@ -446,7 +448,8 @@
sb->s_fs_info = NULL;
kfree(sbi->s_blockgroup_lock);
kfree(sbi);
- return;
+
+ unlock_kernel();
}
static struct kmem_cache *ext3_inode_cachep;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 0d3034c..1d4180b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -577,6 +577,7 @@
int i, err;
lock_super(sb);
+ lock_kernel();
if (sb->s_dirt)
ext4_write_super(sb);
@@ -646,7 +647,6 @@
unlock_super(sb);
kobject_put(&sbi->s_kobj);
wait_for_completion(&sbi->s_kobj_unregister);
- lock_kernel();
kfree(sbi->s_blockgroup_lock);
kfree(sbi);
}
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 4978621..2b88c93a 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -451,6 +451,8 @@
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ lock_kernel();
+
if (sb->s_dirt)
fat_write_super(sb);
@@ -470,6 +472,8 @@
sb->s_fs_info = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
static struct kmem_cache *fat_inode_cachep;
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 1dacda8..cdbd165 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -80,12 +80,16 @@
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
+ lock_kernel();
+
vxfs_put_fake_inode(infp->vsi_fship);
vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist);
brelse(infp->vsi_bp);
kfree(infp);
+
+ unlock_kernel();
}
/**
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 0a68013..c8930b3 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -719,6 +719,8 @@
int error;
struct gfs2_jdesc *jd;
+ lock_kernel();
+
/* Unfreeze the filesystem, if we need to */
mutex_lock(&sdp->sd_freeze_lock);
@@ -785,6 +787,8 @@
/* At this point, we're through participating in the lockspace */
gfs2_sys_fs_del(sdp);
+
+ unlock_kernel();
}
/**
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index e071e6d..9f5eaa0 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -65,11 +65,15 @@
*/
static void hfs_put_super(struct super_block *sb)
{
+ lock_kernel();
+
if (sb->s_dirt)
hfs_write_super(sb);
hfs_mdb_close(sb);
/* release the MDB's resources */
hfs_mdb_put(sb);
+
+ unlock_kernel();
}
/*
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 40bdab7..9b292dc 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -199,6 +199,9 @@
dprint(DBG_SUPER, "hfsplus_put_super\n");
if (!sb->s_fs_info)
return;
+
+ lock_kernel();
+
if (sb->s_dirt)
hfsplus_write_super(sb);
if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) {
@@ -220,6 +223,8 @@
unload_nls(HFSPLUS_SB(sb).nls);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index fc77965..437a32e 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -99,11 +99,16 @@
static void hpfs_put_super(struct super_block *s)
{
struct hpfs_sb_info *sbi = hpfs_sb(s);
+
+ lock_kernel();
+
kfree(sbi->sb_cp_table);
kfree(sbi->sb_bmp_dir);
unmark_dirty(s);
s->s_fs_info = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index b4cbe96..068b34b 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -42,11 +42,16 @@
static void isofs_put_super(struct super_block *sb)
{
struct isofs_sb_info *sbi = ISOFS_SB(sb);
+
#ifdef CONFIG_JOLIET
+ lock_kernel();
+
if (sbi->s_nls_iocharset) {
unload_nls(sbi->s_nls_iocharset);
sbi->s_nls_iocharset = NULL;
}
+
+ unlock_kernel();
#endif
kfree(sbi);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 5059e96..37b1212 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -174,6 +174,8 @@
D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
+ lock_kernel();
+
if (sb->s_dirt)
jffs2_write_super(sb);
@@ -195,6 +197,8 @@
if (c->mtd->sync)
c->mtd->sync(c->mtd);
+ unlock_kernel();
+
D1(printk(KERN_DEBUG "jffs2_put_super returning\n"));
}
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index d9b0e92..3eb13ad 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -183,6 +183,9 @@
int rc;
jfs_info("In jfs_put_super");
+
+ lock_kernel();
+
rc = jfs_umount(sb);
if (rc)
jfs_err("jfs_umount failed with return code %d", rc);
@@ -195,6 +198,8 @@
sbi->direct_inode = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
enum {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index daad3c2..7eb5397 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -35,6 +35,8 @@
int i;
struct minix_sb_info *sbi = minix_sb(sb);
+ lock_kernel();
+
if (!(sb->s_flags & MS_RDONLY)) {
if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
sbi->s_ms->s_state = sbi->s_mount_state;
@@ -49,7 +51,7 @@
sb->s_fs_info = NULL;
kfree(sbi);
- return;
+ unlock_kernel();
}
static struct kmem_cache * minix_inode_cachep;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index d642f0e..b99ce20 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -736,6 +736,8 @@
{
struct ncp_server *server = NCP_SBP(sb);
+ lock_kernel();
+
ncp_lock_server(server);
ncp_disconnect(server);
ncp_unlock_server(server);
@@ -769,6 +771,8 @@
vfree(server->packet);
sb->s_fs_info = NULL;
kfree(server);
+
+ unlock_kernel();
}
static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 7901d8c..7262e84 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -316,6 +316,8 @@
struct nilfs_sb_info *sbi = NILFS_SB(sb);
struct the_nilfs *nilfs = sbi->s_nilfs;
+ lock_kernel();
+
if (sb->s_dirt)
nilfs_write_super(sb);
@@ -333,6 +335,8 @@
sbi->s_super = NULL;
sb->s_fs_info = NULL;
kfree(sbi);
+
+ unlock_kernel();
}
/**
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 6aa7c47..a9ec4e1 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2246,6 +2246,9 @@
ntfs_volume *vol = NTFS_SB(sb);
ntfs_debug("Entering.");
+
+ lock_kernel();
+
#ifdef NTFS_RW
/*
* Commit all inodes while they are still open in case some of them
@@ -2444,7 +2447,8 @@
}
sb->s_fs_info = NULL;
kfree(vol);
- return;
+
+ unlock_kernel();
}
/**
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 3eb076c..0273759 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1536,9 +1536,13 @@
{
mlog_entry("(0x%p)\n", sb);
+ lock_kernel();
+
ocfs2_sync_blockdev(sb);
ocfs2_dismount_volume(sb, 0);
+ unlock_kernel();
+
mlog_exit_void();
}
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 3da0401c..90dcb7b 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -465,6 +465,8 @@
struct reiserfs_transaction_handle th;
th.t_trans_id = 0;
+ lock_kernel();
+
if (s->s_dirt)
reiserfs_write_super(s);
@@ -500,7 +502,7 @@
kfree(s->s_fs_info);
s->s_fs_info = NULL;
- return;
+ unlock_kernel();
}
static struct kmem_cache *reiserfs_inode_cachep;
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index fc27fbfc..1402d2d 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -474,6 +474,8 @@
{
struct smb_sb_info *server = SMB_SB(sb);
+ lock_kernel();
+
smb_lock_server(server);
server->state = CONN_INVALID;
smbiod_unregister_server(server);
@@ -489,6 +491,8 @@
smb_unlock_server(server);
put_pid(server->conn_pid);
kfree(server);
+
+ unlock_kernel();
}
static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 0adc624..3b52770 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -338,6 +338,8 @@
static void squashfs_put_super(struct super_block *sb)
{
+ lock_kernel();
+
if (sb->s_fs_info) {
struct squashfs_sb_info *sbi = sb->s_fs_info;
squashfs_cache_delete(sbi->block_cache);
@@ -350,6 +352,8 @@
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
}
+
+ unlock_kernel();
}
diff --git a/fs/super.c b/fs/super.c
index 54fd331..bdd7158 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -309,7 +309,6 @@
/* bad name - it should be evict_inodes() */
invalidate_inodes(sb);
- lock_kernel();
if (sop->put_super)
sop->put_super(sb);
@@ -320,8 +319,6 @@
"Self-destruct in 5 seconds. Have a nice day...\n",
sb->s_id);
}
-
- unlock_kernel();
put_fs_excl();
}
spin_lock(&sb_lock);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index cd80316..a818986 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -72,6 +72,8 @@
{
struct sysv_sb_info *sbi = SYSV_SB(sb);
+ lock_kernel();
+
if (sb->s_dirt)
sysv_write_super(sb);
@@ -87,6 +89,8 @@
brelse(sbi->s_bh2);
kfree(sbi);
+
+ unlock_kernel();
}
static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 84f3c7f..522c3fd 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1684,6 +1684,9 @@
ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num,
c->vi.vol_id);
+
+ lock_kernel();
+
/*
* The following asserts are only valid if there has not been a failure
* of the media. For example, there will be dirty inodes if we failed
@@ -1750,6 +1753,8 @@
ubi_close_volume(c->ubi);
mutex_unlock(&c->umount_mutex);
kfree(c);
+
+ unlock_kernel();
}
static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 0ba4410..04802cc 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -2062,6 +2062,9 @@
struct udf_sb_info *sbi;
sbi = UDF_SB(sb);
+
+ lock_kernel();
+
if (sbi->s_vat_inode)
iput(sbi->s_vat_inode);
if (sbi->s_partitions)
@@ -2077,6 +2080,8 @@
kfree(sbi->s_partmaps);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
+
+ unlock_kernel();
}
static int udf_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 74afb9f..2b4d2b6 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -594,6 +594,9 @@
UFSD("ENTER\n");
+
+ lock_kernel();
+
ufs_put_cstotal(sb);
size = uspi->s_cssize;
blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
@@ -621,6 +624,9 @@
brelse (sbi->s_ucg[i]);
kfree (sbi->s_ucg);
kfree (base);
+
+ unlock_kernel();
+
UFSD("EXIT\n");
}