aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/read.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-12 13:42:02 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-15 09:12:17 -0400
commit275acaafd45fbc8ecc3beabd6367e60b3049606a (patch)
tree7da9d9a606c274742d41860cb429c7d25a917f1d /fs/nfs/read.c
parent3b6091846d5b6113d695c79caec7cc96b62d469b (diff)
NFS: Clean up: split out the RPC transmission from nfs_pagein_multi/one
...and do the same for nfs_flush_multi/one. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r--fs/nfs/read.c92
1 files changed, 50 insertions, 42 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 581534a4aed7..0215bac35fc6 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -30,8 +30,6 @@
30 30
31#define NFSDBG_FACILITY NFSDBG_PAGECACHE 31#define NFSDBG_FACILITY NFSDBG_PAGECACHE
32 32
33static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc);
34static int nfs_pagein_one(struct nfs_pageio_descriptor *desc);
35static const struct nfs_pageio_ops nfs_pageio_read_ops; 33static const struct nfs_pageio_ops nfs_pageio_read_ops;
36static const struct rpc_call_ops nfs_read_partial_ops; 34static const struct rpc_call_ops nfs_read_partial_ops;
37static const struct rpc_call_ops nfs_read_full_ops; 35static const struct rpc_call_ops nfs_read_full_ops;
@@ -253,6 +251,27 @@ static int nfs_do_read(struct nfs_read_data *data,
253 return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops); 251 return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops);
254} 252}
255 253
254static int
255nfs_do_multiple_reads(struct list_head *head,
256 const struct rpc_call_ops *call_ops,
257 struct pnfs_layout_segment *lseg)
258{
259 struct nfs_read_data *data;
260 int ret = 0;
261
262 while (!list_empty(head)) {
263 int ret2;
264
265 data = list_entry(head->next, struct nfs_read_data, list);
266 list_del_init(&data->list);
267
268 ret2 = nfs_do_read(data, call_ops, lseg);
269 if (ret == 0)
270 ret = ret2;
271 }
272 return ret;
273}
274
256static void 275static void
257nfs_async_read_error(struct list_head *head) 276nfs_async_read_error(struct list_head *head)
258{ 277{
@@ -279,7 +298,7 @@ nfs_async_read_error(struct list_head *head)
279 * won't see the new data until our attribute cache is updated. This is more 298 * won't see the new data until our attribute cache is updated. This is more
280 * or less conventional NFS client behavior. 299 * or less conventional NFS client behavior.
281 */ 300 */
282static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc) 301static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, struct list_head *res)
283{ 302{
284 struct nfs_page *req = nfs_list_entry(desc->pg_list.next); 303 struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
285 struct page *page = req->wb_page; 304 struct page *page = req->wb_page;
@@ -288,11 +307,10 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
288 unsigned int offset; 307 unsigned int offset;
289 int requests = 0; 308 int requests = 0;
290 int ret = 0; 309 int ret = 0;
291 struct pnfs_layout_segment *lseg = desc->pg_lseg;
292 LIST_HEAD(list);
293 310
294 nfs_list_remove_request(req); 311 nfs_list_remove_request(req);
295 312
313 offset = 0;
296 nbytes = desc->pg_count; 314 nbytes = desc->pg_count;
297 do { 315 do {
298 size_t len = min(nbytes,rsize); 316 size_t len = min(nbytes,rsize);
@@ -300,57 +318,33 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
300 data = nfs_readdata_alloc(1); 318 data = nfs_readdata_alloc(1);
301 if (!data) 319 if (!data)
302 goto out_bad; 320 goto out_bad;
303 list_add(&data->list, &list); 321 data->pagevec[0] = page;
322 nfs_read_rpcsetup(req, data, len, offset);
323 list_add(&data->list, res);
304 requests++; 324 requests++;
305 nbytes -= len; 325 nbytes -= len;
326 offset += len;
306 } while(nbytes != 0); 327 } while(nbytes != 0);
307 atomic_set(&req->wb_complete, requests); 328 atomic_set(&req->wb_complete, requests);
308
309 ClearPageError(page); 329 ClearPageError(page);
310 offset = 0;
311 nbytes = desc->pg_count;
312 do {
313 int ret2;
314
315 data = list_entry(list.next, struct nfs_read_data, list);
316 list_del_init(&data->list);
317
318 data->pagevec[0] = page;
319
320 if (nbytes < rsize)
321 rsize = nbytes;
322 nfs_read_rpcsetup(req, data, rsize, offset);
323 ret2 = nfs_do_read(data, &nfs_read_partial_ops, lseg);
324 if (ret == 0)
325 ret = ret2;
326 offset += rsize;
327 nbytes -= rsize;
328 } while (nbytes != 0);
329 put_lseg(lseg);
330 desc->pg_lseg = NULL;
331
332 return ret; 330 return ret;
333
334out_bad: 331out_bad:
335 while (!list_empty(&list)) { 332 while (!list_empty(res)) {
336 data = list_entry(list.next, struct nfs_read_data, list); 333 data = list_entry(res->next, struct nfs_read_data, list);
337 list_del(&data->list); 334 list_del(&data->list);
338 nfs_readdata_free(data); 335 nfs_readdata_free(data);
339 } 336 }
340 SetPageError(page); 337 SetPageError(page);
341 nfs_readpage_release(req); 338 nfs_readpage_release(req);
342 put_lseg(lseg);
343 desc->pg_lseg = NULL;
344 return -ENOMEM; 339 return -ENOMEM;
345} 340}
346 341
347static int nfs_pagein_one(struct nfs_pageio_descriptor *desc) 342static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, struct list_head *res)
348{ 343{
349 struct nfs_page *req; 344 struct nfs_page *req;
350 struct page **pages; 345 struct page **pages;
351 struct nfs_read_data *data; 346 struct nfs_read_data *data;
352 struct list_head *head = &desc->pg_list; 347 struct list_head *head = &desc->pg_list;
353 struct pnfs_layout_segment *lseg = desc->pg_lseg;
354 int ret = 0; 348 int ret = 0;
355 349
356 data = nfs_readdata_alloc(nfs_page_array_len(desc->pg_base, 350 data = nfs_readdata_alloc(nfs_page_array_len(desc->pg_base,
@@ -372,18 +366,32 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc)
372 req = nfs_list_entry(data->pages.next); 366 req = nfs_list_entry(data->pages.next);
373 367
374 nfs_read_rpcsetup(req, data, desc->pg_count, 0); 368 nfs_read_rpcsetup(req, data, desc->pg_count, 0);
375 ret = nfs_do_read(data, &nfs_read_full_ops, lseg); 369 list_add(&data->list, res);
376out: 370out:
377 put_lseg(lseg);
378 desc->pg_lseg = NULL;
379 return ret; 371 return ret;
380} 372}
381 373
382int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) 374int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
383{ 375{
384 if (desc->pg_bsize < PAGE_CACHE_SIZE) 376 LIST_HEAD(head);
385 return nfs_pagein_multi(desc); 377 int ret;
386 return nfs_pagein_one(desc); 378
379 if (desc->pg_bsize < PAGE_CACHE_SIZE) {
380 ret = nfs_pagein_multi(desc, &head);
381 if (ret == 0)
382 ret = nfs_do_multiple_reads(&head,
383 &nfs_read_partial_ops,
384 desc->pg_lseg);
385 } else {
386 ret = nfs_pagein_one(desc, &head);
387 if (ret == 0)
388 ret = nfs_do_multiple_reads(&head,
389 &nfs_read_full_ops,
390 desc->pg_lseg);
391 }
392 put_lseg(desc->pg_lseg);
393 desc->pg_lseg = NULL;
394 return ret;
387} 395}
388EXPORT_SYMBOL_GPL(nfs_generic_pg_readpages); 396EXPORT_SYMBOL_GPL(nfs_generic_pg_readpages);
389 397