diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-01 12:06:30 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-15 11:54:47 -0400 |
commit | bd37d6fce184836bd5e7cd90ce40116a4fadaf2a (patch) | |
tree | e78e447ff93a80dcf5d8b5311d1a57bb6d16a611 /fs/nfs/write.c | |
parent | 7e8a30f8b497315a6467d86c82f6cc8acaa9db61 (diff) |
NFSv4: Convert nfs_lock_and_join_requests() to use nfs_page_find_head_request()
Hide the locking from nfs_lock_and_join_requests() so that we can
separate out the requirements for swapcache pages.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 759e37d26acf..a06167e20b72 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -154,6 +154,14 @@ static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | |||
154 | set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | 154 | set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
155 | } | 155 | } |
156 | 156 | ||
157 | static struct nfs_page * | ||
158 | nfs_page_private_request(struct page *page) | ||
159 | { | ||
160 | if (!PagePrivate(page)) | ||
161 | return NULL; | ||
162 | return (struct nfs_page *)page_private(page); | ||
163 | } | ||
164 | |||
157 | /* | 165 | /* |
158 | * nfs_page_find_head_request_locked - find head request associated with @page | 166 | * nfs_page_find_head_request_locked - find head request associated with @page |
159 | * | 167 | * |
@@ -164,11 +172,10 @@ static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | |||
164 | static struct nfs_page * | 172 | static struct nfs_page * |
165 | nfs_page_find_head_request_locked(struct nfs_inode *nfsi, struct page *page) | 173 | nfs_page_find_head_request_locked(struct nfs_inode *nfsi, struct page *page) |
166 | { | 174 | { |
167 | struct nfs_page *req = NULL; | 175 | struct nfs_page *req; |
168 | 176 | ||
169 | if (PagePrivate(page)) | 177 | req = nfs_page_private_request(page); |
170 | req = (struct nfs_page *)page_private(page); | 178 | if (!req && unlikely(PageSwapCache(page))) |
171 | else if (unlikely(PageSwapCache(page))) | ||
172 | req = nfs_page_search_commits_for_head_request_locked(nfsi, | 179 | req = nfs_page_search_commits_for_head_request_locked(nfsi, |
173 | page); | 180 | page); |
174 | 181 | ||
@@ -448,31 +455,29 @@ nfs_lock_and_join_requests(struct page *page) | |||
448 | int ret; | 455 | int ret; |
449 | 456 | ||
450 | try_again: | 457 | try_again: |
451 | if (!(PagePrivate(page) || PageSwapCache(page))) | ||
452 | return NULL; | ||
453 | spin_lock(&inode->i_lock); | ||
454 | /* | 458 | /* |
455 | * A reference is taken only on the head request which acts as a | 459 | * A reference is taken only on the head request which acts as a |
456 | * reference to the whole page group - the group will not be destroyed | 460 | * reference to the whole page group - the group will not be destroyed |
457 | * until the head reference is released. | 461 | * until the head reference is released. |
458 | */ | 462 | */ |
459 | head = nfs_page_find_head_request_locked(NFS_I(inode), page); | 463 | head = nfs_page_find_head_request(page); |
460 | 464 | if (!head) | |
461 | if (!head) { | ||
462 | spin_unlock(&inode->i_lock); | ||
463 | return NULL; | 465 | return NULL; |
464 | } | ||
465 | 466 | ||
466 | /* lock the page head first in order to avoid an ABBA inefficiency */ | 467 | /* lock the page head first in order to avoid an ABBA inefficiency */ |
467 | if (!nfs_lock_request(head)) { | 468 | if (!nfs_lock_request(head)) { |
468 | spin_unlock(&inode->i_lock); | ||
469 | ret = nfs_wait_on_request(head); | 469 | ret = nfs_wait_on_request(head); |
470 | nfs_release_request(head); | 470 | nfs_release_request(head); |
471 | if (ret < 0) | 471 | if (ret < 0) |
472 | return ERR_PTR(ret); | 472 | return ERR_PTR(ret); |
473 | goto try_again; | 473 | goto try_again; |
474 | } | 474 | } |
475 | spin_unlock(&inode->i_lock); | 475 | |
476 | /* Ensure that nobody removed the request before we locked it */ | ||
477 | if (head != nfs_page_private_request(page) && !PageSwapCache(page)) { | ||
478 | nfs_unlock_and_release_request(head); | ||
479 | goto try_again; | ||
480 | } | ||
476 | 481 | ||
477 | ret = nfs_page_group_lock(head); | 482 | ret = nfs_page_group_lock(head); |
478 | if (ret < 0) { | 483 | if (ret < 0) { |
@@ -559,7 +564,7 @@ try_again: | |||
559 | return NULL; | 564 | return NULL; |
560 | } | 565 | } |
561 | 566 | ||
562 | /* still holds ref on head from nfs_page_find_head_request_locked | 567 | /* still holds ref on head from nfs_page_find_head_request |
563 | * and still has lock on head from lock loop */ | 568 | * and still has lock on head from lock loop */ |
564 | return head; | 569 | return head; |
565 | } | 570 | } |