diff options
| author | Weston Andros Adamson <dros@primarydata.com> | 2014-07-17 20:42:15 -0400 |
|---|---|---|
| committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-08-03 17:05:24 -0400 |
| commit | e7029206ff43f6cf7d6fcb741adb126f47200516 (patch) | |
| tree | 177e5c715690fdc397a2054c48ec61b9b5cbbea4 | |
| parent | ec25422c669d38f4e8a83da7f77950094349de48 (diff) | |
nfs: check wait_on_bit_lock err in page_group_lock
Return errors from wait_on_bit_lock from nfs_page_group_lock.
Add a bool argument @wait to nfs_page_group_lock. If true, loop over
wait_on_bit_lock until it returns cleanly. If false, return the error
from wait_on_bit_lock.
Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
| -rw-r--r-- | fs/nfs/pagelist.c | 29 | ||||
| -rw-r--r-- | fs/nfs/write.c | 6 | ||||
| -rw-r--r-- | include/linux/nfs_page.h | 2 |
3 files changed, 28 insertions, 9 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e76a40e298f2..9425118e91d7 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
| @@ -147,17 +147,25 @@ static int nfs_wait_bit_uninterruptible(void *word) | |||
| 147 | * @req - request in group that is to be locked | 147 | * @req - request in group that is to be locked |
| 148 | * | 148 | * |
| 149 | * this lock must be held if modifying the page group list | 149 | * this lock must be held if modifying the page group list |
| 150 | * | ||
| 151 | * returns result from wait_on_bit_lock: 0 on success, < 0 on error | ||
| 150 | */ | 152 | */ |
| 151 | void | 153 | int |
| 152 | nfs_page_group_lock(struct nfs_page *req) | 154 | nfs_page_group_lock(struct nfs_page *req, bool wait) |
| 153 | { | 155 | { |
| 154 | struct nfs_page *head = req->wb_head; | 156 | struct nfs_page *head = req->wb_head; |
| 157 | int ret; | ||
| 155 | 158 | ||
| 156 | WARN_ON_ONCE(head != head->wb_head); | 159 | WARN_ON_ONCE(head != head->wb_head); |
| 157 | 160 | ||
| 158 | wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, | 161 | do { |
| 162 | ret = wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, | ||
| 159 | nfs_wait_bit_uninterruptible, | 163 | nfs_wait_bit_uninterruptible, |
| 160 | TASK_UNINTERRUPTIBLE); | 164 | TASK_UNINTERRUPTIBLE); |
| 165 | } while (wait && ret != 0); | ||
| 166 | |||
| 167 | WARN_ON_ONCE(ret > 0); | ||
| 168 | return ret; | ||
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | /* | 171 | /* |
| @@ -218,7 +226,7 @@ bool nfs_page_group_sync_on_bit(struct nfs_page *req, unsigned int bit) | |||
| 218 | { | 226 | { |
| 219 | bool ret; | 227 | bool ret; |
| 220 | 228 | ||
| 221 | nfs_page_group_lock(req); | 229 | nfs_page_group_lock(req, true); |
| 222 | ret = nfs_page_group_sync_on_bit_locked(req, bit); | 230 | ret = nfs_page_group_sync_on_bit_locked(req, bit); |
| 223 | nfs_page_group_unlock(req); | 231 | nfs_page_group_unlock(req); |
| 224 | 232 | ||
| @@ -858,8 +866,13 @@ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
| 858 | struct nfs_page *subreq; | 866 | struct nfs_page *subreq; |
| 859 | unsigned int bytes_left = 0; | 867 | unsigned int bytes_left = 0; |
| 860 | unsigned int offset, pgbase; | 868 | unsigned int offset, pgbase; |
| 869 | int ret; | ||
| 861 | 870 | ||
| 862 | nfs_page_group_lock(req); | 871 | ret = nfs_page_group_lock(req, false); |
| 872 | if (ret < 0) { | ||
| 873 | desc->pg_error = ret; | ||
| 874 | return 0; | ||
| 875 | } | ||
| 863 | 876 | ||
| 864 | subreq = req; | 877 | subreq = req; |
| 865 | bytes_left = subreq->wb_bytes; | 878 | bytes_left = subreq->wb_bytes; |
| @@ -881,7 +894,11 @@ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | |||
| 881 | if (desc->pg_recoalesce) | 894 | if (desc->pg_recoalesce) |
| 882 | return 0; | 895 | return 0; |
| 883 | /* retry add_request for this subreq */ | 896 | /* retry add_request for this subreq */ |
| 884 | nfs_page_group_lock(req); | 897 | ret = nfs_page_group_lock(req, false); |
| 898 | if (ret < 0) { | ||
| 899 | desc->pg_error = ret; | ||
| 900 | return 0; | ||
| 901 | } | ||
| 885 | continue; | 902 | continue; |
| 886 | } | 903 | } |
| 887 | 904 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d357728ed8ba..8d1ed2b9c16c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -216,7 +216,7 @@ static bool nfs_page_group_covers_page(struct nfs_page *req) | |||
| 216 | unsigned int pos = 0; | 216 | unsigned int pos = 0; |
| 217 | unsigned int len = nfs_page_length(req->wb_page); | 217 | unsigned int len = nfs_page_length(req->wb_page); |
| 218 | 218 | ||
| 219 | nfs_page_group_lock(req); | 219 | nfs_page_group_lock(req, true); |
| 220 | 220 | ||
| 221 | do { | 221 | do { |
| 222 | tmp = nfs_page_group_search_locked(req->wb_head, pos); | 222 | tmp = nfs_page_group_search_locked(req->wb_head, pos); |
| @@ -456,7 +456,9 @@ try_again: | |||
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | /* lock each request in the page group */ | 458 | /* lock each request in the page group */ |
| 459 | nfs_page_group_lock(head); | 459 | ret = nfs_page_group_lock(head, false); |
| 460 | if (ret < 0) | ||
| 461 | return ERR_PTR(ret); | ||
| 460 | subreq = head; | 462 | subreq = head; |
| 461 | do { | 463 | do { |
| 462 | /* | 464 | /* |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 4b48548e700e..291924ca9517 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
| @@ -122,7 +122,7 @@ extern size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, | |||
| 122 | extern int nfs_wait_on_request(struct nfs_page *); | 122 | extern int nfs_wait_on_request(struct nfs_page *); |
| 123 | extern void nfs_unlock_request(struct nfs_page *req); | 123 | extern void nfs_unlock_request(struct nfs_page *req); |
| 124 | extern void nfs_unlock_and_release_request(struct nfs_page *); | 124 | extern void nfs_unlock_and_release_request(struct nfs_page *); |
| 125 | extern void nfs_page_group_lock(struct nfs_page *); | 125 | extern int nfs_page_group_lock(struct nfs_page *, bool); |
| 126 | extern void nfs_page_group_unlock(struct nfs_page *); | 126 | extern void nfs_page_group_unlock(struct nfs_page *); |
| 127 | extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); | 127 | extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); |
| 128 | 128 | ||
