diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2011-08-27 00:04:52 -0400 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2011-10-14 12:54:40 -0400 |
commit | bbf9a31bba8c985780fe94da059cc5813a7920f5 (patch) | |
tree | 882d91f165dad978295f14fb8226a1296ca72073 /fs/exofs | |
parent | 154a9300cd87eee7538f356c9d339f06b0b1d257 (diff) |
ore: Support for short read/writes
Memory conditions and max_bio constraints might cause us to
not comply to the full length of the requested IO. Instead of
failing the complete IO we can issue a shorter read/write and
report how much was actually executed in the ios->length
member.
All users must check ios->length at IO_done or upon return of
ore_read/write and re-issue the reminder of the bytes. Because
other wise there is no error returned like before.
This is part of the effort to support the pnfs-obj layout driver.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/exofs')
-rw-r--r-- | fs/exofs/ore.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index d0f8db5e46c5..8354fe061d1c 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c | |||
@@ -377,8 +377,8 @@ static int _add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
377 | unsigned pg = *cur_pg; | 377 | unsigned pg = *cur_pg; |
378 | struct request_queue *q = | 378 | struct request_queue *q = |
379 | osd_request_queue(_ios_od(ios, per_dev->dev)); | 379 | osd_request_queue(_ios_od(ios, per_dev->dev)); |
380 | 380 | unsigned len = cur_len; | |
381 | per_dev->length += cur_len; | 381 | int ret; |
382 | 382 | ||
383 | if (per_dev->bio == NULL) { | 383 | if (per_dev->bio == NULL) { |
384 | unsigned pages_in_stripe = ios->layout->group_width * | 384 | unsigned pages_in_stripe = ios->layout->group_width * |
@@ -390,7 +390,8 @@ static int _add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
390 | if (unlikely(!per_dev->bio)) { | 390 | if (unlikely(!per_dev->bio)) { |
391 | ORE_DBGMSG("Failed to allocate BIO size=%u\n", | 391 | ORE_DBGMSG("Failed to allocate BIO size=%u\n", |
392 | bio_size); | 392 | bio_size); |
393 | return -ENOMEM; | 393 | ret = -ENOMEM; |
394 | goto out; | ||
394 | } | 395 | } |
395 | } | 396 | } |
396 | 397 | ||
@@ -403,15 +404,24 @@ static int _add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, | |||
403 | 404 | ||
404 | added_len = bio_add_pc_page(q, per_dev->bio, ios->pages[pg], | 405 | added_len = bio_add_pc_page(q, per_dev->bio, ios->pages[pg], |
405 | pglen, pgbase); | 406 | pglen, pgbase); |
406 | if (unlikely(pglen != added_len)) | 407 | if (unlikely(pglen != added_len)) { |
407 | return -ENOMEM; | 408 | ret = -ENOMEM; |
409 | goto out; | ||
410 | } | ||
408 | pgbase = 0; | 411 | pgbase = 0; |
409 | ++pg; | 412 | ++pg; |
410 | } | 413 | } |
411 | BUG_ON(cur_len); | 414 | BUG_ON(cur_len); |
412 | 415 | ||
416 | per_dev->length += len; | ||
413 | *cur_pg = pg; | 417 | *cur_pg = pg; |
414 | return 0; | 418 | ret = 0; |
419 | out: /* we fail the complete unit on an error eg don't advance | ||
420 | * per_dev->length and cur_pg. This means that we might have a bigger | ||
421 | * bio than the CDB requested length (per_dev->length). That's fine | ||
422 | * only the oposite is fatal. | ||
423 | */ | ||
424 | return ret; | ||
415 | } | 425 | } |
416 | 426 | ||
417 | static int _prepare_for_striping(struct ore_io_state *ios) | 427 | static int _prepare_for_striping(struct ore_io_state *ios) |
@@ -472,7 +482,13 @@ static int _prepare_for_striping(struct ore_io_state *ios) | |||
472 | out: | 482 | out: |
473 | ios->numdevs = devs_in_group; | 483 | ios->numdevs = devs_in_group; |
474 | ios->pages_consumed = cur_pg; | 484 | ios->pages_consumed = cur_pg; |
475 | return ret; | 485 | if (unlikely(ret)) { |
486 | if (length == ios->length) | ||
487 | return ret; | ||
488 | else | ||
489 | ios->length -= length; | ||
490 | } | ||
491 | return 0; | ||
476 | } | 492 | } |
477 | 493 | ||
478 | int ore_create(struct ore_io_state *ios) | 494 | int ore_create(struct ore_io_state *ios) |