diff options
Diffstat (limited to 'fs/exofs/ore.c')
-rw-r--r-- | fs/exofs/ore.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index b74422888604..dae884694bd9 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c | |||
@@ -103,7 +103,7 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) | |||
103 | 103 | ||
104 | layout->max_io_length = | 104 | layout->max_io_length = |
105 | (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE - layout->stripe_unit) * | 105 | (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE - layout->stripe_unit) * |
106 | layout->group_width; | 106 | (layout->group_width - layout->parity); |
107 | if (layout->parity) { | 107 | if (layout->parity) { |
108 | unsigned stripe_length = | 108 | unsigned stripe_length = |
109 | (layout->group_width - layout->parity) * | 109 | (layout->group_width - layout->parity) * |
@@ -286,7 +286,8 @@ int ore_get_rw_state(struct ore_layout *layout, struct ore_components *oc, | |||
286 | if (length) { | 286 | if (length) { |
287 | ore_calc_stripe_info(layout, offset, length, &ios->si); | 287 | ore_calc_stripe_info(layout, offset, length, &ios->si); |
288 | ios->length = ios->si.length; | 288 | ios->length = ios->si.length; |
289 | ios->nr_pages = (ios->length + PAGE_SIZE - 1) / PAGE_SIZE; | 289 | ios->nr_pages = ((ios->offset & (PAGE_SIZE - 1)) + |
290 | ios->length + PAGE_SIZE - 1) / PAGE_SIZE; | ||
290 | if (layout->parity) | 291 | if (layout->parity) |
291 | _ore_post_alloc_raid_stuff(ios); | 292 | _ore_post_alloc_raid_stuff(ios); |
292 | } | 293 | } |
@@ -430,8 +431,12 @@ int ore_check_io(struct ore_io_state *ios, ore_on_dev_error on_dev_error) | |||
430 | if (likely(!ret)) | 431 | if (likely(!ret)) |
431 | continue; | 432 | continue; |
432 | 433 | ||
433 | if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) { | 434 | if ((OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) && |
434 | /* start read offset passed endof file */ | 435 | per_dev->bio) { |
436 | /* start read offset passed endof file. | ||
437 | * Note: if we do not have bio it means read-attributes | ||
438 | * In this case we should return error to caller. | ||
439 | */ | ||
435 | _clear_bio(per_dev->bio); | 440 | _clear_bio(per_dev->bio); |
436 | ORE_DBGMSG("start read offset passed end of file " | 441 | ORE_DBGMSG("start read offset passed end of file " |
437 | "offset=0x%llx, length=0x%llx\n", | 442 | "offset=0x%llx, length=0x%llx\n", |
@@ -536,6 +541,7 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, | |||
536 | u64 H = LmodS - G * T; | 541 | u64 H = LmodS - G * T; |
537 | 542 | ||
538 | u32 N = div_u64(H, U); | 543 | u32 N = div_u64(H, U); |
544 | u32 Nlast; | ||
539 | 545 | ||
540 | /* "H - (N * U)" is just "H % U" so it's bound to u32 */ | 546 | /* "H - (N * U)" is just "H % U" so it's bound to u32 */ |
541 | u32 C = (u32)(H - (N * U)) / stripe_unit + G * group_width; | 547 | u32 C = (u32)(H - (N * U)) / stripe_unit + G * group_width; |
@@ -568,6 +574,10 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, | |||
568 | si->length = T - H; | 574 | si->length = T - H; |
569 | if (si->length > length) | 575 | if (si->length > length) |
570 | si->length = length; | 576 | si->length = length; |
577 | |||
578 | Nlast = div_u64(H + si->length + U - 1, U); | ||
579 | si->maxdevUnits = Nlast - N; | ||
580 | |||
571 | si->M = M; | 581 | si->M = M; |
572 | } | 582 | } |
573 | EXPORT_SYMBOL(ore_calc_stripe_info); | 583 | EXPORT_SYMBOL(ore_calc_stripe_info); |
@@ -583,13 +593,16 @@ int _ore_add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
583 | int ret; | 593 | int ret; |
584 | 594 | ||
585 | if (per_dev->bio == NULL) { | 595 | if (per_dev->bio == NULL) { |
586 | unsigned pages_in_stripe = ios->layout->group_width * | 596 | unsigned bio_size; |
587 | (ios->layout->stripe_unit / PAGE_SIZE); | 597 | |
588 | unsigned nr_pages = ios->nr_pages * ios->layout->group_width / | 598 | if (!ios->reading) { |
589 | (ios->layout->group_width - | 599 | bio_size = ios->si.maxdevUnits; |
590 | ios->layout->parity); | 600 | } else { |
591 | unsigned bio_size = (nr_pages + pages_in_stripe) / | 601 | bio_size = (ios->si.maxdevUnits + 1) * |
592 | ios->layout->group_width; | 602 | (ios->layout->group_width - ios->layout->parity) / |
603 | ios->layout->group_width; | ||
604 | } | ||
605 | bio_size *= (ios->layout->stripe_unit / PAGE_SIZE); | ||
593 | 606 | ||
594 | per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size); | 607 | per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size); |
595 | if (unlikely(!per_dev->bio)) { | 608 | if (unlikely(!per_dev->bio)) { |
@@ -609,8 +622,12 @@ int _ore_add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
609 | added_len = bio_add_pc_page(q, per_dev->bio, pages[pg], | 622 | added_len = bio_add_pc_page(q, per_dev->bio, pages[pg], |
610 | pglen, pgbase); | 623 | pglen, pgbase); |
611 | if (unlikely(pglen != added_len)) { | 624 | if (unlikely(pglen != added_len)) { |
612 | ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=%u\n", | 625 | /* If bi_vcnt == bi_max then this is a SW BUG */ |
613 | per_dev->bio->bi_vcnt); | 626 | ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=0x%x " |
627 | "bi_max=0x%x BIO_MAX=0x%x cur_len=0x%x\n", | ||
628 | per_dev->bio->bi_vcnt, | ||
629 | per_dev->bio->bi_max_vecs, | ||
630 | BIO_MAX_PAGES_KMALLOC, cur_len); | ||
614 | ret = -ENOMEM; | 631 | ret = -ENOMEM; |
615 | goto out; | 632 | goto out; |
616 | } | 633 | } |
@@ -1098,7 +1115,7 @@ int ore_truncate(struct ore_layout *layout, struct ore_components *oc, | |||
1098 | size_attr->attr = g_attr_logical_length; | 1115 | size_attr->attr = g_attr_logical_length; |
1099 | size_attr->attr.val_ptr = &size_attr->newsize; | 1116 | size_attr->attr.val_ptr = &size_attr->newsize; |
1100 | 1117 | ||
1101 | ORE_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n", | 1118 | ORE_DBGMSG2("trunc(0x%llx) obj_offset=0x%llx dev=%d\n", |
1102 | _LLU(oc->comps->obj.id), _LLU(obj_size), i); | 1119 | _LLU(oc->comps->obj.id), _LLU(obj_size), i); |
1103 | ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, | 1120 | ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, |
1104 | &size_attr->attr); | 1121 | &size_attr->attr); |