linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags
@ 2009-04-07 23:15 Oleg Drokin
  2009-04-07 23:25 ` Jeff Garzik
  2009-04-12 20:50 ` [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Jamie Lokier
  0 siblings, 2 replies; 7+ messages in thread
From: Oleg Drokin @ 2009-04-07 23:15 UTC (permalink / raw)
  To: linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 746 bytes --]

Hello!

   This is reworked Mark Fasheh's patch + my earlier patch.
   It allows one to specify which specific struct stat fields are needed
   out of the fstatat call, and also a request to obtain most uptodate
   information for inode (for NFS mostly).

   Also it adds AT_STAT_SELF flag to mean that the stat should be executed not
   on a path, but on the passed filedecriptor itself.

   A first real kernel user for this added in loop block driver that does
   not care about size or anything else besides rdev and inode number.

   I see various architectures replicate bits of vfs_*stat* in some compat
   code, I am not sure if we need to update those as well or not.

   This patch does away with all the extra syscalls.

Bye,
    Oleg

[-- Attachment #2: stat_light_vfs.diff --]
[-- Type: text/plain, Size: 21422 bytes --]

 arch/arm/kernel/sys_oabi-compat.c |    6 +--
 arch/ia64/ia32/sys_ia32.c         |    2 -
 arch/s390/kernel/compat_linux.c   |    6 +--
 arch/sparc/kernel/sys_sparc32.c   |    6 +--
 arch/x86/ia32/sys_ia32.c          |    6 +--
 drivers/block/loop.c              |    3 +
 fs/compat.c                       |   10 ++---
 fs/libfs.c                        |    2 -
 fs/nfsd/nfs3proc.c                |    2 -
 fs/nfsd/nfs3xdr.c                 |    5 +-
 fs/nfsd/nfs4xdr.c                 |    5 +-
 fs/nfsd/nfsproc.c                 |    6 +--
 fs/nfsd/nfsxdr.c                  |    3 +
 fs/stat.c                         |   64 +++++++++++++++++++++++---------------
 include/linux/fcntl.h             |   31 ++++++++++++++++++
 include/linux/fs.h                |   14 ++++----
 16 files changed, 112 insertions(+), 59 deletions(-)

Index: linux-2.6.29/arch/arm/kernel/sys_oabi-compat.c
===================================================================
--- linux-2.6.29.orig/arch/arm/kernel/sys_oabi-compat.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/arch/arm/kernel/sys_oabi-compat.c	2009-04-07 18:21:49.000000000 -0400
@@ -164,7 +164,7 @@
 				 struct oldabi_stat64 __user * statbuf)
 {
 	struct kstat stat;
-	int error = vfs_fstat(fd, &stat);
+	int error = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 	if (!error)
 		error = cp_oldabi_stat64(&stat, statbuf);
 	return error;
@@ -182,9 +182,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 	error = cp_oldabi_stat64(&stat, statbuf);
Index: linux-2.6.29/arch/s390/kernel/compat_linux.c
===================================================================
--- linux-2.6.29.orig/arch/s390/kernel/compat_linux.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/arch/s390/kernel/compat_linux.c	2009-04-07 18:48:11.000000000 -0400
@@ -692,7 +692,7 @@
 asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
 {
 	struct kstat stat;
-	int ret = vfs_fstat(fd, &stat);
+	int ret = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 	if (!ret)
 		ret = cp_stat64(statbuf, &stat);
 	return ret;
@@ -708,9 +708,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 		error = cp_stat64(statbuf, &stat);
Index: linux-2.6.29/arch/sparc/kernel/sys_sparc32.c
===================================================================
--- linux-2.6.29.orig/arch/sparc/kernel/sys_sparc32.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/arch/sparc/kernel/sys_sparc32.c	2009-04-07 18:48:39.000000000 -0400
@@ -195,7 +195,7 @@
 		struct compat_stat64 __user * statbuf)
 {
 	struct kstat stat;
-	int error = vfs_fstat(fd, &stat);
+	int error = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_compat_stat64(&stat, statbuf);
@@ -212,9 +212,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 		error = cp_compat_stat64(&stat, statbuf);
Index: linux-2.6.29/arch/x86/ia32/sys_ia32.c
===================================================================
--- linux-2.6.29.orig/arch/x86/ia32/sys_ia32.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/arch/x86/ia32/sys_ia32.c	2009-04-07 18:48:59.000000000 -0400
@@ -119,7 +119,7 @@
 asmlinkage long sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf)
 {
 	struct kstat stat;
-	int ret = vfs_fstat(fd, &stat);
+	int ret = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 	if (!ret)
 		ret = cp_stat64(statbuf, &stat);
 	return ret;
@@ -135,9 +135,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 		error = cp_stat64(statbuf, &stat);
Index: linux-2.6.29/drivers/block/loop.c
===================================================================
--- linux-2.6.29.orig/drivers/block/loop.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/drivers/block/loop.c	2009-04-07 17:49:36.000000000 -0400
@@ -1027,7 +1027,8 @@
 
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
-	error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
+	error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat,
+			    STAT_INO|STAT_RDEV);
 	if (error)
 		return error;
 	memset(info, 0, sizeof(*info));
Index: linux-2.6.29/fs/compat.c
===================================================================
--- linux-2.6.29.orig/fs/compat.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/compat.c	2009-04-07 18:49:18.000000000 -0400
@@ -180,7 +180,7 @@
 		struct compat_stat __user *statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_compat_stat(&stat, statbuf);
@@ -191,7 +191,7 @@
 		struct compat_stat __user *statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_compat_stat(&stat, statbuf);
@@ -209,9 +209,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 		error = cp_compat_stat(&stat, statbuf);
@@ -225,7 +225,7 @@
 		struct compat_stat __user * statbuf)
 {
 	struct kstat stat;
-	int error = vfs_fstat(fd, &stat);
+	int error = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_compat_stat(&stat, statbuf);
Index: linux-2.6.29/fs/libfs.c
===================================================================
--- linux-2.6.29.orig/fs/libfs.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/libfs.c	2009-04-07 17:44:22.000000000 -0400
@@ -13,7 +13,7 @@
 #include <asm/uaccess.h>
 
 int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
-		   struct kstat *stat)
+		   struct kstat *stat, int flags)
 {
 	struct inode *inode = dentry->d_inode;
 	generic_fillattr(inode, stat);
Index: linux-2.6.29/fs/nfsd/nfs3proc.c
===================================================================
--- linux-2.6.29.orig/fs/nfsd/nfs3proc.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/nfsd/nfs3proc.c	2009-04-07 17:44:22.000000000 -0400
@@ -69,7 +69,7 @@
 		RETURN_STATUS(nfserr);
 
 	err = vfs_getattr(resp->fh.fh_export->ex_path.mnt,
-			  resp->fh.fh_dentry, &resp->stat);
+			  resp->fh.fh_dentry, &resp->stat, STAT_EVERYTHING);
 	nfserr = nfserrno(err);
 
 	RETURN_STATUS(nfserr);
Index: linux-2.6.29/fs/nfsd/nfs3xdr.c
===================================================================
--- linux-2.6.29.orig/fs/nfsd/nfs3xdr.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/nfsd/nfs3xdr.c	2009-04-07 17:44:51.000000000 -0400
@@ -218,7 +218,8 @@
 	        int err;
 		struct kstat stat;
 
-		err = vfs_getattr(fhp->fh_export->ex_path.mnt, dentry, &stat);
+		err = vfs_getattr(fhp->fh_export->ex_path.mnt, dentry, &stat,
+				  STAT_EVERYTHING);
 		if (!err) {
 			*p++ = xdr_one;		/* attributes follow */
 			lease_get_mtime(dentry->d_inode, &stat.mtime);
@@ -271,7 +272,7 @@
 		printk("nfsd: inode locked twice during operation.\n");
 
 	err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
-			&fhp->fh_post_attr);
+			  &fhp->fh_post_attr, STAT_EVERYTHING);
 	if (err)
 		fhp->fh_post_saved = 0;
 	else
Index: linux-2.6.29/fs/nfsd/nfs4xdr.c
===================================================================
--- linux-2.6.29.orig/fs/nfsd/nfs4xdr.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/nfsd/nfs4xdr.c	2009-04-07 17:44:22.000000000 -0400
@@ -1436,7 +1436,7 @@
 			goto out;
 	}
 
-	err = vfs_getattr(exp->ex_path.mnt, dentry, &stat);
+	err = vfs_getattr(exp->ex_path.mnt, dentry, &stat, STAT_EVERYTHING);
 	if (err)
 		goto out_nfserr;
 	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
@@ -1795,7 +1795,8 @@
 		if (ignore_crossmnt == 0 &&
 		    exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) {
 			err = vfs_getattr(exp->ex_path.mnt->mnt_parent,
-				exp->ex_path.mnt->mnt_mountpoint, &stat);
+					  exp->ex_path.mnt->mnt_mountpoint,
+					  &stat, STAT_EVERYTHING);
 			if (err)
 				goto out_nfserr;
 		}
Index: linux-2.6.29/fs/nfsd/nfsproc.c
===================================================================
--- linux-2.6.29.orig/fs/nfsd/nfsproc.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/nfsd/nfsproc.c	2009-04-07 17:44:22.000000000 -0400
@@ -43,7 +43,7 @@
 	if (err) return err;
 	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_path.mnt,
 				    resp->fh.fh_dentry,
-				    &resp->stat));
+				    &resp->stat, STAT_EVERYTHING));
 }
 static __be32
 nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp)
@@ -51,7 +51,7 @@
 	if (err) return err;
 	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_path.mnt,
 				    resp->fh.fh_dentry,
-				    &resp->stat));
+				    &resp->stat, STAT_EVERYTHING));
 }
 /*
  * Get a file's attributes
@@ -167,7 +167,7 @@
 	if (nfserr) return nfserr;
 	return nfserrno(vfs_getattr(resp->fh.fh_export->ex_path.mnt,
 				    resp->fh.fh_dentry,
-				    &resp->stat));
+				    &resp->stat, STAT_EVERYTHING));
 }
 
 /*
Index: linux-2.6.29/fs/nfsd/nfsxdr.c
===================================================================
--- linux-2.6.29.orig/fs/nfsd/nfsxdr.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/nfsd/nfsxdr.c	2009-04-07 17:45:16.000000000 -0400
@@ -207,7 +207,8 @@
 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
 	struct kstat stat;
-	vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &stat);
+	vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &stat,
+		    STAT_EVERYTHING);
 	return encode_fattr(rqstp, p, fhp, &stat);
 }
 
Index: linux-2.6.29/fs/stat.c
===================================================================
--- linux-2.6.29.orig/fs/stat.c	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/fs/stat.c	2009-04-07 18:55:01.000000000 -0400
@@ -37,7 +37,8 @@
 
 EXPORT_SYMBOL(generic_fillattr);
 
-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat,
+		int flags)
 {
 	struct inode *inode = dentry->d_inode;
 	int retval;
@@ -47,7 +48,7 @@
 		return retval;
 
 	if (inode->i_op->getattr)
-		return inode->i_op->getattr(mnt, dentry, stat);
+		return inode->i_op->getattr(mnt, dentry, stat, flags);
 
 	generic_fillattr(inode, stat);
 	return 0;
@@ -55,14 +56,14 @@
 
 EXPORT_SYMBOL(vfs_getattr);
 
-int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
+int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat, int flags)
 {
 	struct path path;
 	int error;
 
 	error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path);
 	if (!error) {
-		error = vfs_getattr(path.mnt, path.dentry, stat);
+		error = vfs_getattr(path.mnt, path.dentry, stat, flags);
 		path_put(&path);
 	}
 	return error;
@@ -70,19 +71,19 @@
 
 int vfs_stat(char __user *name, struct kstat *stat)
 {
-	return vfs_stat_fd(AT_FDCWD, name, stat);
+	return vfs_stat_fd(AT_FDCWD, name, stat, STAT_EVERYTHING);
 }
 
 EXPORT_SYMBOL(vfs_stat);
 
-int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
+int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat, int flags)
 {
 	struct path path;
 	int error;
 
 	error = user_path_at(dfd, name, 0, &path);
 	if (!error) {
-		error = vfs_getattr(path.mnt, path.dentry, stat);
+		error = vfs_getattr(path.mnt, path.dentry, stat, flags);
 		path_put(&path);
 	}
 	return error;
@@ -90,18 +91,19 @@
 
 int vfs_lstat(char __user *name, struct kstat *stat)
 {
-	return vfs_lstat_fd(AT_FDCWD, name, stat);
+	return vfs_lstat_fd(AT_FDCWD, name, stat, STAT_EVERYTHING);
 }
 
 EXPORT_SYMBOL(vfs_lstat);
 
-int vfs_fstat(unsigned int fd, struct kstat *stat)
+int vfs_fstat(unsigned int fd, struct kstat *stat, int flags)
 {
 	struct file *f = fget(fd);
 	int error = -EBADF;
 
 	if (f) {
-		error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat);
+		error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat,
+				    flags);
 		fput(f);
 	}
 	return error;
@@ -155,7 +157,7 @@
 SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_old_stat(&stat, statbuf);
@@ -166,7 +168,7 @@
 SYSCALL_DEFINE2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_old_stat(&stat, statbuf);
@@ -177,7 +179,7 @@
 SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_fstat(fd, &stat);
+	int error = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_old_stat(&stat, statbuf);
@@ -240,7 +242,7 @@
 SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
@@ -251,7 +253,7 @@
 SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
@@ -266,13 +268,20 @@
 	struct kstat stat;
 	int error = -EINVAL;
 
-	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+	if (((flag & AT_FLAGS_SET) & ~AT_SYMLINK_NOFOLLOW) != 0)
 		goto out;
 
-	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+	if ((flag & ~AT_FLAGS_SET) == 0)
+		flag |= STAT_EVERYTHING;
+	else
+		memset(&stat, 0, sizeof(stat));
+
+	if (flag & AT_STAT_SELF)
+		error = vfs_fstat(dfd, &stat, flag);
+	else if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
@@ -285,7 +294,7 @@
 SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_fstat(fd, &stat);
+	int error = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
@@ -406,13 +415,20 @@
 	struct kstat stat;
 	int error = -EINVAL;
 
-	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+	if (((flag & AT_FLAGS_SET) & ~AT_SYMLINK_NOFOLLOW) != 0)
 		goto out;
 
-	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+	if ((flag & ~AT_FLAGS_SET) == 0)
+		flag |= STAT_EVERYTHING;
+	else
+		memset(&stat, 0, sizeof(stat));
+
+	if (flag & AT_STAT_SELF)
+		error = vfs_fstat(dfd, &stat, flag);
+	else if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat_fd(dfd, filename, &stat, flag);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, flag);
 
 	if (!error)
 		error = cp_new_stat64(&stat, statbuf);
Index: linux-2.6.29/include/linux/fcntl.h
===================================================================
--- linux-2.6.29.orig/include/linux/fcntl.h	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/include/linux/fcntl.h	2009-04-07 18:17:52.000000000 -0400
@@ -40,6 +40,37 @@
                                            unlinking file.  */
 #define AT_SYMLINK_FOLLOW	0x400   /* Follow symbolic links.  */
 
+#define AT_FLAGS_SET		0x700   /* All of the above flags for masking */
+
+#define	AT_STAT_SELF		0x800   /* Stat the actual fd passed to fstatat */
+
+/* Bits to define what fields the fstatat shoult fill in struct stat,
+ * should not intersect with above AT_* bits. No flags means get everthing
+ * for compatibility reasons */
+#define STAT_REVALIDATE	     0x000001	/* For NFS and other non local
+					   filesystems, do get the latest
+					   possible info */
+#define	STAT_INO	     0x001000   /* inode number */
+#define STAT_TYPE	     0x002000	/* file type */
+#define STAT_MODE	     0x004000	/* access mode */
+#define STAT_NLINK	     0x008000	/* nlink count */
+#define STAT_UID	     0x010000	/* owner uid */
+#define STAT_GID	     0x020000   /* owner gid */
+#define STAT_ATIME	     0x040000	/* atime */
+#define STAT_MTIME	     0x080000	/* mtime */
+#define STAT_CTIME	     0x100000	/* ctime */
+#define STAT_SIZE	     0x200000	/* file size */
+#define STAT_BLOCK	     0x400000	/* number of blocks allocated */
+#define STAT_RDEV	     0x800000	/* rdev */
+/* ->dev is assumed to be too lightweight to have its own bit, so you
+ * always get it. ->blksize is consideret to be unimportant in this case, so
+ * you always get it too. */
+
+/* Now some useful aggregators */
+#define STAT_EVERYTHING	     0xfff000   /* Avoid the temptation to use ~0 here*/
+#define STAT_TIMES	     (STAT_ATIME|STAT_MTIME|STAT_CTIME)
+#define STAT_ACCESS	     (STAT_MODE|STAT_UID|STAT_GID)
+
 #ifdef __KERNEL__
 
 #ifndef force_o_largefile
Index: linux-2.6.29/include/linux/fs.h
===================================================================
--- linux-2.6.29.orig/include/linux/fs.h	2009-04-07 17:39:39.000000000 -0400
+++ linux-2.6.29/include/linux/fs.h	2009-04-07 18:19:28.000000000 -0400
@@ -366,6 +366,8 @@
 #define ATTR_OPEN	(1 << 15) /* Truncating from open(O_TRUNC) */
 #define ATTR_TIMES_SET	(1 << 16)
 
+#define ATTR_STAT_ALL	(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME)
+
 /*
  * This is the Inode Attributes structure, used for notify_change().  It
  * uses the above definitions as flags, to know which values have changed.
@@ -1353,7 +1355,7 @@
 	void (*truncate) (struct inode *);
 	int (*permission) (struct inode *, int);
 	int (*setattr) (struct dentry *, struct iattr *);
-	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *, int);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
 	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -2062,7 +2064,7 @@
 extern const struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
-extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *, int);
 void inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_sub_bytes(struct inode *inode, loff_t bytes);
 loff_t inode_get_bytes(struct inode *inode);
@@ -2072,9 +2074,9 @@
 
 extern int vfs_stat(char __user *, struct kstat *);
 extern int vfs_lstat(char __user *, struct kstat *);
-extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
-extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
-extern int vfs_fstat(unsigned int, struct kstat *);
+extern int vfs_stat_fd(int dfd, char __user *, struct kstat *, int);
+extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *, int);
+extern int vfs_fstat(unsigned int, struct kstat *, int);
 
 extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 		    unsigned long arg);
@@ -2096,7 +2098,7 @@
 extern int dcache_dir_close(struct inode *, struct file *);
 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
 extern int dcache_readdir(struct file *, void *, filldir_t);
-extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *, int);
 extern int simple_statfs(struct dentry *, struct kstatfs *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *);
 extern int simple_unlink(struct inode *, struct dentry *);
Index: linux-2.6.29/arch/ia64/ia32/sys_ia32.c
===================================================================
--- linux-2.6.29.orig/arch/ia64/ia32/sys_ia32.c	2009-03-23 19:12:14.000000000 -0400
+++ linux-2.6.29/arch/ia64/ia32/sys_ia32.c	2009-04-07 18:22:50.000000000 -0400
@@ -1885,7 +1885,7 @@
 sys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf)
 {
 	struct kstat s;
-	long ret = vfs_fstat(fd, &s);
+	long ret = vfs_fstat(fd, &s, STAT_EVERYTHING);
 	if (!ret)
 		ret = putstat64(statbuf, &s);
 	return ret;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags
  2009-04-07 23:15 [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Oleg Drokin
@ 2009-04-07 23:25 ` Jeff Garzik
  2009-04-08  6:56   ` forwarding -fsdevel to -kernel (was Re: [PATCH 1/3] VFS "stat ...) flags Miklos Szeredi
  2009-04-12 20:50 ` [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Jamie Lokier
  1 sibling, 1 reply; 7+ messages in thread
From: Jeff Garzik @ 2009-04-07 23:25 UTC (permalink / raw)
  To: Oleg Drokin; +Cc: linux-fsdevel, LKML

Oleg Drokin wrote:
> Hello!
> 
>    This is reworked Mark Fasheh's patch + my earlier patch.
>    It allows one to specify which specific struct stat fields are needed
>    out of the fstatat call, and also a request to obtain most uptodate
>    information for inode (for NFS mostly).
> 
>    Also it adds AT_STAT_SELF flag to mean that the stat should be executed not
>    on a path, but on the passed filedecriptor itself.
> 
>    A first real kernel user for this added in loop block driver that does
>    not care about size or anything else besides rdev and inode number.
> 
>    I see various architectures replicate bits of vfs_*stat* in some compat
>    code, I am not sure if we need to update those as well or not.
> 
>    This patch does away with all the extra syscalls.


linux-kernel should be included in the discussion of this syscall.

	Jeff



^ permalink raw reply	[flat|nested] 7+ messages in thread

* forwarding -fsdevel to -kernel  (was Re: [PATCH 1/3] VFS "stat ...) flags
  2009-04-07 23:25 ` Jeff Garzik
@ 2009-04-08  6:56   ` Miklos Szeredi
  2009-04-08  7:35     ` David Miller
  0 siblings, 1 reply; 7+ messages in thread
From: Miklos Szeredi @ 2009-04-08  6:56 UTC (permalink / raw)
  To: jeff, davem; +Cc: green, linux-fsdevel, linux-kernel

On Tue, 07 Apr 2009, Jeff Garzik wrote:
> linux-kernel should be included in the discussion of this syscall.

Would it be possible to automatically forward all posts from -fsdevel,
and possibly other lists, to linux-kernel?

The rationale is that linux-kernel is a collection of all subtopics,
it's already CC-d on most threads.

Thanks,
Miklos

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: forwarding -fsdevel to -kernel (was Re: [PATCH 1/3] VFS "stat ...) flags
  2009-04-08  6:56   ` forwarding -fsdevel to -kernel (was Re: [PATCH 1/3] VFS "stat ...) flags Miklos Szeredi
@ 2009-04-08  7:35     ` David Miller
  0 siblings, 0 replies; 7+ messages in thread
From: David Miller @ 2009-04-08  7:35 UTC (permalink / raw)
  To: miklos; +Cc: jeff, green, linux-fsdevel, linux-kernel

From: Miklos Szeredi <miklos@szeredi.hu>
Date: Wed, 08 Apr 2009 08:56:16 +0200

> On Tue, 07 Apr 2009, Jeff Garzik wrote:
>> linux-kernel should be included in the discussion of this syscall.
> 
> Would it be possible to automatically forward all posts from -fsdevel,
> and possibly other lists, to linux-kernel?
> 
> The rationale is that linux-kernel is a collection of all subtopics,
> it's already CC-d on most threads.

No.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags
  2009-04-07 23:15 [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Oleg Drokin
  2009-04-07 23:25 ` Jeff Garzik
@ 2009-04-12 20:50 ` Jamie Lokier
  2009-04-12 21:46   ` Oleg Drokin
  1 sibling, 1 reply; 7+ messages in thread
From: Jamie Lokier @ 2009-04-12 20:50 UTC (permalink / raw)
  To: Oleg Drokin; +Cc: linux-fsdevel

Oleg Drokin wrote:
>    Also it adds AT_STAT_SELF flag to mean that the stat should be executed not
>    on a path, but on the passed filedecriptor itself.

Do you think this is more attractive?

    ret = fstatat(fd, 0, &stat, AT_STAT_SELF|AT_STAT_TYPE|AT_STAT_SIZE);

Or this?

    ret = fstatat(fd, 0, &stat, AT_STAT_TYPE|AT_STAT_SIZE);

Where 0 in the path automatically means AT_STAT_SELF.

Or this?

    ret = fstatat(fd, AT_STAT_SELF, &stat, AT_STAT_TYPE|AT_STAT_SIZE);

Where AT_STAT_SELF is defined as (const char *)-1 in system headers,
to better catch null pointer application bugs.

-- Jamie

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags
  2009-04-12 20:50 ` [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Jamie Lokier
@ 2009-04-12 21:46   ` Oleg Drokin
  2009-04-21 10:20     ` VFS "stat light" fstatat, inconsistent *at() function interfaces Jamie Lokier
  0 siblings, 1 reply; 7+ messages in thread
From: Oleg Drokin @ 2009-04-12 21:46 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: linux-fsdevel

Hello!

On Apr 12, 2009, at 4:50 PM, Jamie Lokier wrote:
>>   Also it adds AT_STAT_SELF flag to mean that the stat should be  
>> executed not
>>   on a path, but on the passed filedecriptor itself.
> Do you think this is more attractive?
>
>    ret = fstatat(fd, 0, &stat, AT_STAT_SELF|AT_STAT_TYPE| 
> AT_STAT_SIZE);
>
> Or this?
>    ret = fstatat(fd, 0, &stat, AT_STAT_TYPE|AT_STAT_SIZE);
> Where 0 in the path automatically means AT_STAT_SELF.
> Or this?
>    ret = fstatat(fd, AT_STAT_SELF, &stat, AT_STAT_TYPE|AT_STAT_SIZE);
> Where AT_STAT_SELF is defined as (const char *)-1 in system headers,
> to better catch null pointer application bugs.

While I think the last one might be attractive, we also need to think
about compatibility, unaware kernels would return -EFAULT if you pass  
some
nonsense as a path, which is much less useful than say nice EINVAL.

Bye,
     Oleg

^ permalink raw reply	[flat|nested] 7+ messages in thread

* VFS "stat light" fstatat, inconsistent *at() function interfaces
  2009-04-12 21:46   ` Oleg Drokin
@ 2009-04-21 10:20     ` Jamie Lokier
  0 siblings, 0 replies; 7+ messages in thread
From: Jamie Lokier @ 2009-04-21 10:20 UTC (permalink / raw)
  To: Oleg Drokin; +Cc: linux-fsdevel

Oleg Drokin wrote:
> Also it adds AT_STAT_SELF flag to mean that the stat should be  
> executed not on a path, but on the passed filedecriptor itself.

Ok.  See below.

> Jamie Lokier wrote:
>>    ret = fstatat(fd, 0, &stat, AT_STAT_TYPE|AT_STAT_SIZE);
>> Where 0 in the path automatically means AT_STAT_SELF.
>> Or this?
>>    ret = fstatat(fd, AT_STAT_SELF, &stat, AT_STAT_TYPE|AT_STAT_SIZE);
>> Where AT_STAT_SELF is defined as (const char *)-1 in system headers,
>> to better catch null pointer application bugs.
> 
> While I think the last one might be attractive, we also need to think
> about compatibility, unaware kernels would return -EFAULT if you pass  
> some nonsense as a path, which is much less useful than say nice EINVAL.

About compatibility, you might look at this in "man utimensat":

       On Linux, futimens() is a library function implemented on  top  of  the
       utimensat() system call.  To support this, the Linux utimensat() system
       call implements a non-standard feature: if pathname is NULL,  then  the
       call  modifies  the  timestamps  of  the  file  referred to by the file
       descriptor dirfd (which may refer to any type  of  file).   Using  this
       feature, the call futimens(fd, times) is implemented as:

           utimensat(fd, NULL, times, 0);

It's inconsistent to have AT_STAT_SELF for the stat-light call, but
NULL path for the utimensat() call (system call; Glibc hides it)
to mean the same thing, which is act on the passed file descriptor.

I think your scheme is better :-) And safer when an application passes
NULL due to programming eror.  But it is inconsistent.

It would be nice if they weren't, or if they used a common flag, in
the same way that other flags like AT_SYMLINK_NOFOLLOW have the same
meaning for all the *at() calls.

Then again, the *at() system calls are somewhat inconsistent anyway.
fchmodat() doesn't accept AT_SYMLINK_NOFOLLOW according to the man
page I have here.

-- Jamie

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-04-21 10:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-07 23:15 [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Oleg Drokin
2009-04-07 23:25 ` Jeff Garzik
2009-04-08  6:56   ` forwarding -fsdevel to -kernel (was Re: [PATCH 1/3] VFS "stat ...) flags Miklos Szeredi
2009-04-08  7:35     ` David Miller
2009-04-12 20:50 ` [PATCH 1/3] VFS "stat light" out of fstatat, and fine grained flags Jamie Lokier
2009-04-12 21:46   ` Oleg Drokin
2009-04-21 10:20     ` VFS "stat light" fstatat, inconsistent *at() function interfaces Jamie Lokier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).