Commit 08fead2a authored by Trond Myklebust's avatar Trond Myklebust

NFS: Ensure we always dereference the page head last

This fixes a race with nfs_page_group_sync_on_bit() whereby the
call to wake_up_bit() in nfs_page_group_unlock() could occur after
the page header had been freed.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 1403390d
...@@ -306,14 +306,11 @@ static void ...@@ -306,14 +306,11 @@ static void
nfs_page_group_destroy(struct kref *kref) nfs_page_group_destroy(struct kref *kref)
{ {
struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref); struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
struct nfs_page *head = req->wb_head;
struct nfs_page *tmp, *next; struct nfs_page *tmp, *next;
/* subrequests must release the ref on the head request */
if (req->wb_head != req)
nfs_release_request(req->wb_head);
if (!nfs_page_group_sync_on_bit(req, PG_TEARDOWN)) if (!nfs_page_group_sync_on_bit(req, PG_TEARDOWN))
return; goto out;
tmp = req; tmp = req;
do { do {
...@@ -324,6 +321,10 @@ nfs_page_group_destroy(struct kref *kref) ...@@ -324,6 +321,10 @@ nfs_page_group_destroy(struct kref *kref)
nfs_free_request(tmp); nfs_free_request(tmp);
tmp = next; tmp = next;
} while (tmp != req); } while (tmp != req);
out:
/* subrequests must release the ref on the head request */
if (head != req)
nfs_release_request(head);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment