All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr()
@ 2017-03-31 17:31 David Howells
  2017-03-31 17:31 ` [PATCH 2/8] statx: reject unknown flags when using NULL path David Howells
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:31 UTC (permalink / raw)
  To: viro
  Cc: dhowells, Eric Biggers, linux-kernel, hch, linux-fsdevel,
	linux-ext4, linux-xfs

From: Eric Biggers <ebiggers@google.com>

Following the recent merge of statx, correct the documented prototype
for the ->getattr() inode operation, and add an entry to the porting
file.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 Documentation/filesystems/Locking |    3 +--
 Documentation/filesystems/porting |    6 ++++++
 Documentation/filesystems/vfs.txt |    3 +--
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index fdcfdd79682a..fe25787ff6d4 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -58,8 +58,7 @@ prototypes:
 	int (*permission) (struct inode *, int, unsigned int);
 	int (*get_acl)(struct inode *, int);
 	int (*setattr) (struct dentry *, struct iattr *);
-	int (*getattr) (const struct path *, struct dentry *, struct kstat *,
-			u32, unsigned int);
+	int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
 	void (*update_time)(struct inode *, struct timespec *, int);
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 95280079c0b3..5fb17f49f7a2 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -600,3 +600,9 @@ in your dentry operations instead.
 [recommended]
 	->readlink is optional for symlinks.  Don't set, unless filesystem needs
 	to fake something for readlink(2).
+--
+[mandatory]
+	->getattr() is now passed a struct path rather than a vfsmount and
+	dentry separately, and it now has request_mask and query_flags arguments
+	to specify the fields and sync type requested by statx.  Filesystems not
+	supporting any statx-specific features may ignore the new arguments.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 569211703721..94dd27ef4a76 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -382,8 +382,7 @@ struct inode_operations {
 	int (*permission) (struct inode *, int);
 	int (*get_acl)(struct inode *, int);
 	int (*setattr) (struct dentry *, struct iattr *);
-	int (*getattr) (const struct path *, struct dentry *, struct kstat *,
-			u32, unsigned int);
+	int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	void (*update_time)(struct inode *, struct timespec *, int);
 	int (*atomic_open)(struct inode *, struct dentry *, struct file *,

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/8] statx: reject unknown flags when using NULL path
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
@ 2017-03-31 17:31 ` David Howells
  2017-03-31 17:31 ` [PATCH 3/8] statx: remove incorrect part of vfs_statx() comment David Howells
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:31 UTC (permalink / raw)
  To: viro
  Cc: dhowells, Eric Biggers, linux-kernel, hch, linux-fsdevel,
	linux-ext4, linux-xfs

From: Eric Biggers <ebiggers@google.com>

The statx() system call currently accepts unknown flags when called with
a NULL path to operate on a file descriptor.  Left unchanged, this could
make it hard to introduce new query flags in the future, since
applications may not be able to tell whether a given flag is supported.

Fix this by failing the system call with EINVAL if any flags other than
KSTAT_QUERY_FLAGS are specified in combination with a NULL path.

Arguably, we could still permit known lookup-related flags such as
AT_SYMLINK_NOFOLLOW.  However, that would be inconsistent with how
sys_utimensat() behaves when passed a NULL path, which seems to be the
closest precedent.  And given that the NULL path case is (I believe)
mainly intended to be used to implement a wrapper function like fstatx()
that doesn't have a path argument, I think rejecting lookup-related
flags too is probably the best choice.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/stat.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/stat.c b/fs/stat.c
index fa0be59340cc..df484a60846d 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -130,9 +130,13 @@ EXPORT_SYMBOL(vfs_getattr);
 int vfs_statx_fd(unsigned int fd, struct kstat *stat,
 		 u32 request_mask, unsigned int query_flags)
 {
-	struct fd f = fdget_raw(fd);
+	struct fd f;
 	int error = -EBADF;
 
+	if (query_flags & ~KSTAT_QUERY_FLAGS)
+		return -EINVAL;
+
+	f = fdget_raw(fd);
 	if (f.file) {
 		error = vfs_getattr(&f.file->f_path, stat,
 				    request_mask, query_flags);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/8] statx: remove incorrect part of vfs_statx() comment
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
  2017-03-31 17:31 ` [PATCH 2/8] statx: reject unknown flags when using NULL path David Howells
@ 2017-03-31 17:31 ` David Howells
  2017-03-31 17:31 ` [PATCH 4/8] statx: optimize copy of struct statx to userspace David Howells
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:31 UTC (permalink / raw)
  To: viro
  Cc: dhowells, linux-xfs, Eric Biggers, linux-kernel, hch,
	linux-fsdevel, linux-ext4, Christoph Hellwig

From: Eric Biggers <ebiggers@google.com>

request_mask and query_flags are function arguments, not passed in
struct kstat.  So remove the part of the comment which claims otherwise.
This was apparently left over from an earlier version of the statx
patch.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---

 fs/stat.c |    3 ---
 1 file changed, 3 deletions(-)

diff --git a/fs/stat.c b/fs/stat.c
index df484a60846d..b792dd201c31 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -159,9 +159,6 @@ EXPORT_SYMBOL(vfs_statx_fd);
  * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
  * at the given name from being referenced.
  *
- * The caller must have preset stat->request_mask as for vfs_getattr().  The
- * flags are also used to load up stat->query_flags.
- *
  * 0 will be returned on success, and a -ve error code if unsuccessful.
  */
 int vfs_statx(int dfd, const char __user *filename, int flags,

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/8] statx: optimize copy of struct statx to userspace
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
  2017-03-31 17:31 ` [PATCH 2/8] statx: reject unknown flags when using NULL path David Howells
  2017-03-31 17:31 ` [PATCH 3/8] statx: remove incorrect part of vfs_statx() comment David Howells
@ 2017-03-31 17:31 ` David Howells
  2017-03-31 17:31 ` [PATCH 5/8] ext4: Add statx support David Howells
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:31 UTC (permalink / raw)
  To: viro
  Cc: dhowells, Eric Biggers, linux-kernel, hch, linux-fsdevel,
	linux-ext4, linux-xfs

From: Eric Biggers <ebiggers@google.com>

I found that statx() was significantly slower than stat().  As a
microbenchmark, I compared 10,000,000 invocations of fstat() on a tmpfs
file to the same with statx() passed a NULL path:

	$ time ./stat_benchmark

	real	0m1.464s
	user	0m0.275s
	sys	0m1.187s

	$ time ./statx_benchmark

	real	0m5.530s
	user	0m0.281s
	sys	0m5.247s

statx is expected to be a little slower than stat because struct statx
is larger than struct stat, but not by *that* much.  It turns out that
most of the overhead was in copying struct statx to userspace, mostly in
all the stac/clac instructions that got generated for each __put_user()
call.  (This was on x86_64, but some other architectures, e.g. arm64,
have something similar now too.)

stat() instead initializes its struct on the stack and copies it to
userspace with a single call to copy_to_user().  This turns out to be
much faster, and changing statx to do this makes it almost as fast as
stat:

	$ time ./statx_benchmark

	real	0m1.624s
	user	0m0.270s
	sys	0m1.354s

For zeroing the reserved fields, start by zeroing the full struct with
memset.  This makes it clear that every byte copied to userspace is
initialized, even implicit padding bytes (though there are none
currently).  In the scenarios I tested, it also performed the same as a
designated initializer.  Manually initializing each field was still
slightly faster, but would have been more error-prone and less
verifiable.

Also rename statx_set_result() to cp_statx() for consistency with
cp_old_stat() et al., and make it noinline so that struct statx doesn't
add to the stack usage during the main portion of the syscall execution.

Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/stat.c |   74 ++++++++++++++++++++++++++-----------------------------------
 1 file changed, 32 insertions(+), 42 deletions(-)

diff --git a/fs/stat.c b/fs/stat.c
index b792dd201c31..ab27f2868588 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -510,46 +510,37 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
 }
 #endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
 
-static inline int __put_timestamp(struct timespec *kts,
-				  struct statx_timestamp __user *uts)
+static noinline_for_stack int
+cp_statx(const struct kstat *stat, struct statx __user *buffer)
 {
-	return (__put_user(kts->tv_sec,		&uts->tv_sec		) ||
-		__put_user(kts->tv_nsec,	&uts->tv_nsec		) ||
-		__put_user(0,			&uts->__reserved	));
-}
-
-/*
- * Set the statx results.
- */
-static long statx_set_result(struct kstat *stat, struct statx __user *buffer)
-{
-	uid_t uid = from_kuid_munged(current_user_ns(), stat->uid);
-	gid_t gid = from_kgid_munged(current_user_ns(), stat->gid);
-
-	if (__put_user(stat->result_mask,	&buffer->stx_mask	) ||
-	    __put_user(stat->mode,		&buffer->stx_mode	) ||
-	    __clear_user(&buffer->__spare0, sizeof(buffer->__spare0))	  ||
-	    __put_user(stat->nlink,		&buffer->stx_nlink	) ||
-	    __put_user(uid,			&buffer->stx_uid	) ||
-	    __put_user(gid,			&buffer->stx_gid	) ||
-	    __put_user(stat->attributes,	&buffer->stx_attributes	) ||
-	    __put_user(stat->blksize,		&buffer->stx_blksize	) ||
-	    __put_user(MAJOR(stat->rdev),	&buffer->stx_rdev_major	) ||
-	    __put_user(MINOR(stat->rdev),	&buffer->stx_rdev_minor	) ||
-	    __put_user(MAJOR(stat->dev),	&buffer->stx_dev_major	) ||
-	    __put_user(MINOR(stat->dev),	&buffer->stx_dev_minor	) ||
-	    __put_timestamp(&stat->atime,	&buffer->stx_atime	) ||
-	    __put_timestamp(&stat->btime,	&buffer->stx_btime	) ||
-	    __put_timestamp(&stat->ctime,	&buffer->stx_ctime	) ||
-	    __put_timestamp(&stat->mtime,	&buffer->stx_mtime	) ||
-	    __put_user(stat->ino,		&buffer->stx_ino	) ||
-	    __put_user(stat->size,		&buffer->stx_size	) ||
-	    __put_user(stat->blocks,		&buffer->stx_blocks	) ||
-	    __clear_user(&buffer->__spare1, sizeof(buffer->__spare1))	  ||
-	    __clear_user(&buffer->__spare2, sizeof(buffer->__spare2)))
-		return -EFAULT;
-
-	return 0;
+	struct statx tmp;
+
+	memset(&tmp, 0, sizeof(tmp));
+
+	tmp.stx_mask = stat->result_mask;
+	tmp.stx_blksize = stat->blksize;
+	tmp.stx_attributes = stat->attributes;
+	tmp.stx_nlink = stat->nlink;
+	tmp.stx_uid = from_kuid_munged(current_user_ns(), stat->uid);
+	tmp.stx_gid = from_kgid_munged(current_user_ns(), stat->gid);
+	tmp.stx_mode = stat->mode;
+	tmp.stx_ino = stat->ino;
+	tmp.stx_size = stat->size;
+	tmp.stx_blocks = stat->blocks;
+	tmp.stx_atime.tv_sec = stat->atime.tv_sec;
+	tmp.stx_atime.tv_nsec = stat->atime.tv_nsec;
+	tmp.stx_btime.tv_sec = stat->btime.tv_sec;
+	tmp.stx_btime.tv_nsec = stat->btime.tv_nsec;
+	tmp.stx_ctime.tv_sec = stat->ctime.tv_sec;
+	tmp.stx_ctime.tv_nsec = stat->ctime.tv_nsec;
+	tmp.stx_mtime.tv_sec = stat->mtime.tv_sec;
+	tmp.stx_mtime.tv_nsec = stat->mtime.tv_nsec;
+	tmp.stx_rdev_major = MAJOR(stat->rdev);
+	tmp.stx_rdev_minor = MINOR(stat->rdev);
+	tmp.stx_dev_major = MAJOR(stat->dev);
+	tmp.stx_dev_minor = MINOR(stat->dev);
+
+	return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
 /**
@@ -573,8 +564,6 @@ SYSCALL_DEFINE5(statx,
 
 	if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
 		return -EINVAL;
-	if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer)))
-		return -EFAULT;
 
 	if (filename)
 		error = vfs_statx(dfd, filename, flags, &stat, mask);
@@ -582,7 +571,8 @@ SYSCALL_DEFINE5(statx,
 		error = vfs_statx_fd(dfd, &stat, mask, flags);
 	if (error)
 		return error;
-	return statx_set_result(&stat, buffer);
+
+	return cp_statx(&stat, buffer);
 }
 
 /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/8] ext4: Add statx support
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
                   ` (2 preceding siblings ...)
  2017-03-31 17:31 ` [PATCH 4/8] statx: optimize copy of struct statx to userspace David Howells
@ 2017-03-31 17:31 ` David Howells
  2017-03-31 17:32 ` [PATCH 6/8] xfs: report crtime and attribute flags to statx David Howells
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:31 UTC (permalink / raw)
  To: viro; +Cc: dhowells, linux-kernel, hch, linux-fsdevel, linux-ext4, linux-xfs

Return enhanced file attributes from the Ext4 filesystem.  This includes
the following:

 (1) The inode creation time (i_crtime) as stx_btime, setting STATX_BTIME.

 (2) Certain FS_xxx_FL flags are mapped to stx_attribute flags.

This requires that all ext4 inodes have a getattr call, not just some of
them, so to this end, split the ext4_getattr() function and only call part
of it where appropriate.

Example output:

	[root@andromeda ~]# touch foo
	[root@andromeda ~]# chattr +ai foo
	[root@andromeda ~]# /tmp/test-statx foo
	statx(foo) = 0
	results=fff
	  Size: 0               Blocks: 0          IO Block: 4096    regular file
	Device: 08:12           Inode: 2101950     Links: 1
	Access: (0644/-rw-r--r--)  Uid:     0   Gid:     0
	Access: 2016-02-11 17:08:29.031795451+0000
	Modify: 2016-02-11 17:08:29.031795451+0000
	Change: 2016-02-11 17:11:11.987790114+0000
	 Birth: 2016-02-11 17:08:29.031795451+0000
	Attributes: 0000000000000030 (-------- -------- -------- -------- -------- -------- -------- --ai----)

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/ext4/ext4.h    |    1 +
 fs/ext4/file.c    |    2 +-
 fs/ext4/inode.c   |   35 ++++++++++++++++++++++++++++++++---
 fs/ext4/namei.c   |    2 ++
 fs/ext4/symlink.c |    3 +++
 5 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f493af666591..fb69ee2388db 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2466,6 +2466,7 @@ extern int  ext4_setattr(struct dentry *, struct iattr *);
 extern int  ext4_getattr(const struct path *, struct kstat *, u32, unsigned int);
 extern void ext4_evict_inode(struct inode *);
 extern void ext4_clear_inode(struct inode *);
+extern int  ext4_file_getattr(const struct path *, struct kstat *, u32, unsigned int);
 extern int  ext4_sync_inode(handle_t *, struct inode *);
 extern void ext4_dirty_inode(struct inode *, int);
 extern int ext4_change_inode_journal_flag(struct inode *, int);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 8210c1f43556..cefa9835f275 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -744,7 +744,7 @@ const struct file_operations ext4_file_operations = {
 
 const struct inode_operations ext4_file_inode_operations = {
 	.setattr	= ext4_setattr,
-	.getattr	= ext4_getattr,
+	.getattr	= ext4_file_getattr,
 	.listxattr	= ext4_listxattr,
 	.get_acl	= ext4_get_acl,
 	.set_acl	= ext4_set_acl,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 4247d8d25687..5d02b922afa3 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5390,11 +5390,40 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 int ext4_getattr(const struct path *path, struct kstat *stat,
 		 u32 request_mask, unsigned int query_flags)
 {
-	struct inode *inode;
-	unsigned long long delalloc_blocks;
+	struct inode *inode = d_inode(path->dentry);
+	struct ext4_inode *raw_inode;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	unsigned int flags;
+
+	if (EXT4_FITS_IN_INODE(raw_inode, ei, i_crtime)) {
+		stat->result_mask |= STATX_BTIME;
+		stat->btime.tv_sec = ei->i_crtime.tv_sec;
+		stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
+	}
+
+	flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
+	if (flags & EXT4_APPEND_FL)
+		stat->attributes |= STATX_ATTR_APPEND;
+	if (flags & EXT4_COMPR_FL)
+		stat->attributes |= STATX_ATTR_COMPRESSED;
+	if (flags & EXT4_ENCRYPT_FL)
+		stat->attributes |= STATX_ATTR_ENCRYPTED;
+	if (flags & EXT4_IMMUTABLE_FL)
+		stat->attributes |= STATX_ATTR_IMMUTABLE;
+	if (flags & EXT4_NODUMP_FL)
+		stat->attributes |= STATX_ATTR_NODUMP;
 
-	inode = d_inode(path->dentry);
 	generic_fillattr(inode, stat);
+	return 0;
+}
+
+int ext4_file_getattr(const struct path *path, struct kstat *stat,
+		      u32 request_mask, unsigned int query_flags)
+{
+	struct inode *inode = d_inode(path->dentry);
+	u64 delalloc_blocks;
+
+	ext4_getattr(path, stat, request_mask, query_flags);
 
 	/*
 	 * If there is inline data in the inode, the inode will normally not
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 6ad612c576fc..07e5e1405771 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3912,6 +3912,7 @@ const struct inode_operations ext4_dir_inode_operations = {
 	.tmpfile	= ext4_tmpfile,
 	.rename		= ext4_rename2,
 	.setattr	= ext4_setattr,
+	.getattr	= ext4_getattr,
 	.listxattr	= ext4_listxattr,
 	.get_acl	= ext4_get_acl,
 	.set_acl	= ext4_set_acl,
@@ -3920,6 +3921,7 @@ const struct inode_operations ext4_dir_inode_operations = {
 
 const struct inode_operations ext4_special_inode_operations = {
 	.setattr	= ext4_setattr,
+	.getattr	= ext4_getattr,
 	.listxattr	= ext4_listxattr,
 	.get_acl	= ext4_get_acl,
 	.set_acl	= ext4_set_acl,
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index 73b184d161fc..5c8fc53cb0e5 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -85,17 +85,20 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry,
 const struct inode_operations ext4_encrypted_symlink_inode_operations = {
 	.get_link	= ext4_encrypted_get_link,
 	.setattr	= ext4_setattr,
+	.getattr	= ext4_getattr,
 	.listxattr	= ext4_listxattr,
 };
 
 const struct inode_operations ext4_symlink_inode_operations = {
 	.get_link	= page_get_link,
 	.setattr	= ext4_setattr,
+	.getattr	= ext4_getattr,
 	.listxattr	= ext4_listxattr,
 };
 
 const struct inode_operations ext4_fast_symlink_inode_operations = {
 	.get_link	= simple_get_link,
 	.setattr	= ext4_setattr,
+	.getattr	= ext4_getattr,
 	.listxattr	= ext4_listxattr,
 };

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/8] xfs: report crtime and attribute flags to statx
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
                   ` (3 preceding siblings ...)
  2017-03-31 17:31 ` [PATCH 5/8] ext4: Add statx support David Howells
@ 2017-03-31 17:32 ` David Howells
  2017-03-31 17:32 ` [PATCH 7/8] statx: Reserve the top bit of the mask for future struct expansion David Howells
  2017-03-31 17:32 ` [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx David Howells
  6 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:32 UTC (permalink / raw)
  To: viro
  Cc: dhowells, Darrick J. Wong, linux-kernel, hch, linux-fsdevel,
	linux-ext4, linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

statx has the ability to report inode creation times and inode flags, so
hook up di_crtime and di_flags to that functionality.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/xfs/xfs_iops.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 229cc6a6d8ef..ebfc13350f9a 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -516,6 +516,20 @@ xfs_vn_getattr(
 	stat->blocks =
 		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
 
+	if (ip->i_d.di_version == 3) {
+		if (request_mask & STATX_BTIME) {
+			stat->result_mask |= STATX_BTIME;
+			stat->btime.tv_sec = ip->i_d.di_crtime.t_sec;
+			stat->btime.tv_nsec = ip->i_d.di_crtime.t_nsec;
+		}
+	}
+
+	if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
+		stat->attributes |= STATX_ATTR_IMMUTABLE;
+	if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
+		stat->attributes |= STATX_ATTR_APPEND;
+	if (ip->i_d.di_flags & XFS_DIFLAG_NODUMP)
+		stat->attributes |= STATX_ATTR_NODUMP;
 
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFBLK:

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/8] statx: Reserve the top bit of the mask for future struct expansion
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
                   ` (4 preceding siblings ...)
  2017-03-31 17:32 ` [PATCH 6/8] xfs: report crtime and attribute flags to statx David Howells
@ 2017-03-31 17:32 ` David Howells
  2017-03-31 17:32 ` [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx David Howells
  6 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:32 UTC (permalink / raw)
  To: viro; +Cc: dhowells, linux-kernel, hch, linux-fsdevel, linux-ext4, linux-xfs

Reserve the top bit of the mask for future expansion of the statx struct
and give an error if statx() sees it set.  All the other bits are ignored
if we see them set but don't support the bit; we just clear the bit in the
returned mask.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/stat.c                 |    2 ++
 include/uapi/linux/stat.h |    1 +
 2 files changed, 3 insertions(+)

diff --git a/fs/stat.c b/fs/stat.c
index ab27f2868588..0c7e6cdc435c 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -562,6 +562,8 @@ SYSCALL_DEFINE5(statx,
 	struct kstat stat;
 	int error;
 
+	if (mask & STATX__RESERVED)
+		return -EINVAL;
 	if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
 		return -EINVAL;
 
diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h
index 51a6b86e3700..0869b9eaa8ce 100644
--- a/include/uapi/linux/stat.h
+++ b/include/uapi/linux/stat.h
@@ -152,6 +152,7 @@ struct statx {
 #define STATX_BASIC_STATS	0x000007ffU	/* The stuff in the normal stat struct */
 #define STATX_BTIME		0x00000800U	/* Want/got stx_btime */
 #define STATX_ALL		0x00000fffU	/* All currently supported flags */
+#define STATX__RESERVED		0x80000000U	/* Reserved for future struct statx expansion */
 
 /*
  * Attributes to be found in stx_attributes

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx
  2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
                   ` (5 preceding siblings ...)
  2017-03-31 17:32 ` [PATCH 7/8] statx: Reserve the top bit of the mask for future struct expansion David Howells
@ 2017-03-31 17:32 ` David Howells
  2017-03-31 17:41   ` Darrick J. Wong
  2017-04-04  7:12   ` Christoph Hellwig
  6 siblings, 2 replies; 11+ messages in thread
From: David Howells @ 2017-03-31 17:32 UTC (permalink / raw)
  To: viro; +Cc: dhowells, linux-kernel, hch, linux-fsdevel, linux-ext4, linux-xfs

Include a mask in struct stat to indicate which bits of stx_attributes the
filesystem actually supports.

This would also be useful if we add another system call that allows you to
do a 'bulk attribute set' and pass in a statx struct with the masks
appropriately set to say what you want to set.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/ext4/inode.c            |    6 ++++++
 fs/stat.c                  |    1 +
 include/linux/stat.h       |    1 +
 include/uapi/linux/stat.h  |    4 ++--
 samples/statx/test-statx.c |   12 ++++++++----
 5 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5d02b922afa3..349f97ae3c87 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5413,6 +5413,12 @@ int ext4_getattr(const struct path *path, struct kstat *stat,
 	if (flags & EXT4_NODUMP_FL)
 		stat->attributes |= STATX_ATTR_NODUMP;
 
+	stat->attributes_mask |= (STATX_ATTR_APPEND |
+				  STATX_ATTR_COMPRESSED |
+				  STATX_ATTR_ENCRYPTED |
+				  STATX_ATTR_IMMUTABLE |
+				  STATX_ATTR_NODUMP);
+	
 	generic_fillattr(inode, stat);
 	return 0;
 }
diff --git a/fs/stat.c b/fs/stat.c
index 0c7e6cdc435c..c6c963b2546b 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -527,6 +527,7 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
 	tmp.stx_ino = stat->ino;
 	tmp.stx_size = stat->size;
 	tmp.stx_blocks = stat->blocks;
+	tmp.stx_attributes_mask = stat->attributes_mask;
 	tmp.stx_atime.tv_sec = stat->atime.tv_sec;
 	tmp.stx_atime.tv_nsec = stat->atime.tv_nsec;
 	tmp.stx_btime.tv_sec = stat->btime.tv_sec;
diff --git a/include/linux/stat.h b/include/linux/stat.h
index c76e524fb34b..64b6b3aece21 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -26,6 +26,7 @@ struct kstat {
 	unsigned int	nlink;
 	uint32_t	blksize;	/* Preferred I/O size */
 	u64		attributes;
+	u64		attributes_mask;
 #define KSTAT_ATTR_FS_IOC_FLAGS				\
 	(STATX_ATTR_COMPRESSED |			\
 	 STATX_ATTR_IMMUTABLE |				\
diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h
index 0869b9eaa8ce..d538897b8e08 100644
--- a/include/uapi/linux/stat.h
+++ b/include/uapi/linux/stat.h
@@ -114,7 +114,7 @@ struct statx {
 	__u64	stx_ino;	/* Inode number */
 	__u64	stx_size;	/* File size */
 	__u64	stx_blocks;	/* Number of 512-byte blocks allocated */
-	__u64	__spare1[1];
+	__u64	stx_attributes_mask; /* Mask to show what's supported in stx_attributes */
 	/* 0x40 */
 	struct statx_timestamp	stx_atime;	/* Last access time */
 	struct statx_timestamp	stx_btime;	/* File creation time */
@@ -155,7 +155,7 @@ struct statx {
 #define STATX__RESERVED		0x80000000U	/* Reserved for future struct statx expansion */
 
 /*
- * Attributes to be found in stx_attributes
+ * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
  *
  * These give information about the features or the state of a file that might
  * be of use to ordinary userspace programs such as GUIs or ls rather than
diff --git a/samples/statx/test-statx.c b/samples/statx/test-statx.c
index 8571d766331d..d4d77b09412c 100644
--- a/samples/statx/test-statx.c
+++ b/samples/statx/test-statx.c
@@ -141,8 +141,8 @@ static void dump_statx(struct statx *stx)
 	if (stx->stx_mask & STATX_BTIME)
 		print_time(" Birth: ", &stx->stx_btime);
 
-	if (stx->stx_attributes) {
-		unsigned char bits;
+	if (stx->stx_attributes_mask) {
+		unsigned char bits, mbits;
 		int loop, byte;
 
 		static char attr_representation[64 + 1] =
@@ -160,14 +160,18 @@ static void dump_statx(struct statx *stx)
 		printf("Attributes: %016llx (", stx->stx_attributes);
 		for (byte = 64 - 8; byte >= 0; byte -= 8) {
 			bits = stx->stx_attributes >> byte;
+			mbits = stx->stx_attributes_mask >> byte;
 			for (loop = 7; loop >= 0; loop--) {
 				int bit = byte + loop;
 
-				if (bits & 0x80)
+				if (!(mbits & 0x80))
+					putchar('.');	/* Not supported */
+				else if (bits & 0x80)
 					putchar(attr_representation[63 - bit]);
 				else
-					putchar('-');
+					putchar('-');	/* Not set */
 				bits <<= 1;
+				mbits <<= 1;
 			}
 			if (byte)
 				putchar(' ');

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx
  2017-03-31 17:32 ` [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx David Howells
@ 2017-03-31 17:41   ` Darrick J. Wong
  2017-04-04  7:12   ` Christoph Hellwig
  1 sibling, 0 replies; 11+ messages in thread
From: Darrick J. Wong @ 2017-03-31 17:41 UTC (permalink / raw)
  To: David Howells
  Cc: viro, linux-kernel, hch, linux-fsdevel, linux-ext4, linux-xfs

On Fri, Mar 31, 2017 at 06:32:17PM +0100, David Howells wrote:
> Include a mask in struct stat to indicate which bits of stx_attributes the
> filesystem actually supports.
> 
> This would also be useful if we add another system call that allows you to
> do a 'bulk attribute set' and pass in a statx struct with the masks
> appropriately set to say what you want to set.
> 
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> 
>  fs/ext4/inode.c            |    6 ++++++
>  fs/stat.c                  |    1 +
>  include/linux/stat.h       |    1 +
>  include/uapi/linux/stat.h  |    4 ++--
>  samples/statx/test-statx.c |   12 ++++++++----
>  5 files changed, 18 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 5d02b922afa3..349f97ae3c87 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5413,6 +5413,12 @@ int ext4_getattr(const struct path *path, struct kstat *stat,
>  	if (flags & EXT4_NODUMP_FL)
>  		stat->attributes |= STATX_ATTR_NODUMP;
>  
> +	stat->attributes_mask |= (STATX_ATTR_APPEND |
> +				  STATX_ATTR_COMPRESSED |

ext4 doesn't actually support compressed files.

(I know, the feature/inode flags exist, but there's no code and afaik
probably never will be...)

--D

> +				  STATX_ATTR_ENCRYPTED |
> +				  STATX_ATTR_IMMUTABLE |
> +				  STATX_ATTR_NODUMP);
> +	
>  	generic_fillattr(inode, stat);
>  	return 0;
>  }
> diff --git a/fs/stat.c b/fs/stat.c
> index 0c7e6cdc435c..c6c963b2546b 100644
> --- a/fs/stat.c
> +++ b/fs/stat.c
> @@ -527,6 +527,7 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
>  	tmp.stx_ino = stat->ino;
>  	tmp.stx_size = stat->size;
>  	tmp.stx_blocks = stat->blocks;
> +	tmp.stx_attributes_mask = stat->attributes_mask;
>  	tmp.stx_atime.tv_sec = stat->atime.tv_sec;
>  	tmp.stx_atime.tv_nsec = stat->atime.tv_nsec;
>  	tmp.stx_btime.tv_sec = stat->btime.tv_sec;
> diff --git a/include/linux/stat.h b/include/linux/stat.h
> index c76e524fb34b..64b6b3aece21 100644
> --- a/include/linux/stat.h
> +++ b/include/linux/stat.h
> @@ -26,6 +26,7 @@ struct kstat {
>  	unsigned int	nlink;
>  	uint32_t	blksize;	/* Preferred I/O size */
>  	u64		attributes;
> +	u64		attributes_mask;
>  #define KSTAT_ATTR_FS_IOC_FLAGS				\
>  	(STATX_ATTR_COMPRESSED |			\
>  	 STATX_ATTR_IMMUTABLE |				\
> diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h
> index 0869b9eaa8ce..d538897b8e08 100644
> --- a/include/uapi/linux/stat.h
> +++ b/include/uapi/linux/stat.h
> @@ -114,7 +114,7 @@ struct statx {
>  	__u64	stx_ino;	/* Inode number */
>  	__u64	stx_size;	/* File size */
>  	__u64	stx_blocks;	/* Number of 512-byte blocks allocated */
> -	__u64	__spare1[1];
> +	__u64	stx_attributes_mask; /* Mask to show what's supported in stx_attributes */
>  	/* 0x40 */
>  	struct statx_timestamp	stx_atime;	/* Last access time */
>  	struct statx_timestamp	stx_btime;	/* File creation time */
> @@ -155,7 +155,7 @@ struct statx {
>  #define STATX__RESERVED		0x80000000U	/* Reserved for future struct statx expansion */
>  
>  /*
> - * Attributes to be found in stx_attributes
> + * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
>   *
>   * These give information about the features or the state of a file that might
>   * be of use to ordinary userspace programs such as GUIs or ls rather than
> diff --git a/samples/statx/test-statx.c b/samples/statx/test-statx.c
> index 8571d766331d..d4d77b09412c 100644
> --- a/samples/statx/test-statx.c
> +++ b/samples/statx/test-statx.c
> @@ -141,8 +141,8 @@ static void dump_statx(struct statx *stx)
>  	if (stx->stx_mask & STATX_BTIME)
>  		print_time(" Birth: ", &stx->stx_btime);
>  
> -	if (stx->stx_attributes) {
> -		unsigned char bits;
> +	if (stx->stx_attributes_mask) {
> +		unsigned char bits, mbits;
>  		int loop, byte;
>  
>  		static char attr_representation[64 + 1] =
> @@ -160,14 +160,18 @@ static void dump_statx(struct statx *stx)
>  		printf("Attributes: %016llx (", stx->stx_attributes);
>  		for (byte = 64 - 8; byte >= 0; byte -= 8) {
>  			bits = stx->stx_attributes >> byte;
> +			mbits = stx->stx_attributes_mask >> byte;
>  			for (loop = 7; loop >= 0; loop--) {
>  				int bit = byte + loop;
>  
> -				if (bits & 0x80)
> +				if (!(mbits & 0x80))
> +					putchar('.');	/* Not supported */
> +				else if (bits & 0x80)
>  					putchar(attr_representation[63 - bit]);
>  				else
> -					putchar('-');
> +					putchar('-');	/* Not set */
>  				bits <<= 1;
> +				mbits <<= 1;
>  			}
>  			if (byte)
>  				putchar(' ');
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx
  2017-03-31 17:32 ` [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx David Howells
  2017-03-31 17:41   ` Darrick J. Wong
@ 2017-04-04  7:12   ` Christoph Hellwig
  2017-04-12 15:12     ` Christoph Hellwig
  1 sibling, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-04  7:12 UTC (permalink / raw)
  To: David Howells
  Cc: viro, linux-kernel, hch, linux-fsdevel, linux-ext4, linux-xfs

On Fri, Mar 31, 2017 at 06:32:17PM +0100, David Howells wrote:
> Include a mask in struct stat to indicate which bits of stx_attributes the
> filesystem actually supports.

What's the use case for this?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx
  2017-04-04  7:12   ` Christoph Hellwig
@ 2017-04-12 15:12     ` Christoph Hellwig
  0 siblings, 0 replies; 11+ messages in thread
From: Christoph Hellwig @ 2017-04-12 15:12 UTC (permalink / raw)
  To: David Howells
  Cc: viro, linux-kernel, hch, linux-fsdevel, linux-ext4, linux-xfs

On Tue, Apr 04, 2017 at 12:12:52AM -0700, Christoph Hellwig wrote:
> On Fri, Mar 31, 2017 at 06:32:17PM +0100, David Howells wrote:
> > Include a mask in struct stat to indicate which bits of stx_attributes the
> > filesystem actually supports.
> 
> What's the use case for this?

ping!

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-04-12 15:12 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-31 17:31 [PATCH 1/8] Documentation/filesystems: fix documentation for ->getattr() David Howells
2017-03-31 17:31 ` [PATCH 2/8] statx: reject unknown flags when using NULL path David Howells
2017-03-31 17:31 ` [PATCH 3/8] statx: remove incorrect part of vfs_statx() comment David Howells
2017-03-31 17:31 ` [PATCH 4/8] statx: optimize copy of struct statx to userspace David Howells
2017-03-31 17:31 ` [PATCH 5/8] ext4: Add statx support David Howells
2017-03-31 17:32 ` [PATCH 6/8] xfs: report crtime and attribute flags to statx David Howells
2017-03-31 17:32 ` [PATCH 7/8] statx: Reserve the top bit of the mask for future struct expansion David Howells
2017-03-31 17:32 ` [PATCH 8/8] statx: Include a mask for stx_attributes in struct statx David Howells
2017-03-31 17:41   ` Darrick J. Wong
2017-04-04  7:12   ` Christoph Hellwig
2017-04-12 15:12     ` Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.