diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exofs/ios.c | 73 |
1 files changed, 53 insertions, 20 deletions
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c index f74a2ec027a6..fbb47ba2cd71 100644 --- a/fs/exofs/ios.c +++ b/fs/exofs/ios.c | |||
@@ -305,20 +305,21 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid) | |||
305 | struct _striping_info { | 305 | struct _striping_info { |
306 | u64 obj_offset; | 306 | u64 obj_offset; |
307 | u64 group_length; | 307 | u64 group_length; |
308 | u64 M; /* for truncate */ | ||
308 | unsigned dev; | 309 | unsigned dev; |
309 | unsigned unit_off; | 310 | unsigned unit_off; |
310 | }; | 311 | }; |
311 | 312 | ||
312 | static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset, | 313 | static void _calc_stripe_info(struct exofs_layout *layout, u64 file_offset, |
313 | struct _striping_info *si) | 314 | struct _striping_info *si) |
314 | { | 315 | { |
315 | u32 stripe_unit = ios->layout->stripe_unit; | 316 | u32 stripe_unit = layout->stripe_unit; |
316 | u32 group_width = ios->layout->group_width; | 317 | u32 group_width = layout->group_width; |
317 | u64 group_depth = ios->layout->group_depth; | 318 | u64 group_depth = layout->group_depth; |
318 | 319 | ||
319 | u32 U = stripe_unit * group_width; | 320 | u32 U = stripe_unit * group_width; |
320 | u64 T = U * group_depth; | 321 | u64 T = U * group_depth; |
321 | u64 S = T * ios->layout->group_count; | 322 | u64 S = T * layout->group_count; |
322 | u64 M = div64_u64(file_offset, S); | 323 | u64 M = div64_u64(file_offset, S); |
323 | 324 | ||
324 | /* | 325 | /* |
@@ -333,7 +334,7 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset, | |||
333 | 334 | ||
334 | /* "H - (N * U)" is just "H % U" so it's bound to u32 */ | 335 | /* "H - (N * U)" is just "H % U" so it's bound to u32 */ |
335 | si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width; | 336 | si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width; |
336 | si->dev *= ios->layout->mirrors_p1; | 337 | si->dev *= layout->mirrors_p1; |
337 | 338 | ||
338 | div_u64_rem(file_offset, stripe_unit, &si->unit_off); | 339 | div_u64_rem(file_offset, stripe_unit, &si->unit_off); |
339 | 340 | ||
@@ -341,6 +342,7 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset, | |||
341 | (M * group_depth * stripe_unit); | 342 | (M * group_depth * stripe_unit); |
342 | 343 | ||
343 | si->group_length = T - H; | 344 | si->group_length = T - H; |
345 | si->M = M; | ||
344 | } | 346 | } |
345 | 347 | ||
346 | static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, | 348 | static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, |
@@ -454,7 +456,7 @@ static int _prepare_for_striping(struct exofs_io_state *ios) | |||
454 | if (ios->kern_buff) { | 456 | if (ios->kern_buff) { |
455 | struct exofs_per_dev_state *per_dev = &ios->per_dev[0]; | 457 | struct exofs_per_dev_state *per_dev = &ios->per_dev[0]; |
456 | 458 | ||
457 | _calc_stripe_info(ios, ios->offset, &si); | 459 | _calc_stripe_info(ios->layout, ios->offset, &si); |
458 | per_dev->offset = si.obj_offset; | 460 | per_dev->offset = si.obj_offset; |
459 | per_dev->dev = si.dev; | 461 | per_dev->dev = si.dev; |
460 | 462 | ||
@@ -468,7 +470,7 @@ static int _prepare_for_striping(struct exofs_io_state *ios) | |||
468 | } | 470 | } |
469 | 471 | ||
470 | while (length) { | 472 | while (length) { |
471 | _calc_stripe_info(ios, offset, &si); | 473 | _calc_stripe_info(ios->layout, offset, &si); |
472 | 474 | ||
473 | if (length < si.group_length) | 475 | if (length < si.group_length) |
474 | si.group_length = length; | 476 | si.group_length = length; |
@@ -745,6 +747,31 @@ static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp, | |||
745 | return 0; | 747 | return 0; |
746 | } | 748 | } |
747 | 749 | ||
750 | struct _trunc_info { | ||
751 | struct _striping_info si; | ||
752 | u64 prev_group_obj_off; | ||
753 | u64 next_group_obj_off; | ||
754 | |||
755 | unsigned first_group_dev; | ||
756 | unsigned nex_group_dev; | ||
757 | unsigned max_devs; | ||
758 | }; | ||
759 | |||
760 | void _calc_trunk_info(struct exofs_layout *layout, u64 file_offset, | ||
761 | struct _trunc_info *ti) | ||
762 | { | ||
763 | unsigned stripe_unit = layout->stripe_unit; | ||
764 | |||
765 | _calc_stripe_info(layout, file_offset, &ti->si); | ||
766 | |||
767 | ti->prev_group_obj_off = ti->si.M * stripe_unit; | ||
768 | ti->next_group_obj_off = ti->si.M ? (ti->si.M - 1) * stripe_unit : 0; | ||
769 | |||
770 | ti->first_group_dev = ti->si.dev - (ti->si.dev % layout->group_width); | ||
771 | ti->nex_group_dev = ti->first_group_dev + layout->group_width; | ||
772 | ti->max_devs = layout->group_width * layout->group_count; | ||
773 | } | ||
774 | |||
748 | int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) | 775 | int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) |
749 | { | 776 | { |
750 | struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info; | 777 | struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info; |
@@ -753,14 +780,16 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) | |||
753 | struct osd_attr attr; | 780 | struct osd_attr attr; |
754 | __be64 newsize; | 781 | __be64 newsize; |
755 | } *size_attrs; | 782 | } *size_attrs; |
756 | struct _striping_info si; | 783 | struct _trunc_info ti; |
757 | int i, ret; | 784 | int i, ret; |
758 | 785 | ||
759 | ret = exofs_get_io_state(&sbi->layout, &ios); | 786 | ret = exofs_get_io_state(&sbi->layout, &ios); |
760 | if (unlikely(ret)) | 787 | if (unlikely(ret)) |
761 | return ret; | 788 | return ret; |
762 | 789 | ||
763 | size_attrs = kcalloc(ios->layout->group_width, sizeof(*size_attrs), | 790 | _calc_trunk_info(ios->layout, size, &ti); |
791 | |||
792 | size_attrs = kcalloc(ti.max_devs, sizeof(*size_attrs), | ||
764 | GFP_KERNEL); | 793 | GFP_KERNEL); |
765 | if (unlikely(!size_attrs)) { | 794 | if (unlikely(!size_attrs)) { |
766 | ret = -ENOMEM; | 795 | ret = -ENOMEM; |
@@ -769,26 +798,30 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) | |||
769 | 798 | ||
770 | ios->obj.id = exofs_oi_objno(oi); | 799 | ios->obj.id = exofs_oi_objno(oi); |
771 | ios->cred = oi->i_cred; | 800 | ios->cred = oi->i_cred; |
772 | |||
773 | ios->numdevs = ios->layout->s_numdevs; | 801 | ios->numdevs = ios->layout->s_numdevs; |
774 | _calc_stripe_info(ios, size, &si); | ||
775 | 802 | ||
776 | for (i = 0; i < ios->layout->group_width; ++i) { | 803 | for (i = 0; i < ti.max_devs; ++i) { |
777 | struct exofs_trunc_attr *size_attr = &size_attrs[i]; | 804 | struct exofs_trunc_attr *size_attr = &size_attrs[i]; |
778 | u64 obj_size; | 805 | u64 obj_size; |
779 | 806 | ||
780 | if (i < si.dev) | 807 | if (i < ti.first_group_dev) |
781 | obj_size = si.obj_offset + | 808 | obj_size = ti.prev_group_obj_off; |
782 | ios->layout->stripe_unit - si.unit_off; | 809 | else if (i >= ti.nex_group_dev) |
783 | else if (i == si.dev) | 810 | obj_size = ti.next_group_obj_off; |
784 | obj_size = si.obj_offset; | 811 | else if (i < ti.si.dev) /* dev within this group */ |
785 | else /* i > si.dev */ | 812 | obj_size = ti.si.obj_offset + |
786 | obj_size = si.obj_offset - si.unit_off; | 813 | ios->layout->stripe_unit - ti.si.unit_off; |
814 | else if (i == ti.si.dev) | ||
815 | obj_size = ti.si.obj_offset; | ||
816 | else /* i > ti.dev */ | ||
817 | obj_size = ti.si.obj_offset - ti.si.unit_off; | ||
787 | 818 | ||
788 | size_attr->newsize = cpu_to_be64(obj_size); | 819 | size_attr->newsize = cpu_to_be64(obj_size); |
789 | size_attr->attr = g_attr_logical_length; | 820 | size_attr->attr = g_attr_logical_length; |
790 | size_attr->attr.val_ptr = &size_attr->newsize; | 821 | size_attr->attr.val_ptr = &size_attr->newsize; |
791 | 822 | ||
823 | EXOFS_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n", | ||
824 | _LLU(ios->obj.id), _LLU(obj_size), i); | ||
792 | ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, | 825 | ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, |
793 | &size_attr->attr); | 826 | &size_attr->attr); |
794 | if (unlikely(ret)) | 827 | if (unlikely(ret)) |