aboutsummaryrefslogtreecommitdiffstats
path: root/fs/netfs/buffered_read.c
diff options
context:
space:
mode:
authorXiubo Li <[email protected]>2022-07-11 04:11:21 +0000
committerIlya Dryomov <[email protected]>2022-07-14 08:10:12 +0000
commitfac47b43c760ea90e64b895dba60df0327be7775 (patch)
treece9fe5b54a150c80acf4683288924f94a6b5cfc8 /fs/netfs/buffered_read.c
parentLinux 5.19-rc6 (diff)
downloadkernel-fac47b43c760ea90e64b895dba60df0327be7775.tar.gz
kernel-fac47b43c760ea90e64b895dba60df0327be7775.zip
netfs: do not unlock and put the folio twice
check_write_begin() will unlock and put the folio when return non-zero. So we should avoid unlocking and putting it twice in netfs layer. Change the way ->check_write_begin() works in the following two ways: (1) Pass it a pointer to the folio pointer, allowing it to unlock and put the folio prior to doing the stuff it wants to do, provided it clears the folio pointer. (2) Change the return values such that 0 with folio pointer set means continue, 0 with folio pointer cleared means re-get and all error codes indicating an error (no special treatment for -EAGAIN). [ bagasdotme: use Sphinx code text syntax for *foliop pointer ] Cc: [email protected] Link: https://tracker.ceph.com/issues/56423 Link: https://lore.kernel.org/r/[email protected] Co-developed-by: David Howells <[email protected]> Signed-off-by: Xiubo Li <[email protected]> Signed-off-by: David Howells <[email protected]> Signed-off-by: Bagas Sanjaya <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
Diffstat (limited to 'fs/netfs/buffered_read.c')
-rw-r--r--fs/netfs/buffered_read.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c
index 42f892c5712e..0ce535852151 100644
--- a/fs/netfs/buffered_read.c
+++ b/fs/netfs/buffered_read.c
@@ -319,8 +319,9 @@ zero_out:
* conflicting writes once the folio is grabbed and locked. It is passed a
* pointer to the fsdata cookie that gets returned to the VM to be passed to
* write_end. It is permitted to sleep. It should return 0 if the request
- * should go ahead; unlock the folio and return -EAGAIN to cause the folio to
- * be regot; or return an error.
+ * should go ahead or it may return an error. It may also unlock and put the
+ * folio, provided it sets ``*foliop`` to NULL, in which case a return of 0
+ * will cause the folio to be re-got and the process to be retried.
*
* The calling netfs must initialise a netfs context contiguous to the vfs
* inode before calling this.
@@ -348,13 +349,13 @@ retry:
if (ctx->ops->check_write_begin) {
/* Allow the netfs (eg. ceph) to flush conflicts. */
- ret = ctx->ops->check_write_begin(file, pos, len, folio, _fsdata);
+ ret = ctx->ops->check_write_begin(file, pos, len, &folio, _fsdata);
if (ret < 0) {
trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin);
- if (ret == -EAGAIN)
- goto retry;
goto error;
}
+ if (!folio)
+ goto retry;
}
if (folio_test_uptodate(folio))
@@ -416,8 +417,10 @@ have_folio_no_wait:
error_put:
netfs_put_request(rreq, false, netfs_rreq_trace_put_failed);
error:
- folio_unlock(folio);
- folio_put(folio);
+ if (folio) {
+ folio_unlock(folio);
+ folio_put(folio);
+ }
_leave(" = %d", ret);
return ret;
}