aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r--fs/nfs/read.c94
1 files changed, 55 insertions, 39 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 5a70be589bbe..16f57e0af999 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -58,22 +58,19 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
58 return p; 58 return p;
59} 59}
60 60
61static void nfs_readdata_rcu_free(struct rcu_head *head) 61static void nfs_readdata_free(struct nfs_read_data *p)
62{ 62{
63 struct nfs_read_data *p = container_of(head, struct nfs_read_data, task.u.tk_rcu);
64 if (p && (p->pagevec != &p->page_array[0])) 63 if (p && (p->pagevec != &p->page_array[0]))
65 kfree(p->pagevec); 64 kfree(p->pagevec);
66 mempool_free(p, nfs_rdata_mempool); 65 mempool_free(p, nfs_rdata_mempool);
67} 66}
68 67
69static void nfs_readdata_free(struct nfs_read_data *rdata)
70{
71 call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
72}
73
74void nfs_readdata_release(void *data) 68void nfs_readdata_release(void *data)
75{ 69{
76 nfs_readdata_free(data); 70 struct nfs_read_data *rdata = data;
71
72 put_nfs_open_context(rdata->args.context);
73 nfs_readdata_free(rdata);
77} 74}
78 75
79static 76static
@@ -156,7 +153,7 @@ static void nfs_readpage_release(struct nfs_page *req)
156/* 153/*
157 * Set up the NFS read request struct 154 * Set up the NFS read request struct
158 */ 155 */
159static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, 156static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
160 const struct rpc_call_ops *call_ops, 157 const struct rpc_call_ops *call_ops,
161 unsigned int count, unsigned int offset) 158 unsigned int count, unsigned int offset)
162{ 159{
@@ -174,6 +171,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
174 .rpc_message = &msg, 171 .rpc_message = &msg,
175 .callback_ops = call_ops, 172 .callback_ops = call_ops,
176 .callback_data = data, 173 .callback_data = data,
174 .workqueue = nfsiod_workqueue,
177 .flags = RPC_TASK_ASYNC | swap_flags, 175 .flags = RPC_TASK_ASYNC | swap_flags,
178 }; 176 };
179 177
@@ -186,7 +184,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
186 data->args.pgbase = req->wb_pgbase + offset; 184 data->args.pgbase = req->wb_pgbase + offset;
187 data->args.pages = data->pagevec; 185 data->args.pages = data->pagevec;
188 data->args.count = count; 186 data->args.count = count;
189 data->args.context = req->wb_context; 187 data->args.context = get_nfs_open_context(req->wb_context);
190 188
191 data->res.fattr = &data->fattr; 189 data->res.fattr = &data->fattr;
192 data->res.count = count; 190 data->res.count = count;
@@ -204,8 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
204 (unsigned long long)data->args.offset); 202 (unsigned long long)data->args.offset);
205 203
206 task = rpc_run_task(&task_setup_data); 204 task = rpc_run_task(&task_setup_data);
207 if (!IS_ERR(task)) 205 if (IS_ERR(task))
208 rpc_put_task(task); 206 return PTR_ERR(task);
207 rpc_put_task(task);
208 return 0;
209} 209}
210 210
211static void 211static void
@@ -242,6 +242,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
242 size_t rsize = NFS_SERVER(inode)->rsize, nbytes; 242 size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
243 unsigned int offset; 243 unsigned int offset;
244 int requests = 0; 244 int requests = 0;
245 int ret = 0;
245 LIST_HEAD(list); 246 LIST_HEAD(list);
246 247
247 nfs_list_remove_request(req); 248 nfs_list_remove_request(req);
@@ -253,7 +254,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
253 data = nfs_readdata_alloc(1); 254 data = nfs_readdata_alloc(1);
254 if (!data) 255 if (!data)
255 goto out_bad; 256 goto out_bad;
256 INIT_LIST_HEAD(&data->pages);
257 list_add(&data->pages, &list); 257 list_add(&data->pages, &list);
258 requests++; 258 requests++;
259 nbytes -= len; 259 nbytes -= len;
@@ -264,6 +264,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
264 offset = 0; 264 offset = 0;
265 nbytes = count; 265 nbytes = count;
266 do { 266 do {
267 int ret2;
268
267 data = list_entry(list.next, struct nfs_read_data, pages); 269 data = list_entry(list.next, struct nfs_read_data, pages);
268 list_del_init(&data->pages); 270 list_del_init(&data->pages);
269 271
@@ -271,13 +273,15 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
271 273
272 if (nbytes < rsize) 274 if (nbytes < rsize)
273 rsize = nbytes; 275 rsize = nbytes;
274 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, 276 ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
275 rsize, offset); 277 rsize, offset);
278 if (ret == 0)
279 ret = ret2;
276 offset += rsize; 280 offset += rsize;
277 nbytes -= rsize; 281 nbytes -= rsize;
278 } while (nbytes != 0); 282 } while (nbytes != 0);
279 283
280 return 0; 284 return ret;
281 285
282out_bad: 286out_bad:
283 while (!list_empty(&list)) { 287 while (!list_empty(&list)) {
@@ -295,12 +299,12 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
295 struct nfs_page *req; 299 struct nfs_page *req;
296 struct page **pages; 300 struct page **pages;
297 struct nfs_read_data *data; 301 struct nfs_read_data *data;
302 int ret = -ENOMEM;
298 303
299 data = nfs_readdata_alloc(npages); 304 data = nfs_readdata_alloc(npages);
300 if (!data) 305 if (!data)
301 goto out_bad; 306 goto out_bad;
302 307
303 INIT_LIST_HEAD(&data->pages);
304 pages = data->pagevec; 308 pages = data->pagevec;
305 while (!list_empty(head)) { 309 while (!list_empty(head)) {
306 req = nfs_list_entry(head->next); 310 req = nfs_list_entry(head->next);
@@ -311,11 +315,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
311 } 315 }
312 req = nfs_list_entry(data->pages.next); 316 req = nfs_list_entry(data->pages.next);
313 317
314 nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); 318 return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
315 return 0;
316out_bad: 319out_bad:
317 nfs_async_read_error(head); 320 nfs_async_read_error(head);
318 return -ENOMEM; 321 return ret;
319} 322}
320 323
321/* 324/*
@@ -342,26 +345,25 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
342 return 0; 345 return 0;
343} 346}
344 347
345static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data) 348static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
346{ 349{
347 struct nfs_readargs *argp = &data->args; 350 struct nfs_readargs *argp = &data->args;
348 struct nfs_readres *resp = &data->res; 351 struct nfs_readres *resp = &data->res;
349 352
350 if (resp->eof || resp->count == argp->count) 353 if (resp->eof || resp->count == argp->count)
351 return 0; 354 return;
352 355
353 /* This is a short read! */ 356 /* This is a short read! */
354 nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); 357 nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
355 /* Has the server at least made some progress? */ 358 /* Has the server at least made some progress? */
356 if (resp->count == 0) 359 if (resp->count == 0)
357 return 0; 360 return;
358 361
359 /* Yes, so retry the read at the end of the data */ 362 /* Yes, so retry the read at the end of the data */
360 argp->offset += resp->count; 363 argp->offset += resp->count;
361 argp->pgbase += resp->count; 364 argp->pgbase += resp->count;
362 argp->count -= resp->count; 365 argp->count -= resp->count;
363 rpc_restart_call(task); 366 rpc_restart_call(task);
364 return -EAGAIN;
365} 367}
366 368
367/* 369/*
@@ -370,29 +372,37 @@ static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
370static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata) 372static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
371{ 373{
372 struct nfs_read_data *data = calldata; 374 struct nfs_read_data *data = calldata;
373 struct nfs_page *req = data->req;
374 struct page *page = req->wb_page;
375 375
376 if (nfs_readpage_result(task, data) != 0) 376 if (nfs_readpage_result(task, data) != 0)
377 return; 377 return;
378 if (task->tk_status < 0)
379 return;
378 380
379 if (likely(task->tk_status >= 0)) { 381 nfs_readpage_truncate_uninitialised_page(data);
380 nfs_readpage_truncate_uninitialised_page(data); 382 nfs_readpage_retry(task, data);
381 if (nfs_readpage_retry(task, data) != 0) 383}
382 return; 384
383 } 385static void nfs_readpage_release_partial(void *calldata)
384 if (unlikely(task->tk_status < 0)) 386{
387 struct nfs_read_data *data = calldata;
388 struct nfs_page *req = data->req;
389 struct page *page = req->wb_page;
390 int status = data->task.tk_status;
391
392 if (status < 0)
385 SetPageError(page); 393 SetPageError(page);
394
386 if (atomic_dec_and_test(&req->wb_complete)) { 395 if (atomic_dec_and_test(&req->wb_complete)) {
387 if (!PageError(page)) 396 if (!PageError(page))
388 SetPageUptodate(page); 397 SetPageUptodate(page);
389 nfs_readpage_release(req); 398 nfs_readpage_release(req);
390 } 399 }
400 nfs_readdata_release(calldata);
391} 401}
392 402
393static const struct rpc_call_ops nfs_read_partial_ops = { 403static const struct rpc_call_ops nfs_read_partial_ops = {
394 .rpc_call_done = nfs_readpage_result_partial, 404 .rpc_call_done = nfs_readpage_result_partial,
395 .rpc_release = nfs_readdata_release, 405 .rpc_release = nfs_readpage_release_partial,
396}; 406};
397 407
398static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) 408static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
@@ -427,29 +437,35 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
427 437
428 if (nfs_readpage_result(task, data) != 0) 438 if (nfs_readpage_result(task, data) != 0)
429 return; 439 return;
440 if (task->tk_status < 0)
441 return;
430 /* 442 /*
431 * Note: nfs_readpage_retry may change the values of 443 * Note: nfs_readpage_retry may change the values of
432 * data->args. In the multi-page case, we therefore need 444 * data->args. In the multi-page case, we therefore need
433 * to ensure that we call nfs_readpage_set_pages_uptodate() 445 * to ensure that we call nfs_readpage_set_pages_uptodate()
434 * first. 446 * first.
435 */ 447 */
436 if (likely(task->tk_status >= 0)) { 448 nfs_readpage_truncate_uninitialised_page(data);
437 nfs_readpage_truncate_uninitialised_page(data); 449 nfs_readpage_set_pages_uptodate(data);
438 nfs_readpage_set_pages_uptodate(data); 450 nfs_readpage_retry(task, data);
439 if (nfs_readpage_retry(task, data) != 0) 451}
440 return; 452
441 } 453static void nfs_readpage_release_full(void *calldata)
454{
455 struct nfs_read_data *data = calldata;
456
442 while (!list_empty(&data->pages)) { 457 while (!list_empty(&data->pages)) {
443 struct nfs_page *req = nfs_list_entry(data->pages.next); 458 struct nfs_page *req = nfs_list_entry(data->pages.next);
444 459
445 nfs_list_remove_request(req); 460 nfs_list_remove_request(req);
446 nfs_readpage_release(req); 461 nfs_readpage_release(req);
447 } 462 }
463 nfs_readdata_release(calldata);
448} 464}
449 465
450static const struct rpc_call_ops nfs_read_full_ops = { 466static const struct rpc_call_ops nfs_read_full_ops = {
451 .rpc_call_done = nfs_readpage_result_full, 467 .rpc_call_done = nfs_readpage_result_full,
452 .rpc_release = nfs_readdata_release, 468 .rpc_release = nfs_readpage_release_full,
453}; 469};
454 470
455/* 471/*