summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/Locking3
-rw-r--r--Documentation/filesystems/vfs.txt3
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl1
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl1
-rw-r--r--drivers/base/devtmpfs.c3
-rw-r--r--drivers/block/loop.c3
-rw-r--r--drivers/mtd/ubi/build.c2
-rw-r--r--drivers/mtd/ubi/kapi.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/file.c9
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_internal.h3
-rw-r--r--fs/9p/vfs_inode.c10
-rw-r--r--fs/9p/vfs_inode_dotl.c5
-rw-r--r--fs/afs/inode.c8
-rw-r--r--fs/afs/internal.h2
-rw-r--r--fs/bad_inode.c4
-rw-r--r--fs/btrfs/inode.c6
-rw-r--r--fs/ceph/inode.c6
-rw-r--r--fs/ceph/super.h4
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/inode.c5
-rw-r--r--fs/coda/coda_linux.h2
-rw-r--r--fs/coda/inode.c7
-rw-r--r--fs/ecryptfs/inode.c13
-rw-r--r--fs/exportfs/expfs.c3
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/inode.c6
-rw-r--r--fs/f2fs/f2fs.h4
-rw-r--r--fs/f2fs/file.c6
-rw-r--r--fs/fat/fat.h4
-rw-r--r--fs/fat/file.c5
-rw-r--r--fs/fuse/dir.c6
-rw-r--r--fs/gfs2/inode.c11
-rw-r--r--fs/kernfs/inode.c8
-rw-r--r--fs/kernfs/kernfs-internal.h4
-rw-r--r--fs/libfs.c12
-rw-r--r--fs/minix/inode.c11
-rw-r--r--fs/minix/minix.h2
-rw-r--r--fs/nfs/inode.c13
-rw-r--r--fs/nfs/namespace.c9
-rw-r--r--fs/nfsd/nfs4xdr.c4
-rw-r--r--fs/nfsd/vfs.h3
-rw-r--r--fs/ocfs2/file.c11
-rw-r--r--fs/ocfs2/file.h4
-rw-r--r--fs/orangefs/inode.c13
-rw-r--r--fs/orangefs/orangefs-kernel.h5
-rw-r--r--fs/overlayfs/copy_up.c6
-rw-r--r--fs/overlayfs/dir.c10
-rw-r--r--fs/overlayfs/inode.c7
-rw-r--r--fs/proc/base.c12
-rw-r--r--fs/proc/generic.c6
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/proc_net.c6
-rw-r--r--fs/proc/proc_sysctl.c5
-rw-r--r--fs/proc/root.c6
-rw-r--r--fs/stat.c214
-rw-r--r--fs/sysv/itree.c7
-rw-r--r--fs/sysv/sysv.h2
-rw-r--r--fs/ubifs/dir.c6
-rw-r--r--fs/ubifs/ubifs.h4
-rw-r--r--fs/udf/symlink.c5
-rw-r--r--fs/xfs/xfs_iops.c9
-rw-r--r--include/linux/fs.h35
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/stat.h24
-rw-r--r--include/linux/syscalls.h3
-rw-r--r--include/uapi/linux/fcntl.h5
-rw-r--r--include/uapi/linux/stat.h131
-rw-r--r--mm/shmem.c6
-rw-r--r--samples/Kconfig6
-rw-r--r--samples/Makefile2
-rw-r--r--samples/statx/Makefile10
-rw-r--r--samples/statx/test-statx.c254
72 files changed, 822 insertions, 214 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index ace63cd7af8c..fdcfdd79682a 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -58,7 +58,8 @@ prototypes:
58 int (*permission) (struct inode *, int, unsigned int); 58 int (*permission) (struct inode *, int, unsigned int);
59 int (*get_acl)(struct inode *, int); 59 int (*get_acl)(struct inode *, int);
60 int (*setattr) (struct dentry *, struct iattr *); 60 int (*setattr) (struct dentry *, struct iattr *);
61 int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *); 61 int (*getattr) (const struct path *, struct dentry *, struct kstat *,
62 u32, unsigned int);
62 ssize_t (*listxattr) (struct dentry *, char *, size_t); 63 ssize_t (*listxattr) (struct dentry *, char *, size_t);
63 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); 64 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
64 void (*update_time)(struct inode *, struct timespec *, int); 65 void (*update_time)(struct inode *, struct timespec *, int);
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index b968084eeac1..569211703721 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -382,7 +382,8 @@ struct inode_operations {
382 int (*permission) (struct inode *, int); 382 int (*permission) (struct inode *, int);
383 int (*get_acl)(struct inode *, int); 383 int (*get_acl)(struct inode *, int);
384 int (*setattr) (struct dentry *, struct iattr *); 384 int (*setattr) (struct dentry *, struct iattr *);
385 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 385 int (*getattr) (const struct path *, struct dentry *, struct kstat *,
386 u32, unsigned int);
386 ssize_t (*listxattr) (struct dentry *, char *, size_t); 387 ssize_t (*listxattr) (struct dentry *, char *, size_t);
387 void (*update_time)(struct inode *, struct timespec *, int); 388 void (*update_time)(struct inode *, struct timespec *, int);
388 int (*atomic_open)(struct inode *, struct dentry *, struct file *, 389 int (*atomic_open)(struct inode *, struct dentry *, struct file *,
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 2b3618542544..9ba050fe47f3 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -389,3 +389,4 @@
389380 i386 pkey_mprotect sys_pkey_mprotect 389380 i386 pkey_mprotect sys_pkey_mprotect
390381 i386 pkey_alloc sys_pkey_alloc 390381 i386 pkey_alloc sys_pkey_alloc
391382 i386 pkey_free sys_pkey_free 391382 i386 pkey_free sys_pkey_free
392383 i386 statx sys_statx
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index e93ef0b38db8..5aef183e2f85 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -338,6 +338,7 @@
338329 common pkey_mprotect sys_pkey_mprotect 338329 common pkey_mprotect sys_pkey_mprotect
339330 common pkey_alloc sys_pkey_alloc 339330 common pkey_alloc sys_pkey_alloc
340331 common pkey_free sys_pkey_free 340331 common pkey_free sys_pkey_free
341332 common statx sys_statx
341 342
342# 343#
343# x32-specific system call numbers start at 512 to avoid cache impact 344# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 44a74cf1372c..d2fb9c8ed205 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -309,7 +309,8 @@ static int handle_remove(const char *nodename, struct device *dev)
309 if (d_really_is_positive(dentry)) { 309 if (d_really_is_positive(dentry)) {
310 struct kstat stat; 310 struct kstat stat;
311 struct path p = {.mnt = parent.mnt, .dentry = dentry}; 311 struct path p = {.mnt = parent.mnt, .dentry = dentry};
312 err = vfs_getattr(&p, &stat); 312 err = vfs_getattr(&p, &stat, STATX_TYPE | STATX_MODE,
313 AT_STATX_SYNC_AS_STAT);
313 if (!err && dev_mynode(dev, d_inode(dentry), &stat)) { 314 if (!err && dev_mynode(dev, d_inode(dentry), &stat)) {
314 struct iattr newattrs; 315 struct iattr newattrs;
315 /* 316 /*
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index eeb1db73f44e..8f4051999741 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1175,7 +1175,8 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
1175 1175
1176 if (lo->lo_state != Lo_bound) 1176 if (lo->lo_state != Lo_bound)
1177 return -ENXIO; 1177 return -ENXIO;
1178 error = vfs_getattr(&file->f_path, &stat); 1178 error = vfs_getattr(&file->f_path, &stat,
1179 STATX_INO, AT_STATX_SYNC_AS_STAT);
1179 if (error) 1180 if (error)
1180 return error; 1181 return error;
1181 memset(info, 0, sizeof(*info)); 1182 memset(info, 0, sizeof(*info));
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 85d54f37e28f..77513195f50e 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1159,7 +1159,7 @@ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
1159 if (err) 1159 if (err)
1160 return ERR_PTR(err); 1160 return ERR_PTR(err);
1161 1161
1162 err = vfs_getattr(&path, &stat); 1162 err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
1163 path_put(&path); 1163 path_put(&path);
1164 if (err) 1164 if (err)
1165 return ERR_PTR(err); 1165 return ERR_PTR(err);
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 88b1897aeb40..d4b2e8744498 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -314,7 +314,7 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
314 if (error) 314 if (error)
315 return ERR_PTR(error); 315 return ERR_PTR(error);
316 316
317 error = vfs_getattr(&path, &stat); 317 error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
318 path_put(&path); 318 path_put(&path);
319 if (error) 319 if (error)
320 return ERR_PTR(error); 320 return ERR_PTR(error);
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index 10adfcdd7035..481c0d01d4c6 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -2952,15 +2952,16 @@ static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
2952 return rc; 2952 return rc;
2953} 2953}
2954 2954
2955int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) 2955int ll_getattr(const struct path *path, struct kstat *stat,
2956 u32 request_mask, unsigned int flags)
2956{ 2957{
2957 struct inode *inode = d_inode(de); 2958 struct inode *inode = d_inode(path->dentry);
2958 struct ll_sb_info *sbi = ll_i2sbi(inode); 2959 struct ll_sb_info *sbi = ll_i2sbi(inode);
2959 struct ll_inode_info *lli = ll_i2info(inode); 2960 struct ll_inode_info *lli = ll_i2info(inode);
2960 int res; 2961 int res;
2961 2962
2962 res = ll_inode_revalidate(de, MDS_INODELOCK_UPDATE | 2963 res = ll_inode_revalidate(path->dentry,
2963 MDS_INODELOCK_LOOKUP); 2964 MDS_INODELOCK_UPDATE | MDS_INODELOCK_LOOKUP);
2964 ll_stats_ops_tally(sbi, LPROC_LL_GETATTR, 1); 2965 ll_stats_ops_tally(sbi, LPROC_LL_GETATTR, 1);
2965 2966
2966 if (res) 2967 if (res)
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index ecdfd0c29b7f..55f68acd85d1 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -750,7 +750,8 @@ int ll_file_open(struct inode *inode, struct file *file);
750int ll_file_release(struct inode *inode, struct file *file); 750int ll_file_release(struct inode *inode, struct file *file);
751int ll_release_openhandle(struct inode *, struct lookup_intent *); 751int ll_release_openhandle(struct inode *, struct lookup_intent *);
752int ll_md_real_close(struct inode *inode, fmode_t fmode); 752int ll_md_real_close(struct inode *inode, fmode_t fmode);
753int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); 753int ll_getattr(const struct path *path, struct kstat *stat,
754 u32 request_mask, unsigned int flags);
754struct posix_acl *ll_get_acl(struct inode *inode, int type); 755struct posix_acl *ll_get_acl(struct inode *inode, int type);
755int ll_migrate(struct inode *parent, struct file *file, int mdtidx, 756int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
756 const char *name, int namelen); 757 const char *name, int namelen);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index f4f4450119e4..f1d96233670c 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1047,16 +1047,18 @@ done:
1047 1047
1048/** 1048/**
1049 * v9fs_vfs_getattr - retrieve file metadata 1049 * v9fs_vfs_getattr - retrieve file metadata
1050 * @mnt: mount information 1050 * @path: Object to query
1051 * @dentry: file to get attributes on
1052 * @stat: metadata structure to populate 1051 * @stat: metadata structure to populate
1052 * @request_mask: Mask of STATX_xxx flags indicating the caller's interests
1053 * @flags: AT_STATX_xxx setting
1053 * 1054 *
1054 */ 1055 */
1055 1056
1056static int 1057static int
1057v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1058v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
1058 struct kstat *stat) 1059 u32 request_mask, unsigned int flags)
1059{ 1060{
1061 struct dentry *dentry = path->dentry;
1060 struct v9fs_session_info *v9ses; 1062 struct v9fs_session_info *v9ses;
1061 struct p9_fid *fid; 1063 struct p9_fid *fid;
1062 struct p9_wstat *st; 1064 struct p9_wstat *st;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 5999bd050678..570e63ee5b71 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -468,9 +468,10 @@ error:
468} 468}
469 469
470static int 470static int
471v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, 471v9fs_vfs_getattr_dotl(const struct path *path, struct kstat *stat,
472 struct kstat *stat) 472 u32 request_mask, unsigned int flags)
473{ 473{
474 struct dentry *dentry = path->dentry;
474 struct v9fs_session_info *v9ses; 475 struct v9fs_session_info *v9ses;
475 struct p9_fid *fid; 476 struct p9_fid *fid;
476 struct p9_stat_dotl *st; 477 struct p9_stat_dotl *st;
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 86cc7264c21c..1e4897a048d2 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -375,12 +375,10 @@ error_unlock:
375/* 375/*
376 * read the attributes of an inode 376 * read the attributes of an inode
377 */ 377 */
378int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, 378int afs_getattr(const struct path *path, struct kstat *stat,
379 struct kstat *stat) 379 u32 request_mask, unsigned int query_flags)
380{ 380{
381 struct inode *inode; 381 struct inode *inode = d_inode(path->dentry);
382
383 inode = d_inode(dentry);
384 382
385 _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation); 383 _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
386 384
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 8acf3670e756..5dfa56903a2d 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -533,7 +533,7 @@ extern struct inode *afs_iget(struct super_block *, struct key *,
533 struct afs_callback *); 533 struct afs_callback *);
534extern void afs_zap_data(struct afs_vnode *); 534extern void afs_zap_data(struct afs_vnode *);
535extern int afs_validate(struct afs_vnode *, struct key *); 535extern int afs_validate(struct afs_vnode *, struct key *);
536extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 536extern int afs_getattr(const struct path *, struct kstat *, u32, unsigned int);
537extern int afs_setattr(struct dentry *, struct iattr *); 537extern int afs_setattr(struct dentry *, struct iattr *);
538extern void afs_evict_inode(struct inode *); 538extern void afs_evict_inode(struct inode *);
539extern int afs_drop_inode(struct inode *); 539extern int afs_drop_inode(struct inode *);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 5f685c819298..bb53728c7a31 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -89,8 +89,8 @@ static int bad_inode_permission(struct inode *inode, int mask)
89 return -EIO; 89 return -EIO;
90} 90}
91 91
92static int bad_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, 92static int bad_inode_getattr(const struct path *path, struct kstat *stat,
93 struct kstat *stat) 93 u32 request_mask, unsigned int query_flags)
94{ 94{
95 return -EIO; 95 return -EIO;
96} 96}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ee6978d80491..c40060cc481f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -9413,11 +9413,11 @@ fail:
9413 return -ENOMEM; 9413 return -ENOMEM;
9414} 9414}
9415 9415
9416static int btrfs_getattr(struct vfsmount *mnt, 9416static int btrfs_getattr(const struct path *path, struct kstat *stat,
9417 struct dentry *dentry, struct kstat *stat) 9417 u32 request_mask, unsigned int flags)
9418{ 9418{
9419 u64 delalloc_bytes; 9419 u64 delalloc_bytes;
9420 struct inode *inode = d_inode(dentry); 9420 struct inode *inode = d_inode(path->dentry);
9421 u32 blocksize = inode->i_sb->s_blocksize; 9421 u32 blocksize = inode->i_sb->s_blocksize;
9422 9422
9423 generic_fillattr(inode, stat); 9423 generic_fillattr(inode, stat);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index fd8f771f99b7..d449e1c03cbd 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2187,10 +2187,10 @@ int ceph_permission(struct inode *inode, int mask)
2187 * Get all attributes. Hopefully somedata we'll have a statlite() 2187 * Get all attributes. Hopefully somedata we'll have a statlite()
2188 * and can limit the fields we require to be accurate. 2188 * and can limit the fields we require to be accurate.
2189 */ 2189 */
2190int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, 2190int ceph_getattr(const struct path *path, struct kstat *stat,
2191 struct kstat *stat) 2191 u32 request_mask, unsigned int flags)
2192{ 2192{
2193 struct inode *inode = d_inode(dentry); 2193 struct inode *inode = d_inode(path->dentry);
2194 struct ceph_inode_info *ci = ceph_inode(inode); 2194 struct ceph_inode_info *ci = ceph_inode(inode);
2195 int err; 2195 int err;
2196 2196
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index e9410bcf4113..fe6b9cfc4013 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -784,8 +784,8 @@ static inline int ceph_do_getattr(struct inode *inode, int mask, bool force)
784extern int ceph_permission(struct inode *inode, int mask); 784extern int ceph_permission(struct inode *inode, int mask);
785extern int __ceph_setattr(struct inode *inode, struct iattr *attr); 785extern int __ceph_setattr(struct inode *inode, struct iattr *attr);
786extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); 786extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
787extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, 787extern int ceph_getattr(const struct path *path, struct kstat *stat,
788 struct kstat *stat); 788 u32 request_mask, unsigned int flags);
789 789
790/* xattr.c */ 790/* xattr.c */
791int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int); 791int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index c9c00a862036..da717fee3026 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -83,7 +83,7 @@ extern int cifs_revalidate_dentry(struct dentry *);
83extern int cifs_invalidate_mapping(struct inode *inode); 83extern int cifs_invalidate_mapping(struct inode *inode);
84extern int cifs_revalidate_mapping(struct inode *inode); 84extern int cifs_revalidate_mapping(struct inode *inode);
85extern int cifs_zap_mapping(struct inode *inode); 85extern int cifs_zap_mapping(struct inode *inode);
86extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 86extern int cifs_getattr(const struct path *, struct kstat *, u32, unsigned int);
87extern int cifs_setattr(struct dentry *, struct iattr *); 87extern int cifs_setattr(struct dentry *, struct iattr *);
88 88
89extern const struct inode_operations cifs_file_inode_ops; 89extern const struct inode_operations cifs_file_inode_ops;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 7ab5be7944aa..1363fff460b9 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1990,9 +1990,10 @@ int cifs_revalidate_dentry(struct dentry *dentry)
1990 return cifs_revalidate_mapping(inode); 1990 return cifs_revalidate_mapping(inode);
1991} 1991}
1992 1992
1993int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1993int cifs_getattr(const struct path *path, struct kstat *stat,
1994 struct kstat *stat) 1994 u32 request_mask, unsigned int flags)
1995{ 1995{
1996 struct dentry *dentry = path->dentry;
1996 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); 1997 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
1997 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 1998 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
1998 struct inode *inode = d_inode(dentry); 1999 struct inode *inode = d_inode(dentry);
diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
index 5104d84c4f64..d3c361883c28 100644
--- a/fs/coda/coda_linux.h
+++ b/fs/coda/coda_linux.h
@@ -47,7 +47,7 @@ int coda_open(struct inode *i, struct file *f);
47int coda_release(struct inode *i, struct file *f); 47int coda_release(struct inode *i, struct file *f);
48int coda_permission(struct inode *inode, int mask); 48int coda_permission(struct inode *inode, int mask);
49int coda_revalidate_inode(struct inode *); 49int coda_revalidate_inode(struct inode *);
50int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); 50int coda_getattr(const struct path *, struct kstat *, u32, unsigned int);
51int coda_setattr(struct dentry *, struct iattr *); 51int coda_setattr(struct dentry *, struct iattr *);
52 52
53/* this file: heloers */ 53/* this file: heloers */
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 71dbe7e287ce..2dea594da199 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -255,11 +255,12 @@ static void coda_evict_inode(struct inode *inode)
255 coda_cache_clear_inode(inode); 255 coda_cache_clear_inode(inode);
256} 256}
257 257
258int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 258int coda_getattr(const struct path *path, struct kstat *stat,
259 u32 request_mask, unsigned int flags)
259{ 260{
260 int err = coda_revalidate_inode(d_inode(dentry)); 261 int err = coda_revalidate_inode(d_inode(path->dentry));
261 if (!err) 262 if (!err)
262 generic_fillattr(d_inode(dentry), stat); 263 generic_fillattr(d_inode(path->dentry), stat);
263 return err; 264 return err;
264} 265}
265 266
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index e7413f82d27b..efc2db42d175 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -959,9 +959,10 @@ out:
959 return rc; 959 return rc;
960} 960}
961 961
962static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry, 962static int ecryptfs_getattr_link(const struct path *path, struct kstat *stat,
963 struct kstat *stat) 963 u32 request_mask, unsigned int flags)
964{ 964{
965 struct dentry *dentry = path->dentry;
965 struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 966 struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
966 int rc = 0; 967 int rc = 0;
967 968
@@ -983,13 +984,15 @@ static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
983 return rc; 984 return rc;
984} 985}
985 986
986static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 987static int ecryptfs_getattr(const struct path *path, struct kstat *stat,
987 struct kstat *stat) 988 u32 request_mask, unsigned int flags)
988{ 989{
990 struct dentry *dentry = path->dentry;
989 struct kstat lower_stat; 991 struct kstat lower_stat;
990 int rc; 992 int rc;
991 993
992 rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat); 994 rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat,
995 request_mask, flags);
993 if (!rc) { 996 if (!rc) {
994 fsstack_copy_attr_all(d_inode(dentry), 997 fsstack_copy_attr_all(d_inode(dentry),
995 ecryptfs_inode_to_lower(d_inode(dentry))); 998 ecryptfs_inode_to_lower(d_inode(dentry)));
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index a4b531be9168..f2d24bb8d745 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -299,7 +299,8 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
299 * filesystem supports 64-bit inode numbers. So we need to 299 * filesystem supports 64-bit inode numbers. So we need to
300 * actually call ->getattr, not just read i_ino: 300 * actually call ->getattr, not just read i_ino:
301 */ 301 */
302 error = vfs_getattr_nosec(&child_path, &stat); 302 error = vfs_getattr_nosec(&child_path, &stat,
303 STATX_INO, AT_STATX_SYNC_AS_STAT);
303 if (error) 304 if (error)
304 return error; 305 return error;
305 buffer.ino = stat.ino; 306 buffer.ino = stat.ino;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 2fd17e8e4984..025d2e85f454 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2462,8 +2462,7 @@ extern struct inode *ext4_iget(struct super_block *, unsigned long);
2462extern struct inode *ext4_iget_normal(struct super_block *, unsigned long); 2462extern struct inode *ext4_iget_normal(struct super_block *, unsigned long);
2463extern int ext4_write_inode(struct inode *, struct writeback_control *); 2463extern int ext4_write_inode(struct inode *, struct writeback_control *);
2464extern int ext4_setattr(struct dentry *, struct iattr *); 2464extern int ext4_setattr(struct dentry *, struct iattr *);
2465extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, 2465extern int ext4_getattr(const struct path *, struct kstat *, u32, unsigned int);
2466 struct kstat *stat);
2467extern void ext4_evict_inode(struct inode *); 2466extern void ext4_evict_inode(struct inode *);
2468extern void ext4_clear_inode(struct inode *); 2467extern void ext4_clear_inode(struct inode *);
2469extern int ext4_sync_inode(handle_t *, struct inode *); 2468extern int ext4_sync_inode(handle_t *, struct inode *);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 971f66342080..7385e6a6b6cb 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5387,13 +5387,13 @@ err_out:
5387 return error; 5387 return error;
5388} 5388}
5389 5389
5390int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, 5390int ext4_getattr(const struct path *path, struct kstat *stat,
5391 struct kstat *stat) 5391 u32 request_mask, unsigned int query_flags)
5392{ 5392{
5393 struct inode *inode; 5393 struct inode *inode;
5394 unsigned long long delalloc_blocks; 5394 unsigned long long delalloc_blocks;
5395 5395
5396 inode = d_inode(dentry); 5396 inode = d_inode(path->dentry);
5397 generic_fillattr(inode, stat); 5397 generic_fillattr(inode, stat);
5398 5398
5399 /* 5399 /*
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d1483136fed6..e849f83d6114 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2040,8 +2040,8 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
2040void truncate_data_blocks(struct dnode_of_data *dn); 2040void truncate_data_blocks(struct dnode_of_data *dn);
2041int truncate_blocks(struct inode *inode, u64 from, bool lock); 2041int truncate_blocks(struct inode *inode, u64 from, bool lock);
2042int f2fs_truncate(struct inode *inode); 2042int f2fs_truncate(struct inode *inode);
2043int f2fs_getattr(struct vfsmount *mnt, struct dentry *dentry, 2043int f2fs_getattr(const struct path *path, struct kstat *stat,
2044 struct kstat *stat); 2044 u32 request_mask, unsigned int flags);
2045int f2fs_setattr(struct dentry *dentry, struct iattr *attr); 2045int f2fs_setattr(struct dentry *dentry, struct iattr *attr);
2046int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end); 2046int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end);
2047int truncate_data_blocks_range(struct dnode_of_data *dn, int count); 2047int truncate_data_blocks_range(struct dnode_of_data *dn, int count);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 78e65288f2b2..5f7317875a67 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -633,10 +633,10 @@ int f2fs_truncate(struct inode *inode)
633 return 0; 633 return 0;
634} 634}
635 635
636int f2fs_getattr(struct vfsmount *mnt, 636int f2fs_getattr(const struct path *path, struct kstat *stat,
637 struct dentry *dentry, struct kstat *stat) 637 u32 request_mask, unsigned int flags)
638{ 638{
639 struct inode *inode = d_inode(dentry); 639 struct inode *inode = d_inode(path->dentry);
640 generic_fillattr(inode, stat); 640 generic_fillattr(inode, stat);
641 stat->blocks <<= 3; 641 stat->blocks <<= 3;
642 return 0; 642 return 0;
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index e6b764a17a9c..051dac1ce3be 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -364,8 +364,8 @@ extern const struct file_operations fat_file_operations;
364extern const struct inode_operations fat_file_inode_operations; 364extern const struct inode_operations fat_file_inode_operations;
365extern int fat_setattr(struct dentry *dentry, struct iattr *attr); 365extern int fat_setattr(struct dentry *dentry, struct iattr *attr);
366extern void fat_truncate_blocks(struct inode *inode, loff_t offset); 366extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
367extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, 367extern int fat_getattr(const struct path *path, struct kstat *stat,
368 struct kstat *stat); 368 u32 request_mask, unsigned int flags);
369extern int fat_file_fsync(struct file *file, loff_t start, loff_t end, 369extern int fat_file_fsync(struct file *file, loff_t start, loff_t end,
370 int datasync); 370 int datasync);
371 371
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 3d04b124bce0..4724cc9ad650 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -365,9 +365,10 @@ void fat_truncate_blocks(struct inode *inode, loff_t offset)
365 fat_flush_inodes(inode->i_sb, inode, NULL); 365 fat_flush_inodes(inode->i_sb, inode, NULL);
366} 366}
367 367
368int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 368int fat_getattr(const struct path *path, struct kstat *stat,
369 u32 request_mask, unsigned int flags)
369{ 370{
370 struct inode *inode = d_inode(dentry); 371 struct inode *inode = d_inode(path->dentry);
371 generic_fillattr(inode, stat); 372 generic_fillattr(inode, stat);
372 stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size; 373 stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
373 374
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 811fd8929a18..beb3d64f16e2 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1777,10 +1777,10 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1777 return ret; 1777 return ret;
1778} 1778}
1779 1779
1780static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1780static int fuse_getattr(const struct path *path, struct kstat *stat,
1781 struct kstat *stat) 1781 u32 request_mask, unsigned int flags)
1782{ 1782{
1783 struct inode *inode = d_inode(entry); 1783 struct inode *inode = d_inode(path->dentry);
1784 struct fuse_conn *fc = get_fuse_conn(inode); 1784 struct fuse_conn *fc = get_fuse_conn(inode);
1785 1785
1786 if (!fuse_allow_current_process(fc)) 1786 if (!fuse_allow_current_process(fc))
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index eb7724b8578a..288c15f385bd 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1959,9 +1959,10 @@ out:
1959 1959
1960/** 1960/**
1961 * gfs2_getattr - Read out an inode's attributes 1961 * gfs2_getattr - Read out an inode's attributes
1962 * @mnt: The vfsmount the inode is being accessed from 1962 * @path: Object to query
1963 * @dentry: The dentry to stat
1964 * @stat: The inode's stats 1963 * @stat: The inode's stats
1964 * @request_mask: Mask of STATX_xxx flags indicating the caller's interests
1965 * @flags: AT_STATX_xxx setting
1965 * 1966 *
1966 * This may be called from the VFS directly, or from within GFS2 with the 1967 * This may be called from the VFS directly, or from within GFS2 with the
1967 * inode locked, so we look to see if the glock is already locked and only 1968 * inode locked, so we look to see if the glock is already locked and only
@@ -1972,10 +1973,10 @@ out:
1972 * Returns: errno 1973 * Returns: errno
1973 */ 1974 */
1974 1975
1975static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, 1976static int gfs2_getattr(const struct path *path, struct kstat *stat,
1976 struct kstat *stat) 1977 u32 request_mask, unsigned int flags)
1977{ 1978{
1978 struct inode *inode = d_inode(dentry); 1979 struct inode *inode = d_inode(path->dentry);
1979 struct gfs2_inode *ip = GFS2_I(inode); 1980 struct gfs2_inode *ip = GFS2_I(inode);
1980 struct gfs2_holder gh; 1981 struct gfs2_holder gh;
1981 int error; 1982 int error;
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index ac9e108ce1ea..fb4b4a79a0d6 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -200,11 +200,11 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
200 set_nlink(inode, kn->dir.subdirs + 2); 200 set_nlink(inode, kn->dir.subdirs + 2);
201} 201}
202 202
203int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, 203int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
204 struct kstat *stat) 204 u32 request_mask, unsigned int query_flags)
205{ 205{
206 struct kernfs_node *kn = dentry->d_fsdata; 206 struct kernfs_node *kn = path->dentry->d_fsdata;
207 struct inode *inode = d_inode(dentry); 207 struct inode *inode = d_inode(path->dentry);
208 208
209 mutex_lock(&kernfs_mutex); 209 mutex_lock(&kernfs_mutex);
210 kernfs_refresh_inode(kn, inode); 210 kernfs_refresh_inode(kn, inode);
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 3100987cf8ba..2d5144ab4251 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -80,8 +80,8 @@ extern const struct xattr_handler *kernfs_xattr_handlers[];
80void kernfs_evict_inode(struct inode *inode); 80void kernfs_evict_inode(struct inode *inode);
81int kernfs_iop_permission(struct inode *inode, int mask); 81int kernfs_iop_permission(struct inode *inode, int mask);
82int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr); 82int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
83int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, 83int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
84 struct kstat *stat); 84 u32 request_mask, unsigned int query_flags);
85ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); 85ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
86 86
87/* 87/*
diff --git a/fs/libfs.c b/fs/libfs.c
index 28d6f35feed6..1dfaf8f606c0 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -20,10 +20,10 @@
20 20
21#include "internal.h" 21#include "internal.h"
22 22
23int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, 23int simple_getattr(const struct path *path, struct kstat *stat,
24 struct kstat *stat) 24 u32 request_mask, unsigned int query_flags)
25{ 25{
26 struct inode *inode = d_inode(dentry); 26 struct inode *inode = d_inode(path->dentry);
27 generic_fillattr(inode, stat); 27 generic_fillattr(inode, stat);
28 stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9); 28 stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9);
29 return 0; 29 return 0;
@@ -1143,10 +1143,10 @@ static struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry,
1143 return ERR_PTR(-ENOENT); 1143 return ERR_PTR(-ENOENT);
1144} 1144}
1145 1145
1146static int empty_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, 1146static int empty_dir_getattr(const struct path *path, struct kstat *stat,
1147 struct kstat *stat) 1147 u32 request_mask, unsigned int query_flags)
1148{ 1148{
1149 struct inode *inode = d_inode(dentry); 1149 struct inode *inode = d_inode(path->dentry);
1150 generic_fillattr(inode, stat); 1150 generic_fillattr(inode, stat);
1151 return 0; 1151 return 0;
1152} 1152}
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index e7d9bf86d975..6ac76b0434e9 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -622,11 +622,14 @@ static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
622 return err; 622 return err;
623} 623}
624 624
625int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 625int minix_getattr(const struct path *path, struct kstat *stat,
626 u32 request_mask, unsigned int flags)
626{ 627{
627 struct super_block *sb = dentry->d_sb; 628 struct super_block *sb = path->dentry->d_sb;
628 generic_fillattr(d_inode(dentry), stat); 629 struct inode *inode = d_inode(path->dentry);
629 if (INODE_VERSION(d_inode(dentry)) == MINIX_V1) 630
631 generic_fillattr(inode, stat);
632 if (INODE_VERSION(inode) == MINIX_V1)
630 stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb); 633 stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
631 else 634 else
632 stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb); 635 stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index 01ad81dcacc5..663d66138d06 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -51,7 +51,7 @@ extern unsigned long minix_count_free_inodes(struct super_block *sb);
51extern int minix_new_block(struct inode * inode); 51extern int minix_new_block(struct inode * inode);
52extern void minix_free_block(struct inode *inode, unsigned long block); 52extern void minix_free_block(struct inode *inode, unsigned long block);
53extern unsigned long minix_count_free_blocks(struct super_block *sb); 53extern unsigned long minix_count_free_blocks(struct super_block *sb);
54extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *); 54extern int minix_getattr(const struct path *, struct kstat *, u32, unsigned int);
55extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len); 55extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len);
56 56
57extern void V1_minix_truncate(struct inode *); 57extern void V1_minix_truncate(struct inode *);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5ca4d96b1942..b5425315adcc 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -703,9 +703,10 @@ static bool nfs_need_revalidate_inode(struct inode *inode)
703 return false; 703 return false;
704} 704}
705 705
706int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 706int nfs_getattr(const struct path *path, struct kstat *stat,
707 u32 request_mask, unsigned int query_flags)
707{ 708{
708 struct inode *inode = d_inode(dentry); 709 struct inode *inode = d_inode(path->dentry);
709 int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; 710 int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
710 int err = 0; 711 int err = 0;
711 712
@@ -726,17 +727,17 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
726 * - NFS never sets MS_NOATIME or MS_NODIRATIME so there is 727 * - NFS never sets MS_NOATIME or MS_NODIRATIME so there is
727 * no point in checking those. 728 * no point in checking those.
728 */ 729 */
729 if ((mnt->mnt_flags & MNT_NOATIME) || 730 if ((path->mnt->mnt_flags & MNT_NOATIME) ||
730 ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))) 731 ((path->mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
731 need_atime = 0; 732 need_atime = 0;
732 733
733 if (need_atime || nfs_need_revalidate_inode(inode)) { 734 if (need_atime || nfs_need_revalidate_inode(inode)) {
734 struct nfs_server *server = NFS_SERVER(inode); 735 struct nfs_server *server = NFS_SERVER(inode);
735 736
736 nfs_readdirplus_parent_cache_miss(dentry); 737 nfs_readdirplus_parent_cache_miss(path->dentry);
737 err = __nfs_revalidate_inode(server, inode); 738 err = __nfs_revalidate_inode(server, inode);
738 } else 739 } else
739 nfs_readdirplus_parent_cache_hit(dentry); 740 nfs_readdirplus_parent_cache_hit(path->dentry);
740 if (!err) { 741 if (!err) {
741 generic_fillattr(inode, stat); 742 generic_fillattr(inode, stat);
742 stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); 743 stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index e49d831c4e85..786f17580582 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -178,11 +178,12 @@ out_nofree:
178} 178}
179 179
180static int 180static int
181nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 181nfs_namespace_getattr(const struct path *path, struct kstat *stat,
182 u32 request_mask, unsigned int query_flags)
182{ 183{
183 if (NFS_FH(d_inode(dentry))->size != 0) 184 if (NFS_FH(d_inode(path->dentry))->size != 0)
184 return nfs_getattr(mnt, dentry, stat); 185 return nfs_getattr(path, stat, request_mask, query_flags);
185 generic_fillattr(d_inode(dentry), stat); 186 generic_fillattr(d_inode(path->dentry), stat);
186 return 0; 187 return 0;
187} 188}
188 189
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 382c1fd05b4c..33017d652b1d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2301,7 +2301,7 @@ static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
2301 if (path.dentry != path.mnt->mnt_root) 2301 if (path.dentry != path.mnt->mnt_root)
2302 break; 2302 break;
2303 } 2303 }
2304 err = vfs_getattr(&path, stat); 2304 err = vfs_getattr(&path, stat, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
2305 path_put(&path); 2305 path_put(&path);
2306 return err; 2306 return err;
2307} 2307}
@@ -2385,7 +2385,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2385 goto out; 2385 goto out;
2386 } 2386 }
2387 2387
2388 err = vfs_getattr(&path, &stat); 2388 err = vfs_getattr(&path, &stat, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
2389 if (err) 2389 if (err)
2390 goto out_nfserr; 2390 goto out_nfserr;
2391 if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | 2391 if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index db98c48c735a..1bbdccecbf3d 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -135,7 +135,8 @@ static inline __be32 fh_getattr(struct svc_fh *fh, struct kstat *stat)
135{ 135{
136 struct path p = {.mnt = fh->fh_export->ex_path.mnt, 136 struct path p = {.mnt = fh->fh_export->ex_path.mnt,
137 .dentry = fh->fh_dentry}; 137 .dentry = fh->fh_dentry};
138 return nfserrno(vfs_getattr(&p, stat)); 138 return nfserrno(vfs_getattr(&p, stat, STATX_BASIC_STATS,
139 AT_STATX_SYNC_AS_STAT));
139} 140}
140 141
141static inline int nfsd_create_is_exclusive(int createmode) 142static inline int nfsd_create_is_exclusive(int createmode)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8836305eb378..bfeb647459d9 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1306,16 +1306,15 @@ bail:
1306 return status; 1306 return status;
1307} 1307}
1308 1308
1309int ocfs2_getattr(struct vfsmount *mnt, 1309int ocfs2_getattr(const struct path *path, struct kstat *stat,
1310 struct dentry *dentry, 1310 u32 request_mask, unsigned int flags)
1311 struct kstat *stat)
1312{ 1311{
1313 struct inode *inode = d_inode(dentry); 1312 struct inode *inode = d_inode(path->dentry);
1314 struct super_block *sb = dentry->d_sb; 1313 struct super_block *sb = path->dentry->d_sb;
1315 struct ocfs2_super *osb = sb->s_fs_info; 1314 struct ocfs2_super *osb = sb->s_fs_info;
1316 int err; 1315 int err;
1317 1316
1318 err = ocfs2_inode_revalidate(dentry); 1317 err = ocfs2_inode_revalidate(path->dentry);
1319 if (err) { 1318 if (err) {
1320 if (err != -ENOENT) 1319 if (err != -ENOENT)
1321 mlog_errno(err); 1320 mlog_errno(err);
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 897fd9a2e51d..1fdc9839cd93 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -68,8 +68,8 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh,
68int ocfs2_extend_allocation(struct inode *inode, u32 logical_start, 68int ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
69 u32 clusters_to_add, int mark_unwritten); 69 u32 clusters_to_add, int mark_unwritten);
70int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); 70int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
71int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, 71int ocfs2_getattr(const struct path *path, struct kstat *stat,
72 struct kstat *stat); 72 u32 request_mask, unsigned int flags);
73int ocfs2_permission(struct inode *inode, int mask); 73int ocfs2_permission(struct inode *inode, int mask);
74 74
75int ocfs2_should_update_atime(struct inode *inode, 75int ocfs2_should_update_atime(struct inode *inode,
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 5cd617980fbf..a304bf34b212 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -245,25 +245,24 @@ out:
245/* 245/*
246 * Obtain attributes of an object given a dentry 246 * Obtain attributes of an object given a dentry
247 */ 247 */
248int orangefs_getattr(struct vfsmount *mnt, 248int orangefs_getattr(const struct path *path, struct kstat *stat,
249 struct dentry *dentry, 249 u32 request_mask, unsigned int flags)
250 struct kstat *kstat)
251{ 250{
252 int ret = -ENOENT; 251 int ret = -ENOENT;
253 struct inode *inode = dentry->d_inode; 252 struct inode *inode = path->dentry->d_inode;
254 struct orangefs_inode_s *orangefs_inode = NULL; 253 struct orangefs_inode_s *orangefs_inode = NULL;
255 254
256 gossip_debug(GOSSIP_INODE_DEBUG, 255 gossip_debug(GOSSIP_INODE_DEBUG,
257 "orangefs_getattr: called on %pd\n", 256 "orangefs_getattr: called on %pd\n",
258 dentry); 257 path->dentry);
259 258
260 ret = orangefs_inode_getattr(inode, 0, 0); 259 ret = orangefs_inode_getattr(inode, 0, 0);
261 if (ret == 0) { 260 if (ret == 0) {
262 generic_fillattr(inode, kstat); 261 generic_fillattr(inode, stat);
263 262
264 /* override block size reported to stat */ 263 /* override block size reported to stat */
265 orangefs_inode = ORANGEFS_I(inode); 264 orangefs_inode = ORANGEFS_I(inode);
266 kstat->blksize = orangefs_inode->blksize; 265 stat->blksize = orangefs_inode->blksize;
267 } 266 }
268 return ret; 267 return ret;
269} 268}
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 70355a9a2596..0c4f03c22ce0 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -439,9 +439,8 @@ struct inode *orangefs_new_inode(struct super_block *sb,
439 439
440int orangefs_setattr(struct dentry *dentry, struct iattr *iattr); 440int orangefs_setattr(struct dentry *dentry, struct iattr *iattr);
441 441
442int orangefs_getattr(struct vfsmount *mnt, 442int orangefs_getattr(const struct path *path, struct kstat *stat,
443 struct dentry *dentry, 443 u32 request_mask, unsigned int flags);
444 struct kstat *kstat);
445 444
446int orangefs_permission(struct inode *inode, int mask); 445int orangefs_permission(struct inode *inode, int mask);
447 446
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index f57043dace62..a6f9ca621e0b 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -346,7 +346,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
346 ovl_path_upper(parent, &parentpath); 346 ovl_path_upper(parent, &parentpath);
347 upperdir = parentpath.dentry; 347 upperdir = parentpath.dentry;
348 348
349 err = vfs_getattr(&parentpath, &pstat); 349 err = vfs_getattr(&parentpath, &pstat,
350 STATX_ATIME | STATX_MTIME, AT_STATX_SYNC_AS_STAT);
350 if (err) 351 if (err)
351 return err; 352 return err;
352 353
@@ -409,7 +410,8 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
409 } 410 }
410 411
411 ovl_path_lower(next, &lowerpath); 412 ovl_path_lower(next, &lowerpath);
412 err = vfs_getattr(&lowerpath, &stat); 413 err = vfs_getattr(&lowerpath, &stat,
414 STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
413 /* maybe truncate regular file. this has no effect on dirs */ 415 /* maybe truncate regular file. this has no effect on dirs */
414 if (flags & O_TRUNC) 416 if (flags & O_TRUNC)
415 stat.size = 0; 417 stat.size = 0;
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 16e06dd89457..6515796460df 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -138,9 +138,10 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
138 return err; 138 return err;
139} 139}
140 140
141static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, 141static int ovl_dir_getattr(const struct path *path, struct kstat *stat,
142 struct kstat *stat) 142 u32 request_mask, unsigned int flags)
143{ 143{
144 struct dentry *dentry = path->dentry;
144 int err; 145 int err;
145 enum ovl_path_type type; 146 enum ovl_path_type type;
146 struct path realpath; 147 struct path realpath;
@@ -148,7 +149,7 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
148 149
149 type = ovl_path_real(dentry, &realpath); 150 type = ovl_path_real(dentry, &realpath);
150 old_cred = ovl_override_creds(dentry->d_sb); 151 old_cred = ovl_override_creds(dentry->d_sb);
151 err = vfs_getattr(&realpath, stat); 152 err = vfs_getattr(&realpath, stat, request_mask, flags);
152 revert_creds(old_cred); 153 revert_creds(old_cred);
153 if (err) 154 if (err)
154 return err; 155 return err;
@@ -264,7 +265,8 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
264 goto out; 265 goto out;
265 266
266 ovl_path_upper(dentry, &upperpath); 267 ovl_path_upper(dentry, &upperpath);
267 err = vfs_getattr(&upperpath, &stat); 268 err = vfs_getattr(&upperpath, &stat,
269 STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
268 if (err) 270 if (err)
269 goto out_unlock; 271 goto out_unlock;
270 272
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 08643ac44a02..d4bb54f7b6b4 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -56,16 +56,17 @@ out:
56 return err; 56 return err;
57} 57}
58 58
59static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, 59static int ovl_getattr(const struct path *path, struct kstat *stat,
60 struct kstat *stat) 60 u32 request_mask, unsigned int flags)
61{ 61{
62 struct dentry *dentry = path->dentry;
62 struct path realpath; 63 struct path realpath;
63 const struct cred *old_cred; 64 const struct cred *old_cred;
64 int err; 65 int err;
65 66
66 ovl_path_real(dentry, &realpath); 67 ovl_path_real(dentry, &realpath);
67 old_cred = ovl_override_creds(dentry->d_sb); 68 old_cred = ovl_override_creds(dentry->d_sb);
68 err = vfs_getattr(&realpath, stat); 69 err = vfs_getattr(&realpath, stat, request_mask, flags);
69 revert_creds(old_cred); 70 revert_creds(old_cred);
70 return err; 71 return err;
71} 72}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1e1e182d571b..3b5e6aa2a326 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1724,11 +1724,12 @@ out_unlock:
1724 return NULL; 1724 return NULL;
1725} 1725}
1726 1726
1727int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 1727int pid_getattr(const struct path *path, struct kstat *stat,
1728 u32 request_mask, unsigned int query_flags)
1728{ 1729{
1729 struct inode *inode = d_inode(dentry); 1730 struct inode *inode = d_inode(path->dentry);
1730 struct task_struct *task; 1731 struct task_struct *task;
1731 struct pid_namespace *pid = dentry->d_sb->s_fs_info; 1732 struct pid_namespace *pid = path->dentry->d_sb->s_fs_info;
1732 1733
1733 generic_fillattr(inode, stat); 1734 generic_fillattr(inode, stat);
1734 1735
@@ -3511,9 +3512,10 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
3511 return 0; 3512 return 0;
3512} 3513}
3513 3514
3514static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 3515static int proc_task_getattr(const struct path *path, struct kstat *stat,
3516 u32 request_mask, unsigned int query_flags)
3515{ 3517{
3516 struct inode *inode = d_inode(dentry); 3518 struct inode *inode = d_inode(path->dentry);
3517 struct task_struct *p = get_proc_task(inode); 3519 struct task_struct *p = get_proc_task(inode);
3518 generic_fillattr(inode, stat); 3520 generic_fillattr(inode, stat);
3519 3521
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 06c73904d497..ee27feb34cf4 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -118,10 +118,10 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
118 return 0; 118 return 0;
119} 119}
120 120
121static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry, 121static int proc_getattr(const struct path *path, struct kstat *stat,
122 struct kstat *stat) 122 u32 request_mask, unsigned int query_flags)
123{ 123{
124 struct inode *inode = d_inode(dentry); 124 struct inode *inode = d_inode(path->dentry);
125 struct proc_dir_entry *de = PDE(inode); 125 struct proc_dir_entry *de = PDE(inode);
126 if (de && de->nlink) 126 if (de && de->nlink)
127 set_nlink(inode, de->nlink); 127 set_nlink(inode, de->nlink);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 5d6960f5f1c0..e93cdc6ddb31 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -149,7 +149,7 @@ extern int proc_pid_statm(struct seq_file *, struct pid_namespace *,
149 * base.c 149 * base.c
150 */ 150 */
151extern const struct dentry_operations pid_dentry_operations; 151extern const struct dentry_operations pid_dentry_operations;
152extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *); 152extern int pid_getattr(const struct path *, struct kstat *, u32, unsigned int);
153extern int proc_setattr(struct dentry *, struct iattr *); 153extern int proc_setattr(struct dentry *, struct iattr *);
154extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t); 154extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t);
155extern int pid_revalidate(struct dentry *, unsigned int); 155extern int pid_revalidate(struct dentry *, unsigned int);
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index ffd72a6c6e04..9db1df2537fc 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -140,10 +140,10 @@ static struct dentry *proc_tgid_net_lookup(struct inode *dir,
140 return de; 140 return de;
141} 141}
142 142
143static int proc_tgid_net_getattr(struct vfsmount *mnt, struct dentry *dentry, 143static int proc_tgid_net_getattr(const struct path *path, struct kstat *stat,
144 struct kstat *stat) 144 u32 request_mask, unsigned int query_flags)
145{ 145{
146 struct inode *inode = d_inode(dentry); 146 struct inode *inode = d_inode(path->dentry);
147 struct net *net; 147 struct net *net;
148 148
149 net = get_proc_task_net(inode); 149 net = get_proc_task_net(inode);
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 3e64c6502dc8..3d8726445ad1 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -801,9 +801,10 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
801 return 0; 801 return 0;
802} 802}
803 803
804static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 804static int proc_sys_getattr(const struct path *path, struct kstat *stat,
805 u32 request_mask, unsigned int query_flags)
805{ 806{
806 struct inode *inode = d_inode(dentry); 807 struct inode *inode = d_inode(path->dentry);
807 struct ctl_table_header *head = grab_header(inode); 808 struct ctl_table_header *head = grab_header(inode);
808 struct ctl_table *table = PROC_I(inode)->sysctl_entry; 809 struct ctl_table *table = PROC_I(inode)->sysctl_entry;
809 810
diff --git a/fs/proc/root.c b/fs/proc/root.c
index b90da888b81a..fb1955c82274 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -149,10 +149,10 @@ void __init proc_root_init(void)
149 proc_sys_init(); 149 proc_sys_init();
150} 150}
151 151
152static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat 152static int proc_root_getattr(const struct path *path, struct kstat *stat,
153) 153 u32 request_mask, unsigned int query_flags)
154{ 154{
155 generic_fillattr(d_inode(dentry), stat); 155 generic_fillattr(d_inode(path->dentry), stat);
156 stat->nlink = proc_root.nlink + nr_processes(); 156 stat->nlink = proc_root.nlink + nr_processes();
157 return 0; 157 return 0;
158} 158}
diff --git a/fs/stat.c b/fs/stat.c
index 3f14d1ef0868..a3804feadade 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -18,6 +18,15 @@
18#include <linux/uaccess.h> 18#include <linux/uaccess.h>
19#include <asm/unistd.h> 19#include <asm/unistd.h>
20 20
21/**
22 * generic_fillattr - Fill in the basic attributes from the inode struct
23 * @inode: Inode to use as the source
24 * @stat: Where to fill in the attributes
25 *
26 * Fill in the basic attributes in the kstat structure from data that's to be
27 * found on the VFS inode structure. This is the default if no getattr inode
28 * operation is supplied.
29 */
21void generic_fillattr(struct inode *inode, struct kstat *stat) 30void generic_fillattr(struct inode *inode, struct kstat *stat)
22{ 31{
23 stat->dev = inode->i_sb->s_dev; 32 stat->dev = inode->i_sb->s_dev;
@@ -33,81 +42,147 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
33 stat->ctime = inode->i_ctime; 42 stat->ctime = inode->i_ctime;
34 stat->blksize = i_blocksize(inode); 43 stat->blksize = i_blocksize(inode);
35 stat->blocks = inode->i_blocks; 44 stat->blocks = inode->i_blocks;
36}
37 45
46 if (IS_NOATIME(inode))
47 stat->result_mask &= ~STATX_ATIME;
48 if (IS_AUTOMOUNT(inode))
49 stat->attributes |= STATX_ATTR_AUTOMOUNT;
50}
38EXPORT_SYMBOL(generic_fillattr); 51EXPORT_SYMBOL(generic_fillattr);
39 52
40/** 53/**
41 * vfs_getattr_nosec - getattr without security checks 54 * vfs_getattr_nosec - getattr without security checks
42 * @path: file to get attributes from 55 * @path: file to get attributes from
43 * @stat: structure to return attributes in 56 * @stat: structure to return attributes in
57 * @request_mask: STATX_xxx flags indicating what the caller wants
58 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
44 * 59 *
45 * Get attributes without calling security_inode_getattr. 60 * Get attributes without calling security_inode_getattr.
46 * 61 *
47 * Currently the only caller other than vfs_getattr is internal to the 62 * Currently the only caller other than vfs_getattr is internal to the
48 * filehandle lookup code, which uses only the inode number and returns 63 * filehandle lookup code, which uses only the inode number and returns no
49 * no attributes to any user. Any other code probably wants 64 * attributes to any user. Any other code probably wants vfs_getattr.
50 * vfs_getattr.
51 */ 65 */
52int vfs_getattr_nosec(struct path *path, struct kstat *stat) 66int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
67 u32 request_mask, unsigned int query_flags)
53{ 68{
54 struct inode *inode = d_backing_inode(path->dentry); 69 struct inode *inode = d_backing_inode(path->dentry);
55 70
71 memset(stat, 0, sizeof(*stat));
72 stat->result_mask |= STATX_BASIC_STATS;
73 request_mask &= STATX_ALL;
74 query_flags &= KSTAT_QUERY_FLAGS;
56 if (inode->i_op->getattr) 75 if (inode->i_op->getattr)
57 return inode->i_op->getattr(path->mnt, path->dentry, stat); 76 return inode->i_op->getattr(path, stat, request_mask,
77 query_flags);
58 78
59 generic_fillattr(inode, stat); 79 generic_fillattr(inode, stat);
60 return 0; 80 return 0;
61} 81}
62
63EXPORT_SYMBOL(vfs_getattr_nosec); 82EXPORT_SYMBOL(vfs_getattr_nosec);
64 83
65int vfs_getattr(struct path *path, struct kstat *stat) 84/*
85 * vfs_getattr - Get the enhanced basic attributes of a file
86 * @path: The file of interest
87 * @stat: Where to return the statistics
88 * @request_mask: STATX_xxx flags indicating what the caller wants
89 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
90 *
91 * Ask the filesystem for a file's attributes. The caller must indicate in
92 * request_mask and query_flags to indicate what they want.
93 *
94 * If the file is remote, the filesystem can be forced to update the attributes
95 * from the backing store by passing AT_STATX_FORCE_SYNC in query_flags or can
96 * suppress the update by passing AT_STATX_DONT_SYNC.
97 *
98 * Bits must have been set in request_mask to indicate which attributes the
99 * caller wants retrieving. Any such attribute not requested may be returned
100 * anyway, but the value may be approximate, and, if remote, may not have been
101 * synchronised with the server.
102 *
103 * 0 will be returned on success, and a -ve error code if unsuccessful.
104 */
105int vfs_getattr(const struct path *path, struct kstat *stat,
106 u32 request_mask, unsigned int query_flags)
66{ 107{
67 int retval; 108 int retval;
68 109
69 retval = security_inode_getattr(path); 110 retval = security_inode_getattr(path);
70 if (retval) 111 if (retval)
71 return retval; 112 return retval;
72 return vfs_getattr_nosec(path, stat); 113 return vfs_getattr_nosec(path, stat, request_mask, query_flags);
73} 114}
74
75EXPORT_SYMBOL(vfs_getattr); 115EXPORT_SYMBOL(vfs_getattr);
76 116
77int vfs_fstat(unsigned int fd, struct kstat *stat) 117/**
118 * vfs_statx_fd - Get the enhanced basic attributes by file descriptor
119 * @fd: The file descriptor referring to the file of interest
120 * @stat: The result structure to fill in.
121 * @request_mask: STATX_xxx flags indicating what the caller wants
122 * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
123 *
124 * This function is a wrapper around vfs_getattr(). The main difference is
125 * that it uses a file descriptor to determine the file location.
126 *
127 * 0 will be returned on success, and a -ve error code if unsuccessful.
128 */
129int vfs_statx_fd(unsigned int fd, struct kstat *stat,
130 u32 request_mask, unsigned int query_flags)
78{ 131{
79 struct fd f = fdget_raw(fd); 132 struct fd f = fdget_raw(fd);
80 int error = -EBADF; 133 int error = -EBADF;
81 134
82 if (f.file) { 135 if (f.file) {
83 error = vfs_getattr(&f.file->f_path, stat); 136 error = vfs_getattr(&f.file->f_path, stat,
137 request_mask, query_flags);
84 fdput(f); 138 fdput(f);
85 } 139 }
86 return error; 140 return error;
87} 141}
88EXPORT_SYMBOL(vfs_fstat); 142EXPORT_SYMBOL(vfs_statx_fd);
89 143
90int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, 144/**
91 int flag) 145 * vfs_statx - Get basic and extra attributes by filename
146 * @dfd: A file descriptor representing the base dir for a relative filename
147 * @filename: The name of the file of interest
148 * @flags: Flags to control the query
149 * @stat: The result structure to fill in.
150 * @request_mask: STATX_xxx flags indicating what the caller wants
151 *
152 * This function is a wrapper around vfs_getattr(). The main difference is
153 * that it uses a filename and base directory to determine the file location.
154 * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
155 * at the given name from being referenced.
156 *
157 * The caller must have preset stat->request_mask as for vfs_getattr(). The
158 * flags are also used to load up stat->query_flags.
159 *
160 * 0 will be returned on success, and a -ve error code if unsuccessful.
161 */
162int vfs_statx(int dfd, const char __user *filename, int flags,
163 struct kstat *stat, u32 request_mask)
92{ 164{
93 struct path path; 165 struct path path;
94 int error = -EINVAL; 166 int error = -EINVAL;
95 unsigned int lookup_flags = 0; 167 unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
96 168
97 if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | 169 if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
98 AT_EMPTY_PATH)) != 0) 170 AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0)
99 goto out; 171 return -EINVAL;
100 172
101 if (!(flag & AT_SYMLINK_NOFOLLOW)) 173 if (flags & AT_SYMLINK_NOFOLLOW)
102 lookup_flags |= LOOKUP_FOLLOW; 174 lookup_flags &= ~LOOKUP_FOLLOW;
103 if (flag & AT_EMPTY_PATH) 175 if (flags & AT_NO_AUTOMOUNT)
176 lookup_flags &= ~LOOKUP_AUTOMOUNT;
177 if (flags & AT_EMPTY_PATH)
104 lookup_flags |= LOOKUP_EMPTY; 178 lookup_flags |= LOOKUP_EMPTY;
179
105retry: 180retry:
106 error = user_path_at(dfd, filename, lookup_flags, &path); 181 error = user_path_at(dfd, filename, lookup_flags, &path);
107 if (error) 182 if (error)
108 goto out; 183 goto out;
109 184
110 error = vfs_getattr(&path, stat); 185 error = vfs_getattr(&path, stat, request_mask, flags);
111 path_put(&path); 186 path_put(&path);
112 if (retry_estale(error, lookup_flags)) { 187 if (retry_estale(error, lookup_flags)) {
113 lookup_flags |= LOOKUP_REVAL; 188 lookup_flags |= LOOKUP_REVAL;
@@ -116,19 +191,7 @@ retry:
116out: 191out:
117 return error; 192 return error;
118} 193}
119EXPORT_SYMBOL(vfs_fstatat); 194EXPORT_SYMBOL(vfs_statx);
120
121int vfs_stat(const char __user *name, struct kstat *stat)
122{
123 return vfs_fstatat(AT_FDCWD, name, stat, 0);
124}
125EXPORT_SYMBOL(vfs_stat);
126
127int vfs_lstat(const char __user *name, struct kstat *stat)
128{
129 return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
130}
131EXPORT_SYMBOL(vfs_lstat);
132 195
133 196
134#ifdef __ARCH_WANT_OLD_STAT 197#ifdef __ARCH_WANT_OLD_STAT
@@ -141,7 +204,7 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
141{ 204{
142 static int warncount = 5; 205 static int warncount = 5;
143 struct __old_kernel_stat tmp; 206 struct __old_kernel_stat tmp;
144 207
145 if (warncount > 0) { 208 if (warncount > 0) {
146 warncount--; 209 warncount--;
147 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n", 210 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
@@ -166,7 +229,7 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
166#if BITS_PER_LONG == 32 229#if BITS_PER_LONG == 32
167 if (stat->size > MAX_NON_LFS) 230 if (stat->size > MAX_NON_LFS)
168 return -EOVERFLOW; 231 return -EOVERFLOW;
169#endif 232#endif
170 tmp.st_size = stat->size; 233 tmp.st_size = stat->size;
171 tmp.st_atime = stat->atime.tv_sec; 234 tmp.st_atime = stat->atime.tv_sec;
172 tmp.st_mtime = stat->mtime.tv_sec; 235 tmp.st_mtime = stat->mtime.tv_sec;
@@ -445,6 +508,81 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
445} 508}
446#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */ 509#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
447 510
511static inline int __put_timestamp(struct timespec *kts,
512 struct statx_timestamp __user *uts)
513{
514 return (__put_user(kts->tv_sec, &uts->tv_sec ) ||
515 __put_user(kts->tv_nsec, &uts->tv_nsec ) ||
516 __put_user(0, &uts->__reserved ));
517}
518
519/*
520 * Set the statx results.
521 */
522static long statx_set_result(struct kstat *stat, struct statx __user *buffer)
523{
524 uid_t uid = from_kuid_munged(current_user_ns(), stat->uid);
525 gid_t gid = from_kgid_munged(current_user_ns(), stat->gid);
526
527 if (__put_user(stat->result_mask, &buffer->stx_mask ) ||
528 __put_user(stat->mode, &buffer->stx_mode ) ||
529 __clear_user(&buffer->__spare0, sizeof(buffer->__spare0)) ||
530 __put_user(stat->nlink, &buffer->stx_nlink ) ||
531 __put_user(uid, &buffer->stx_uid ) ||
532 __put_user(gid, &buffer->stx_gid ) ||
533 __put_user(stat->attributes, &buffer->stx_attributes ) ||
534 __put_user(stat->blksize, &buffer->stx_blksize ) ||
535 __put_user(MAJOR(stat->rdev), &buffer->stx_rdev_major ) ||
536 __put_user(MINOR(stat->rdev), &buffer->stx_rdev_minor ) ||
537 __put_user(MAJOR(stat->dev), &buffer->stx_dev_major ) ||
538 __put_user(MINOR(stat->dev), &buffer->stx_dev_minor ) ||
539 __put_timestamp(&stat->atime, &buffer->stx_atime ) ||
540 __put_timestamp(&stat->btime, &buffer->stx_btime ) ||
541 __put_timestamp(&stat->ctime, &buffer->stx_ctime ) ||
542 __put_timestamp(&stat->mtime, &buffer->stx_mtime ) ||
543 __put_user(stat->ino, &buffer->stx_ino ) ||
544 __put_user(stat->size, &buffer->stx_size ) ||
545 __put_user(stat->blocks, &buffer->stx_blocks ) ||
546 __clear_user(&buffer->__spare1, sizeof(buffer->__spare1)) ||
547 __clear_user(&buffer->__spare2, sizeof(buffer->__spare2)))
548 return -EFAULT;
549
550 return 0;
551}
552
553/**
554 * sys_statx - System call to get enhanced stats
555 * @dfd: Base directory to pathwalk from *or* fd to stat.
556 * @filename: File to stat *or* NULL.
557 * @flags: AT_* flags to control pathwalk.
558 * @mask: Parts of statx struct actually required.
559 * @buffer: Result buffer.
560 *
561 * Note that if filename is NULL, then it does the equivalent of fstat() using
562 * dfd to indicate the file of interest.
563 */
564SYSCALL_DEFINE5(statx,
565 int, dfd, const char __user *, filename, unsigned, flags,
566 unsigned int, mask,
567 struct statx __user *, buffer)
568{
569 struct kstat stat;
570 int error;
571
572 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
573 return -EINVAL;
574 if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer)))
575 return -EFAULT;
576
577 if (filename)
578 error = vfs_statx(dfd, filename, flags, &stat, mask);
579 else
580 error = vfs_statx_fd(dfd, &stat, mask, flags);
581 if (error)
582 return error;
583 return statx_set_result(&stat, buffer);
584}
585
448/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ 586/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
449void __inode_add_bytes(struct inode *inode, loff_t bytes) 587void __inode_add_bytes(struct inode *inode, loff_t bytes)
450{ 588{
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 08d3e630b49c..83809f5b5eca 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -440,10 +440,11 @@ static unsigned sysv_nblocks(struct super_block *s, loff_t size)
440 return blocks; 440 return blocks;
441} 441}
442 442
443int sysv_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 443int sysv_getattr(const struct path *path, struct kstat *stat,
444 u32 request_mask, unsigned int flags)
444{ 445{
445 struct super_block *s = dentry->d_sb; 446 struct super_block *s = path->dentry->d_sb;
446 generic_fillattr(d_inode(dentry), stat); 447 generic_fillattr(d_inode(path->dentry), stat);
447 stat->blocks = (s->s_blocksize / 512) * sysv_nblocks(s, stat->size); 448 stat->blocks = (s->s_blocksize / 512) * sysv_nblocks(s, stat->size);
448 stat->blksize = s->s_blocksize; 449 stat->blksize = s->s_blocksize;
449 return 0; 450 return 0;
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 6c212288adcb..1e7e27c729af 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -142,7 +142,7 @@ extern struct inode *sysv_iget(struct super_block *, unsigned int);
142extern int sysv_write_inode(struct inode *, struct writeback_control *wbc); 142extern int sysv_write_inode(struct inode *, struct writeback_control *wbc);
143extern int sysv_sync_inode(struct inode *); 143extern int sysv_sync_inode(struct inode *);
144extern void sysv_set_inode(struct inode *, dev_t); 144extern void sysv_set_inode(struct inode *, dev_t);
145extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *); 145extern int sysv_getattr(const struct path *, struct kstat *, u32, unsigned int);
146extern int sysv_init_icache(void); 146extern int sysv_init_icache(void);
147extern void sysv_destroy_icache(void); 147extern void sysv_destroy_icache(void);
148 148
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 528369f3e472..30825d882aa9 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1622,11 +1622,11 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
1622 return do_rename(old_dir, old_dentry, new_dir, new_dentry, flags); 1622 return do_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
1623} 1623}
1624 1624
1625int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1625int ubifs_getattr(const struct path *path, struct kstat *stat,
1626 struct kstat *stat) 1626 u32 request_mask, unsigned int flags)
1627{ 1627{
1628 loff_t size; 1628 loff_t size;
1629 struct inode *inode = d_inode(dentry); 1629 struct inode *inode = d_inode(path->dentry);
1630 struct ubifs_inode *ui = ubifs_inode(inode); 1630 struct ubifs_inode *ui = ubifs_inode(inode);
1631 1631
1632 mutex_lock(&ui->ui_mutex); 1632 mutex_lock(&ui->ui_mutex);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index f0c86f076535..4d57e488038e 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1749,8 +1749,8 @@ int ubifs_update_time(struct inode *inode, struct timespec *time, int flags);
1749/* dir.c */ 1749/* dir.c */
1750struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, 1750struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
1751 umode_t mode); 1751 umode_t mode);
1752int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1752int ubifs_getattr(const struct path *path, struct kstat *stat,
1753 struct kstat *stat); 1753 u32 request_mask, unsigned int flags);
1754int ubifs_check_dir_empty(struct inode *dir); 1754int ubifs_check_dir_empty(struct inode *dir);
1755 1755
1756/* xattr.c */ 1756/* xattr.c */
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index f7dfef53f739..6023c97c6da2 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -152,9 +152,10 @@ out_unmap:
152 return err; 152 return err;
153} 153}
154 154
155static int udf_symlink_getattr(struct vfsmount *mnt, struct dentry *dentry, 155static int udf_symlink_getattr(const struct path *path, struct kstat *stat,
156 struct kstat *stat) 156 u32 request_mask, unsigned int flags)
157{ 157{
158 struct dentry *dentry = path->dentry;
158 struct inode *inode = d_backing_inode(dentry); 159 struct inode *inode = d_backing_inode(dentry);
159 struct page *page; 160 struct page *page;
160 161
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 22c16155f1b4..229cc6a6d8ef 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -489,11 +489,12 @@ xfs_vn_get_link_inline(
489 489
490STATIC int 490STATIC int
491xfs_vn_getattr( 491xfs_vn_getattr(
492 struct vfsmount *mnt, 492 const struct path *path,
493 struct dentry *dentry, 493 struct kstat *stat,
494 struct kstat *stat) 494 u32 request_mask,
495 unsigned int query_flags)
495{ 496{
496 struct inode *inode = d_inode(dentry); 497 struct inode *inode = d_inode(path->dentry);
497 struct xfs_inode *ip = XFS_I(inode); 498 struct xfs_inode *ip = XFS_I(inode);
498 struct xfs_mount *mp = ip->i_mount; 499 struct xfs_mount *mp = ip->i_mount;
499 500
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 52350947c670..aad3fd0ff5f8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1709,7 +1709,7 @@ struct inode_operations {
1709 int (*rename) (struct inode *, struct dentry *, 1709 int (*rename) (struct inode *, struct dentry *,
1710 struct inode *, struct dentry *, unsigned int); 1710 struct inode *, struct dentry *, unsigned int);
1711 int (*setattr) (struct dentry *, struct iattr *); 1711 int (*setattr) (struct dentry *, struct iattr *);
1712 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 1712 int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
1713 ssize_t (*listxattr) (struct dentry *, char *, size_t); 1713 ssize_t (*listxattr) (struct dentry *, char *, size_t);
1714 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, 1714 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1715 u64 len); 1715 u64 len);
@@ -2902,8 +2902,8 @@ extern int page_symlink(struct inode *inode, const char *symname, int len);
2902extern const struct inode_operations page_symlink_inode_operations; 2902extern const struct inode_operations page_symlink_inode_operations;
2903extern void kfree_link(void *); 2903extern void kfree_link(void *);
2904extern void generic_fillattr(struct inode *, struct kstat *); 2904extern void generic_fillattr(struct inode *, struct kstat *);
2905int vfs_getattr_nosec(struct path *path, struct kstat *stat); 2905extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
2906extern int vfs_getattr(struct path *, struct kstat *); 2906extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
2907void __inode_add_bytes(struct inode *inode, loff_t bytes); 2907void __inode_add_bytes(struct inode *inode, loff_t bytes);
2908void inode_add_bytes(struct inode *inode, loff_t bytes); 2908void inode_add_bytes(struct inode *inode, loff_t bytes);
2909void __inode_sub_bytes(struct inode *inode, loff_t bytes); 2909void __inode_sub_bytes(struct inode *inode, loff_t bytes);
@@ -2916,10 +2916,29 @@ extern const struct inode_operations simple_symlink_inode_operations;
2916 2916
2917extern int iterate_dir(struct file *, struct dir_context *); 2917extern int iterate_dir(struct file *, struct dir_context *);
2918 2918
2919extern int vfs_stat(const char __user *, struct kstat *); 2919extern int vfs_statx(int, const char __user *, int, struct kstat *, u32);
2920extern int vfs_lstat(const char __user *, struct kstat *); 2920extern int vfs_statx_fd(unsigned int, struct kstat *, u32, unsigned int);
2921extern int vfs_fstat(unsigned int, struct kstat *); 2921
2922extern int vfs_fstatat(int , const char __user *, struct kstat *, int); 2922static inline int vfs_stat(const char __user *filename, struct kstat *stat)
2923{
2924 return vfs_statx(AT_FDCWD, filename, 0, stat, STATX_BASIC_STATS);
2925}
2926static inline int vfs_lstat(const char __user *name, struct kstat *stat)
2927{
2928 return vfs_statx(AT_FDCWD, name, AT_SYMLINK_NOFOLLOW,
2929 stat, STATX_BASIC_STATS);
2930}
2931static inline int vfs_fstatat(int dfd, const char __user *filename,
2932 struct kstat *stat, int flags)
2933{
2934 return vfs_statx(dfd, filename, flags, stat, STATX_BASIC_STATS);
2935}
2936static inline int vfs_fstat(int fd, struct kstat *stat)
2937{
2938 return vfs_statx_fd(fd, stat, STATX_BASIC_STATS, 0);
2939}
2940
2941
2923extern const char *vfs_get_link(struct dentry *, struct delayed_call *); 2942extern const char *vfs_get_link(struct dentry *, struct delayed_call *);
2924extern int vfs_readlink(struct dentry *, char __user *, int); 2943extern int vfs_readlink(struct dentry *, char __user *, int);
2925 2944
@@ -2949,7 +2968,7 @@ extern int dcache_dir_close(struct inode *, struct file *);
2949extern loff_t dcache_dir_lseek(struct file *, loff_t, int); 2968extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
2950extern int dcache_readdir(struct file *, struct dir_context *); 2969extern int dcache_readdir(struct file *, struct dir_context *);
2951extern int simple_setattr(struct dentry *, struct iattr *); 2970extern int simple_setattr(struct dentry *, struct iattr *);
2952extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); 2971extern int simple_getattr(const struct path *, struct kstat *, u32, unsigned int);
2953extern int simple_statfs(struct dentry *, struct kstatfs *); 2972extern int simple_statfs(struct dentry *, struct kstatfs *);
2954extern int simple_open(struct inode *inode, struct file *file); 2973extern int simple_open(struct inode *inode, struct file *file);
2955extern int simple_link(struct dentry *, struct inode *, struct dentry *); 2974extern int simple_link(struct dentry *, struct inode *, struct dentry *);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index f1da8c8dd473..287f34161086 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -335,7 +335,7 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
335extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); 335extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
336extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); 336extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
337extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr); 337extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr);
338extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 338extern int nfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
339extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); 339extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
340extern void nfs_access_set_mask(struct nfs_access_entry *, u32); 340extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
341extern int nfs_permission(struct inode *, int); 341extern int nfs_permission(struct inode *, int);
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 075cb0c7eb2a..c76e524fb34b 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -18,20 +18,32 @@
18#include <linux/time.h> 18#include <linux/time.h>
19#include <linux/uidgid.h> 19#include <linux/uidgid.h>
20 20
21#define KSTAT_QUERY_FLAGS (AT_STATX_SYNC_TYPE)
22
21struct kstat { 23struct kstat {
22 u64 ino; 24 u32 result_mask; /* What fields the user got */
23 dev_t dev;
24 umode_t mode; 25 umode_t mode;
25 unsigned int nlink; 26 unsigned int nlink;
27 uint32_t blksize; /* Preferred I/O size */
28 u64 attributes;
29#define KSTAT_ATTR_FS_IOC_FLAGS \
30 (STATX_ATTR_COMPRESSED | \
31 STATX_ATTR_IMMUTABLE | \
32 STATX_ATTR_APPEND | \
33 STATX_ATTR_NODUMP | \
34 STATX_ATTR_ENCRYPTED \
35 )/* Attrs corresponding to FS_*_FL flags */
36 u64 ino;
37 dev_t dev;
38 dev_t rdev;
26 kuid_t uid; 39 kuid_t uid;
27 kgid_t gid; 40 kgid_t gid;
28 dev_t rdev;
29 loff_t size; 41 loff_t size;
30 struct timespec atime; 42 struct timespec atime;
31 struct timespec mtime; 43 struct timespec mtime;
32 struct timespec ctime; 44 struct timespec ctime;
33 unsigned long blksize; 45 struct timespec btime; /* File creation time */
34 unsigned long long blocks; 46 u64 blocks;
35}; 47};
36 48
37#endif 49#endif
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 91a740f6b884..980c3c9b06f8 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -48,6 +48,7 @@ struct stat;
48struct stat64; 48struct stat64;
49struct statfs; 49struct statfs;
50struct statfs64; 50struct statfs64;
51struct statx;
51struct __sysctl_args; 52struct __sysctl_args;
52struct sysinfo; 53struct sysinfo;
53struct timespec; 54struct timespec;
@@ -902,5 +903,7 @@ asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len,
902 unsigned long prot, int pkey); 903 unsigned long prot, int pkey);
903asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val); 904asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val);
904asmlinkage long sys_pkey_free(int pkey); 905asmlinkage long sys_pkey_free(int pkey);
906asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags,
907 unsigned mask, struct statx __user *buffer);
905 908
906#endif 909#endif
diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h
index beed138bd359..813afd6eee71 100644
--- a/include/uapi/linux/fcntl.h
+++ b/include/uapi/linux/fcntl.h
@@ -63,5 +63,10 @@
63#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */ 63#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
64#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ 64#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
65 65
66#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
67#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
68#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
69#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
70
66 71
67#endif /* _UAPI_LINUX_FCNTL_H */ 72#endif /* _UAPI_LINUX_FCNTL_H */
diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h
index 7fec7e36d921..51a6b86e3700 100644
--- a/include/uapi/linux/stat.h
+++ b/include/uapi/linux/stat.h
@@ -1,6 +1,7 @@
1#ifndef _UAPI_LINUX_STAT_H 1#ifndef _UAPI_LINUX_STAT_H
2#define _UAPI_LINUX_STAT_H 2#define _UAPI_LINUX_STAT_H
3 3
4#include <linux/types.h>
4 5
5#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) 6#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
6 7
@@ -41,5 +42,135 @@
41 42
42#endif 43#endif
43 44
45/*
46 * Timestamp structure for the timestamps in struct statx.
47 *
48 * tv_sec holds the number of seconds before (negative) or after (positive)
49 * 00:00:00 1st January 1970 UTC.
50 *
51 * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is
52 * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time.
53 *
54 * Note that if both tv_sec and tv_nsec are non-zero, then the two values must
55 * either be both positive or both negative.
56 *
57 * __reserved is held in case we need a yet finer resolution.
58 */
59struct statx_timestamp {
60 __s64 tv_sec;
61 __s32 tv_nsec;
62 __s32 __reserved;
63};
64
65/*
66 * Structures for the extended file attribute retrieval system call
67 * (statx()).
68 *
69 * The caller passes a mask of what they're specifically interested in as a
70 * parameter to statx(). What statx() actually got will be indicated in
71 * st_mask upon return.
72 *
73 * For each bit in the mask argument:
74 *
75 * - if the datum is not supported:
76 *
77 * - the bit will be cleared, and
78 *
79 * - the datum will be set to an appropriate fabricated value if one is
80 * available (eg. CIFS can take a default uid and gid), otherwise
81 *
82 * - the field will be cleared;
83 *
84 * - otherwise, if explicitly requested:
85 *
86 * - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
87 * set or if the datum is considered out of date, and
88 *
89 * - the field will be filled in and the bit will be set;
90 *
91 * - otherwise, if not requested, but available in approximate form without any
92 * effort, it will be filled in anyway, and the bit will be set upon return
93 * (it might not be up to date, however, and no attempt will be made to
94 * synchronise the internal state first);
95 *
96 * - otherwise the field and the bit will be cleared before returning.
97 *
98 * Items in STATX_BASIC_STATS may be marked unavailable on return, but they
99 * will have values installed for compatibility purposes so that stat() and
100 * co. can be emulated in userspace.
101 */
102struct statx {
103 /* 0x00 */
104 __u32 stx_mask; /* What results were written [uncond] */
105 __u32 stx_blksize; /* Preferred general I/O size [uncond] */
106 __u64 stx_attributes; /* Flags conveying information about the file [uncond] */
107 /* 0x10 */
108 __u32 stx_nlink; /* Number of hard links */
109 __u32 stx_uid; /* User ID of owner */
110 __u32 stx_gid; /* Group ID of owner */
111 __u16 stx_mode; /* File mode */
112 __u16 __spare0[1];
113 /* 0x20 */
114 __u64 stx_ino; /* Inode number */
115 __u64 stx_size; /* File size */
116 __u64 stx_blocks; /* Number of 512-byte blocks allocated */
117 __u64 __spare1[1];
118 /* 0x40 */
119 struct statx_timestamp stx_atime; /* Last access time */
120 struct statx_timestamp stx_btime; /* File creation time */
121 struct statx_timestamp stx_ctime; /* Last attribute change time */
122 struct statx_timestamp stx_mtime; /* Last data modification time */
123 /* 0x80 */
124 __u32 stx_rdev_major; /* Device ID of special file [if bdev/cdev] */
125 __u32 stx_rdev_minor;
126 __u32 stx_dev_major; /* ID of device containing file [uncond] */
127 __u32 stx_dev_minor;
128 /* 0x90 */
129 __u64 __spare2[14]; /* Spare space for future expansion */
130 /* 0x100 */
131};
132
133/*
134 * Flags to be stx_mask
135 *
136 * Query request/result mask for statx() and struct statx::stx_mask.
137 *
138 * These bits should be set in the mask argument of statx() to request
139 * particular items when calling statx().
140 */
141#define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
142#define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
143#define STATX_NLINK 0x00000004U /* Want/got stx_nlink */
144#define STATX_UID 0x00000008U /* Want/got stx_uid */
145#define STATX_GID 0x00000010U /* Want/got stx_gid */
146#define STATX_ATIME 0x00000020U /* Want/got stx_atime */
147#define STATX_MTIME 0x00000040U /* Want/got stx_mtime */
148#define STATX_CTIME 0x00000080U /* Want/got stx_ctime */
149#define STATX_INO 0x00000100U /* Want/got stx_ino */
150#define STATX_SIZE 0x00000200U /* Want/got stx_size */
151#define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
152#define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
153#define STATX_BTIME 0x00000800U /* Want/got stx_btime */
154#define STATX_ALL 0x00000fffU /* All currently supported flags */
155
156/*
157 * Attributes to be found in stx_attributes
158 *
159 * These give information about the features or the state of a file that might
160 * be of use to ordinary userspace programs such as GUIs or ls rather than
161 * specialised tools.
162 *
163 * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
164 * semantically. Where possible, the numerical value is picked to correspond
165 * also.
166 */
167#define STATX_ATTR_COMPRESSED 0x00000004 /* [I] File is compressed by the fs */
168#define STATX_ATTR_IMMUTABLE 0x00000010 /* [I] File is marked immutable */
169#define STATX_ATTR_APPEND 0x00000020 /* [I] File is append-only */
170#define STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */
171#define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
172
173#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
174
44 175
45#endif /* _UAPI_LINUX_STAT_H */ 176#endif /* _UAPI_LINUX_STAT_H */
diff --git a/mm/shmem.c b/mm/shmem.c
index a26649a6633f..e07728f716b2 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -958,10 +958,10 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
958} 958}
959EXPORT_SYMBOL_GPL(shmem_truncate_range); 959EXPORT_SYMBOL_GPL(shmem_truncate_range);
960 960
961static int shmem_getattr(struct vfsmount *mnt, struct dentry *dentry, 961static int shmem_getattr(const struct path *path, struct kstat *stat,
962 struct kstat *stat) 962 u32 request_mask, unsigned int query_flags)
963{ 963{
964 struct inode *inode = dentry->d_inode; 964 struct inode *inode = path->dentry->d_inode;
965 struct shmem_inode_info *info = SHMEM_I(inode); 965 struct shmem_inode_info *info = SHMEM_I(inode);
966 966
967 if (info->alloced - info->swapped != inode->i_mapping->nrpages) { 967 if (info->alloced - info->swapped != inode->i_mapping->nrpages) {
diff --git a/samples/Kconfig b/samples/Kconfig
index b124f62ed6cb..9cb63188d3ef 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -112,4 +112,10 @@ config SAMPLE_VFIO_MDEV_MTTY
112 Build a virtual tty sample driver for use as a VFIO 112 Build a virtual tty sample driver for use as a VFIO
113 mediated device 113 mediated device
114 114
115config SAMPLE_STATX
116 bool "Build example extended-stat using code"
117 depends on BROKEN
118 help
119 Build example userspace program to use the new extended-stat syscall.
120
115endif # SAMPLES 121endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 86a137e451d9..db54e766ddb1 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -3,4 +3,4 @@
3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ 3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ 4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
5 configfs/ connector/ v4l/ trace_printk/ blackfin/ \ 5 configfs/ connector/ v4l/ trace_printk/ blackfin/ \
6 vfio-mdev/ 6 vfio-mdev/ statx/
diff --git a/samples/statx/Makefile b/samples/statx/Makefile
new file mode 100644
index 000000000000..1f80a3d8cf45
--- /dev/null
+++ b/samples/statx/Makefile
@@ -0,0 +1,10 @@
1# kbuild trick to avoid linker error. Can be omitted if a module is built.
2obj- := dummy.o
3
4# List of programs to build
5hostprogs-$(CONFIG_SAMPLE_STATX) := test-statx
6
7# Tell kbuild to always build the programs
8always := $(hostprogs-y)
9
10HOSTCFLAGS_test-statx.o += -I$(objtree)/usr/include
diff --git a/samples/statx/test-statx.c b/samples/statx/test-statx.c
new file mode 100644
index 000000000000..8571d766331d
--- /dev/null
+++ b/samples/statx/test-statx.c
@@ -0,0 +1,254 @@
1/* Test the statx() system call.
2 *
3 * Note that the output of this program is intended to look like the output of
4 * /bin/stat where possible.
5 *
6 * Copyright (C) 2015 Red Hat, Inc. All Rights Reserved.
7 * Written by David Howells (dhowells@redhat.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public Licence
11 * as published by the Free Software Foundation; either version
12 * 2 of the Licence, or (at your option) any later version.
13 */
14
15#define _GNU_SOURCE
16#define _ATFILE_SOURCE
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <ctype.h>
22#include <errno.h>
23#include <time.h>
24#include <sys/syscall.h>
25#include <sys/types.h>
26#include <linux/stat.h>
27#include <linux/fcntl.h>
28#include <sys/stat.h>
29
30#define AT_STATX_SYNC_TYPE 0x6000
31#define AT_STATX_SYNC_AS_STAT 0x0000
32#define AT_STATX_FORCE_SYNC 0x2000
33#define AT_STATX_DONT_SYNC 0x4000
34
35static __attribute__((unused))
36ssize_t statx(int dfd, const char *filename, unsigned flags,
37 unsigned int mask, struct statx *buffer)
38{
39 return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
40}
41
42static void print_time(const char *field, struct statx_timestamp *ts)
43{
44 struct tm tm;
45 time_t tim;
46 char buffer[100];
47 int len;
48
49 tim = ts->tv_sec;
50 if (!localtime_r(&tim, &tm)) {
51 perror("localtime_r");
52 exit(1);
53 }
54 len = strftime(buffer, 100, "%F %T", &tm);
55 if (len == 0) {
56 perror("strftime");
57 exit(1);
58 }
59 printf("%s", field);
60 fwrite(buffer, 1, len, stdout);
61 printf(".%09u", ts->tv_nsec);
62 len = strftime(buffer, 100, "%z", &tm);
63 if (len == 0) {
64 perror("strftime2");
65 exit(1);
66 }
67 fwrite(buffer, 1, len, stdout);
68 printf("\n");
69}
70
71static void dump_statx(struct statx *stx)
72{
73 char buffer[256], ft = '?';
74
75 printf("results=%x\n", stx->stx_mask);
76
77 printf(" ");
78 if (stx->stx_mask & STATX_SIZE)
79 printf(" Size: %-15llu", (unsigned long long)stx->stx_size);
80 if (stx->stx_mask & STATX_BLOCKS)
81 printf(" Blocks: %-10llu", (unsigned long long)stx->stx_blocks);
82 printf(" IO Block: %-6llu", (unsigned long long)stx->stx_blksize);
83 if (stx->stx_mask & STATX_TYPE) {
84 switch (stx->stx_mode & S_IFMT) {
85 case S_IFIFO: printf(" FIFO\n"); ft = 'p'; break;
86 case S_IFCHR: printf(" character special file\n"); ft = 'c'; break;
87 case S_IFDIR: printf(" directory\n"); ft = 'd'; break;
88 case S_IFBLK: printf(" block special file\n"); ft = 'b'; break;
89 case S_IFREG: printf(" regular file\n"); ft = '-'; break;
90 case S_IFLNK: printf(" symbolic link\n"); ft = 'l'; break;
91 case S_IFSOCK: printf(" socket\n"); ft = 's'; break;
92 default:
93 printf(" unknown type (%o)\n", stx->stx_mode & S_IFMT);
94 break;
95 }
96 } else {
97 printf(" no type\n");
98 }
99
100 sprintf(buffer, "%02x:%02x", stx->stx_dev_major, stx->stx_dev_minor);
101 printf("Device: %-15s", buffer);
102 if (stx->stx_mask & STATX_INO)
103 printf(" Inode: %-11llu", (unsigned long long) stx->stx_ino);
104 if (stx->stx_mask & STATX_NLINK)
105 printf(" Links: %-5u", stx->stx_nlink);
106 if (stx->stx_mask & STATX_TYPE) {
107 switch (stx->stx_mode & S_IFMT) {
108 case S_IFBLK:
109 case S_IFCHR:
110 printf(" Device type: %u,%u",
111 stx->stx_rdev_major, stx->stx_rdev_minor);
112 break;
113 }
114 }
115 printf("\n");
116
117 if (stx->stx_mask & STATX_MODE)
118 printf("Access: (%04o/%c%c%c%c%c%c%c%c%c%c) ",
119 stx->stx_mode & 07777,
120 ft,
121 stx->stx_mode & S_IRUSR ? 'r' : '-',
122 stx->stx_mode & S_IWUSR ? 'w' : '-',
123 stx->stx_mode & S_IXUSR ? 'x' : '-',
124 stx->stx_mode & S_IRGRP ? 'r' : '-',
125 stx->stx_mode & S_IWGRP ? 'w' : '-',
126 stx->stx_mode & S_IXGRP ? 'x' : '-',
127 stx->stx_mode & S_IROTH ? 'r' : '-',
128 stx->stx_mode & S_IWOTH ? 'w' : '-',
129 stx->stx_mode & S_IXOTH ? 'x' : '-');
130 if (stx->stx_mask & STATX_UID)
131 printf("Uid: %5d ", stx->stx_uid);
132 if (stx->stx_mask & STATX_GID)
133 printf("Gid: %5d\n", stx->stx_gid);
134
135 if (stx->stx_mask & STATX_ATIME)
136 print_time("Access: ", &stx->stx_atime);
137 if (stx->stx_mask & STATX_MTIME)
138 print_time("Modify: ", &stx->stx_mtime);
139 if (stx->stx_mask & STATX_CTIME)
140 print_time("Change: ", &stx->stx_ctime);
141 if (stx->stx_mask & STATX_BTIME)
142 print_time(" Birth: ", &stx->stx_btime);
143
144 if (stx->stx_attributes) {
145 unsigned char bits;
146 int loop, byte;
147
148 static char attr_representation[64 + 1] =
149 /* STATX_ATTR_ flags: */
150 "????????" /* 63-56 */
151 "????????" /* 55-48 */
152 "????????" /* 47-40 */
153 "????????" /* 39-32 */
154 "????????" /* 31-24 0x00000000-ff000000 */
155 "????????" /* 23-16 0x00000000-00ff0000 */
156 "???me???" /* 15- 8 0x00000000-0000ff00 */
157 "?dai?c??" /* 7- 0 0x00000000-000000ff */
158 ;
159
160 printf("Attributes: %016llx (", stx->stx_attributes);
161 for (byte = 64 - 8; byte >= 0; byte -= 8) {
162 bits = stx->stx_attributes >> byte;
163 for (loop = 7; loop >= 0; loop--) {
164 int bit = byte + loop;
165
166 if (bits & 0x80)
167 putchar(attr_representation[63 - bit]);
168 else
169 putchar('-');
170 bits <<= 1;
171 }
172 if (byte)
173 putchar(' ');
174 }
175 printf(")\n");
176 }
177}
178
179static void dump_hex(unsigned long long *data, int from, int to)
180{
181 unsigned offset, print_offset = 1, col = 0;
182
183 from /= 8;
184 to = (to + 7) / 8;
185
186 for (offset = from; offset < to; offset++) {
187 if (print_offset) {
188 printf("%04x: ", offset * 8);
189 print_offset = 0;
190 }
191 printf("%016llx", data[offset]);
192 col++;
193 if ((col & 3) == 0) {
194 printf("\n");
195 print_offset = 1;
196 } else {
197 printf(" ");
198 }
199 }
200
201 if (!print_offset)
202 printf("\n");
203}
204
205int main(int argc, char **argv)
206{
207 struct statx stx;
208 int ret, raw = 0, atflag = AT_SYMLINK_NOFOLLOW;
209
210 unsigned int mask = STATX_ALL;
211
212 for (argv++; *argv; argv++) {
213 if (strcmp(*argv, "-F") == 0) {
214 atflag &= ~AT_STATX_SYNC_TYPE;
215 atflag |= AT_STATX_FORCE_SYNC;
216 continue;
217 }
218 if (strcmp(*argv, "-D") == 0) {
219 atflag &= ~AT_STATX_SYNC_TYPE;
220 atflag |= AT_STATX_DONT_SYNC;
221 continue;
222 }
223 if (strcmp(*argv, "-L") == 0) {
224 atflag &= ~AT_SYMLINK_NOFOLLOW;
225 continue;
226 }
227 if (strcmp(*argv, "-O") == 0) {
228 mask &= ~STATX_BASIC_STATS;
229 continue;
230 }
231 if (strcmp(*argv, "-A") == 0) {
232 atflag |= AT_NO_AUTOMOUNT;
233 continue;
234 }
235 if (strcmp(*argv, "-R") == 0) {
236 raw = 1;
237 continue;
238 }
239
240 memset(&stx, 0xbf, sizeof(stx));
241 ret = statx(AT_FDCWD, *argv, atflag, mask, &stx);
242 printf("statx(%s) = %d\n", *argv, ret);
243 if (ret < 0) {
244 perror(*argv);
245 exit(1);
246 }
247
248 if (raw)
249 dump_hex((unsigned long long *)&stx, 0, sizeof(stx));
250
251 dump_statx(&stx);
252 }
253 return 0;
254}