aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/pagelist.c29
-rw-r--r--fs/nfs/write.c6
-rw-r--r--include/linux/nfs_page.h2
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 */
151void 153int
152nfs_page_group_lock(struct nfs_page *req) 154nfs_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,
122extern int nfs_wait_on_request(struct nfs_page *); 122extern int nfs_wait_on_request(struct nfs_page *);
123extern void nfs_unlock_request(struct nfs_page *req); 123extern void nfs_unlock_request(struct nfs_page *req);
124extern void nfs_unlock_and_release_request(struct nfs_page *); 124extern void nfs_unlock_and_release_request(struct nfs_page *);
125extern void nfs_page_group_lock(struct nfs_page *); 125extern int nfs_page_group_lock(struct nfs_page *, bool);
126extern void nfs_page_group_unlock(struct nfs_page *); 126extern void nfs_page_group_unlock(struct nfs_page *);
127extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); 127extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
128 128