On Sat, 26 Jun 2010 11:35:07 +0200 Christoph Hellwig <hch@xxxxxx> wrote: > Add a flags field to help glibc implementing statvfs(3) efficiently. > > We copy the flag values from glibc, and add a new ST_VALID flag to > denote that f_flags is implemented. Hi Christoph, while we are adding flags to statfs, I wonder if it might be possible to do something to make f_fsid more useful - particularly for nfs-utils. Currently some filesystems (e.g. VFAT) set f_fsid based on the device that the filesystem is mounted from, while others (e.g. ext3) set f_fsid based on the filesystem itself (i.e. from the UUID stored in the superblock). This makes f_fsid not generally usable to make the filesystem part of a filehandle, as we really don't want to based it in the device if at all possible. This is particularly frustrating as for btrfs, f_fsid is the only way to differentiate between subvolumes. If we could have a flag "ST_FSID_STABLE" (or similar) which indicates that the f_fsid is known to be stable across device renames, then I could remove some special casing that was recently added to nfs-utils for btrfs (or at least deprecate it). And if it was acceptable to use a couple more of the 'spares' to provide a full 128bit fsid rather than just a 64bit one, that would be even better. But I'm not sure it is worth it (64bits is still quite a lot). Thanks, NeilBrown > > Signed-off-by: Christoph Hellwig <hch@xxxxxx> > > Index: linux-2.6/arch/mips/include/asm/statfs.h > =================================================================== > --- linux-2.6.orig/arch/mips/include/asm/statfs.h 2010-06-26 09:26:56.000000000 +0200 > +++ linux-2.6/arch/mips/include/asm/statfs.h 2010-06-26 10:00:33.864004297 +0200 > @@ -33,7 +33,8 @@ struct statfs { > /* Linux specials */ > __kernel_fsid_t f_fsid; > long f_namelen; > - long f_spare[6]; > + long f_flags; > + long f_spare[5]; > }; > > #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) > @@ -53,7 +54,8 @@ struct statfs64 { > __u64 f_bavail; > __kernel_fsid_t f_fsid; > __u32 f_namelen; > - __u32 f_spare[6]; > + __u32 f_flags; > + __u32 f_spare[5]; > }; > > #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ > @@ -73,7 +75,8 @@ struct statfs64 { /* Same as struct st > /* Linux specials */ > __kernel_fsid_t f_fsid; > long f_namelen; > - long f_spare[6]; > + long f_flags; > + long f_spare[5]; > }; > > struct compat_statfs64 { > @@ -88,7 +91,8 @@ struct compat_statfs64 { > __u64 f_bavail; > __kernel_fsid_t f_fsid; > __u32 f_namelen; > - __u32 f_spare[6]; > + __u32 f_flags; > + __u32 f_spare[5]; > }; > > #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ > Index: linux-2.6/arch/s390/include/asm/statfs.h > =================================================================== > --- linux-2.6.orig/arch/s390/include/asm/statfs.h 2010-06-26 09:26:56.000000000 +0200 > +++ linux-2.6/arch/s390/include/asm/statfs.h 2010-06-26 10:00:33.864004297 +0200 > @@ -33,7 +33,8 @@ struct statfs { > __kernel_fsid_t f_fsid; > int f_namelen; > int f_frsize; > - int f_spare[5]; > + int f_flags; > + int f_spare[4]; > }; > > struct statfs64 { > @@ -47,7 +48,8 @@ struct statfs64 { > __kernel_fsid_t f_fsid; > int f_namelen; > int f_frsize; > - int f_spare[5]; > + int f_flags; > + int f_spare[4]; > }; > > struct compat_statfs64 { > @@ -61,7 +63,8 @@ struct compat_statfs64 { > __kernel_fsid_t f_fsid; > __u32 f_namelen; > __u32 f_frsize; > - __u32 f_spare[5]; > + __u32 f_flags; > + __u32 f_spare[4]; > }; > > #endif /* __s390x__ */ > Index: linux-2.6/include/asm-generic/statfs.h > =================================================================== > --- linux-2.6.orig/include/asm-generic/statfs.h 2010-06-26 09:26:56.000000000 +0200 > +++ linux-2.6/include/asm-generic/statfs.h 2010-06-26 10:00:33.868047809 +0200 > @@ -33,7 +33,8 @@ struct statfs { > __kernel_fsid_t f_fsid; > __statfs_word f_namelen; > __statfs_word f_frsize; > - __statfs_word f_spare[5]; > + __statfs_word f_flags; > + __statfs_word f_spare[4]; > }; > > /* > @@ -55,7 +56,8 @@ struct statfs64 { > __kernel_fsid_t f_fsid; > __statfs_word f_namelen; > __statfs_word f_frsize; > - __statfs_word f_spare[5]; > + __statfs_word f_flags; > + __statfs_word f_spare[4]; > } ARCH_PACK_STATFS64; > > /* > @@ -77,6 +79,7 @@ struct compat_statfs64 { > __kernel_fsid_t f_fsid; > __u32 f_namelen; > __u32 f_frsize; > + __u32 f_flags[5]; > __u32 f_spare[5]; > } ARCH_PACK_COMPAT_STATFS64; > > Index: linux-2.6/include/linux/statfs.h > =================================================================== > --- linux-2.6.orig/include/linux/statfs.h 2010-06-26 09:26:56.000000000 +0200 > +++ linux-2.6/include/linux/statfs.h 2010-06-26 10:19:53.609016448 +0200 > @@ -2,7 +2,6 @@ > #define _LINUX_STATFS_H > > #include <linux/types.h> > - > #include <asm/statfs.h> > > struct kstatfs { > @@ -16,7 +15,29 @@ struct kstatfs { > __kernel_fsid_t f_fsid; > long f_namelen; > long f_frsize; > - long f_spare[5]; > + long f_flags; > + long f_spare[4]; > }; > > +/* > + * Definitions for the flag in f_flag. > + * > + * Generally these flags are equivalent to the MS_ flags used in the mount > + * ABI. The exception is ST_VALID which has the same value as MS_REMOUNT > + * which doesn't make any sense for statfs. > + */ > +#define ST_RDONLY 0x0001 /* mount read-only */ > +#define ST_NOSUID 0x0002 /* ignore suid and sgid bits */ > +#define ST_NODEV 0x0004 /* disallow access to device special files */ > +#define ST_NOEXEC 0x0008 /* disallow program execution */ > +#define ST_SYNCHRONOUS 0x0010 /* writes are synced at once */ > +#define ST_VALID 0x0020 /* f_flags support is implemented */ > +#define ST_MANDLOCK 0x0040 /* allow mandatory locks on an FS */ > +/* 0x0080 used for ST_WRITE in glibc */ > +/* 0x0100 used for ST_APPEND in glibc */ > +/* 0x0200 used for ST_IMMUTABLE in glibc */ > +#define ST_NOATIME 0x0400 /* do not update access times */ > +#define ST_NODIRATIME 0x0800 /* do not update directory access times */ > +#define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ > + > #endif > Index: linux-2.6/fs/statfs.c > =================================================================== > --- linux-2.6.orig/fs/statfs.c 2010-06-26 09:40:08.000000000 +0200 > +++ linux-2.6/fs/statfs.c 2010-06-26 10:24:27.674272979 +0200 > @@ -2,11 +2,40 @@ > #include <linux/module.h> > #include <linux/fs.h> > #include <linux/file.h> > +#include <linux/mount.h> > #include <linux/namei.h> > #include <linux/statfs.h> > #include <linux/security.h> > #include <linux/uaccess.h> > > +static int calculate_f_flags(struct vfsmount *mnt) > +{ > + struct super_block *sb = mnt->mnt_sb; > + long flags = ST_VALID; > + > + if (mnt->mnt_flags & MNT_READONLY) > + flags |= ST_RDONLY; > + if (mnt->mnt_flags & MNT_NOSUID) > + flags |= ST_NOSUID; > + if (mnt->mnt_flags & MNT_NODEV) > + flags |= ST_NODEV; > + if (mnt->mnt_flags & MNT_NOEXEC) > + flags |= ST_NOEXEC; > + if (mnt->mnt_flags & MNT_NOATIME) > + flags |= ST_NOATIME; > + if (mnt->mnt_flags & MNT_NODIRATIME) > + flags |= ST_NODIRATIME; > + if (mnt->mnt_flags & MNT_RELATIME) > + flags |= ST_RELATIME; > + > + if (sb->s_flags & MS_SYNCHRONOUS) > + flags |= ST_SYNCHRONOUS; > + if (sb->s_flags & MS_MANDLOCK) > + flags |= ST_MANDLOCK; > + > + return flags; > +} > + > int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf) > { > int retval; > @@ -26,7 +55,12 @@ int statfs_by_dentry(struct dentry *dent > > int vfs_statfs(struct path *path, struct kstatfs *buf) > { > - return statfs_by_dentry(path->dentry, buf); > + int error; > + > + error = statfs_by_dentry(path->dentry, buf); > + if (!error) > + buf->f_flags = calculate_f_flags(path->mnt); > + return error; > } > EXPORT_SYMBOL(vfs_statfs); > > @@ -69,6 +103,7 @@ static int do_statfs_native(struct path > buf->f_fsid = st.f_fsid; > buf->f_namelen = st.f_namelen; > buf->f_frsize = st.f_frsize; > + buf->f_flags = st.f_flags; > memset(buf->f_spare, 0, sizeof(buf->f_spare)); > } > return 0; > @@ -96,6 +131,7 @@ static int do_statfs64(struct path *path > buf->f_fsid = st.f_fsid; > buf->f_namelen = st.f_namelen; > buf->f_frsize = st.f_frsize; > + buf->f_flags = st.f_flags; > memset(buf->f_spare, 0, sizeof(buf->f_spare)); > } > return 0; > -- > To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html