aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/blocklayout
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2012-04-20 14:47:44 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-27 14:10:37 -0400
commitcd841605f7a721878d8a2d1362484723d8abf569 (patch)
treeb5c37db575cd545a183577249909e042fe38d646 /fs/nfs/blocklayout
parentb5542849764aa56fd3f05c0041195b637b9d2ac2 (diff)
NFS: create common nfs_pgio_header for both read and write
In order to avoid duplicating all the data in nfs_read_data whenever we split it up into multiple RPC calls (either due to a short read result or due to rsize < PAGE_SIZE), we split out the bits that are the same per RPC call into a separate "header" structure. The goal this patch moves towards is to have a single header refcounted by several rpc_data structures. Thus, want to always refer from rpc_data to the header, and not the other way. This patch comes close to that ideal, but the directio code currently needs some special casing, isolated in the nfs_direct_[read_write]hdr_release() functions. This will be dealt with in a future patch. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/blocklayout')
-rw-r--r--fs/nfs/blocklayout/blocklayout.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 7f6a23f0244e..7a482517f4c6 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -187,7 +187,6 @@ static void bl_end_io_read(struct bio *bio, int err)
187 struct parallel_io *par = bio->bi_private; 187 struct parallel_io *par = bio->bi_private;
188 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); 188 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
189 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; 189 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
190 struct nfs_read_data *rdata = (struct nfs_read_data *)par->data;
191 190
192 do { 191 do {
193 struct page *page = bvec->bv_page; 192 struct page *page = bvec->bv_page;
@@ -198,9 +197,12 @@ static void bl_end_io_read(struct bio *bio, int err)
198 SetPageUptodate(page); 197 SetPageUptodate(page);
199 } while (bvec >= bio->bi_io_vec); 198 } while (bvec >= bio->bi_io_vec);
200 if (!uptodate) { 199 if (!uptodate) {
201 if (!rdata->pnfs_error) 200 struct nfs_read_data *rdata = par->data;
202 rdata->pnfs_error = -EIO; 201 struct nfs_pgio_header *header = rdata->header;
203 pnfs_set_lo_fail(rdata->lseg); 202
203 if (!header->pnfs_error)
204 header->pnfs_error = -EIO;
205 pnfs_set_lo_fail(header->lseg);
204 } 206 }
205 bio_put(bio); 207 bio_put(bio);
206 put_parallel(par); 208 put_parallel(par);
@@ -221,7 +223,7 @@ bl_end_par_io_read(void *data, int unused)
221{ 223{
222 struct nfs_read_data *rdata = data; 224 struct nfs_read_data *rdata = data;
223 225
224 rdata->task.tk_status = rdata->pnfs_error; 226 rdata->task.tk_status = rdata->header->pnfs_error;
225 INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup); 227 INIT_WORK(&rdata->task.u.tk_work, bl_read_cleanup);
226 schedule_work(&rdata->task.u.tk_work); 228 schedule_work(&rdata->task.u.tk_work);
227} 229}
@@ -229,6 +231,7 @@ bl_end_par_io_read(void *data, int unused)
229static enum pnfs_try_status 231static enum pnfs_try_status
230bl_read_pagelist(struct nfs_read_data *rdata) 232bl_read_pagelist(struct nfs_read_data *rdata)
231{ 233{
234 struct nfs_pgio_header *header = rdata->header;
232 int i, hole; 235 int i, hole;
233 struct bio *bio = NULL; 236 struct bio *bio = NULL;
234 struct pnfs_block_extent *be = NULL, *cow_read = NULL; 237 struct pnfs_block_extent *be = NULL, *cow_read = NULL;
@@ -256,10 +259,10 @@ bl_read_pagelist(struct nfs_read_data *rdata)
256 bl_put_extent(cow_read); 259 bl_put_extent(cow_read);
257 bio = bl_submit_bio(READ, bio); 260 bio = bl_submit_bio(READ, bio);
258 /* Get the next one */ 261 /* Get the next one */
259 be = bl_find_get_extent(BLK_LSEG2EXT(rdata->lseg), 262 be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg),
260 isect, &cow_read); 263 isect, &cow_read);
261 if (!be) { 264 if (!be) {
262 rdata->pnfs_error = -EIO; 265 header->pnfs_error = -EIO;
263 goto out; 266 goto out;
264 } 267 }
265 extent_length = be->be_length - 268 extent_length = be->be_length -
@@ -286,7 +289,7 @@ bl_read_pagelist(struct nfs_read_data *rdata)
286 isect, pages[i], be_read, 289 isect, pages[i], be_read,
287 bl_end_io_read, par); 290 bl_end_io_read, par);
288 if (IS_ERR(bio)) { 291 if (IS_ERR(bio)) {
289 rdata->pnfs_error = PTR_ERR(bio); 292 header->pnfs_error = PTR_ERR(bio);
290 bio = NULL; 293 bio = NULL;
291 goto out; 294 goto out;
292 } 295 }
@@ -294,9 +297,9 @@ bl_read_pagelist(struct nfs_read_data *rdata)
294 isect += PAGE_CACHE_SECTORS; 297 isect += PAGE_CACHE_SECTORS;
295 extent_length -= PAGE_CACHE_SECTORS; 298 extent_length -= PAGE_CACHE_SECTORS;
296 } 299 }
297 if ((isect << SECTOR_SHIFT) >= rdata->inode->i_size) { 300 if ((isect << SECTOR_SHIFT) >= header->inode->i_size) {
298 rdata->res.eof = 1; 301 rdata->res.eof = 1;
299 rdata->res.count = rdata->inode->i_size - f_offset; 302 rdata->res.count = header->inode->i_size - f_offset;
300 } else { 303 } else {
301 rdata->res.count = (isect << SECTOR_SHIFT) - f_offset; 304 rdata->res.count = (isect << SECTOR_SHIFT) - f_offset;
302 } 305 }
@@ -345,7 +348,6 @@ static void bl_end_io_write_zero(struct bio *bio, int err)
345 struct parallel_io *par = bio->bi_private; 348 struct parallel_io *par = bio->bi_private;
346 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); 349 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
347 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; 350 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
348 struct nfs_write_data *wdata = (struct nfs_write_data *)par->data;
349 351
350 do { 352 do {
351 struct page *page = bvec->bv_page; 353 struct page *page = bvec->bv_page;
@@ -358,9 +360,12 @@ static void bl_end_io_write_zero(struct bio *bio, int err)
358 } while (bvec >= bio->bi_io_vec); 360 } while (bvec >= bio->bi_io_vec);
359 361
360 if (unlikely(!uptodate)) { 362 if (unlikely(!uptodate)) {
361 if (!wdata->pnfs_error) 363 struct nfs_write_data *data = par->data;
362 wdata->pnfs_error = -EIO; 364 struct nfs_pgio_header *header = data->header;
363 pnfs_set_lo_fail(wdata->lseg); 365
366 if (!header->pnfs_error)
367 header->pnfs_error = -EIO;
368 pnfs_set_lo_fail(header->lseg);
364 } 369 }
365 bio_put(bio); 370 bio_put(bio);
366 put_parallel(par); 371 put_parallel(par);
@@ -370,12 +375,13 @@ static void bl_end_io_write(struct bio *bio, int err)
370{ 375{
371 struct parallel_io *par = bio->bi_private; 376 struct parallel_io *par = bio->bi_private;
372 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); 377 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
373 struct nfs_write_data *wdata = (struct nfs_write_data *)par->data; 378 struct nfs_write_data *data = par->data;
379 struct nfs_pgio_header *header = data->header;
374 380
375 if (!uptodate) { 381 if (!uptodate) {
376 if (!wdata->pnfs_error) 382 if (!header->pnfs_error)
377 wdata->pnfs_error = -EIO; 383 header->pnfs_error = -EIO;
378 pnfs_set_lo_fail(wdata->lseg); 384 pnfs_set_lo_fail(header->lseg);
379 } 385 }
380 bio_put(bio); 386 bio_put(bio);
381 put_parallel(par); 387 put_parallel(par);
@@ -391,9 +397,9 @@ static void bl_write_cleanup(struct work_struct *work)
391 dprintk("%s enter\n", __func__); 397 dprintk("%s enter\n", __func__);
392 task = container_of(work, struct rpc_task, u.tk_work); 398 task = container_of(work, struct rpc_task, u.tk_work);
393 wdata = container_of(task, struct nfs_write_data, task); 399 wdata = container_of(task, struct nfs_write_data, task);
394 if (likely(!wdata->pnfs_error)) { 400 if (likely(!wdata->header->pnfs_error)) {
395 /* Marks for LAYOUTCOMMIT */ 401 /* Marks for LAYOUTCOMMIT */
396 mark_extents_written(BLK_LSEG2EXT(wdata->lseg), 402 mark_extents_written(BLK_LSEG2EXT(wdata->header->lseg),
397 wdata->args.offset, wdata->args.count); 403 wdata->args.offset, wdata->args.count);
398 } 404 }
399 pnfs_ld_write_done(wdata); 405 pnfs_ld_write_done(wdata);
@@ -404,12 +410,12 @@ static void bl_end_par_io_write(void *data, int num_se)
404{ 410{
405 struct nfs_write_data *wdata = data; 411 struct nfs_write_data *wdata = data;
406 412
407 if (unlikely(wdata->pnfs_error)) { 413 if (unlikely(wdata->header->pnfs_error)) {
408 bl_free_short_extents(&BLK_LSEG2EXT(wdata->lseg)->bl_inval, 414 bl_free_short_extents(&BLK_LSEG2EXT(wdata->header->lseg)->bl_inval,
409 num_se); 415 num_se);
410 } 416 }
411 417
412 wdata->task.tk_status = wdata->pnfs_error; 418 wdata->task.tk_status = wdata->header->pnfs_error;
413 wdata->verf.committed = NFS_FILE_SYNC; 419 wdata->verf.committed = NFS_FILE_SYNC;
414 INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup); 420 INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup);
415 schedule_work(&wdata->task.u.tk_work); 421 schedule_work(&wdata->task.u.tk_work);
@@ -540,6 +546,7 @@ check_page:
540static enum pnfs_try_status 546static enum pnfs_try_status
541bl_write_pagelist(struct nfs_write_data *wdata, int sync) 547bl_write_pagelist(struct nfs_write_data *wdata, int sync)
542{ 548{
549 struct nfs_pgio_header *header = wdata->header;
543 int i, ret, npg_zero, pg_index, last = 0; 550 int i, ret, npg_zero, pg_index, last = 0;
544 struct bio *bio = NULL; 551 struct bio *bio = NULL;
545 struct pnfs_block_extent *be = NULL, *cow_read = NULL; 552 struct pnfs_block_extent *be = NULL, *cow_read = NULL;
@@ -552,7 +559,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
552 pgoff_t index; 559 pgoff_t index;
553 u64 temp; 560 u64 temp;
554 int npg_per_block = 561 int npg_per_block =
555 NFS_SERVER(wdata->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; 562 NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
556 563
557 dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); 564 dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
558 /* At this point, wdata->pages is a (sequential) list of nfs_pages. 565 /* At this point, wdata->pages is a (sequential) list of nfs_pages.
@@ -566,7 +573,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
566 /* At this point, have to be more careful with error handling */ 573 /* At this point, have to be more careful with error handling */
567 574
568 isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT); 575 isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT);
569 be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), isect, &cow_read); 576 be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), isect, &cow_read);
570 if (!be || !is_writable(be, isect)) { 577 if (!be || !is_writable(be, isect)) {
571 dprintk("%s no matching extents!\n", __func__); 578 dprintk("%s no matching extents!\n", __func__);
572 goto out_mds; 579 goto out_mds;
@@ -597,10 +604,10 @@ fill_invalid_ext:
597 dprintk("%s zero %dth page: index %lu isect %llu\n", 604 dprintk("%s zero %dth page: index %lu isect %llu\n",
598 __func__, npg_zero, index, 605 __func__, npg_zero, index,
599 (unsigned long long)isect); 606 (unsigned long long)isect);
600 page = bl_find_get_zeroing_page(wdata->inode, index, 607 page = bl_find_get_zeroing_page(header->inode, index,
601 cow_read); 608 cow_read);
602 if (unlikely(IS_ERR(page))) { 609 if (unlikely(IS_ERR(page))) {
603 wdata->pnfs_error = PTR_ERR(page); 610 header->pnfs_error = PTR_ERR(page);
604 goto out; 611 goto out;
605 } else if (page == NULL) 612 } else if (page == NULL)
606 goto next_page; 613 goto next_page;
@@ -612,7 +619,7 @@ fill_invalid_ext:
612 __func__, ret); 619 __func__, ret);
613 end_page_writeback(page); 620 end_page_writeback(page);
614 page_cache_release(page); 621 page_cache_release(page);
615 wdata->pnfs_error = ret; 622 header->pnfs_error = ret;
616 goto out; 623 goto out;
617 } 624 }
618 if (likely(!bl_push_one_short_extent(be->be_inval))) 625 if (likely(!bl_push_one_short_extent(be->be_inval)))
@@ -620,11 +627,11 @@ fill_invalid_ext:
620 else { 627 else {
621 end_page_writeback(page); 628 end_page_writeback(page);
622 page_cache_release(page); 629 page_cache_release(page);
623 wdata->pnfs_error = -ENOMEM; 630 header->pnfs_error = -ENOMEM;
624 goto out; 631 goto out;
625 } 632 }
626 /* FIXME: This should be done in bi_end_io */ 633 /* FIXME: This should be done in bi_end_io */
627 mark_extents_written(BLK_LSEG2EXT(wdata->lseg), 634 mark_extents_written(BLK_LSEG2EXT(header->lseg),
628 page->index << PAGE_CACHE_SHIFT, 635 page->index << PAGE_CACHE_SHIFT,
629 PAGE_CACHE_SIZE); 636 PAGE_CACHE_SIZE);
630 637
@@ -632,7 +639,7 @@ fill_invalid_ext:
632 isect, page, be, 639 isect, page, be,
633 bl_end_io_write_zero, par); 640 bl_end_io_write_zero, par);
634 if (IS_ERR(bio)) { 641 if (IS_ERR(bio)) {
635 wdata->pnfs_error = PTR_ERR(bio); 642 header->pnfs_error = PTR_ERR(bio);
636 bio = NULL; 643 bio = NULL;
637 goto out; 644 goto out;
638 } 645 }
@@ -653,10 +660,10 @@ next_page:
653 bl_put_extent(be); 660 bl_put_extent(be);
654 bio = bl_submit_bio(WRITE, bio); 661 bio = bl_submit_bio(WRITE, bio);
655 /* Get the next one */ 662 /* Get the next one */
656 be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), 663 be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg),
657 isect, NULL); 664 isect, NULL);
658 if (!be || !is_writable(be, isect)) { 665 if (!be || !is_writable(be, isect)) {
659 wdata->pnfs_error = -EINVAL; 666 header->pnfs_error = -EINVAL;
660 goto out; 667 goto out;
661 } 668 }
662 if (be->be_state == PNFS_BLOCK_INVALID_DATA) { 669 if (be->be_state == PNFS_BLOCK_INVALID_DATA) {
@@ -664,7 +671,7 @@ next_page:
664 be->be_inval))) 671 be->be_inval)))
665 par->bse_count++; 672 par->bse_count++;
666 else { 673 else {
667 wdata->pnfs_error = -ENOMEM; 674 header->pnfs_error = -ENOMEM;
668 goto out; 675 goto out;
669 } 676 }
670 } 677 }
@@ -677,7 +684,7 @@ next_page:
677 if (unlikely(ret)) { 684 if (unlikely(ret)) {
678 dprintk("%s bl_mark_sectors_init fail %d\n", 685 dprintk("%s bl_mark_sectors_init fail %d\n",
679 __func__, ret); 686 __func__, ret);
680 wdata->pnfs_error = ret; 687 header->pnfs_error = ret;
681 goto out; 688 goto out;
682 } 689 }
683 } 690 }
@@ -685,7 +692,7 @@ next_page:
685 isect, pages[i], be, 692 isect, pages[i], be,
686 bl_end_io_write, par); 693 bl_end_io_write, par);
687 if (IS_ERR(bio)) { 694 if (IS_ERR(bio)) {
688 wdata->pnfs_error = PTR_ERR(bio); 695 header->pnfs_error = PTR_ERR(bio);
689 bio = NULL; 696 bio = NULL;
690 goto out; 697 goto out;
691 } 698 }