Commit 85710a83 authored by Weston Andros Adamson's avatar Weston Andros Adamson Committed by Trond Myklebust

nfs: nfs_page should take a ref on the head req

nfs_pages that aren't the the head of a group must take a reference on the
head as long as ->wb_head is set to it. This stops the head from hitting
a refcount of 0 while there is still an active nfs_page for the page group.

This avoids kref warnings in the writeback code when the page group head
is found and referenced.
Signed-off-by: default avatarWeston Andros Adamson <dros@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 17089a29
...@@ -239,15 +239,21 @@ nfs_page_group_init(struct nfs_page *req, struct nfs_page *prev) ...@@ -239,15 +239,21 @@ nfs_page_group_init(struct nfs_page *req, struct nfs_page *prev)
WARN_ON_ONCE(prev == req); WARN_ON_ONCE(prev == req);
if (!prev) { if (!prev) {
/* a head request */
req->wb_head = req; req->wb_head = req;
req->wb_this_page = req; req->wb_this_page = req;
} else { } else {
/* a subrequest */
WARN_ON_ONCE(prev->wb_this_page != prev->wb_head); WARN_ON_ONCE(prev->wb_this_page != prev->wb_head);
WARN_ON_ONCE(!test_bit(PG_HEADLOCK, &prev->wb_head->wb_flags)); WARN_ON_ONCE(!test_bit(PG_HEADLOCK, &prev->wb_head->wb_flags));
req->wb_head = prev->wb_head; req->wb_head = prev->wb_head;
req->wb_this_page = prev->wb_this_page; req->wb_this_page = prev->wb_this_page;
prev->wb_this_page = req; prev->wb_this_page = req;
/* All subrequests take a ref on the head request until
* nfs_page_group_destroy is called */
kref_get(&req->wb_head->wb_kref);
/* grab extra ref if head request has extra ref from /* grab extra ref if head request has extra ref from
* the write/commit path to handle handoff between write * the write/commit path to handle handoff between write
* and commit lists */ * and commit lists */
...@@ -271,6 +277,10 @@ nfs_page_group_destroy(struct kref *kref) ...@@ -271,6 +277,10 @@ 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 *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; return;
......
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