diff options
Diffstat (limited to 'fs/nfs/blocklayout/blocklayout.c')
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 90 |
1 files changed, 49 insertions, 41 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 7f6a23f0244e..7ae8a608956f 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) | |||
229 | static enum pnfs_try_status | 231 | static enum pnfs_try_status |
230 | bl_read_pagelist(struct nfs_read_data *rdata) | 232 | bl_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; |
@@ -239,7 +242,7 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
239 | int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT; | 242 | int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT; |
240 | 243 | ||
241 | dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__, | 244 | dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__, |
242 | rdata->npages, f_offset, (unsigned int)rdata->args.count); | 245 | rdata->pages.npages, f_offset, (unsigned int)rdata->args.count); |
243 | 246 | ||
244 | par = alloc_parallel(rdata); | 247 | par = alloc_parallel(rdata); |
245 | if (!par) | 248 | if (!par) |
@@ -249,17 +252,17 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
249 | 252 | ||
250 | isect = (sector_t) (f_offset >> SECTOR_SHIFT); | 253 | isect = (sector_t) (f_offset >> SECTOR_SHIFT); |
251 | /* Code assumes extents are page-aligned */ | 254 | /* Code assumes extents are page-aligned */ |
252 | for (i = pg_index; i < rdata->npages; i++) { | 255 | for (i = pg_index; i < rdata->pages.npages; i++) { |
253 | if (!extent_length) { | 256 | if (!extent_length) { |
254 | /* We've used up the previous extent */ | 257 | /* We've used up the previous extent */ |
255 | bl_put_extent(be); | 258 | bl_put_extent(be); |
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 - |
@@ -282,11 +285,12 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
282 | struct pnfs_block_extent *be_read; | 285 | struct pnfs_block_extent *be_read; |
283 | 286 | ||
284 | be_read = (hole && cow_read) ? cow_read : be; | 287 | be_read = (hole && cow_read) ? cow_read : be; |
285 | bio = bl_add_page_to_bio(bio, rdata->npages - i, READ, | 288 | bio = bl_add_page_to_bio(bio, rdata->pages.npages - i, |
289 | READ, | ||
286 | isect, pages[i], be_read, | 290 | isect, pages[i], be_read, |
287 | bl_end_io_read, par); | 291 | bl_end_io_read, par); |
288 | if (IS_ERR(bio)) { | 292 | if (IS_ERR(bio)) { |
289 | rdata->pnfs_error = PTR_ERR(bio); | 293 | header->pnfs_error = PTR_ERR(bio); |
290 | bio = NULL; | 294 | bio = NULL; |
291 | goto out; | 295 | goto out; |
292 | } | 296 | } |
@@ -294,9 +298,9 @@ bl_read_pagelist(struct nfs_read_data *rdata) | |||
294 | isect += PAGE_CACHE_SECTORS; | 298 | isect += PAGE_CACHE_SECTORS; |
295 | extent_length -= PAGE_CACHE_SECTORS; | 299 | extent_length -= PAGE_CACHE_SECTORS; |
296 | } | 300 | } |
297 | if ((isect << SECTOR_SHIFT) >= rdata->inode->i_size) { | 301 | if ((isect << SECTOR_SHIFT) >= header->inode->i_size) { |
298 | rdata->res.eof = 1; | 302 | rdata->res.eof = 1; |
299 | rdata->res.count = rdata->inode->i_size - f_offset; | 303 | rdata->res.count = header->inode->i_size - f_offset; |
300 | } else { | 304 | } else { |
301 | rdata->res.count = (isect << SECTOR_SHIFT) - f_offset; | 305 | rdata->res.count = (isect << SECTOR_SHIFT) - f_offset; |
302 | } | 306 | } |
@@ -345,7 +349,6 @@ static void bl_end_io_write_zero(struct bio *bio, int err) | |||
345 | struct parallel_io *par = bio->bi_private; | 349 | struct parallel_io *par = bio->bi_private; |
346 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 350 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
347 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 351 | 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 | 352 | ||
350 | do { | 353 | do { |
351 | struct page *page = bvec->bv_page; | 354 | struct page *page = bvec->bv_page; |
@@ -358,9 +361,12 @@ static void bl_end_io_write_zero(struct bio *bio, int err) | |||
358 | } while (bvec >= bio->bi_io_vec); | 361 | } while (bvec >= bio->bi_io_vec); |
359 | 362 | ||
360 | if (unlikely(!uptodate)) { | 363 | if (unlikely(!uptodate)) { |
361 | if (!wdata->pnfs_error) | 364 | struct nfs_write_data *data = par->data; |
362 | wdata->pnfs_error = -EIO; | 365 | struct nfs_pgio_header *header = data->header; |
363 | pnfs_set_lo_fail(wdata->lseg); | 366 | |
367 | if (!header->pnfs_error) | ||
368 | header->pnfs_error = -EIO; | ||
369 | pnfs_set_lo_fail(header->lseg); | ||
364 | } | 370 | } |
365 | bio_put(bio); | 371 | bio_put(bio); |
366 | put_parallel(par); | 372 | put_parallel(par); |
@@ -370,12 +376,13 @@ static void bl_end_io_write(struct bio *bio, int err) | |||
370 | { | 376 | { |
371 | struct parallel_io *par = bio->bi_private; | 377 | struct parallel_io *par = bio->bi_private; |
372 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 378 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
373 | struct nfs_write_data *wdata = (struct nfs_write_data *)par->data; | 379 | struct nfs_write_data *data = par->data; |
380 | struct nfs_pgio_header *header = data->header; | ||
374 | 381 | ||
375 | if (!uptodate) { | 382 | if (!uptodate) { |
376 | if (!wdata->pnfs_error) | 383 | if (!header->pnfs_error) |
377 | wdata->pnfs_error = -EIO; | 384 | header->pnfs_error = -EIO; |
378 | pnfs_set_lo_fail(wdata->lseg); | 385 | pnfs_set_lo_fail(header->lseg); |
379 | } | 386 | } |
380 | bio_put(bio); | 387 | bio_put(bio); |
381 | put_parallel(par); | 388 | put_parallel(par); |
@@ -391,9 +398,9 @@ static void bl_write_cleanup(struct work_struct *work) | |||
391 | dprintk("%s enter\n", __func__); | 398 | dprintk("%s enter\n", __func__); |
392 | task = container_of(work, struct rpc_task, u.tk_work); | 399 | task = container_of(work, struct rpc_task, u.tk_work); |
393 | wdata = container_of(task, struct nfs_write_data, task); | 400 | wdata = container_of(task, struct nfs_write_data, task); |
394 | if (likely(!wdata->pnfs_error)) { | 401 | if (likely(!wdata->header->pnfs_error)) { |
395 | /* Marks for LAYOUTCOMMIT */ | 402 | /* Marks for LAYOUTCOMMIT */ |
396 | mark_extents_written(BLK_LSEG2EXT(wdata->lseg), | 403 | mark_extents_written(BLK_LSEG2EXT(wdata->header->lseg), |
397 | wdata->args.offset, wdata->args.count); | 404 | wdata->args.offset, wdata->args.count); |
398 | } | 405 | } |
399 | pnfs_ld_write_done(wdata); | 406 | pnfs_ld_write_done(wdata); |
@@ -404,12 +411,12 @@ static void bl_end_par_io_write(void *data, int num_se) | |||
404 | { | 411 | { |
405 | struct nfs_write_data *wdata = data; | 412 | struct nfs_write_data *wdata = data; |
406 | 413 | ||
407 | if (unlikely(wdata->pnfs_error)) { | 414 | if (unlikely(wdata->header->pnfs_error)) { |
408 | bl_free_short_extents(&BLK_LSEG2EXT(wdata->lseg)->bl_inval, | 415 | bl_free_short_extents(&BLK_LSEG2EXT(wdata->header->lseg)->bl_inval, |
409 | num_se); | 416 | num_se); |
410 | } | 417 | } |
411 | 418 | ||
412 | wdata->task.tk_status = wdata->pnfs_error; | 419 | wdata->task.tk_status = wdata->header->pnfs_error; |
413 | wdata->verf.committed = NFS_FILE_SYNC; | 420 | wdata->verf.committed = NFS_FILE_SYNC; |
414 | INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup); | 421 | INIT_WORK(&wdata->task.u.tk_work, bl_write_cleanup); |
415 | schedule_work(&wdata->task.u.tk_work); | 422 | schedule_work(&wdata->task.u.tk_work); |
@@ -540,6 +547,7 @@ check_page: | |||
540 | static enum pnfs_try_status | 547 | static enum pnfs_try_status |
541 | bl_write_pagelist(struct nfs_write_data *wdata, int sync) | 548 | bl_write_pagelist(struct nfs_write_data *wdata, int sync) |
542 | { | 549 | { |
550 | struct nfs_pgio_header *header = wdata->header; | ||
543 | int i, ret, npg_zero, pg_index, last = 0; | 551 | int i, ret, npg_zero, pg_index, last = 0; |
544 | struct bio *bio = NULL; | 552 | struct bio *bio = NULL; |
545 | struct pnfs_block_extent *be = NULL, *cow_read = NULL; | 553 | struct pnfs_block_extent *be = NULL, *cow_read = NULL; |
@@ -552,7 +560,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) | |||
552 | pgoff_t index; | 560 | pgoff_t index; |
553 | u64 temp; | 561 | u64 temp; |
554 | int npg_per_block = | 562 | int npg_per_block = |
555 | NFS_SERVER(wdata->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; | 563 | NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT; |
556 | 564 | ||
557 | dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); | 565 | dprintk("%s enter, %Zu@%lld\n", __func__, count, offset); |
558 | /* At this point, wdata->pages is a (sequential) list of nfs_pages. | 566 | /* At this point, wdata->pages is a (sequential) list of nfs_pages. |
@@ -566,7 +574,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) | |||
566 | /* At this point, have to be more careful with error handling */ | 574 | /* At this point, have to be more careful with error handling */ |
567 | 575 | ||
568 | isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT); | 576 | isect = (sector_t) ((offset & (long)PAGE_CACHE_MASK) >> SECTOR_SHIFT); |
569 | be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), isect, &cow_read); | 577 | be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), isect, &cow_read); |
570 | if (!be || !is_writable(be, isect)) { | 578 | if (!be || !is_writable(be, isect)) { |
571 | dprintk("%s no matching extents!\n", __func__); | 579 | dprintk("%s no matching extents!\n", __func__); |
572 | goto out_mds; | 580 | goto out_mds; |
@@ -597,10 +605,10 @@ fill_invalid_ext: | |||
597 | dprintk("%s zero %dth page: index %lu isect %llu\n", | 605 | dprintk("%s zero %dth page: index %lu isect %llu\n", |
598 | __func__, npg_zero, index, | 606 | __func__, npg_zero, index, |
599 | (unsigned long long)isect); | 607 | (unsigned long long)isect); |
600 | page = bl_find_get_zeroing_page(wdata->inode, index, | 608 | page = bl_find_get_zeroing_page(header->inode, index, |
601 | cow_read); | 609 | cow_read); |
602 | if (unlikely(IS_ERR(page))) { | 610 | if (unlikely(IS_ERR(page))) { |
603 | wdata->pnfs_error = PTR_ERR(page); | 611 | header->pnfs_error = PTR_ERR(page); |
604 | goto out; | 612 | goto out; |
605 | } else if (page == NULL) | 613 | } else if (page == NULL) |
606 | goto next_page; | 614 | goto next_page; |
@@ -612,7 +620,7 @@ fill_invalid_ext: | |||
612 | __func__, ret); | 620 | __func__, ret); |
613 | end_page_writeback(page); | 621 | end_page_writeback(page); |
614 | page_cache_release(page); | 622 | page_cache_release(page); |
615 | wdata->pnfs_error = ret; | 623 | header->pnfs_error = ret; |
616 | goto out; | 624 | goto out; |
617 | } | 625 | } |
618 | if (likely(!bl_push_one_short_extent(be->be_inval))) | 626 | if (likely(!bl_push_one_short_extent(be->be_inval))) |
@@ -620,11 +628,11 @@ fill_invalid_ext: | |||
620 | else { | 628 | else { |
621 | end_page_writeback(page); | 629 | end_page_writeback(page); |
622 | page_cache_release(page); | 630 | page_cache_release(page); |
623 | wdata->pnfs_error = -ENOMEM; | 631 | header->pnfs_error = -ENOMEM; |
624 | goto out; | 632 | goto out; |
625 | } | 633 | } |
626 | /* FIXME: This should be done in bi_end_io */ | 634 | /* FIXME: This should be done in bi_end_io */ |
627 | mark_extents_written(BLK_LSEG2EXT(wdata->lseg), | 635 | mark_extents_written(BLK_LSEG2EXT(header->lseg), |
628 | page->index << PAGE_CACHE_SHIFT, | 636 | page->index << PAGE_CACHE_SHIFT, |
629 | PAGE_CACHE_SIZE); | 637 | PAGE_CACHE_SIZE); |
630 | 638 | ||
@@ -632,7 +640,7 @@ fill_invalid_ext: | |||
632 | isect, page, be, | 640 | isect, page, be, |
633 | bl_end_io_write_zero, par); | 641 | bl_end_io_write_zero, par); |
634 | if (IS_ERR(bio)) { | 642 | if (IS_ERR(bio)) { |
635 | wdata->pnfs_error = PTR_ERR(bio); | 643 | header->pnfs_error = PTR_ERR(bio); |
636 | bio = NULL; | 644 | bio = NULL; |
637 | goto out; | 645 | goto out; |
638 | } | 646 | } |
@@ -647,16 +655,16 @@ next_page: | |||
647 | 655 | ||
648 | /* Middle pages */ | 656 | /* Middle pages */ |
649 | pg_index = wdata->args.pgbase >> PAGE_CACHE_SHIFT; | 657 | pg_index = wdata->args.pgbase >> PAGE_CACHE_SHIFT; |
650 | for (i = pg_index; i < wdata->npages; i++) { | 658 | for (i = pg_index; i < wdata->pages.npages; i++) { |
651 | if (!extent_length) { | 659 | if (!extent_length) { |
652 | /* We've used up the previous extent */ | 660 | /* We've used up the previous extent */ |
653 | bl_put_extent(be); | 661 | bl_put_extent(be); |
654 | bio = bl_submit_bio(WRITE, bio); | 662 | bio = bl_submit_bio(WRITE, bio); |
655 | /* Get the next one */ | 663 | /* Get the next one */ |
656 | be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), | 664 | be = bl_find_get_extent(BLK_LSEG2EXT(header->lseg), |
657 | isect, NULL); | 665 | isect, NULL); |
658 | if (!be || !is_writable(be, isect)) { | 666 | if (!be || !is_writable(be, isect)) { |
659 | wdata->pnfs_error = -EINVAL; | 667 | header->pnfs_error = -EINVAL; |
660 | goto out; | 668 | goto out; |
661 | } | 669 | } |
662 | if (be->be_state == PNFS_BLOCK_INVALID_DATA) { | 670 | if (be->be_state == PNFS_BLOCK_INVALID_DATA) { |
@@ -664,7 +672,7 @@ next_page: | |||
664 | be->be_inval))) | 672 | be->be_inval))) |
665 | par->bse_count++; | 673 | par->bse_count++; |
666 | else { | 674 | else { |
667 | wdata->pnfs_error = -ENOMEM; | 675 | header->pnfs_error = -ENOMEM; |
668 | goto out; | 676 | goto out; |
669 | } | 677 | } |
670 | } | 678 | } |
@@ -677,15 +685,15 @@ next_page: | |||
677 | if (unlikely(ret)) { | 685 | if (unlikely(ret)) { |
678 | dprintk("%s bl_mark_sectors_init fail %d\n", | 686 | dprintk("%s bl_mark_sectors_init fail %d\n", |
679 | __func__, ret); | 687 | __func__, ret); |
680 | wdata->pnfs_error = ret; | 688 | header->pnfs_error = ret; |
681 | goto out; | 689 | goto out; |
682 | } | 690 | } |
683 | } | 691 | } |
684 | bio = bl_add_page_to_bio(bio, wdata->npages - i, WRITE, | 692 | bio = bl_add_page_to_bio(bio, wdata->pages.npages - i, WRITE, |
685 | isect, pages[i], be, | 693 | isect, pages[i], be, |
686 | bl_end_io_write, par); | 694 | bl_end_io_write, par); |
687 | if (IS_ERR(bio)) { | 695 | if (IS_ERR(bio)) { |
688 | wdata->pnfs_error = PTR_ERR(bio); | 696 | header->pnfs_error = PTR_ERR(bio); |
689 | bio = NULL; | 697 | bio = NULL; |
690 | goto out; | 698 | goto out; |
691 | } | 699 | } |