NFS: Fix races nfs_page_group_destroy() vs nfs_destroy_unlinked_subrequests()
When a subrequest is being detached from the subgroup, we want to
ensure that it is not holding the group lock, or in the process
of waiting for the group lock.
Fixes: 5b2b5187fa
("NFS: Fix nfs_page_group_destroy() and nfs_lock_and_join_requests() race cases")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
@@ -428,22 +428,28 @@ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list,
|
||||
destroy_list = (subreq->wb_this_page == old_head) ?
|
||||
NULL : subreq->wb_this_page;
|
||||
|
||||
/* Note: lock subreq in order to change subreq->wb_head */
|
||||
nfs_page_set_headlock(subreq);
|
||||
WARN_ON_ONCE(old_head != subreq->wb_head);
|
||||
|
||||
/* make sure old group is not used */
|
||||
subreq->wb_this_page = subreq;
|
||||
subreq->wb_head = subreq;
|
||||
|
||||
clear_bit(PG_REMOVE, &subreq->wb_flags);
|
||||
|
||||
/* Note: races with nfs_page_group_destroy() */
|
||||
if (!kref_read(&subreq->wb_kref)) {
|
||||
/* Check if we raced with nfs_page_group_destroy() */
|
||||
if (test_and_clear_bit(PG_TEARDOWN, &subreq->wb_flags))
|
||||
if (test_and_clear_bit(PG_TEARDOWN, &subreq->wb_flags)) {
|
||||
nfs_page_clear_headlock(subreq);
|
||||
nfs_free_request(subreq);
|
||||
} else
|
||||
nfs_page_clear_headlock(subreq);
|
||||
continue;
|
||||
}
|
||||
nfs_page_clear_headlock(subreq);
|
||||
|
||||
subreq->wb_head = subreq;
|
||||
nfs_release_request(old_head);
|
||||
|
||||
if (test_and_clear_bit(PG_INODE_REF, &subreq->wb_flags)) {
|
||||
|
Reference in New Issue
Block a user