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