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; |
