Re: Patch to implement getattr [patch]

Magnus Ahltorp (map@stacken.kth.se)
15 Jul 1999 19:00:03 +0200


> > > 1. Having getattr is nice, but I'ld rather turned the old code into
> > > generic_getattr() and let the filesystems refer to it.
> > > [...]
> > > 2. I think that having a wrapper around the thing (vfs_getattr()) would be
> > > the right thing. Just look how arch/*/* stuff does stat() emulation for
> > > personalities with different struct stat layout. set_fs();sys_stat();set_fs();
> > > and then reshuffle the stuff...<shudder>

We (I and Assar Westerlund <assar@sics.se>) produced a patch that
should solved those issues. Comments?

--- fs/stat.c.orig Tue Jul 13 20:17:22 1999
+++ fs/stat.c Thu Jul 15 18:14:00 1999
@@ -24,56 +24,22 @@
}


-#if !defined(__alpha__) && !defined(__sparc__)
-
-/*
- * For backward compatibility? Maybe this should be moved
- * into arch/i386 instead?
- */
-static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
-{
- static int warncount = 5;
- struct __old_kernel_stat tmp;
-
- if (warncount) {
- warncount--;
- printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
- current->comm);
- }
-
- tmp.st_dev = kdev_t_to_nr(inode->i_dev);
- tmp.st_ino = inode->i_ino;
- tmp.st_mode = inode->i_mode;
- tmp.st_nlink = inode->i_nlink;
- tmp.st_uid = inode->i_uid;
- tmp.st_gid = inode->i_gid;
- tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
- tmp.st_ctime = inode->i_ctime;
- return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
-}
-
-#endif
-
-static int cp_new_stat(struct inode * inode, struct stat * statbuf)
+int generic_getattr(struct inode * inode, struct stat * statbuf)
{
- struct stat tmp;
unsigned int blocks, indirect;

- memset(&tmp, 0, sizeof(tmp));
- tmp.st_dev = kdev_t_to_nr(inode->i_dev);
- tmp.st_ino = inode->i_ino;
- tmp.st_mode = inode->i_mode;
- tmp.st_nlink = inode->i_nlink;
- tmp.st_uid = inode->i_uid;
- tmp.st_gid = inode->i_gid;
- tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
- tmp.st_ctime = inode->i_ctime;
+ memset(statbuf, 0, sizeof(*statbuf));
+ statbuf->st_dev = kdev_t_to_nr(inode->i_dev);
+ statbuf->st_ino = inode->i_ino;
+ statbuf->st_mode = inode->i_mode;
+ statbuf->st_nlink = inode->i_nlink;
+ statbuf->st_uid = inode->i_uid;
+ statbuf->st_gid = inode->i_gid;
+ statbuf->st_rdev = kdev_t_to_nr(inode->i_rdev);
+ statbuf->st_size = inode->i_size;
+ statbuf->st_atime = inode->i_atime;
+ statbuf->st_mtime = inode->i_mtime;
+ statbuf->st_ctime = inode->i_ctime;
/*
* st_blocks and st_blksize are approximated with a simple algorithm if
* they aren't supported directly by the filesystem. The minix and msdos
@@ -87,13 +53,13 @@
* Use minix fs values for the number of direct and indirect blocks. The
* count is now exact for the minix fs except that it counts zero blocks.
* Everything is in units of BLOCK_SIZE until the assignment to
- * tmp.st_blksize.
+ * statbuf->st_blksize.
*/
#define D_B 7
#define I_B (BLOCK_SIZE / sizeof(unsigned short))

if (!inode->i_blksize) {
- blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ blocks = (statbuf->st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
if (blocks > D_B) {
indirect = (blocks - D_B + I_B - 1) / I_B;
blocks += indirect;
@@ -104,15 +70,72 @@
blocks++;
}
}
- tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
- tmp.st_blksize = BLOCK_SIZE;
+ statbuf->st_blocks = (BLOCK_SIZE / 512) * blocks;
+ statbuf->st_blksize = BLOCK_SIZE;
} else {
- tmp.st_blocks = inode->i_blocks;
- tmp.st_blksize = inode->i_blksize;
+ statbuf->st_blocks = inode->i_blocks;
+ statbuf->st_blksize = inode->i_blksize;
+ }
+ return 0;
+}
+
+int vfs_getattr(struct inode * inode, struct stat * statbuf)
+{
+ if (inode->i_op && inode->i_op->getattr)
+ return inode->i_op->getattr (inode, statbuf);
+ else
+ return generic_getattr (inode, statbuf);
}
+
+#if !defined(__alpha__) && !defined(__sparc__)
+
+/*
+ * For backward compatibility? Maybe this should be moved
+ * into arch/i386 instead?
+ */
+static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
+{
+ static int warncount = 5;
+ struct __old_kernel_stat tmp;
+ struct stat new_tmp;
+ int ret;
+
+ if (warncount) {
+ warncount--;
+ printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
+ current->comm);
+ }
+
+ ret = vfs_getattr (inode, &new_tmp);
+ if (ret)
+ return ret;
+ tmp.st_dev = new_tmp.st_dev;
+ tmp.st_ino = new_tmp.st_ino;
+ tmp.st_mode = new_tmp.st_mode;
+ tmp.st_nlink = new_tmp.st_nlink;
+ tmp.st_uid = new_tmp.st_uid;
+ tmp.st_gid = new_tmp.st_gid;
+ tmp.st_rdev = new_tmp.st_rdev;
+ tmp.st_size = new_tmp.st_size;
+ tmp.st_atime = new_tmp.st_atime;
+ tmp.st_mtime = new_tmp.st_mtime;
+ tmp.st_ctime = new_tmp.st_ctime;
+
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

+#endif
+
+static int cp_new_stat(struct inode * inode, struct stat * statbuf)
+{
+ struct stat tmp;
+ int ret;
+
+ ret = vfs_getattr (inode, &tmp);
+ if (ret)
+ return ret;
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}

#if !defined(__alpha__) && !defined(__sparc__)
/*
--- include/linux/fs.h.orig Tue Jan 26 05:00:51 1999
+++ include/linux/fs.h Thu Jul 15 18:10:10 1999
@@ -613,6 +613,7 @@
int (*smap) (struct inode *,int);
int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int);
int (*revalidate) (struct dentry *);
+ int (*getattr) (struct inode *, struct stat *);
};

struct super_operations {
@@ -876,6 +877,9 @@

extern int inode_change_ok(struct inode *, struct iattr *);
extern void inode_setattr(struct inode *, struct iattr *);
+
+extern int generic_getattr(struct inode *, struct stat *);
+extern int vfs_getattr(struct inode * inode, struct stat * statbuf);

/* kludge to get SCSI modules working */
#include <linux/minix_fs.h>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/