diff options
| author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2025-08-16 17:25:20 +0300 |
|---|---|---|
| committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2025-08-19 21:16:02 +0300 |
| commit | 76d2e3890fb169168c73f2e4f8375c7cc24a765e (patch) | |
| tree | 5d23b867c67851ea8ba45cbbd2ad1a85b74e3cc0 /include | |
| parent | c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9 (diff) | |
| download | linux-76d2e3890fb169168c73f2e4f8375c7cc24a765e.tar.xz | |
NFS: Fix a race when updating an existing write
After nfs_lock_and_join_requests() tests for whether the request is
still attached to the mapping, nothing prevents a call to
nfs_inode_remove_request() from succeeding until we actually lock the
page group.
The reason is that whoever called nfs_inode_remove_request() doesn't
necessarily have a lock on the page group head.
So in order to avoid races, let's take the page group lock earlier in
nfs_lock_and_join_requests(), and hold it across the removal of the
request in nfs_inode_remove_request().
Reported-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Joe Quanaim <jdq@meta.com>
Tested-by: Andrew Steffen <aksteffen@meta.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Fixes: bd37d6fce184 ("NFSv4: Convert nfs_lock_and_join_requests() to use nfs_page_find_head_request()")
Cc: stable@vger.kernel.org
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/nfs_page.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 169b4ae30ff4..9aed39abc94b 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -160,6 +160,7 @@ extern void nfs_join_page_group(struct nfs_page *head, extern int nfs_page_group_lock(struct nfs_page *); extern void nfs_page_group_unlock(struct nfs_page *); extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); +extern bool nfs_page_group_sync_on_bit_locked(struct nfs_page *, unsigned int); extern int nfs_page_set_headlock(struct nfs_page *req); extern void nfs_page_clear_headlock(struct nfs_page *req); extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *); |
