--- 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>
