Skip to content

Commit 16f75bb

Browse files
author
Boaz Harrosh
committed
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>
1 parent 9ce7304 commit 16f75bb

File tree

1 file changed

+53
-20
lines changed

1 file changed

+53
-20
lines changed

fs/exofs/ios.c

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -305,20 +305,21 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
305305
struct _striping_info {
306306
u64 obj_offset;
307307
u64 group_length;
308+
u64 M; /* for truncate */
308309
unsigned dev;
309310
unsigned unit_off;
310311
};
311312

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,
313314
struct _striping_info *si)
314315
{
315-
u32 stripe_unit = ios->layout->stripe_unit;
316-
u32 group_width = ios->layout->group_width;
317-
u64 group_depth = ios->layout->group_depth;
316+
u32 stripe_unit = layout->stripe_unit;
317+
u32 group_width = layout->group_width;
318+
u64 group_depth = layout->group_depth;
318319

319320
u32 U = stripe_unit * group_width;
320321
u64 T = U * group_depth;
321-
u64 S = T * ios->layout->group_count;
322+
u64 S = T * layout->group_count;
322323
u64 M = div64_u64(file_offset, S);
323324

324325
/*
@@ -333,14 +334,15 @@ static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
333334

334335
/* "H - (N * U)" is just "H % U" so it's bound to u32 */
335336
si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
336-
si->dev *= ios->layout->mirrors_p1;
337+
si->dev *= layout->mirrors_p1;
337338

338339
div_u64_rem(file_offset, stripe_unit, &si->unit_off);
339340

340341
si->obj_offset = si->unit_off + (N * stripe_unit) +
341342
(M * group_depth * stripe_unit);
342343

343344
si->group_length = T - H;
345+
si->M = M;
344346
}
345347

346348
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)
454456
if (ios->kern_buff) {
455457
struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
456458

457-
_calc_stripe_info(ios, ios->offset, &si);
459+
_calc_stripe_info(ios->layout, ios->offset, &si);
458460
per_dev->offset = si.obj_offset;
459461
per_dev->dev = si.dev;
460462

@@ -468,7 +470,7 @@ static int _prepare_for_striping(struct exofs_io_state *ios)
468470
}
469471

470472
while (length) {
471-
_calc_stripe_info(ios, offset, &si);
473+
_calc_stripe_info(ios->layout, offset, &si);
472474

473475
if (length < si.group_length)
474476
si.group_length = length;
@@ -745,6 +747,31 @@ static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp,
745747
return 0;
746748
}
747749

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+
748775
int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
749776
{
750777
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)
753780
struct osd_attr attr;
754781
__be64 newsize;
755782
} *size_attrs;
756-
struct _striping_info si;
783+
struct _trunc_info ti;
757784
int i, ret;
758785

759786
ret = exofs_get_io_state(&sbi->layout, &ios);
760787
if (unlikely(ret))
761788
return ret;
762789

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),
764793
GFP_KERNEL);
765794
if (unlikely(!size_attrs)) {
766795
ret = -ENOMEM;
@@ -769,26 +798,30 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
769798

770799
ios->obj.id = exofs_oi_objno(oi);
771800
ios->cred = oi->i_cred;
772-
773801
ios->numdevs = ios->layout->s_numdevs;
774-
_calc_stripe_info(ios, size, &si);
775802

776-
for (i = 0; i < ios->layout->group_width; ++i) {
803+
for (i = 0; i < ti.max_devs; ++i) {
777804
struct exofs_trunc_attr *size_attr = &size_attrs[i];
778805
u64 obj_size;
779806

780-
if (i < si.dev)
781-
obj_size = si.obj_offset +
782-
ios->layout->stripe_unit - si.unit_off;
783-
else if (i == si.dev)
784-
obj_size = si.obj_offset;
785-
else /* i > si.dev */
786-
obj_size = si.obj_offset - si.unit_off;
807+
if (i < ti.first_group_dev)
808+
obj_size = ti.prev_group_obj_off;
809+
else if (i >= ti.nex_group_dev)
810+
obj_size = ti.next_group_obj_off;
811+
else if (i < ti.si.dev) /* dev within this group */
812+
obj_size = ti.si.obj_offset +
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;
787818

788819
size_attr->newsize = cpu_to_be64(obj_size);
789820
size_attr->attr = g_attr_logical_length;
790821
size_attr->attr.val_ptr = &size_attr->newsize;
791822

823+
EXOFS_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
824+
_LLU(ios->obj.id), _LLU(obj_size), i);
792825
ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
793826
&size_attr->attr);
794827
if (unlikely(ret))

0 commit comments

Comments
 (0)