Commit 726c3342 authored by David Howells's avatar David Howells Committed by Linus Torvalds
Browse files

[PATCH] VFS: Permit filesystem to perform statfs with a known root dentry



Give the statfs superblock operation a dentry pointer rather than a superblock
pointer.

This complements the get_sb() patch.  That reduced the significance of
sb->s_root, allowing NFS to place a fake root there.  However, NFS does
require a dentry to use as a target for the statfs operation.  This permits
the root in the vfsmount to be used instead.

linux/mount.h has been added where necessary to make allyesconfig build
successfully.

Interest has also been expressed for use with the FUSE and XFS filesystems.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Cc: Nathan Scott <nathans@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 454e2398
...@@ -236,8 +236,9 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr ...@@ -236,8 +236,9 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr
/* fsid is left zero */ /* fsid is left zero */
} }
static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb;
struct fuse_conn *fc = get_fuse_conn_super(sb); struct fuse_conn *fc = get_fuse_conn_super(sb);
struct fuse_req *req; struct fuse_req *req;
struct fuse_statfs_out outarg; struct fuse_statfs_out outarg;
......
...@@ -80,8 +80,10 @@ static void hfs_put_super(struct super_block *sb) ...@@ -80,8 +80,10 @@ static void hfs_put_super(struct super_block *sb)
* *
* changed f_files/f_ffree to reflect the fs_ablock/free_ablocks. * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
*/ */
static int hfs_statfs(struct super_block *sb, struct kstatfs *buf) static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb;
buf->f_type = HFS_SUPER_MAGIC; buf->f_type = HFS_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div; buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div;
......
...@@ -212,8 +212,10 @@ static void hfsplus_put_super(struct super_block *sb) ...@@ -212,8 +212,10 @@ static void hfsplus_put_super(struct super_block *sb)
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
} }
static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb;
buf->f_type = HFSPLUS_SUPER_MAGIC; buf->f_type = HFSPLUS_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift;
......
...@@ -239,7 +239,7 @@ static int read_inode(struct inode *ino) ...@@ -239,7 +239,7 @@ static int read_inode(struct inode *ino)
return(err); return(err);
} }
int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
{ {
/* do_statfs uses struct statfs64 internally, but the linux kernel /* do_statfs uses struct statfs64 internally, but the linux kernel
* struct statfs still has 32-bit versions for most of these fields, * struct statfs still has 32-bit versions for most of these fields,
...@@ -252,7 +252,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) ...@@ -252,7 +252,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
long long f_files; long long f_files;
long long f_ffree; long long f_ffree;
err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename,
&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
&sf->f_namelen, sf->f_spare); &sf->f_namelen, sf->f_spare);
......
...@@ -135,8 +135,9 @@ static unsigned count_bitmaps(struct super_block *s) ...@@ -135,8 +135,9 @@ static unsigned count_bitmaps(struct super_block *s)
return count; return count;
} }
static int hpfs_statfs(struct super_block *s, struct kstatfs *buf) static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *s = dentry->d_sb;
struct hpfs_sb_info *sbi = hpfs_sb(s); struct hpfs_sb_info *sbi = hpfs_sb(s);
lock_kernel(); lock_kernel();
......
...@@ -616,7 +616,7 @@ static const struct file_operations hppfs_dir_fops = { ...@@ -616,7 +616,7 @@ static const struct file_operations hppfs_dir_fops = {
.fsync = hppfs_fsync, .fsync = hppfs_fsync,
}; };
static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
{ {
sf->f_blocks = 0; sf->f_blocks = 0;
sf->f_bfree = 0; sf->f_bfree = 0;
......
...@@ -467,9 +467,9 @@ static int hugetlbfs_set_page_dirty(struct page *page) ...@@ -467,9 +467,9 @@ static int hugetlbfs_set_page_dirty(struct page *page)
return 0; return 0;
} }
static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf) static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb); struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
buf->f_type = HUGETLBFS_MAGIC; buf->f_type = HUGETLBFS_MAGIC;
buf->f_bsize = HPAGE_SIZE; buf->f_bsize = HPAGE_SIZE;
......
...@@ -56,7 +56,7 @@ static void isofs_put_super(struct super_block *sb) ...@@ -56,7 +56,7 @@ static void isofs_put_super(struct super_block *sb)
} }
static void isofs_read_inode(struct inode *); static void isofs_read_inode(struct inode *);
static int isofs_statfs (struct super_block *, struct kstatfs *); static int isofs_statfs (struct dentry *, struct kstatfs *);
static kmem_cache_t *isofs_inode_cachep; static kmem_cache_t *isofs_inode_cachep;
...@@ -901,8 +901,10 @@ out_freesbi: ...@@ -901,8 +901,10 @@ out_freesbi:
return -EINVAL; return -EINVAL;
} }
static int isofs_statfs (struct super_block *sb, struct kstatfs *buf) static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb;
buf->f_type = ISOFS_SUPER_MAGIC; buf->f_type = ISOFS_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = (ISOFS_SB(sb)->s_nzones buf->f_blocks = (ISOFS_SB(sb)->s_nzones
......
...@@ -377,9 +377,9 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, ...@@ -377,9 +377,9 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
/* Get statistics of the file system. */ /* Get statistics of the file system. */
static int static int
jffs_statfs(struct super_block *sb, struct kstatfs *buf) jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct jffs_control *c = (struct jffs_control *) sb->s_fs_info; struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
struct jffs_fmcontrol *fmc; struct jffs_fmcontrol *fmc;
lock_kernel(); lock_kernel();
......
...@@ -192,9 +192,9 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) ...@@ -192,9 +192,9 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
return rc; return rc;
} }
int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);
unsigned long avail; unsigned long avail;
buf->f_type = JFFS2_SUPER_MAGIC; buf->f_type = JFFS2_SUPER_MAGIC;
......
...@@ -175,7 +175,7 @@ void jffs2_clear_inode (struct inode *); ...@@ -175,7 +175,7 @@ void jffs2_clear_inode (struct inode *);
void jffs2_dirty_inode(struct inode *inode); void jffs2_dirty_inode(struct inode *inode);
struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
struct jffs2_raw_inode *ri); struct jffs2_raw_inode *ri);
int jffs2_statfs (struct super_block *, struct kstatfs *); int jffs2_statfs (struct dentry *, struct kstatfs *);
void jffs2_write_super (struct super_block *); void jffs2_write_super (struct super_block *);
int jffs2_remount_fs (struct super_block *, int *, char *); int jffs2_remount_fs (struct super_block *, int *, char *);
int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
......
...@@ -139,9 +139,9 @@ static void jfs_destroy_inode(struct inode *inode) ...@@ -139,9 +139,9 @@ static void jfs_destroy_inode(struct inode *inode)
kmem_cache_free(jfs_inode_cachep, ji); kmem_cache_free(jfs_inode_cachep, ji);
} }
static int jfs_statfs(struct super_block *sb, struct kstatfs *buf) static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct jfs_sb_info *sbi = JFS_SBI(sb); struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb);
s64 maxinodes; s64 maxinodes;
struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
......
...@@ -20,9 +20,9 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -20,9 +20,9 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
return 0; return 0;
} }
int simple_statfs(struct super_block *sb, struct kstatfs *buf) int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
buf->f_type = sb->s_magic; buf->f_type = dentry->d_sb->s_magic;
buf->f_bsize = PAGE_CACHE_SIZE; buf->f_bsize = PAGE_CACHE_SIZE;
buf->f_namelen = NAME_MAX; buf->f_namelen = NAME_MAX;
return 0; return 0;
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
static void minix_read_inode(struct inode * inode); static void minix_read_inode(struct inode * inode);
static int minix_write_inode(struct inode * inode, int wait); static int minix_write_inode(struct inode * inode, int wait);
static int minix_statfs(struct super_block *sb, struct kstatfs *buf); static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
static int minix_remount (struct super_block * sb, int * flags, char * data); static int minix_remount (struct super_block * sb, int * flags, char * data);
static void minix_delete_inode(struct inode *inode) static void minix_delete_inode(struct inode *inode)
...@@ -296,11 +296,11 @@ out_bad_sb: ...@@ -296,11 +296,11 @@ out_bad_sb:
return -EINVAL; return -EINVAL;
} }
static int minix_statfs(struct super_block *sb, struct kstatfs *buf) static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct minix_sb_info *sbi = minix_sb(sb); struct minix_sb_info *sbi = minix_sb(dentry->d_sb);
buf->f_type = sb->s_magic; buf->f_type = dentry->d_sb->s_magic;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = dentry->d_sb->s_blocksize;
buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
buf->f_bfree = minix_count_free_blocks(sbi); buf->f_bfree = minix_count_free_blocks(sbi);
buf->f_bavail = buf->f_bfree; buf->f_bavail = buf->f_bfree;
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
static void ncp_delete_inode(struct inode *); static void ncp_delete_inode(struct inode *);
static void ncp_put_super(struct super_block *); static void ncp_put_super(struct super_block *);
static int ncp_statfs(struct super_block *, struct kstatfs *); static int ncp_statfs(struct dentry *, struct kstatfs *);
static kmem_cache_t * ncp_inode_cachep; static kmem_cache_t * ncp_inode_cachep;
...@@ -724,13 +724,14 @@ static void ncp_put_super(struct super_block *sb) ...@@ -724,13 +724,14 @@ static void ncp_put_super(struct super_block *sb)
kfree(server); kfree(server);
} }
static int ncp_statfs(struct super_block *sb, struct kstatfs *buf) static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct dentry* d; struct dentry* d;
struct inode* i; struct inode* i;
struct ncp_inode_info* ni; struct ncp_inode_info* ni;
struct ncp_server* s; struct ncp_server* s;
struct ncp_volume_info vi; struct ncp_volume_info vi;
struct super_block *sb = dentry->d_sb;
int err; int err;
__u8 dh; __u8 dh;
......
...@@ -65,7 +65,7 @@ static int nfs_write_inode(struct inode *,int); ...@@ -65,7 +65,7 @@ static int nfs_write_inode(struct inode *,int);
static void nfs_delete_inode(struct inode *); static void nfs_delete_inode(struct inode *);
static void nfs_clear_inode(struct inode *); static void nfs_clear_inode(struct inode *);
static void nfs_umount_begin(struct super_block *); static void nfs_umount_begin(struct super_block *);
static int nfs_statfs(struct super_block *, struct kstatfs *); static int nfs_statfs(struct dentry *, struct kstatfs *);
static int nfs_show_options(struct seq_file *, struct vfsmount *); static int nfs_show_options(struct seq_file *, struct vfsmount *);
static int nfs_show_stats(struct seq_file *, struct vfsmount *); static int nfs_show_stats(struct seq_file *, struct vfsmount *);
static void nfs_zap_acl_cache(struct inode *); static void nfs_zap_acl_cache(struct inode *);
...@@ -534,8 +534,9 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) ...@@ -534,8 +534,9 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
} }
static int static int
nfs_statfs(struct super_block *sb, struct kstatfs *buf) nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb;
struct nfs_server *server = NFS_SB(sb); struct nfs_server *server = NFS_SB(sb);
unsigned char blockbits; unsigned char blockbits;
unsigned long blockres; unsigned long blockres;
......
...@@ -1310,7 +1310,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, ...@@ -1310,7 +1310,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
(bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
FATTR4_WORD1_SPACE_TOTAL))) { FATTR4_WORD1_SPACE_TOTAL))) {
status = vfs_statfs(dentry->d_inode->i_sb, &statfs); status = vfs_statfs(dentry, &statfs);
if (status) if (status)
goto out_nfserr; goto out_nfserr;
} }
......
...@@ -1737,7 +1737,7 @@ int ...@@ -1737,7 +1737,7 @@ int
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
{ {
int err = fh_verify(rqstp, fhp, 0, MAY_NOP); int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat)) if (!err && vfs_statfs(fhp->fh_dentry,stat))
err = nfserr_io; err = nfserr_io;
return err; return err;
} }
......
...@@ -2601,10 +2601,10 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, ...@@ -2601,10 +2601,10 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
/** /**
* ntfs_statfs - return information about mounted NTFS volume * ntfs_statfs - return information about mounted NTFS volume
* @sb: super block of mounted volume * @dentry: dentry from mounted volume
* @sfs: statfs structure in which to return the information * @sfs: statfs structure in which to return the information
* *
* Return information about the mounted NTFS volume @sb in the statfs structure * Return information about the mounted NTFS volume @dentry in the statfs structure
* pointed to by @sfs (this is initialized with zeros before ntfs_statfs is * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is
* called). We interpret the values to be correct of the moment in time at * called). We interpret the values to be correct of the moment in time at
* which we are called. Most values are variable otherwise and this isn't just * which we are called. Most values are variable otherwise and this isn't just
...@@ -2617,8 +2617,9 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, ...@@ -2617,8 +2617,9 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
* *
* Return 0 on success or -errno on error. * Return 0 on success or -errno on error.
*/ */
static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
{ {
struct super_block *sb = dentry->d_sb;
s64 size; s64 size;
ntfs_volume *vol = NTFS_SB(sb); ntfs_volume *vol = NTFS_SB(sb);
ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); ntfs_inode *mft_ni = NTFS_I(vol->mft_ino);
......
...@@ -100,7 +100,7 @@ static int ocfs2_initialize_mem_caches(void); ...@@ -100,7 +100,7 @@ static int ocfs2_initialize_mem_caches(void);
static void ocfs2_free_mem_caches(void); static void ocfs2_free_mem_caches(void);
static void ocfs2_delete_osb(struct ocfs2_super *osb); static void ocfs2_delete_osb(struct ocfs2_super *osb);
static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf); static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf);
static int ocfs2_sync_fs(struct super_block *sb, int wait); static int ocfs2_sync_fs(struct super_block *sb, int wait);
...@@ -857,7 +857,7 @@ static void ocfs2_put_super(struct super_block *sb) ...@@ -857,7 +857,7 @@ static void ocfs2_put_super(struct super_block *sb)
mlog_exit_void(); mlog_exit_void();
} }
static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct ocfs2_super *osb; struct ocfs2_super *osb;
u32 numbits, freebits; u32 numbits, freebits;
...@@ -866,9 +866,9 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) ...@@ -866,9 +866,9 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf)
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
struct inode *inode = NULL; struct inode *inode = NULL;
mlog_entry("(%p, %p)\n", sb, buf); mlog_entry("(%p, %p)\n", dentry->d_sb, buf);
osb = OCFS2_SB(sb); osb = OCFS2_SB(dentry->d_sb);
inode = ocfs2_get_system_file_inode(osb, inode = ocfs2_get_system_file_inode(osb,
GLOBAL_BITMAP_SYSTEM_INODE, GLOBAL_BITMAP_SYSTEM_INODE,
...@@ -891,7 +891,7 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) ...@@ -891,7 +891,7 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf)
freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used); freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);
buf->f_type = OCFS2_SUPER_MAGIC; buf->f_type = OCFS2_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = dentry->d_sb->s_blocksize;
buf->f_namelen = OCFS2_MAX_FILENAME_LEN; buf->f_namelen = OCFS2_MAX_FILENAME_LEN;
buf->f_blocks = ((sector_t) numbits) * buf->f_blocks = ((sector_t) numbits) *
(osb->s_clustersize >> osb->sb->s_blocksize_bits); (osb->s_clustersize >> osb->sb->s_blocksize_bits);
......
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