All of lore.kernel.org
 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 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.