aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs/ore_raid.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exofs/ore_raid.c')
-rw-r--r--fs/exofs/ore_raid.c56
1 files changed, 30 insertions, 26 deletions
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
index 4e2c032ab8a1..7f20f25c232c 100644
--- a/fs/exofs/ore_raid.c
+++ b/fs/exofs/ore_raid.c
@@ -218,22 +218,28 @@ static unsigned _sp2d_max_pg(struct __stripe_pages_2d *sp2d)
218static void _gen_xor_unit(struct __stripe_pages_2d *sp2d) 218static void _gen_xor_unit(struct __stripe_pages_2d *sp2d)
219{ 219{
220 unsigned p; 220 unsigned p;
221 unsigned tx_flags = ASYNC_TX_ACK;
222
223 if (sp2d->parity == 1)
224 tx_flags |= ASYNC_TX_XOR_ZERO_DST;
225
221 for (p = 0; p < sp2d->pages_in_unit; p++) { 226 for (p = 0; p < sp2d->pages_in_unit; p++) {
222 struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p]; 227 struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
223 228
224 if (!_1ps->write_count) 229 if (!_1ps->write_count)
225 continue; 230 continue;
226 231
227 init_async_submit(&_1ps->submit, 232 init_async_submit(&_1ps->submit, tx_flags,
228 ASYNC_TX_XOR_ZERO_DST | ASYNC_TX_ACK, 233 NULL, NULL, NULL, (addr_conv_t *)_1ps->scribble);
229 NULL, 234
230 NULL, NULL, 235 if (sp2d->parity == 1)
231 (addr_conv_t *)_1ps->scribble); 236 _1ps->tx = async_xor(_1ps->pages[sp2d->data_devs],
232 237 _1ps->pages, 0, sp2d->data_devs,
233 /* TODO: raid6 */ 238 PAGE_SIZE, &_1ps->submit);
234 _1ps->tx = async_xor(_1ps->pages[sp2d->data_devs], _1ps->pages, 239 else /* parity == 2 */
235 0, sp2d->data_devs, PAGE_SIZE, 240 _1ps->tx = async_gen_syndrome(_1ps->pages, 0,
236 &_1ps->submit); 241 sp2d->data_devs + sp2d->parity,
242 PAGE_SIZE, &_1ps->submit);
237 } 243 }
238 244
239 for (p = 0; p < sp2d->pages_in_unit; p++) { 245 for (p = 0; p < sp2d->pages_in_unit; p++) {
@@ -404,9 +410,8 @@ static int _add_to_r4w_last_page(struct ore_io_state *ios, u64 *offset)
404 410
405 ore_calc_stripe_info(ios->layout, *offset, 0, &si); 411 ore_calc_stripe_info(ios->layout, *offset, 0, &si);
406 412
407 p = si.unit_off / PAGE_SIZE; 413 p = si.cur_pg;
408 c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1, 414 c = si.cur_comp;
409 ios->layout->mirrors_p1, si.par_dev, si.dev);
410 page = ios->sp2d->_1p_stripes[p].pages[c]; 415 page = ios->sp2d->_1p_stripes[p].pages[c];
411 416
412 pg_len = PAGE_SIZE - (si.unit_off % PAGE_SIZE); 417 pg_len = PAGE_SIZE - (si.unit_off % PAGE_SIZE);
@@ -534,9 +539,8 @@ static int _read_4_write_last_stripe(struct ore_io_state *ios)
534 goto read_it; 539 goto read_it;
535 540
536 ore_calc_stripe_info(ios->layout, offset, 0, &read_si); 541 ore_calc_stripe_info(ios->layout, offset, 0, &read_si);
537 p = read_si.unit_off / PAGE_SIZE; 542 p = read_si.cur_pg;
538 c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1, 543 c = read_si.cur_comp;
539 ios->layout->mirrors_p1, read_si.par_dev, read_si.dev);
540 544
541 if (min_p == sp2d->pages_in_unit) { 545 if (min_p == sp2d->pages_in_unit) {
542 /* Didn't do it yet */ 546 /* Didn't do it yet */
@@ -620,7 +624,7 @@ static int _read_4_write_execute(struct ore_io_state *ios)
620int _ore_add_parity_unit(struct ore_io_state *ios, 624int _ore_add_parity_unit(struct ore_io_state *ios,
621 struct ore_striping_info *si, 625 struct ore_striping_info *si,
622 struct ore_per_dev_state *per_dev, 626 struct ore_per_dev_state *per_dev,
623 unsigned cur_len) 627 unsigned cur_len, bool do_xor)
624{ 628{
625 if (ios->reading) { 629 if (ios->reading) {
626 if (per_dev->cur_sg >= ios->sgs_per_dev) { 630 if (per_dev->cur_sg >= ios->sgs_per_dev) {
@@ -640,17 +644,16 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
640 si->cur_pg = _sp2d_min_pg(sp2d); 644 si->cur_pg = _sp2d_min_pg(sp2d);
641 num_pages = _sp2d_max_pg(sp2d) + 1 - si->cur_pg; 645 num_pages = _sp2d_max_pg(sp2d) + 1 - si->cur_pg;
642 646
643 if (!cur_len) /* If last stripe operate on parity comp */
644 si->cur_comp = sp2d->data_devs;
645
646 if (!per_dev->length) { 647 if (!per_dev->length) {
647 per_dev->offset += si->cur_pg * PAGE_SIZE; 648 per_dev->offset += si->cur_pg * PAGE_SIZE;
648 /* If first stripe, Read in all read4write pages 649 /* If first stripe, Read in all read4write pages
649 * (if needed) before we calculate the first parity. 650 * (if needed) before we calculate the first parity.
650 */ 651 */
651 _read_4_write_first_stripe(ios); 652 if (do_xor)
653 _read_4_write_first_stripe(ios);
652 } 654 }
653 if (!cur_len) /* If last stripe r4w pages of last stripe */ 655 if (!cur_len && do_xor)
656 /* If last stripe r4w pages of last stripe */
654 _read_4_write_last_stripe(ios); 657 _read_4_write_last_stripe(ios);
655 _read_4_write_execute(ios); 658 _read_4_write_execute(ios);
656 659
@@ -662,7 +665,7 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
662 ++(ios->cur_par_page); 665 ++(ios->cur_par_page);
663 } 666 }
664 667
665 BUG_ON(si->cur_comp != sp2d->data_devs); 668 BUG_ON(si->cur_comp < sp2d->data_devs);
666 BUG_ON(si->cur_pg + num_pages > sp2d->pages_in_unit); 669 BUG_ON(si->cur_pg + num_pages > sp2d->pages_in_unit);
667 670
668 ret = _ore_add_stripe_unit(ios, &array_start, 0, pages, 671 ret = _ore_add_stripe_unit(ios, &array_start, 0, pages,
@@ -670,9 +673,10 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
670 if (unlikely(ret)) 673 if (unlikely(ret))
671 return ret; 674 return ret;
672 675
673 /* TODO: raid6 if (last_parity_dev) */ 676 if (do_xor) {
674 _gen_xor_unit(sp2d); 677 _gen_xor_unit(sp2d);
675 _sp2d_reset(sp2d, ios->r4w, ios->private); 678 _sp2d_reset(sp2d, ios->r4w, ios->private);
679 }
676 } 680 }
677 return 0; 681 return 0;
678} 682}