linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jens Axboe <axboe@kernel.dk>
To: linux-fsdevel@vger.kernel.org, io-uring@vger.kernel.org
Cc: torvalds@linux-foundation.org, viro@zeniv.linux.org.uk,
	Jens Axboe <axboe@kernel.dk>
Subject: [PATCH 2/3] fs: ensure that ->getattr() honors AT_STATX_CACHED
Date: Mon, 25 Jan 2021 14:36:13 -0700	[thread overview]
Message-ID: <20210125213614.24001-3-axboe@kernel.dk> (raw)
In-Reply-To: <20210125213614.24001-1-axboe@kernel.dk>

For filesystems that provide a private ->getattr() implementation, some of
them need to do IO to satisfy the request. If we need to block off
->getattr() and AT_STATX_CACHED is set, then return -EAGAIN and have the
caller retry.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 fs/9p/vfs_inode.c   | 2 ++
 fs/afs/inode.c      | 3 +++
 fs/ceph/inode.c     | 2 ++
 fs/cifs/inode.c     | 3 +++
 fs/coda/inode.c     | 7 ++++++-
 fs/ecryptfs/inode.c | 3 +++
 fs/fuse/dir.c       | 2 ++
 fs/gfs2/inode.c     | 2 ++
 fs/kernfs/inode.c   | 8 +++++++-
 fs/nfs/inode.c      | 3 +++
 fs/ocfs2/file.c     | 3 +++
 fs/orangefs/inode.c | 3 +++
 fs/ubifs/dir.c      | 7 ++++++-
 fs/udf/symlink.c    | 3 +++
 fs/vboxsf/utils.c   | 4 ++++
 15 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 4a937fac1acb..291d74bcf582 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1030,6 +1030,8 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
 		generic_fillattr(d_inode(dentry), stat);
 		return 0;
 	}
+	if (flags & AT_STATX_CACHED)
+		return -EAGAIN;
 	fid = v9fs_fid_lookup(dentry);
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index b0d7b892090d..19ba728ff18f 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -743,6 +743,9 @@ int afs_getattr(const struct path *path, struct kstat *stat,
 
 	_enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
 
+	if (query_flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
 	do {
 		read_seqbegin_or_lock(&vnode->cb_lock, &seq);
 		generic_fillattr(inode, stat);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index adc8fc3c5d85..997f380646fd 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2378,6 +2378,8 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
 
 	/* Skip the getattr altogether if we're asked not to sync */
 	if (!(flags & AT_STATX_DONT_SYNC)) {
+		if (flags & AT_STATX_CACHED)
+			return -EAGAIN;
 		err = ceph_do_getattr(inode,
 				statx_to_caps(request_mask, inode->i_mode),
 				flags & AT_STATX_FORCE_SYNC);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a83b3a8ffaac..1f8007caa27c 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -2379,6 +2379,9 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
 	struct inode *inode = d_inode(dentry);
 	int rc;
 
+	if (flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
 	/*
 	 * We need to be sure that all dirty pages are written and the server
 	 * has actual ctime, mtime and file length.
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index b1c70e2b9b1e..444f1ef97b08 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -254,7 +254,12 @@ static void coda_evict_inode(struct inode *inode)
 int coda_getattr(const struct path *path, struct kstat *stat,
 		 u32 request_mask, unsigned int flags)
 {
-	int err = coda_revalidate_inode(d_inode(path->dentry));
+	int err;
+
+	if (flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
+	err = coda_revalidate_inode(d_inode(path->dentry));
 	if (!err)
 		generic_fillattr(d_inode(path->dentry), stat);
 	return err;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index e23752d9a79f..61fdb5a0dbdc 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -980,6 +980,9 @@ static int ecryptfs_getattr_link(const struct path *path, struct kstat *stat,
 		char *target;
 		size_t targetsiz;
 
+		if (flags & AT_STATX_CACHED)
+			return -EAGAIN;
+
 		target = ecryptfs_readlink_lower(dentry, &targetsiz);
 		if (!IS_ERR(target)) {
 			kfree(target);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 78f9f209078c..638722d3c1ed 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1084,6 +1084,8 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
 		sync = time_before64(fi->i_time, get_jiffies_64());
 
 	if (sync) {
+		if (flags & AT_STATX_CACHED)
+			return -EAGAIN;
 		forget_all_cached_acls(inode);
 		err = fuse_do_getattr(inode, stat, file);
 	} else if (stat) {
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index c1b77e8d6b1c..3d485d9f1afe 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2032,6 +2032,8 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat,
 
 	gfs2_holder_mark_uninitialized(&gh);
 	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+		if (flags & AT_STATX_CACHED)
+			return -EAGAIN;
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
 		if (error)
 			return error;
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index fc2469a20fed..2193b3c0b9cd 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -189,7 +189,13 @@ int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
 	struct inode *inode = d_inode(path->dentry);
 	struct kernfs_node *kn = inode->i_private;
 
-	mutex_lock(&kernfs_mutex);
+	if (query_flags & AT_STATX_CACHED) {
+		if (!mutex_trylock(&kernfs_mutex))
+			return -EAGAIN;
+	} else {
+		mutex_lock(&kernfs_mutex);
+	}
+
 	kernfs_refresh_inode(kn, inode);
 	mutex_unlock(&kernfs_mutex);
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 522aa10a1a3e..1eb167c14884 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -799,6 +799,9 @@ int nfs_getattr(const struct path *path, struct kstat *stat,
 
 	trace_nfs_getattr_enter(inode);
 
+	if (query_flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
 	if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) {
 		nfs_readdirplus_parent_cache_hit(path->dentry);
 		goto out_no_update;
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 85979e2214b3..e48d0c33fb46 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1306,6 +1306,9 @@ int ocfs2_getattr(const struct path *path, struct kstat *stat,
 	struct ocfs2_super *osb = sb->s_fs_info;
 	int err;
 
+	if (flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
 	err = ocfs2_inode_revalidate(path->dentry);
 	if (err) {
 		if (err != -ENOENT)
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 48f0547d4850..4864334e40e8 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -900,6 +900,9 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
 		     "orangefs_getattr: called on %pd mask %u\n",
 		     path->dentry, request_mask);
 
+	if (flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
 	ret = orangefs_inode_getattr(inode,
 	    request_mask & STATX_SIZE ? ORANGEFS_GETATTR_SIZE : 0);
 	if (ret == 0) {
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 9a6b8660425a..c199b260c50c 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1573,7 +1573,12 @@ int ubifs_getattr(const struct path *path, struct kstat *stat,
 	struct inode *inode = d_inode(path->dentry);
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
-	mutex_lock(&ui->ui_mutex);
+	if (flags & AT_STATX_CACHED) {
+		if (!mutex_trylock(&ui->ui_mutex))
+			return -EAGAIN;
+	} else {
+		mutex_lock(&ui->ui_mutex);
+	}
 
 	if (ui->flags & UBIFS_APPEND_FL)
 		stat->attributes |= STATX_ATTR_APPEND;
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index c973db239604..0edd973b8a43 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -159,6 +159,9 @@ static int udf_symlink_getattr(const struct path *path, struct kstat *stat,
 	struct inode *inode = d_backing_inode(dentry);
 	struct page *page;
 
+	if (flags & AT_STATX_CACHED)
+		return -EAGAIN;
+
 	generic_fillattr(inode, stat);
 	page = read_mapping_page(inode->i_mapping, 0, NULL);
 	if (IS_ERR(page))
diff --git a/fs/vboxsf/utils.c b/fs/vboxsf/utils.c
index 018057546067..dc93cd59290d 100644
--- a/fs/vboxsf/utils.c
+++ b/fs/vboxsf/utils.c
@@ -228,6 +228,10 @@ int vboxsf_getattr(const struct path *path, struct kstat *kstat,
 		sf_i->force_restat = 1;
 		fallthrough;
 	default:
+		if (flags & AT_STATX_CACHED) {
+			err = -EAGAIN;
+			break;
+		}
 		err = vboxsf_inode_revalidate(dentry);
 	}
 	if (err)
-- 
2.30.0


  parent reply	other threads:[~2021-01-25 21:56 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-25 21:36 [PATCHSET RFC] support RESOLVE_CACHED for statx Jens Axboe
2021-01-25 21:36 ` [PATCH 1/3] fs: add support for AT_STATX_CACHED Jens Axboe
2021-01-25 21:36 ` Jens Axboe [this message]
2021-01-25 21:36 ` [PATCH 3/3] io_uring: use AT_STATX_CACHED for IORING_OP_STATX fast path Jens Axboe
2021-01-25 23:39 ` [PATCHSET RFC] support RESOLVE_CACHED for statx Linus Torvalds
2021-01-26  1:06   ` Jens Axboe
2021-01-26  1:28     ` Linus Torvalds
2021-01-26  1:31       ` Jens Axboe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210125213614.24001-3-axboe@kernel.dk \
    --to=axboe@kernel.dk \
    --cc=io-uring@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).