Attempt at "stat light" implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello!

  Just as we discussed earlier today, here is a simple version that should do everything we need.
  I have separated stat fields into arbitrary categories based on my idea of how this needs to be done,
  that could of course be refined in other ways if desired.
  Only x86* syscall tables updated for now and no 64bit syscalls (probably we don't need them anyway, just
  need to always return 64 bit structure).

  I quickly realized that perhaps we can use just one extra syscall for fstat, and stat/lstat could be
  implemented as statat with just current cwd, though I do not know how desirable that is.

  Also I though that it would be kind of useful to allow the bitmask to be compatible with existing statat
  flags usage so that we do not need a new statat.

  Also perhaps the ->getattr just needs a prototype change to accept the flags argument and if the FS cares
  about it - to use it, but I did not want to do this huge patch touching every FS right now if only to save
  my time should this approach to be determined as undesirable for one reason or another, so
  for now I add a ->getattr_light

  Any comments?

Bye,
    Oleg
--- ./arch/x86/ia32/ia32entry.S.orig	2009-04-07 01:49:27.000000000 -0400
+++ ./arch/x86/ia32/ia32entry.S	2009-04-07 01:52:44.000000000 -0400
@@ -828,4 +828,7 @@
 	.quad sys_dup3			/* 330 */
 	.quad sys_pipe2
 	.quad sys_inotify_init1
+	.quad sys_fstatlight
+	.quad sys_lstatlight
+	.quad sys_statlight
 ia32_syscall_end:
--- ./arch/x86/include/asm/unistd_32.h.orig	2009-04-07 01:26:02.000000000 -0400
+++ ./arch/x86/include/asm/unistd_32.h	2009-04-07 01:38:39.000000000 -0400
@@ -338,6 +338,9 @@
 #define __NR_dup3		330
 #define __NR_pipe2		331
 #define __NR_inotify_init1	332
+#define __NR_fstat_light	333
+#define __NR_lstat_light	334
+#define __NR_stat_light		335
 
 #ifdef __KERNEL__
 
--- ./arch/x86/include/asm/unistd_64.h.orig	2009-04-07 01:26:12.000000000 -0400
+++ ./arch/x86/include/asm/unistd_64.h	2009-04-07 01:53:40.000000000 -0400
@@ -653,7 +653,12 @@
 __SYSCALL(__NR_pipe2, sys_pipe2)
 #define __NR_inotify_init1			294
 __SYSCALL(__NR_inotify_init1, sys_inotify_init1)
-
+#define __NR_fstat_light			295
+__SYSCALL(__NR_fstat_light, sys_fstatlight)
+#define __NR_lstat_light			296
+__SYSCALL(__NR_lstat_light, sys_lstatlight)
+#define __NR_stat_light				297
+__SYSCALL(__NR_inotify_init1, sys_statlight)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
--- ./fs/stat.c.orig	2009-04-07 00:23:22.000000000 -0400
+++ ./fs/stat.c	2009-04-07 01:51:49.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,
+		unsigned int flags)
 {
 	struct inode *inode = dentry->d_inode;
 	int retval;
@@ -46,6 +47,9 @@
 	if (retval)
 		return retval;
 
+	if (inode->i_op->getattr_light)
+		return inode->i_op->getattr_light(mnt, dentry, stat, flags);
+
 	if (inode->i_op->getattr)
 		return inode->i_op->getattr(mnt, dentry, stat);
 
@@ -55,53 +59,56 @@
 
 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,
+		unsigned 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;
 }
 
-int vfs_stat(char __user *name, struct kstat *stat)
+int vfs_stat(char __user *name, struct kstat *stat, unsigned int flags)
 {
-	return vfs_stat_fd(AT_FDCWD, name, stat);
+	return vfs_stat_fd(AT_FDCWD, name, stat, flags);
 }
 
 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,
+		 unsigned 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;
 }
 
-int vfs_lstat(char __user *name, struct kstat *stat)
+int vfs_lstat(char __user *name, struct kstat *stat, unsigned int flags)
 {
-	return vfs_lstat_fd(AT_FDCWD, name, stat);
+	return vfs_lstat_fd(AT_FDCWD, name, stat, flags);
 }
 
 EXPORT_SYMBOL(vfs_lstat);
 
-int vfs_fstat(unsigned int fd, struct kstat *stat)
+int vfs_fstat(unsigned int fd, struct kstat *stat, unsigned 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 +162,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 +173,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 +184,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 +247,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 +258,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);
@@ -270,9 +277,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, STAT_EVERYTHING);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
@@ -285,7 +292,43 @@
 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);
+
+	return error;
+}
+
+SYSCALL_DEFINE3(statlight, char __user *, filename,
+	        struct stat __user *, statbuf, unsigned int, flags)
+{
+	struct kstat stat;
+	int error = vfs_stat_fd(AT_FDCWD, filename, &stat, flags);
+
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
+
+	return error;
+}
+
+SYSCALL_DEFINE3(lstatlight, char __user *, filename,
+		struct stat __user *, statbuf, unsigned int, flags)
+{
+	struct kstat stat;
+	int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, flags);
+
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
+
+	return error;
+}
+
+SYSCALL_DEFINE3(fstatlight, unsigned int, fd, struct stat __user *, statbuf,
+		unsigned int, flags)
+{
+	struct kstat stat;
+	int error = vfs_fstat(fd, &stat, flags);
 
 	if (!error)
 		error = cp_new_stat(&stat, statbuf);
@@ -370,7 +413,7 @@
 SYSCALL_DEFINE2(stat64, char __user *, filename, struct stat64 __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_stat(filename, &stat);
+	int error = vfs_stat(filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat64(&stat, statbuf);
@@ -381,7 +424,7 @@
 SYSCALL_DEFINE2(lstat64, char __user *, filename, struct stat64 __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_lstat(filename, &stat);
+	int error = vfs_lstat(filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat64(&stat, statbuf);
@@ -392,7 +435,7 @@
 SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
 {
 	struct kstat stat;
-	int error = vfs_fstat(fd, &stat);
+	int error = vfs_fstat(fd, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat64(&stat, statbuf);
@@ -410,9 +453,9 @@
 		goto out;
 
 	if (flag & AT_SYMLINK_NOFOLLOW)
-		error = vfs_lstat_fd(dfd, filename, &stat);
+		error = vfs_lstat_fd(dfd, filename, &stat, STAT_EVERYTHING);
 	else
-		error = vfs_stat_fd(dfd, filename, &stat);
+		error = vfs_stat_fd(dfd, filename, &stat, STAT_EVERYTHING);
 
 	if (!error)
 		error = cp_new_stat64(&stat, statbuf);
--- ./include/linux/fcntl.h.orig	2009-04-07 00:31:36.000000000 -0400
+++ ./include/linux/fcntl.h	2009-04-07 00:44:41.000000000 -0400
@@ -40,6 +40,14 @@
                                            unlinking file.  */
 #define AT_SYMLINK_FOLLOW	0x400   /* Follow symbolic links.  */
 
+/* Bits to define what fields the "stat light" syscall must fill in struct stat,
+ * should not intersect with abovr AT_* bits */
+#define STAT_NLINK	0x01000		/* nlink */
+#define STAT_TIMES	0x02000		/* atime, mtime, ctime */
+#define STAT_SIZE	0x04000		/* File size and blocks */
+#define STAT_ACCESS	0x08000		/* mode, user, group */
+#define STAT_EVERYTHING 0x0f000		/* Just a normal stat */
+
 #ifdef __KERNEL__
 
 #ifndef force_o_largefile
--- ./include/linux/fs.h.orig	2009-04-07 00:30:52.000000000 -0400
+++ ./include/linux/fs.h	2009-04-07 01:03:58.000000000 -0400
@@ -1354,6 +1354,8 @@
 	int (*permission) (struct inode *, int);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+	int (*getattr_light) (struct vfsmount *mnt, struct dentry *,
+			      struct kstat *, unsigned 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,8 @@
 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 *,
+		       unsigned 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);
@@ -2070,11 +2073,11 @@
 
 extern int vfs_readdir(struct file *, filldir_t, void *);
 
-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(char __user *, struct kstat *, unsigned int);
+extern int vfs_lstat(char __user *, struct kstat *, unsigned int);
+extern int vfs_stat_fd(int dfd, char __user *, struct kstat *, unsigned int);
+extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *, unsigned int);
+extern int vfs_fstat(unsigned int, struct kstat *, unsigned int);
 
 extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 		    unsigned long arg);
--- ./include/linux/syscalls.h.orig	2009-04-07 01:18:06.000000000 -0400
+++ ./include/linux/syscalls.h	2009-04-07 01:57:34.000000000 -0400
@@ -304,6 +304,13 @@
 				struct stat __user *statbuf);
 asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf);
 asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);
+asmlinkage long sys_fstatlight(unsigned int fd,
+			       struct stat __user *statbuf,
+			       unsigned int);
+asmlinkage long sys_statlight(char __user *filename,
+			      struct stat __user *statbuf, unsigned int);
+asmlinkage long sys_lstatlight(char __user *filename,
+			       struct stat __user *statbuf, unsigned int);
 #if BITS_PER_LONG == 32
 asmlinkage long sys_stat64(char __user *filename,
 				struct stat64 __user *statbuf);

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux