diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-05-29 11:45:57 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-05-29 12:12:27 -0400 |
commit | f868089b09b51bd17ee41dedb96f98a1d0952fec (patch) | |
tree | bb7b2c8503616cea06eba345d7b47cc479695d24 /fs/nfs | |
parent | c1109558ae0f07a3434357cd26203bfc7adfea75 (diff) |
NFS: Fix a potential busy wait in nfs_page_group_lock
We cannot allow nfs_page_group_lock to use TASK_KILLABLE here, since
the loop would cause a busy wait if somebody kills the task.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/pagelist.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 0b8446f1008d..a8759825ac76 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -138,6 +138,12 @@ nfs_iocounter_wait(struct nfs_io_counter *c) | |||
138 | return __nfs_iocounter_wait(c); | 138 | return __nfs_iocounter_wait(c); |
139 | } | 139 | } |
140 | 140 | ||
141 | static int nfs_wait_bit_uninterruptible(void *word) | ||
142 | { | ||
143 | io_schedule(); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
141 | /* | 147 | /* |
142 | * nfs_page_group_lock - lock the head of the page group | 148 | * nfs_page_group_lock - lock the head of the page group |
143 | * @req - request in group that is to be locked | 149 | * @req - request in group that is to be locked |
@@ -148,13 +154,12 @@ void | |||
148 | nfs_page_group_lock(struct nfs_page *req) | 154 | nfs_page_group_lock(struct nfs_page *req) |
149 | { | 155 | { |
150 | struct nfs_page *head = req->wb_head; | 156 | struct nfs_page *head = req->wb_head; |
151 | int err = -EAGAIN; | ||
152 | 157 | ||
153 | WARN_ON_ONCE(head != head->wb_head); | 158 | WARN_ON_ONCE(head != head->wb_head); |
154 | 159 | ||
155 | while (err) | 160 | wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, |
156 | err = wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK, | 161 | nfs_wait_bit_uninterruptible, |
157 | nfs_wait_bit_killable, TASK_KILLABLE); | 162 | TASK_UNINTERRUPTIBLE); |
158 | } | 163 | } |
159 | 164 | ||
160 | /* | 165 | /* |
@@ -410,12 +415,6 @@ void nfs_release_request(struct nfs_page *req) | |||
410 | kref_put(&req->wb_kref, nfs_page_group_destroy); | 415 | kref_put(&req->wb_kref, nfs_page_group_destroy); |
411 | } | 416 | } |
412 | 417 | ||
413 | static int nfs_wait_bit_uninterruptible(void *word) | ||
414 | { | ||
415 | io_schedule(); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /** | 418 | /** |
420 | * nfs_wait_on_request - Wait for a request to complete. | 419 | * nfs_wait_on_request - Wait for a request to complete. |
421 | * @req: request to wait upon. | 420 | * @req: request to wait upon. |