aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-08-03 23:44:16 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-08-04 15:35:25 -0400
commit16f75bb35d54b44356f496272c013f7ace5fa698 (patch)
tree0fbbcf34fbbaed8e2c57ea2f1fd061dcbcd8f511 /fs/exofs
parent9ce730475e1b950d78a69c1be3410109c103ac98 (diff)
exofs: Fix truncate for the raid-groups case
In the general raid-group case the truncate was wrong in that it did not also fix the object length of the neighboring groups. There are two bad cases in the old code: 1. Space that should be freed was not. 2. If a file That was big is truncated small, then made bigger again, the holes would not contain zeros but could expose old data. (If the growing of the file expands to more than a full groups cycle + group size (> S + T)) Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/exofs')
-rw-r--r--fs/exofs/ios.c73
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)
305struct _striping_info { 305struct _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
312static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset, 313static 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
346static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, 348static 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
750struct _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
760void _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
748int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) 775int 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))