]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] (2/5) beginning of getattr series.
authorAlexander Viro <viro@math.psu.edu>
Wed, 6 Feb 2002 02:46:32 +0000 (18:46 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Wed, 6 Feb 2002 02:46:32 +0000 (18:46 -0800)
stat(2) variants in arch/* that used to copy inode fields manually
switched to vfs_*stat() and partially cleaned up

arch/ia64/kernel/sys_ia64.c
arch/mips64/kernel/linux32.c
arch/parisc/hpux/fs.c
arch/s390x/kernel/linux32.c
arch/sparc64/kernel/sys_sparc32.c

index cc312ad8b18f009c55639d4e694e7345ea7a222b..8b4512db776bc70c279e771dbfd19a33f60db1f2 100644 (file)
@@ -282,120 +282,64 @@ ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
  * call - it will be removed later once everybody migrates to the new
  * kernel stat structure that matches the glibc one - Jes
  */
-static __inline__ int
-do_revalidate (struct dentry *dentry)
-{
-       struct inode * inode = dentry->d_inode;
-       if (inode->i_op && inode->i_op->revalidate)
-               return inode->i_op->revalidate(dentry);
-       return 0;
-}
 
 static int
-cp_ia64_old_stat (struct inode *inode, struct ia64_oldstat *statbuf)
+cp_ia64_old_stat (struct kstat *stat, struct ia64_oldstat *statbuf)
 {
        struct ia64_oldstat 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;
-       SET_STAT_UID(tmp, inode->i_uid);
-       SET_STAT_GID(tmp, 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;
-/*
- * st_blocks and st_blksize are approximated with a simple algorithm if
- * they aren't supported directly by the filesystem. The minix and msdos
- * filesystems don't keep track of blocks, so they would either have to
- * be counted explicitly (by delving into the file itself), or by using
- * this simple algorithm to get a reasonable (although not 100% accurate)
- * value.
- */
-
-/*
- * 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.
- */
-#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;
-               if (blocks > D_B) {
-                       indirect = (blocks - D_B + I_B - 1) / I_B;
-                       blocks += indirect;
-                       if (indirect > 1) {
-                               indirect = (indirect - 1 + I_B - 1) / I_B;
-                               blocks += indirect;
-                               if (indirect > 1)
-                                       blocks++;
-                       }
-               }
-               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-               tmp.st_blksize = BLOCK_SIZE;
-       } else {
-               tmp.st_blocks = inode->i_blocks;
-               tmp.st_blksize = inode->i_blksize;
-       }
+       tmp.st_dev = stat->dev;
+       tmp.st_ino = stat->ino;
+       tmp.st_mode = stat->mode;
+       tmp.st_nlink = stat->nlink;
+       SET_STAT_UID(tmp, stat->uid);
+       SET_STAT_GID(tmp, stat->gid);
+       tmp.st_rdev = stat->rdev;
+       tmp.st_size = stat->size;
+       tmp.st_atime = stat->atime;
+       tmp.st_mtime = stat->mtime;
+       tmp.st_ctime = stat->ctime;
+       tmp.st_blocks = stat->i_blocks;
+       tmp.st_blksize = stat->i_blksize;
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage long
 ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
 {
-       struct nameidata nd;
-       int error;
-
-       error = user_path_walk(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-               error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
-               path_release(&nd);
-       }
+       struct kstat stat;
+       int error = vfs_stat(filename, &stat);
+
+       if (!error)
+               error = cp_ia64_old_stat(&stat, statbuf);
+
        return error;
 }
 
-
 asmlinkage long
-ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf) {
-       struct nameidata nd;
-       int error;
-
-       error = user_path_walk_link(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
-               path_release(&nd);
-       }
+ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf)
+{
+       struct kstat stat;
+       int error = vfs_lstat(filename, &stat);
+
+       if (!error)
+               error = cp_ia64_old_stat(&stat, statbuf);
+
        return error;
 }
 
 asmlinkage long
 ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
 {
-       struct file * f;
-       int err = -EBADF;
+       struct kstat stat;
+       int error = vfs_fstat(fd, &stat);
 
-       f = fget(fd);
-       if (f) {
-               struct dentry * dentry = f->f_dentry;
+       if (!error)
+               error = cp_ia64_old_stat(&stat, statbuf);
 
-               err = do_revalidate(dentry);
-               if (!err)
-                       err = cp_ia64_old_stat(dentry->d_inode, statbuf);
-               fput(f);
-       }
-       return err;
+       return error;
 }
 
 #endif
index 5d43147ede345736b2fb4e7e9cde980648469a53..3ca8a28c1da90d4bedcfaf5ce82ba56e5aeffc0c 100644 (file)
 /*
  * Revalidate the inode. This is required for proper NFS attribute caching.
  */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-       struct inode * inode = dentry->d_inode;
-
-       if (inode->i_op && inode->i_op->revalidate)
-               return inode->i_op->revalidate(dentry);
 
-       return 0;
-}
-
-static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
+static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
 {
        struct stat32 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;
-       SET_STAT_UID(tmp, inode->i_uid);
-       SET_STAT_GID(tmp, 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;
-
-       /*
-        * st_blocks and st_blksize are approximated with a simple algorithm if
-        * they aren't supported directly by the filesystem. The minix and msdos
-        * filesystems don't keep track of blocks, so they would either have to
-        * be counted explicitly (by delving into the file itself), or by using
-        * this simple algorithm to get a reasonable (although not 100%
-        * accurate) value.
-        */
-
-       /*
-        * 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.
-        */
-#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;
-               if (blocks > D_B) {
-                       indirect = (blocks - D_B + I_B - 1) / I_B;
-                       blocks += indirect;
-                       if (indirect > 1) {
-                               indirect = (indirect - 1 + I_B - 1) / I_B;
-                               blocks += indirect;
-                               if (indirect > 1)
-                                       blocks++;
-                       }
-               }
-               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-               tmp.st_blksize = BLOCK_SIZE;
-       } else {
-               tmp.st_blocks = inode->i_blocks;
-               tmp.st_blksize = inode->i_blksize;
-       }
-
+       tmp.st_dev = stat->dev;
+       tmp.st_ino = stat->ino;
+       tmp.st_mode = stat->mode;
+       tmp.st_nlink = stat->nlink;
+       SET_STAT_UID(tmp, stat->uid);
+       SET_STAT_GID(tmp, stat->gid);
+       tmp.st_rdev = stat->rdev;
+       tmp.st_size = stat->size;
+       tmp.st_atime = stat->atime;
+       tmp.st_mtime = stat->mtime;
+       tmp.st_ctime = stat->ctime;
+       tmp.st_blocks = stat->blocks;
+       tmp.st_blksize = stat->blksize;
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_stat(filename, &stat);
 
-       error = user_path_walk(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-
-               path_release(&nd);
-       }
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
        return error;
 }
 
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_lstat(filename, &stat);
 
-       error = user_path_walk_link(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-
-               path_release(&nd);
-       }
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
        return error;
 }
 
 asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
 {
-       struct file * f;
-       int err = -EBADF;
-
-       f = fget(fd);
-       if (f) {
-               struct dentry * dentry = f->f_dentry;
+       struct kstat stat;
+       int error = vfs_fstat(fd, &stat);
 
-               err = do_revalidate(dentry);
-               if (!err)
-                       err = cp_new_stat32(dentry->d_inode, statbuf);
-               fput(f);
-       }
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-       return err;
+       return error;
 }
 
 asmlinkage int sys_mmap2(void) {return 0;}
index bbe1a534fd6ee32c2255c1110e931e60b628ddd0..9942c0545265101321fff07ffd3d2b9cef615813 100644 (file)
@@ -141,110 +141,56 @@ int hpux_mount(const char *fs, const char *path, int mflag,
        return -ENOSYS;
 }
 
-static int cp_hpux_stat(struct inode * inode, struct hpux_stat64 * statbuf)
+static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 *statbuf)
 {
        struct hpux_stat64 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;
-
-#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;
-               if (blocks > D_B) {
-                       indirect = (blocks - D_B + I_B - 1) / I_B;
-                       blocks += indirect;
-                       if (indirect > 1) {
-                               indirect = (indirect - 1 + I_B - 1) / I_B;
-                               blocks += indirect;
-                               if (indirect > 1)
-                                       blocks++;
-                       }
-               }
-               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
-               tmp.st_blksize = BLOCK_SIZE;
-       } else {
-               tmp.st_blocks = inode->i_blocks;
-               tmp.st_blksize = inode->i_blksize;
-       }
+       tmp.st_dev = stat->dev;
+       tmp.st_ino = stat->ino;
+       tmp.st_mode = stat->mode;
+       tmp.st_nlink = stat->nlink;
+       tmp.st_uid = stat->uid;
+       tmp.st_gid = stat->gid;
+       tmp.st_rdev = stat->rdev;
+       tmp.st_size = stat->size;
+       tmp.st_atime = stat->atime;
+       tmp.st_mtime = stat->mtime;
+       tmp.st_ctime = stat->ctime;
+       tmp.st_blocks = stat->blocks;
+       tmp.st_blksize = stat->blksize;
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
 
-/*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- * Blatently copied wholesale from fs/stat.c
- */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-       struct inode * inode = dentry->d_inode;
-       if (inode->i_op && inode->i_op->revalidate)
-               return inode->i_op->revalidate(dentry);
-       return 0;
-}
-
 long hpux_stat64(const char *path, struct hpux_stat64 *buf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_stat(filename, &stat);
+
+       if (!error)
+               error = cp_hpux_stat(&stat, statbuf);
 
-       lock_kernel();
-       error = user_path_walk(path, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_hpux_stat(nd.dentry->d_inode, buf);
-               path_release(&nd);
-       }
-       unlock_kernel();
        return error;
 }
 
 long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
 {
-       struct file * f;
-       int err = -EBADF;
+       struct kstat stat;
+       int error = vfs_fstat(fd, &stat);
 
-       lock_kernel();
-       f = fget(fd);
-       if (f) {
-               struct dentry * dentry = f->f_dentry;
-
-               err = do_revalidate(dentry);
-               if (!err)
-                       err = cp_hpux_stat(dentry->d_inode, statbuf);
-               fput(f);
-       }
-       unlock_kernel();
-       return err;
+       if (!error)
+               error = cp_hpux_stat(&stat, statbuf);
+
+       return error;
 }
 
 long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_lstat(filename, &stat);
+
+       if (!error)
+               error = cp_hpux_stat(&stat, statbuf);
 
-       lock_kernel();
-       error = user_path_walk_link(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_hpux_stat(nd.dentry->d_inode, statbuf);
-               path_release(&nd);
-       }
-       unlock_kernel();
        return error;
 }
index 6f85af23b6c185e1b3c709a454697194bde7a09d..0db4c93950bb480e46370f9ba5063f1bf358a207 100644 (file)
@@ -1471,140 +1471,62 @@ out_nofds:
        return ret;
 }
 
-static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
-{
-       unsigned long ino, blksize, blocks;
-       kdev_t dev, rdev;
-       umode_t mode;
-       nlink_t nlink;
-       uid_t uid;
-       gid_t gid;
-       off_t size;
-       time_t atime, mtime, ctime;
-       int err;
-
-       /* Stream the loads of inode data into the load buffer,
-        * then we push it all into the store buffer below.  This
-        * should give optimal cache performance.
-        */
-       ino = inode->i_ino;
-       dev = inode->i_dev;
-       mode = inode->i_mode;
-       nlink = inode->i_nlink;
-       uid = inode->i_uid;
-       gid = inode->i_gid;
-       rdev = inode->i_rdev;
-       size = inode->i_size;
-       atime = inode->i_atime;
-       mtime = inode->i_mtime;
-       ctime = inode->i_ctime;
-       blksize = inode->i_blksize;
-       blocks = inode->i_blocks;
-
-       err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
-       err |= put_user(ino, &statbuf->st_ino);
-       err |= put_user(mode, &statbuf->st_mode);
-       err |= put_user(nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(gid), &statbuf->st_gid);
-       err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
-       err |= put_user(size, &statbuf->st_size);
-       err |= put_user(atime, &statbuf->st_atime);
+static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
+{
+       err  = put_user(stat->dev, &statbuf->st_dev);
+       err |= put_user(stat->ino, &statbuf->st_ino);
+       err |= put_user(stat->mode, &statbuf->st_mode);
+       err |= put_user(stat->nlink, &statbuf->st_nlink);
+       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
+       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
+       err |= put_user(stat->rdev, &statbuf->st_rdev);
+       err |= put_user(stat->size, &statbuf->st_size);
+       err |= put_user(stat->atime, &statbuf->st_atime);
        err |= put_user(0, &statbuf->__unused1);
-       err |= put_user(mtime, &statbuf->st_mtime);
+       err |= put_user(stat->mtime, &statbuf->st_mtime);
        err |= put_user(0, &statbuf->__unused2);
-       err |= put_user(ctime, &statbuf->st_ctime);
+       err |= put_user(stat->ctime, &statbuf->st_ctime);
        err |= put_user(0, &statbuf->__unused3);
-       if (blksize) {
-               err |= put_user(blksize, &statbuf->st_blksize);
-               err |= put_user(blocks, &statbuf->st_blocks);
-       } else {
-               unsigned int tmp_blocks;
-
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-               tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-               if (tmp_blocks > D_B) {
-                       unsigned int indirect;
-
-                       indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
-                       tmp_blocks += indirect;
-                       if (indirect > 1) {
-                               indirect = (indirect - 1 + I_B - 1) / I_B;
-                               tmp_blocks += indirect;
-                               if (indirect > 1)
-                                       tmp_blocks++;
-                       }
-               }
-               err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
-               err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
-#undef D_B
-#undef I_B
-       }
+       err |= put_user(stat->blksize, &statbuf->st_blksize);
+       err |= put_user(stat->blocks, &statbuf->st_blocks);
 /* fixme
        err |= put_user(0, &statbuf->__unused4[0]);
        err |= put_user(0, &statbuf->__unused4[1]);
 */
-
        return err;
 }
 
-/* Perhaps this belongs in fs.h or similar. -DaveM */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-       struct inode * inode = dentry->d_inode;
-       if (inode->i_op && inode->i_op->revalidate)
-               return inode->i_op->revalidate(dentry);
-       return 0;
-}
-
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_stat(filename, &stat);
+
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-       error = user_path_walk(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-               path_release(&nd);
-       }
        return error;
 }
 
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_lstat(filename, &stat);
 
-       error = user_path_walk_link(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-               path_release(&nd);
-       }
        return error;
 }
 
 asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
 {
-       struct file *f;
-       int err = -EBADF;
+       struct kstat stat;
+       int error = vfs_fstat(fd, &stat);
 
-       f = fget(fd);
-       if (f) {
-               struct dentry * dentry = f->f_dentry;
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-               err = do_revalidate(dentry);
-               if (!err)
-                       err = cp_new_stat32(dentry->d_inode, statbuf);
-               fput(f);
-       }
-       return err;
+       return error;
 }
 
 extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
index 5ee8df8c502a61d0ac102710a6aec0689eef3b00..53987ffca5dc2d92a48b15ade6e55cf82ba01d33 100644 (file)
@@ -1459,138 +1459,60 @@ out_nofds:
        return ret;
 }
 
-static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
-{
-       unsigned long ino, blksize, blocks;
-       kdev_t dev, rdev;
-       umode_t mode;
-       nlink_t nlink;
-       uid_t uid;
-       gid_t gid;
-       off_t size;
-       time_t atime, mtime, ctime;
-       int err;
-
-       /* Stream the loads of inode data into the load buffer,
-        * then we push it all into the store buffer below.  This
-        * should give optimal cache performance.
-        */
-       ino = inode->i_ino;
-       dev = inode->i_dev;
-       mode = inode->i_mode;
-       nlink = inode->i_nlink;
-       uid = inode->i_uid;
-       gid = inode->i_gid;
-       rdev = inode->i_rdev;
-       size = inode->i_size;
-       atime = inode->i_atime;
-       mtime = inode->i_mtime;
-       ctime = inode->i_ctime;
-       blksize = inode->i_blksize;
-       blocks = inode->i_blocks;
-
-       err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
-       err |= put_user(ino, &statbuf->st_ino);
-       err |= put_user(mode, &statbuf->st_mode);
-       err |= put_user(nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(gid), &statbuf->st_gid);
-       err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
-       err |= put_user(size, &statbuf->st_size);
-       err |= put_user(atime, &statbuf->st_atime);
+static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
+{
+       err  = put_user(stat->dev, &statbuf->st_dev);
+       err |= put_user(stat->ino, &statbuf->st_ino);
+       err |= put_user(stat->mode, &statbuf->st_mode);
+       err |= put_user(stat->nlink, &statbuf->st_nlink);
+       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
+       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
+       err |= put_user(stat->rdev, &statbuf->st_rdev);
+       err |= put_user(stat->size, &statbuf->st_size);
+       err |= put_user(stat->atime, &statbuf->st_atime);
        err |= put_user(0, &statbuf->__unused1);
-       err |= put_user(mtime, &statbuf->st_mtime);
+       err |= put_user(stat->mtime, &statbuf->st_mtime);
        err |= put_user(0, &statbuf->__unused2);
-       err |= put_user(ctime, &statbuf->st_ctime);
+       err |= put_user(stat->ctime, &statbuf->st_ctime);
        err |= put_user(0, &statbuf->__unused3);
-       if (blksize) {
-               err |= put_user(blksize, &statbuf->st_blksize);
-               err |= put_user(blocks, &statbuf->st_blocks);
-       } else {
-               unsigned int tmp_blocks;
-
-#define D_B   7
-#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
-               tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-               if (tmp_blocks > D_B) {
-                       unsigned int indirect;
-
-                       indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
-                       tmp_blocks += indirect;
-                       if (indirect > 1) {
-                               indirect = (indirect - 1 + I_B - 1) / I_B;
-                               tmp_blocks += indirect;
-                               if (indirect > 1)
-                                       tmp_blocks++;
-                       }
-               }
-               err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
-               err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
-#undef D_B
-#undef I_B
-       }
+       err |= put_user(stat->blksize, &statbuf->st_blksize);
+       err |= put_user(stat->blocks, &statbuf->st_blocks);
        err |= put_user(0, &statbuf->__unused4[0]);
        err |= put_user(0, &statbuf->__unused4[1]);
-
        return err;
 }
 
-/* Perhaps this belongs in fs.h or similar. -DaveM */
-static __inline__ int
-do_revalidate(struct dentry *dentry)
-{
-       struct inode * inode = dentry->d_inode;
-       if (inode->i_op && inode->i_op->revalidate)
-               return inode->i_op->revalidate(dentry);
-       return 0;
-}
-
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_stat(filename, &stat);
+
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-       error = user_path_walk(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
-               path_release(&nd);
-       }
        return error;
 }
 
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-       struct nameidata nd;
-       int error;
+       struct kstat stat;
+       int error = vfs_lstat(filename, &stat);
 
-       error = user_path_walk_link(filename, &nd);
-       if (!error) {
-               error = do_revalidate(nd.dentry);
-               if (!error)
-                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-               path_release(&nd);
-       }
        return error;
 }
 
 asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
 {
-       struct file *f;
-       int err = -EBADF;
+       struct kstat stat;
+       int error = vfs_fstat(fd, &stat);
 
-       f = fget(fd);
-       if (f) {
-               struct dentry * dentry = f->f_dentry;
+       if (!error)
+               error = cp_new_stat32(&stat, statbuf);
 
-               err = do_revalidate(dentry);
-               if (!err)
-                       err = cp_new_stat32(dentry->d_inode, statbuf);
-               fput(f);
-       }
-       return err;
+       return error;
 }
 
 extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);