Commit 0aa838c6 authored by Paul Menage's avatar Paul Menage Committed by Linus Torvalds

[PATCH] Shift BKL into ->statfs()

This patch removes BKL protection from the invocation of the
super_operations ->statfs() method, and shifts it into the filesystems
where necessary. Any out-of-tree filesystems may need to take the BKL in
their statfs() methods if they were relying on it for synchronisation.

All ->statfs() implementations have been modified to take the BKL,
except for those that don't reference any external mutable data or that
already have their own locking.

Additionally, capifs is changed to use simple_statfs rather than its
own home-grown version.

The BKL change has been flagged at the end of
Documentation/filesystems/porting, along with the recent change to
->permission BKL usage.
parent 2ffe5f2f
...@@ -108,7 +108,7 @@ delete_inode: no ...@@ -108,7 +108,7 @@ delete_inode: no
clear_inode: no clear_inode: no
put_super: yes yes maybe (see below) put_super: yes yes maybe (see below)
write_super: no yes maybe (see below) write_super: no yes maybe (see below)
statfs: yes no no statfs: no no no
remount_fs: yes yes maybe (see below) remount_fs: yes yes maybe (see below)
umount_begin: yes no maybe (see below) umount_begin: yes no maybe (see below)
......
...@@ -81,7 +81,7 @@ can relax your locking. ...@@ -81,7 +81,7 @@ can relax your locking.
[mandatory] [mandatory]
->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(), ->lookup(), ->truncate(), ->create(), ->unlink(), ->mknod(), ->mkdir(),
->rmdir(), ->link(), ->lseek(), ->symlink(), ->rename(), ->permission() ->rmdir(), ->link(), ->lseek(), ->symlink(), ->rename()
and ->readdir() are called without BKL now. Grab it on entry, drop upon return and ->readdir() are called without BKL now. Grab it on entry, drop upon return
- that will guarantee the same locking you used to have. If your method or its - that will guarantee the same locking you used to have. If your method or its
parts do not need BKL - better yet, now you can shift lock_kernel() and parts do not need BKL - better yet, now you can shift lock_kernel() and
...@@ -228,3 +228,19 @@ anything from oops to silent memory corruption. ...@@ -228,3 +228,19 @@ anything from oops to silent memory corruption.
Use bdev_read_only(bdev) instead of is_read_only(kdev). The latter Use bdev_read_only(bdev) instead of is_read_only(kdev). The latter
is still alive, but only because of the mess in drivers/s390/block/dasd.c. is still alive, but only because of the mess in drivers/s390/block/dasd.c.
As soon as it gets fixed is_read_only() will die. As soon as it gets fixed is_read_only() will die.
---
[mandatory]
->permission() is called without BKL now. Grab it on entry, drop upon
return - that will guarantee the same locking you used to have. If
your method or its parts do not need BKL - better yet, now you can
shift lock_kernel() and unlock_kernel() so that they would protect
exactly what needs to be protected.
---
[mandatory]
->statfs() is now called without BKL held. BKL should have been
shifted into individual fs sb_op functions where it's not clear that
it's safe to remove it. If you don't need it, remove it.
...@@ -221,11 +221,9 @@ static void capifs_put_super(struct super_block *sb) ...@@ -221,11 +221,9 @@ static void capifs_put_super(struct super_block *sb)
kfree(sbi); kfree(sbi);
} }
static int capifs_statfs(struct super_block *sb, struct statfs *buf);
static struct super_operations capifs_sops = { static struct super_operations capifs_sops = {
put_super: capifs_put_super, put_super: capifs_put_super,
statfs: capifs_statfs, statfs: simple_statfs,
}; };
static int capifs_parse_options(char *options, struct capifs_sb_info *sbi) static int capifs_parse_options(char *options, struct capifs_sb_info *sbi)
...@@ -354,19 +352,6 @@ static int capifs_fill_super(struct super_block *s, void *data, int silent) ...@@ -354,19 +352,6 @@ static int capifs_fill_super(struct super_block *s, void *data, int silent)
return -EINVAL; return -EINVAL;
} }
static int capifs_statfs(struct super_block *sb, struct statfs *buf)
{
buf->f_type = CAPIFS_SUPER_MAGIC;
buf->f_bsize = 1024;
buf->f_blocks = 0;
buf->f_bfree = 0;
buf->f_bavail = 0;
buf->f_files = 0;
buf->f_ffree = 0;
buf->f_namelen = NAME_MAX;
return 0;
}
static struct inode *capifs_new_inode(struct super_block *sb) static struct inode *capifs_new_inode(struct super_block *sb)
{ {
struct inode *inode = new_inode(sb); struct inode *inode = new_inode(sb);
......
...@@ -282,8 +282,12 @@ static int coda_statfs(struct super_block *sb, struct statfs *buf) ...@@ -282,8 +282,12 @@ static int coda_statfs(struct super_block *sb, struct statfs *buf)
{ {
int error; int error;
lock_kernel();
error = venus_statfs(sb, buf); error = venus_statfs(sb, buf);
unlock_kernel();
if (error) { if (error) {
/* fake something like AFS does */ /* fake something like AFS does */
buf->f_blocks = 9000000; buf->f_blocks = 9000000;
......
...@@ -504,7 +504,7 @@ static struct super_operations ext3_sops = { ...@@ -504,7 +504,7 @@ static struct super_operations ext3_sops = {
write_super: ext3_write_super, /* BKL not held. We take it. Needed? */ write_super: ext3_write_super, /* BKL not held. We take it. Needed? */
write_super_lockfs: ext3_write_super_lockfs, /* BKL not held. Take it */ write_super_lockfs: ext3_write_super_lockfs, /* BKL not held. Take it */
unlockfs: ext3_unlockfs, /* BKL not held. We take it */ unlockfs: ext3_unlockfs, /* BKL not held. We take it */
statfs: ext3_statfs, /* BKL held */ statfs: ext3_statfs, /* BKL not held. */
remount_fs: ext3_remount, /* BKL held */ remount_fs: ext3_remount, /* BKL held */
}; };
......
...@@ -98,7 +98,7 @@ vxfs_put_super(struct super_block *sbp) ...@@ -98,7 +98,7 @@ vxfs_put_super(struct super_block *sbp)
* Zero. * Zero.
* *
* Locking: * Locking:
* We are under bkl and @sbp->s_lock. * No locks held.
* *
* Notes: * Notes:
* This is everything but complete... * This is everything but complete...
......
...@@ -134,6 +134,8 @@ static unsigned count_bitmaps(struct super_block *s) ...@@ -134,6 +134,8 @@ static unsigned count_bitmaps(struct super_block *s)
int hpfs_statfs(struct super_block *s, struct statfs *buf) int hpfs_statfs(struct super_block *s, struct statfs *buf)
{ {
lock_kernel();
/*if (s->s_hpfs_n_free == -1) {*/ /*if (s->s_hpfs_n_free == -1) {*/
s->s_hpfs_n_free = count_bitmaps(s); s->s_hpfs_n_free = count_bitmaps(s);
s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap); s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap);
...@@ -146,6 +148,9 @@ int hpfs_statfs(struct super_block *s, struct statfs *buf) ...@@ -146,6 +148,9 @@ int hpfs_statfs(struct super_block *s, struct statfs *buf)
buf->f_files = s->s_hpfs_dirband_size / 4; buf->f_files = s->s_hpfs_dirband_size / 4;
buf->f_ffree = s->s_hpfs_n_free_dnodes; buf->f_ffree = s->s_hpfs_n_free_dnodes;
buf->f_namelen = 254; buf->f_namelen = 254;
unlock_kernel();
return 0; return 0;
} }
......
...@@ -383,7 +383,11 @@ int ...@@ -383,7 +383,11 @@ int
jffs_statfs(struct super_block *sb, struct statfs *buf) jffs_statfs(struct super_block *sb, struct statfs *buf)
{ {
struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp; struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp;
struct jffs_fmcontrol *fmc = c->fmc; struct jffs_fmcontrol *fmc;
lock_kernel();
fmc = c->fmc;
D2(printk("jffs_statfs()\n")); D2(printk("jffs_statfs()\n"));
...@@ -401,6 +405,9 @@ jffs_statfs(struct super_block *sb, struct statfs *buf) ...@@ -401,6 +405,9 @@ jffs_statfs(struct super_block *sb, struct statfs *buf)
buf->f_ffree = buf->f_bfree; buf->f_ffree = buf->f_bfree;
/* buf->f_fsid = 0; */ /* buf->f_fsid = 0; */
buf->f_namelen = JFFS_MAX_NAME_LEN; buf->f_namelen = JFFS_MAX_NAME_LEN;
unlock_kernel();
return 0; return 0;
} }
......
...@@ -474,6 +474,8 @@ nfs_statfs(struct super_block *sb, struct statfs *buf) ...@@ -474,6 +474,8 @@ nfs_statfs(struct super_block *sb, struct statfs *buf)
struct nfs_fsinfo res; struct nfs_fsinfo res;
int error; int error;
lock_kernel();
error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res); error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res);
buf->f_type = NFS_SUPER_MAGIC; buf->f_type = NFS_SUPER_MAGIC;
if (error < 0) if (error < 0)
...@@ -491,11 +493,17 @@ nfs_statfs(struct super_block *sb, struct statfs *buf) ...@@ -491,11 +493,17 @@ nfs_statfs(struct super_block *sb, struct statfs *buf)
if (res.namelen == 0 || res.namelen > server->namelen) if (res.namelen == 0 || res.namelen > server->namelen)
res.namelen = server->namelen; res.namelen = server->namelen;
buf->f_namelen = res.namelen; buf->f_namelen = res.namelen;
out:
unlock_kernel();
return 0; return 0;
out_err: out_err:
printk("nfs_statfs: statfs error = %d\n", -error); printk(KERN_WARNING "nfs_statfs: statfs error = %d\n", -error);
buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
return 0; goto out;
} }
static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
......
...@@ -30,9 +30,7 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf) ...@@ -30,9 +30,7 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf)
retval = -ENOSYS; retval = -ENOSYS;
if (sb->s_op && sb->s_op->statfs) { if (sb->s_op && sb->s_op->statfs) {
memset(buf, 0, sizeof(struct statfs)); memset(buf, 0, sizeof(struct statfs));
lock_kernel();
retval = sb->s_op->statfs(sb, buf); retval = sb->s_op->statfs(sb, buf);
unlock_kernel();
} }
} }
return retval; return retval;
......
...@@ -281,6 +281,8 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock ) ...@@ -281,6 +281,8 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
static int qnx4_statfs(struct super_block *sb, struct statfs *buf) static int qnx4_statfs(struct super_block *sb, struct statfs *buf)
{ {
lock_kernel();
buf->f_type = sb->s_magic; buf->f_type = sb->s_magic;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8; buf->f_blocks = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8;
...@@ -288,6 +290,8 @@ static int qnx4_statfs(struct super_block *sb, struct statfs *buf) ...@@ -288,6 +290,8 @@ static int qnx4_statfs(struct super_block *sb, struct statfs *buf)
buf->f_bavail = buf->f_bfree; buf->f_bavail = buf->f_bfree;
buf->f_namelen = QNX4_NAME_MAX; buf->f_namelen = QNX4_NAME_MAX;
unlock_kernel();
return 0; return 0;
} }
......
...@@ -604,7 +604,13 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -604,7 +604,13 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
static int static int
smb_statfs(struct super_block *sb, struct statfs *buf) smb_statfs(struct super_block *sb, struct statfs *buf)
{ {
int result = smb_proc_dskattr(sb, buf); int result;
lock_kernel();
result = smb_proc_dskattr(sb, buf);
unlock_kernel();
buf->f_type = SMB_SUPER_MAGIC; buf->f_type = SMB_SUPER_MAGIC;
buf->f_namelen = SMB_MAXPATHLEN; buf->f_namelen = SMB_MAXPATHLEN;
......
...@@ -1726,6 +1726,8 @@ udf_put_super(struct super_block *sb) ...@@ -1726,6 +1726,8 @@ udf_put_super(struct super_block *sb)
static int static int
udf_statfs(struct super_block *sb, struct statfs *buf) udf_statfs(struct super_block *sb, struct statfs *buf)
{ {
lock_kernel();
buf->f_type = UDF_SUPER_MAGIC; buf->f_type = UDF_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
...@@ -1738,6 +1740,8 @@ udf_statfs(struct super_block *sb, struct statfs *buf) ...@@ -1738,6 +1740,8 @@ udf_statfs(struct super_block *sb, struct statfs *buf)
/* __kernel_fsid_t f_fsid */ /* __kernel_fsid_t f_fsid */
buf->f_namelen = UDF_NAME_LEN; buf->f_namelen = UDF_NAME_LEN;
unlock_kernel();
return 0; return 0;
} }
......
...@@ -959,6 +959,8 @@ int ufs_statfs (struct super_block * sb, struct statfs * buf) ...@@ -959,6 +959,8 @@ int ufs_statfs (struct super_block * sb, struct statfs * buf)
struct ufs_sb_private_info * uspi; struct ufs_sb_private_info * uspi;
struct ufs_super_block_first * usb1; struct ufs_super_block_first * usb1;
lock_kernel();
uspi = sb->u.ufs_sb.s_uspi; uspi = sb->u.ufs_sb.s_uspi;
usb1 = ubh_get_usb_first (USPI_UBH); usb1 = ubh_get_usb_first (USPI_UBH);
...@@ -972,6 +974,9 @@ int ufs_statfs (struct super_block * sb, struct statfs * buf) ...@@ -972,6 +974,9 @@ int ufs_statfs (struct super_block * sb, struct statfs * buf)
buf->f_files = uspi->s_ncg * uspi->s_ipg; buf->f_files = uspi->s_ncg * uspi->s_ipg;
buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
buf->f_namelen = UFS_MAXNAMLEN; buf->f_namelen = UFS_MAXNAMLEN;
unlock_kernel();
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment