diff options
Diffstat (limited to 'fs/nfs/pagelist.c')
-rw-r--r-- | fs/nfs/pagelist.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 4f1ba723848d..80777f99a58a 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -107,7 +107,7 @@ void nfs_unlock_request(struct nfs_page *req) | |||
107 | smp_mb__before_clear_bit(); | 107 | smp_mb__before_clear_bit(); |
108 | clear_bit(PG_BUSY, &req->wb_flags); | 108 | clear_bit(PG_BUSY, &req->wb_flags); |
109 | smp_mb__after_clear_bit(); | 109 | smp_mb__after_clear_bit(); |
110 | wake_up_all(&req->wb_context->waitq); | 110 | wake_up_bit(&req->wb_flags, PG_BUSY); |
111 | nfs_release_request(req); | 111 | nfs_release_request(req); |
112 | } | 112 | } |
113 | 113 | ||
@@ -180,6 +180,17 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head) | |||
180 | req->wb_list_head = head; | 180 | req->wb_list_head = head; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int nfs_wait_bit_interruptible(void *word) | ||
184 | { | ||
185 | int ret = 0; | ||
186 | |||
187 | if (signal_pending(current)) | ||
188 | ret = -ERESTARTSYS; | ||
189 | else | ||
190 | schedule(); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
183 | /** | 194 | /** |
184 | * nfs_wait_on_request - Wait for a request to complete. | 195 | * nfs_wait_on_request - Wait for a request to complete. |
185 | * @req: request to wait upon. | 196 | * @req: request to wait upon. |
@@ -190,12 +201,22 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head) | |||
190 | int | 201 | int |
191 | nfs_wait_on_request(struct nfs_page *req) | 202 | nfs_wait_on_request(struct nfs_page *req) |
192 | { | 203 | { |
193 | struct inode *inode = req->wb_context->dentry->d_inode; | 204 | struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode); |
194 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | 205 | sigset_t oldmask; |
195 | 206 | int ret = 0; | |
196 | if (!NFS_WBACK_BUSY(req)) | 207 | |
197 | return 0; | 208 | if (!test_bit(PG_BUSY, &req->wb_flags)) |
198 | return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req)); | 209 | goto out; |
210 | /* | ||
211 | * Note: the call to rpc_clnt_sigmask() suffices to ensure that we | ||
212 | * are not interrupted if intr flag is not set | ||
213 | */ | ||
214 | rpc_clnt_sigmask(clnt, &oldmask); | ||
215 | ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY, | ||
216 | nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE); | ||
217 | rpc_clnt_sigunmask(clnt, &oldmask); | ||
218 | out: | ||
219 | return ret; | ||
199 | } | 220 | } |
200 | 221 | ||
201 | /** | 222 | /** |