diff options
Diffstat (limited to 'fs/exofs/ore.c')
-rw-r--r-- | fs/exofs/ore.c | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 0e2a8353f7cc..cfc0205d62c4 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c | |||
@@ -58,9 +58,12 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) | |||
58 | layout->parity = 1; | 58 | layout->parity = 1; |
59 | break; | 59 | break; |
60 | case PNFS_OSD_RAID_PQ: | 60 | case PNFS_OSD_RAID_PQ: |
61 | layout->parity = 2; | ||
62 | break; | ||
61 | case PNFS_OSD_RAID_4: | 63 | case PNFS_OSD_RAID_4: |
62 | default: | 64 | default: |
63 | ORE_ERR("Only RAID_0/5 for now\n"); | 65 | ORE_ERR("Only RAID_0/5/6 for now received-enum=%d\n", |
66 | layout->raid_algorithm); | ||
64 | return -EINVAL; | 67 | return -EINVAL; |
65 | } | 68 | } |
66 | if (0 != (layout->stripe_unit & ~PAGE_MASK)) { | 69 | if (0 != (layout->stripe_unit & ~PAGE_MASK)) { |
@@ -112,6 +115,8 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) | |||
112 | layout->max_io_length /= stripe_length; | 115 | layout->max_io_length /= stripe_length; |
113 | layout->max_io_length *= stripe_length; | 116 | layout->max_io_length *= stripe_length; |
114 | } | 117 | } |
118 | ORE_DBGMSG("max_io_length=0x%lx\n", layout->max_io_length); | ||
119 | |||
115 | return 0; | 120 | return 0; |
116 | } | 121 | } |
117 | EXPORT_SYMBOL(ore_verify_layout); | 122 | EXPORT_SYMBOL(ore_verify_layout); |
@@ -561,7 +566,8 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, | |||
561 | 566 | ||
562 | si->par_dev = (group_width + group_width - parity - RxP) % | 567 | si->par_dev = (group_width + group_width - parity - RxP) % |
563 | group_width + first_dev; | 568 | group_width + first_dev; |
564 | si->dev = (group_width + C - RxP) % group_width + first_dev; | 569 | si->dev = (group_width + group_width + C - RxP) % |
570 | group_width + first_dev; | ||
565 | si->bytes_in_stripe = U; | 571 | si->bytes_in_stripe = U; |
566 | si->first_stripe_start = M * S + G * T + N * U; | 572 | si->first_stripe_start = M * S + G * T + N * U; |
567 | } else { | 573 | } else { |
@@ -651,6 +657,43 @@ out: /* we fail the complete unit on an error eg don't advance | |||
651 | return ret; | 657 | return ret; |
652 | } | 658 | } |
653 | 659 | ||
660 | static int _add_parity_units(struct ore_io_state *ios, | ||
661 | struct ore_striping_info *si, | ||
662 | unsigned dev, unsigned first_dev, | ||
663 | unsigned mirrors_p1, unsigned devs_in_group, | ||
664 | unsigned cur_len) | ||
665 | { | ||
666 | unsigned do_parity; | ||
667 | int ret = 0; | ||
668 | |||
669 | for (do_parity = ios->layout->parity; do_parity; --do_parity) { | ||
670 | struct ore_per_dev_state *per_dev; | ||
671 | |||
672 | per_dev = &ios->per_dev[dev - first_dev]; | ||
673 | if (!per_dev->length && !per_dev->offset) { | ||
674 | /* Only/always the parity unit of the first | ||
675 | * stripe will be empty. So this is a chance to | ||
676 | * initialize the per_dev info. | ||
677 | */ | ||
678 | per_dev->dev = dev; | ||
679 | per_dev->offset = si->obj_offset - si->unit_off; | ||
680 | } | ||
681 | |||
682 | ret = _ore_add_parity_unit(ios, si, per_dev, cur_len, | ||
683 | do_parity == 1); | ||
684 | if (unlikely(ret)) | ||
685 | break; | ||
686 | |||
687 | if (do_parity != 1) { | ||
688 | dev = ((dev + mirrors_p1) % devs_in_group) + first_dev; | ||
689 | si->cur_comp = (si->cur_comp + 1) % | ||
690 | ios->layout->group_width; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | return ret; | ||
695 | } | ||
696 | |||
654 | static int _prepare_for_striping(struct ore_io_state *ios) | 697 | static int _prepare_for_striping(struct ore_io_state *ios) |
655 | { | 698 | { |
656 | struct ore_striping_info *si = &ios->si; | 699 | struct ore_striping_info *si = &ios->si; |
@@ -660,7 +703,6 @@ static int _prepare_for_striping(struct ore_io_state *ios) | |||
660 | unsigned devs_in_group = group_width * mirrors_p1; | 703 | unsigned devs_in_group = group_width * mirrors_p1; |
661 | unsigned dev = si->dev; | 704 | unsigned dev = si->dev; |
662 | unsigned first_dev = dev - (dev % devs_in_group); | 705 | unsigned first_dev = dev - (dev % devs_in_group); |
663 | unsigned dev_order; | ||
664 | unsigned cur_pg = ios->pages_consumed; | 706 | unsigned cur_pg = ios->pages_consumed; |
665 | u64 length = ios->length; | 707 | u64 length = ios->length; |
666 | int ret = 0; | 708 | int ret = 0; |
@@ -672,14 +714,13 @@ static int _prepare_for_striping(struct ore_io_state *ios) | |||
672 | 714 | ||
673 | BUG_ON(length > si->length); | 715 | BUG_ON(length > si->length); |
674 | 716 | ||
675 | dev_order = si->cur_comp; | ||
676 | |||
677 | while (length) { | 717 | while (length) { |
678 | struct ore_per_dev_state *per_dev = | 718 | struct ore_per_dev_state *per_dev = |
679 | &ios->per_dev[dev - first_dev]; | 719 | &ios->per_dev[dev - first_dev]; |
680 | unsigned cur_len, page_off = 0; | 720 | unsigned cur_len, page_off = 0; |
681 | 721 | ||
682 | if (!per_dev->length) { | 722 | if (!per_dev->length && !per_dev->offset) { |
723 | /* First time initialize the per_dev info. */ | ||
683 | per_dev->dev = dev; | 724 | per_dev->dev = dev; |
684 | if (dev == si->dev) { | 725 | if (dev == si->dev) { |
685 | WARN_ON(dev == si->par_dev); | 726 | WARN_ON(dev == si->par_dev); |
@@ -688,13 +729,7 @@ static int _prepare_for_striping(struct ore_io_state *ios) | |||
688 | page_off = si->unit_off & ~PAGE_MASK; | 729 | page_off = si->unit_off & ~PAGE_MASK; |
689 | BUG_ON(page_off && (page_off != ios->pgbase)); | 730 | BUG_ON(page_off && (page_off != ios->pgbase)); |
690 | } else { | 731 | } else { |
691 | if (si->cur_comp > dev_order) | 732 | per_dev->offset = si->obj_offset - si->unit_off; |
692 | per_dev->offset = | ||
693 | si->obj_offset - si->unit_off; | ||
694 | else /* si->cur_comp < dev_order */ | ||
695 | per_dev->offset = | ||
696 | si->obj_offset + stripe_unit - | ||
697 | si->unit_off; | ||
698 | cur_len = stripe_unit; | 733 | cur_len = stripe_unit; |
699 | } | 734 | } |
700 | } else { | 735 | } else { |
@@ -721,20 +756,12 @@ static int _prepare_for_striping(struct ore_io_state *ios) | |||
721 | /* If last stripe operate on parity comp */ | 756 | /* If last stripe operate on parity comp */ |
722 | si->cur_comp = group_width - ios->layout->parity; | 757 | si->cur_comp = group_width - ios->layout->parity; |
723 | } | 758 | } |
724 | per_dev = &ios->per_dev[dev - first_dev]; | ||
725 | if (!per_dev->length) { | ||
726 | /* Only/always the parity unit of the first | ||
727 | * stripe will be empty. So this is a chance to | ||
728 | * initialize the per_dev info. | ||
729 | */ | ||
730 | per_dev->dev = dev; | ||
731 | per_dev->offset = si->obj_offset - si->unit_off; | ||
732 | } | ||
733 | 759 | ||
734 | /* In writes cur_len just means if it's the | 760 | /* In writes cur_len just means if it's the |
735 | * last one. See _ore_add_parity_unit. | 761 | * last one. See _ore_add_parity_unit. |
736 | */ | 762 | */ |
737 | ret = _ore_add_parity_unit(ios, si, per_dev, | 763 | ret = _add_parity_units(ios, si, dev, first_dev, |
764 | mirrors_p1, devs_in_group, | ||
738 | ios->sp2d ? length : cur_len); | 765 | ios->sp2d ? length : cur_len); |
739 | if (unlikely(ret)) | 766 | if (unlikely(ret)) |
740 | goto out; | 767 | goto out; |
@@ -746,6 +773,8 @@ static int _prepare_for_striping(struct ore_io_state *ios) | |||
746 | /* Next stripe, start fresh */ | 773 | /* Next stripe, start fresh */ |
747 | si->cur_comp = 0; | 774 | si->cur_comp = 0; |
748 | si->cur_pg = 0; | 775 | si->cur_pg = 0; |
776 | si->obj_offset += cur_len; | ||
777 | si->unit_off = 0; | ||
749 | } | 778 | } |
750 | } | 779 | } |
751 | out: | 780 | out: |