diff options
-rw-r--r-- | fs/exofs/ios.c | 159 |
1 files changed, 99 insertions, 60 deletions
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c index 263052c77f41..d28febdf54ab 100644 --- a/fs/exofs/ios.c +++ b/fs/exofs/ios.c | |||
@@ -259,28 +259,46 @@ int exofs_check_io(struct exofs_io_state *ios, u64 *resid) | |||
259 | return acumulated_lin_err; | 259 | return acumulated_lin_err; |
260 | } | 260 | } |
261 | 261 | ||
262 | /* REMOVEME: After review | 262 | /* |
263 | Some quoteing from the standard | 263 | * L - logical offset into the file |
264 | 264 | * | |
265 | L = logical offset into the file | 265 | * U - The number of bytes in a full stripe |
266 | W = number of data components in a stripe | 266 | * |
267 | S = W * stripe_unit (S is Stripe length) | 267 | * U = stripe_unit * group_width |
268 | N = L / S (N is the stripe Number) | 268 | * |
269 | C = (L-(N*S)) / stripe_unit (C is the component) | 269 | * N - The stripe number |
270 | O = (N*stripe_unit)+(L%stripe_unit) (O is the object's offset) | 270 | * |
271 | */ | 271 | * N = L / U |
272 | 272 | * | |
273 | static void _offset_dev_unit_off(struct exofs_io_state *ios, u64 file_offset, | 273 | * C - The component index coresponding to L |
274 | u64 *obj_offset, unsigned *dev, unsigned *unit_off) | 274 | * |
275 | * C = (L - (N*U)) / stripe_unit | ||
276 | * | ||
277 | * O - The component offset coresponding to L | ||
278 | * | ||
279 | * (N*stripe_unit)+(L%stripe_unit) | ||
280 | */ | ||
281 | |||
282 | struct _striping_info { | ||
283 | u64 obj_offset; | ||
284 | unsigned dev; | ||
285 | unsigned unit_off; | ||
286 | }; | ||
287 | |||
288 | static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset, | ||
289 | struct _striping_info *si) | ||
275 | { | 290 | { |
276 | unsigned stripe_unit = ios->layout->stripe_unit; | 291 | u32 stripe_unit = ios->layout->stripe_unit; |
277 | unsigned stripe_length = stripe_unit * ios->layout->group_width; | 292 | u32 group_width = ios->layout->group_width; |
278 | u64 stripe_no = file_offset; | 293 | u32 U = stripe_unit * group_width; |
279 | unsigned stripe_mod = do_div(stripe_no, stripe_length); | 294 | |
295 | u32 LmodU; | ||
296 | u64 N = div_u64_rem(file_offset, U, &LmodU); | ||
280 | 297 | ||
281 | *unit_off = stripe_mod % stripe_unit; | 298 | si->unit_off = LmodU % stripe_unit; |
282 | *obj_offset = stripe_no * stripe_unit + *unit_off; | 299 | si->obj_offset = N * stripe_unit + si->unit_off; |
283 | *dev = stripe_mod / stripe_unit * ios->layout->mirrors_p1; | 300 | si->dev = LmodU / stripe_unit; |
301 | si->dev *= ios->layout->mirrors_p1; | ||
284 | } | 302 | } |
285 | 303 | ||
286 | static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, | 304 | static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, |
@@ -327,65 +345,88 @@ static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg, | |||
327 | return 0; | 345 | return 0; |
328 | } | 346 | } |
329 | 347 | ||
330 | static int _prepare_for_striping(struct exofs_io_state *ios) | 348 | static int _prepare_pages(struct exofs_io_state *ios, |
349 | struct _striping_info *si) | ||
331 | { | 350 | { |
332 | u64 length = ios->length; | 351 | u64 length = ios->length; |
333 | u64 offset = ios->offset; | ||
334 | unsigned stripe_unit = ios->layout->stripe_unit; | 352 | unsigned stripe_unit = ios->layout->stripe_unit; |
353 | unsigned mirrors_p1 = ios->layout->mirrors_p1; | ||
354 | unsigned dev = si->dev; | ||
335 | unsigned comp = 0; | 355 | unsigned comp = 0; |
336 | unsigned stripes = 0; | 356 | unsigned stripes = 0; |
337 | unsigned cur_pg = 0; | 357 | unsigned cur_pg = 0; |
338 | int ret = 0; | 358 | int ret = 0; |
339 | 359 | ||
340 | if (!ios->pages) { | ||
341 | if (ios->kern_buff) { | ||
342 | struct exofs_per_dev_state *per_dev = &ios->per_dev[0]; | ||
343 | unsigned unit_off; | ||
344 | |||
345 | _offset_dev_unit_off(ios, offset, &per_dev->offset, | ||
346 | &per_dev->dev, &unit_off); | ||
347 | /* no cross device without page array */ | ||
348 | BUG_ON((ios->layout->group_width > 1) && | ||
349 | (unit_off + length > stripe_unit)); | ||
350 | } | ||
351 | ios->numdevs = ios->layout->mirrors_p1; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | while (length) { | 360 | while (length) { |
356 | struct exofs_per_dev_state *per_dev = &ios->per_dev[comp]; | 361 | struct exofs_per_dev_state *per_dev = &ios->per_dev[comp]; |
357 | unsigned cur_len, page_off; | 362 | unsigned cur_len, page_off = 0; |
358 | 363 | ||
359 | if (!per_dev->length) { | 364 | if (!per_dev->length) { |
360 | unsigned unit_off; | 365 | per_dev->dev = dev; |
366 | if (dev < si->dev) { | ||
367 | per_dev->offset = si->obj_offset + stripe_unit - | ||
368 | si->unit_off; | ||
369 | cur_len = stripe_unit; | ||
370 | } else if (dev == si->dev) { | ||
371 | per_dev->offset = si->obj_offset; | ||
372 | cur_len = stripe_unit - si->unit_off; | ||
373 | page_off = si->unit_off & ~PAGE_MASK; | ||
374 | BUG_ON(page_off && (page_off != ios->pgbase)); | ||
375 | } else { /* dev > si->dev */ | ||
376 | per_dev->offset = si->obj_offset - si->unit_off; | ||
377 | cur_len = stripe_unit; | ||
378 | } | ||
361 | 379 | ||
362 | _offset_dev_unit_off(ios, offset, &per_dev->offset, | ||
363 | &per_dev->dev, &unit_off); | ||
364 | stripes++; | 380 | stripes++; |
365 | cur_len = min_t(u64, stripe_unit - unit_off, length); | 381 | |
366 | offset += cur_len; | 382 | dev += mirrors_p1; |
367 | page_off = unit_off & ~PAGE_MASK; | 383 | dev %= ios->layout->s_numdevs; |
368 | BUG_ON(page_off != ios->pgbase); | ||
369 | } else { | 384 | } else { |
370 | cur_len = min_t(u64, stripe_unit, length); | 385 | cur_len = stripe_unit; |
371 | page_off = 0; | ||
372 | } | 386 | } |
387 | if (cur_len >= length) | ||
388 | cur_len = length; | ||
373 | 389 | ||
374 | ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev, | 390 | ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev, |
375 | cur_len); | 391 | cur_len); |
376 | if (unlikely(ret)) | 392 | if (unlikely(ret)) |
377 | goto out; | 393 | goto out; |
378 | 394 | ||
379 | comp += ios->layout->mirrors_p1; | 395 | comp += mirrors_p1; |
380 | comp %= ios->layout->s_numdevs; | 396 | comp %= ios->layout->s_numdevs; |
381 | 397 | ||
382 | length -= cur_len; | 398 | length -= cur_len; |
383 | } | 399 | } |
384 | out: | 400 | out: |
385 | ios->numdevs = stripes * ios->layout->mirrors_p1; | 401 | ios->numdevs = stripes * mirrors_p1; |
386 | return ret; | 402 | return ret; |
387 | } | 403 | } |
388 | 404 | ||
405 | static int _prepare_for_striping(struct exofs_io_state *ios) | ||
406 | { | ||
407 | struct _striping_info si; | ||
408 | |||
409 | _calc_stripe_info(ios, ios->offset, &si); | ||
410 | |||
411 | if (!ios->pages) { | ||
412 | if (ios->kern_buff) { | ||
413 | struct exofs_per_dev_state *per_dev = &ios->per_dev[0]; | ||
414 | |||
415 | per_dev->offset = si.obj_offset; | ||
416 | per_dev->dev = si.dev; | ||
417 | |||
418 | /* no cross device without page array */ | ||
419 | BUG_ON((ios->layout->group_width > 1) && | ||
420 | (si.unit_off + ios->length > | ||
421 | ios->layout->stripe_unit)); | ||
422 | } | ||
423 | ios->numdevs = ios->layout->mirrors_p1; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | return _prepare_pages(ios, &si); | ||
428 | } | ||
429 | |||
389 | int exofs_sbi_create(struct exofs_io_state *ios) | 430 | int exofs_sbi_create(struct exofs_io_state *ios) |
390 | { | 431 | { |
391 | int i, ret; | 432 | int i, ret; |
@@ -648,9 +689,7 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) | |||
648 | struct osd_attr attr; | 689 | struct osd_attr attr; |
649 | __be64 newsize; | 690 | __be64 newsize; |
650 | } *size_attrs; | 691 | } *size_attrs; |
651 | u64 this_obj_size; | 692 | struct _striping_info si; |
652 | unsigned dev; | ||
653 | unsigned unit_off; | ||
654 | int i, ret; | 693 | int i, ret; |
655 | 694 | ||
656 | ret = exofs_get_io_state(&sbi->layout, &ios); | 695 | ret = exofs_get_io_state(&sbi->layout, &ios); |
@@ -668,19 +707,19 @@ int exofs_oi_truncate(struct exofs_i_info *oi, u64 size) | |||
668 | ios->cred = oi->i_cred; | 707 | ios->cred = oi->i_cred; |
669 | 708 | ||
670 | ios->numdevs = ios->layout->s_numdevs; | 709 | ios->numdevs = ios->layout->s_numdevs; |
671 | _offset_dev_unit_off(ios, size, &this_obj_size, &dev, &unit_off); | 710 | _calc_stripe_info(ios, size, &si); |
672 | 711 | ||
673 | for (i = 0; i < ios->layout->group_width; ++i) { | 712 | for (i = 0; i < ios->layout->group_width; ++i) { |
674 | struct exofs_trunc_attr *size_attr = &size_attrs[i]; | 713 | struct exofs_trunc_attr *size_attr = &size_attrs[i]; |
675 | u64 obj_size; | 714 | u64 obj_size; |
676 | 715 | ||
677 | if (i < dev) | 716 | if (i < si.dev) |
678 | obj_size = this_obj_size + | 717 | obj_size = si.obj_offset + |
679 | ios->layout->stripe_unit - unit_off; | 718 | ios->layout->stripe_unit - si.unit_off; |
680 | else if (i == dev) | 719 | else if (i == si.dev) |
681 | obj_size = this_obj_size; | 720 | obj_size = si.obj_offset; |
682 | else /* i > dev */ | 721 | else /* i > si.dev */ |
683 | obj_size = this_obj_size - unit_off; | 722 | obj_size = si.obj_offset - si.unit_off; |
684 | 723 | ||
685 | size_attr->newsize = cpu_to_be64(obj_size); | 724 | size_attr->newsize = cpu_to_be64(obj_size); |
686 | size_attr->attr = g_attr_logical_length; | 725 | size_attr->attr = g_attr_logical_length; |