diff options
| -rw-r--r-- | fs/exofs/ore_raid.c | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c index d222c77cfa1b..fff2070c6751 100644 --- a/fs/exofs/ore_raid.c +++ b/fs/exofs/ore_raid.c | |||
| @@ -461,16 +461,12 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret) | |||
| 461 | * ios->sp2d[p][*], xor is calculated the same way. These pages are | 461 | * ios->sp2d[p][*], xor is calculated the same way. These pages are |
| 462 | * allocated/freed and don't go through cache | 462 | * allocated/freed and don't go through cache |
| 463 | */ | 463 | */ |
| 464 | static int _read_4_write(struct ore_io_state *ios) | 464 | static int _read_4_write_first_stripe(struct ore_io_state *ios) |
| 465 | { | 465 | { |
| 466 | struct ore_io_state *ios_read; | ||
| 467 | struct ore_striping_info read_si; | 466 | struct ore_striping_info read_si; |
| 468 | struct __stripe_pages_2d *sp2d = ios->sp2d; | 467 | struct __stripe_pages_2d *sp2d = ios->sp2d; |
| 469 | u64 offset = ios->si.first_stripe_start; | 468 | u64 offset = ios->si.first_stripe_start; |
| 470 | u64 last_stripe_end; | 469 | unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1; |
| 471 | unsigned bytes_in_stripe = ios->si.bytes_in_stripe; | ||
| 472 | unsigned i, c, p, min_p = sp2d->pages_in_unit, max_p = -1; | ||
| 473 | int ret; | ||
| 474 | 470 | ||
| 475 | if (offset == ios->offset) /* Go to start collect $200 */ | 471 | if (offset == ios->offset) /* Go to start collect $200 */ |
| 476 | goto read_last_stripe; | 472 | goto read_last_stripe; |
| @@ -478,6 +474,9 @@ static int _read_4_write(struct ore_io_state *ios) | |||
| 478 | min_p = _sp2d_min_pg(sp2d); | 474 | min_p = _sp2d_min_pg(sp2d); |
| 479 | max_p = _sp2d_max_pg(sp2d); | 475 | max_p = _sp2d_max_pg(sp2d); |
| 480 | 476 | ||
| 477 | ORE_DBGMSG("stripe_start=0x%llx ios->offset=0x%llx min_p=%d max_p=%d\n", | ||
| 478 | offset, ios->offset, min_p, max_p); | ||
| 479 | |||
| 481 | for (c = 0; ; c++) { | 480 | for (c = 0; ; c++) { |
| 482 | ore_calc_stripe_info(ios->layout, offset, 0, &read_si); | 481 | ore_calc_stripe_info(ios->layout, offset, 0, &read_si); |
| 483 | read_si.obj_offset += min_p * PAGE_SIZE; | 482 | read_si.obj_offset += min_p * PAGE_SIZE; |
| @@ -512,6 +511,18 @@ static int _read_4_write(struct ore_io_state *ios) | |||
| 512 | } | 511 | } |
| 513 | 512 | ||
| 514 | read_last_stripe: | 513 | read_last_stripe: |
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | static int _read_4_write_last_stripe(struct ore_io_state *ios) | ||
| 518 | { | ||
| 519 | struct ore_striping_info read_si; | ||
| 520 | struct __stripe_pages_2d *sp2d = ios->sp2d; | ||
| 521 | u64 offset; | ||
| 522 | u64 last_stripe_end; | ||
| 523 | unsigned bytes_in_stripe = ios->si.bytes_in_stripe; | ||
| 524 | unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1; | ||
| 525 | |||
| 515 | offset = ios->offset + ios->length; | 526 | offset = ios->offset + ios->length; |
| 516 | if (offset % PAGE_SIZE) | 527 | if (offset % PAGE_SIZE) |
| 517 | _add_to_r4w_last_page(ios, &offset); | 528 | _add_to_r4w_last_page(ios, &offset); |
| @@ -527,15 +538,15 @@ read_last_stripe: | |||
| 527 | c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1, | 538 | c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1, |
| 528 | ios->layout->mirrors_p1, read_si.par_dev, read_si.dev); | 539 | ios->layout->mirrors_p1, read_si.par_dev, read_si.dev); |
| 529 | 540 | ||
| 530 | BUG_ON(ios->si.first_stripe_start + bytes_in_stripe != last_stripe_end); | ||
| 531 | /* unaligned IO must be within a single stripe */ | ||
| 532 | |||
| 533 | if (min_p == sp2d->pages_in_unit) { | 541 | if (min_p == sp2d->pages_in_unit) { |
| 534 | /* Didn't do it yet */ | 542 | /* Didn't do it yet */ |
| 535 | min_p = _sp2d_min_pg(sp2d); | 543 | min_p = _sp2d_min_pg(sp2d); |
| 536 | max_p = _sp2d_max_pg(sp2d); | 544 | max_p = _sp2d_max_pg(sp2d); |
| 537 | } | 545 | } |
| 538 | 546 | ||
| 547 | ORE_DBGMSG("offset=0x%llx stripe_end=0x%llx min_p=%d max_p=%d\n", | ||
| 548 | offset, last_stripe_end, min_p, max_p); | ||
| 549 | |||
| 539 | while (offset < last_stripe_end) { | 550 | while (offset < last_stripe_end) { |
| 540 | struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p]; | 551 | struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p]; |
| 541 | 552 | ||
| @@ -568,6 +579,15 @@ read_last_stripe: | |||
| 568 | } | 579 | } |
| 569 | 580 | ||
| 570 | read_it: | 581 | read_it: |
| 582 | return 0; | ||
| 583 | } | ||
| 584 | |||
| 585 | static int _read_4_write_execute(struct ore_io_state *ios) | ||
| 586 | { | ||
| 587 | struct ore_io_state *ios_read; | ||
| 588 | unsigned i; | ||
| 589 | int ret; | ||
| 590 | |||
| 571 | ios_read = ios->ios_read_4_write; | 591 | ios_read = ios->ios_read_4_write; |
| 572 | if (!ios_read) | 592 | if (!ios_read) |
| 573 | return 0; | 593 | return 0; |
| @@ -591,6 +611,8 @@ read_it: | |||
| 591 | } | 611 | } |
| 592 | 612 | ||
| 593 | _mark_read4write_pages_uptodate(ios_read, ret); | 613 | _mark_read4write_pages_uptodate(ios_read, ret); |
| 614 | ore_put_io_state(ios_read); | ||
| 615 | ios->ios_read_4_write = NULL; /* Might need a reuse at last stripe */ | ||
| 594 | return 0; | 616 | return 0; |
| 595 | } | 617 | } |
| 596 | 618 | ||
| @@ -626,8 +648,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios, | |||
| 626 | /* If first stripe, Read in all read4write pages | 648 | /* If first stripe, Read in all read4write pages |
| 627 | * (if needed) before we calculate the first parity. | 649 | * (if needed) before we calculate the first parity. |
| 628 | */ | 650 | */ |
| 629 | _read_4_write(ios); | 651 | _read_4_write_first_stripe(ios); |
| 630 | } | 652 | } |
| 653 | if (!cur_len) /* If last stripe r4w pages of last stripe */ | ||
| 654 | _read_4_write_last_stripe(ios); | ||
| 655 | _read_4_write_execute(ios); | ||
| 631 | 656 | ||
| 632 | for (i = 0; i < num_pages; i++) { | 657 | for (i = 0; i < num_pages; i++) { |
| 633 | pages[i] = _raid_page_alloc(); | 658 | pages[i] = _raid_page_alloc(); |
| @@ -654,34 +679,14 @@ int _ore_add_parity_unit(struct ore_io_state *ios, | |||
| 654 | 679 | ||
| 655 | int _ore_post_alloc_raid_stuff(struct ore_io_state *ios) | 680 | int _ore_post_alloc_raid_stuff(struct ore_io_state *ios) |
| 656 | { | 681 | { |
| 657 | struct ore_layout *layout = ios->layout; | ||
| 658 | |||
| 659 | if (ios->parity_pages) { | 682 | if (ios->parity_pages) { |
| 683 | struct ore_layout *layout = ios->layout; | ||
| 660 | unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE; | 684 | unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE; |
| 661 | unsigned stripe_size = ios->si.bytes_in_stripe; | ||
| 662 | u64 last_stripe, first_stripe; | ||
| 663 | 685 | ||
| 664 | if (_sp2d_alloc(pages_in_unit, layout->group_width, | 686 | if (_sp2d_alloc(pages_in_unit, layout->group_width, |
| 665 | layout->parity, &ios->sp2d)) { | 687 | layout->parity, &ios->sp2d)) { |
| 666 | return -ENOMEM; | 688 | return -ENOMEM; |
| 667 | } | 689 | } |
| 668 | |||
| 669 | /* Round io down to last full strip */ | ||
| 670 | first_stripe = div_u64(ios->offset, stripe_size); | ||
| 671 | last_stripe = div_u64(ios->offset + ios->length, stripe_size); | ||
| 672 | |||
| 673 | /* If an IO spans more then a single stripe it must end at | ||
| 674 | * a stripe boundary. The reminder at the end is pushed into the | ||
| 675 | * next IO. | ||
| 676 | */ | ||
| 677 | if (last_stripe != first_stripe) { | ||
| 678 | ios->length = last_stripe * stripe_size - ios->offset; | ||
| 679 | |||
| 680 | BUG_ON(!ios->length); | ||
| 681 | ios->nr_pages = (ios->length + PAGE_SIZE - 1) / | ||
| 682 | PAGE_SIZE; | ||
| 683 | ios->si.length = ios->length; /*make it consistent */ | ||
| 684 | } | ||
| 685 | } | 690 | } |
| 686 | return 0; | 691 | return 0; |
| 687 | } | 692 | } |
