diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/pagelist.c | 17 | ||||
-rw-r--r-- | fs/nfs/write.c | 12 |
2 files changed, 28 insertions, 1 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 30c9626f96b0..4ec67f8d70aa 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -168,6 +168,23 @@ nfs_page_group_lock(struct nfs_page *req, bool nonblock) | |||
168 | } | 168 | } |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * nfs_page_group_lock_wait - wait for the lock to clear, but don't grab it | ||
172 | * @req - a request in the group | ||
173 | * | ||
174 | * This is a blocking call to wait for the group lock to be cleared. | ||
175 | */ | ||
176 | void | ||
177 | nfs_page_group_lock_wait(struct nfs_page *req) | ||
178 | { | ||
179 | struct nfs_page *head = req->wb_head; | ||
180 | |||
181 | WARN_ON_ONCE(head != head->wb_head); | ||
182 | |||
183 | wait_on_bit(&head->wb_flags, PG_HEADLOCK, | ||
184 | TASK_UNINTERRUPTIBLE); | ||
185 | } | ||
186 | |||
187 | /* | ||
171 | * nfs_page_group_unlock - unlock the head of the page group | 188 | * nfs_page_group_unlock - unlock the head of the page group |
172 | * @req - request in group that is to be unlocked | 189 | * @req - request in group that is to be unlocked |
173 | */ | 190 | */ |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e056f617adf2..175d5d073ccf 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -478,13 +478,23 @@ try_again: | |||
478 | return NULL; | 478 | return NULL; |
479 | } | 479 | } |
480 | 480 | ||
481 | /* lock each request in the page group */ | 481 | /* holding inode lock, so always make a non-blocking call to try the |
482 | * page group lock */ | ||
482 | ret = nfs_page_group_lock(head, true); | 483 | ret = nfs_page_group_lock(head, true); |
483 | if (ret < 0) { | 484 | if (ret < 0) { |
484 | spin_unlock(&inode->i_lock); | 485 | spin_unlock(&inode->i_lock); |
486 | |||
487 | if (!nonblock && ret == -EAGAIN) { | ||
488 | nfs_page_group_lock_wait(head); | ||
489 | nfs_release_request(head); | ||
490 | goto try_again; | ||
491 | } | ||
492 | |||
485 | nfs_release_request(head); | 493 | nfs_release_request(head); |
486 | return ERR_PTR(ret); | 494 | return ERR_PTR(ret); |
487 | } | 495 | } |
496 | |||
497 | /* lock each request in the page group */ | ||
488 | subreq = head; | 498 | subreq = head; |
489 | do { | 499 | do { |
490 | /* | 500 | /* |