diff options
Diffstat (limited to 'drivers/md')
| -rw-r--r-- | drivers/md/dm-crypt.c | 58 | ||||
| -rw-r--r-- | drivers/md/dm-io.c | 2 | ||||
| -rw-r--r-- | drivers/md/dm-raid1.c | 4 | ||||
| -rw-r--r-- | drivers/md/dm-snap.c | 2 | ||||
| -rw-r--r-- | drivers/md/kcopyd.c | 10 | ||||
| -rw-r--r-- | drivers/md/kcopyd.h | 4 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 51 |
7 files changed, 70 insertions, 61 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index b04f98df94ea..835def11419d 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2003 Christophe Saout <christophe@saout.de> | 2 | * Copyright (C) 2003 Christophe Saout <christophe@saout.de> |
| 3 | * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> | 3 | * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> |
| 4 | * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved. | 4 | * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This file is released under the GPL. | 6 | * This file is released under the GPL. |
| 7 | */ | 7 | */ |
| @@ -93,6 +93,8 @@ struct crypt_config { | |||
| 93 | 93 | ||
| 94 | struct workqueue_struct *io_queue; | 94 | struct workqueue_struct *io_queue; |
| 95 | struct workqueue_struct *crypt_queue; | 95 | struct workqueue_struct *crypt_queue; |
| 96 | wait_queue_head_t writeq; | ||
| 97 | |||
| 96 | /* | 98 | /* |
| 97 | * crypto related data | 99 | * crypto related data |
| 98 | */ | 100 | */ |
| @@ -331,14 +333,7 @@ static void crypt_convert_init(struct crypt_config *cc, | |||
| 331 | ctx->idx_out = bio_out ? bio_out->bi_idx : 0; | 333 | ctx->idx_out = bio_out ? bio_out->bi_idx : 0; |
| 332 | ctx->sector = sector + cc->iv_offset; | 334 | ctx->sector = sector + cc->iv_offset; |
| 333 | init_completion(&ctx->restart); | 335 | init_completion(&ctx->restart); |
| 334 | /* | 336 | atomic_set(&ctx->pending, 1); |
| 335 | * Crypto operation can be asynchronous, | ||
| 336 | * ctx->pending is increased after request submission. | ||
| 337 | * We need to ensure that we don't call the crypt finish | ||
| 338 | * operation before pending got incremented | ||
| 339 | * (dependent on crypt submission return code). | ||
| 340 | */ | ||
| 341 | atomic_set(&ctx->pending, 2); | ||
| 342 | } | 337 | } |
| 343 | 338 | ||
| 344 | static int crypt_convert_block(struct crypt_config *cc, | 339 | static int crypt_convert_block(struct crypt_config *cc, |
| @@ -411,43 +406,42 @@ static void crypt_alloc_req(struct crypt_config *cc, | |||
| 411 | static int crypt_convert(struct crypt_config *cc, | 406 | static int crypt_convert(struct crypt_config *cc, |
| 412 | struct convert_context *ctx) | 407 | struct convert_context *ctx) |
| 413 | { | 408 | { |
| 414 | int r = 0; | 409 | int r; |
| 415 | 410 | ||
| 416 | while(ctx->idx_in < ctx->bio_in->bi_vcnt && | 411 | while(ctx->idx_in < ctx->bio_in->bi_vcnt && |
| 417 | ctx->idx_out < ctx->bio_out->bi_vcnt) { | 412 | ctx->idx_out < ctx->bio_out->bi_vcnt) { |
| 418 | 413 | ||
| 419 | crypt_alloc_req(cc, ctx); | 414 | crypt_alloc_req(cc, ctx); |
| 420 | 415 | ||
| 416 | atomic_inc(&ctx->pending); | ||
| 417 | |||
| 421 | r = crypt_convert_block(cc, ctx, cc->req); | 418 | r = crypt_convert_block(cc, ctx, cc->req); |
| 422 | 419 | ||
| 423 | switch (r) { | 420 | switch (r) { |
| 421 | /* async */ | ||
| 424 | case -EBUSY: | 422 | case -EBUSY: |
| 425 | wait_for_completion(&ctx->restart); | 423 | wait_for_completion(&ctx->restart); |
| 426 | INIT_COMPLETION(ctx->restart); | 424 | INIT_COMPLETION(ctx->restart); |
| 427 | /* fall through*/ | 425 | /* fall through*/ |
| 428 | case -EINPROGRESS: | 426 | case -EINPROGRESS: |
| 429 | atomic_inc(&ctx->pending); | ||
| 430 | cc->req = NULL; | 427 | cc->req = NULL; |
| 431 | r = 0; | 428 | ctx->sector++; |
| 432 | /* fall through*/ | 429 | continue; |
| 430 | |||
| 431 | /* sync */ | ||
| 433 | case 0: | 432 | case 0: |
| 433 | atomic_dec(&ctx->pending); | ||
| 434 | ctx->sector++; | 434 | ctx->sector++; |
| 435 | continue; | 435 | continue; |
| 436 | } | ||
| 437 | 436 | ||
| 438 | break; | 437 | /* error */ |
| 438 | default: | ||
| 439 | atomic_dec(&ctx->pending); | ||
| 440 | return r; | ||
| 441 | } | ||
| 439 | } | 442 | } |
| 440 | 443 | ||
| 441 | /* | 444 | return 0; |
| 442 | * If there are pending crypto operation run async | ||
| 443 | * code. Otherwise process return code synchronously. | ||
| 444 | * The step of 2 ensures that async finish doesn't | ||
| 445 | * call crypto finish too early. | ||
| 446 | */ | ||
| 447 | if (atomic_sub_return(2, &ctx->pending)) | ||
| 448 | return -EINPROGRESS; | ||
| 449 | |||
| 450 | return r; | ||
| 451 | } | 445 | } |
| 452 | 446 | ||
| 453 | static void dm_crypt_bio_destructor(struct bio *bio) | 447 | static void dm_crypt_bio_destructor(struct bio *bio) |
| @@ -624,8 +618,10 @@ static void kcryptd_io_read(struct dm_crypt_io *io) | |||
| 624 | static void kcryptd_io_write(struct dm_crypt_io *io) | 618 | static void kcryptd_io_write(struct dm_crypt_io *io) |
| 625 | { | 619 | { |
| 626 | struct bio *clone = io->ctx.bio_out; | 620 | struct bio *clone = io->ctx.bio_out; |
| 621 | struct crypt_config *cc = io->target->private; | ||
| 627 | 622 | ||
| 628 | generic_make_request(clone); | 623 | generic_make_request(clone); |
| 624 | wake_up(&cc->writeq); | ||
| 629 | } | 625 | } |
| 630 | 626 | ||
| 631 | static void kcryptd_io(struct work_struct *work) | 627 | static void kcryptd_io(struct work_struct *work) |
| @@ -698,7 +694,8 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) | |||
| 698 | 694 | ||
| 699 | r = crypt_convert(cc, &io->ctx); | 695 | r = crypt_convert(cc, &io->ctx); |
| 700 | 696 | ||
| 701 | if (r != -EINPROGRESS) { | 697 | if (atomic_dec_and_test(&io->ctx.pending)) { |
| 698 | /* processed, no running async crypto */ | ||
| 702 | kcryptd_crypt_write_io_submit(io, r, 0); | 699 | kcryptd_crypt_write_io_submit(io, r, 0); |
| 703 | if (unlikely(r < 0)) | 700 | if (unlikely(r < 0)) |
| 704 | return; | 701 | return; |
| @@ -706,8 +703,12 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) | |||
| 706 | atomic_inc(&io->pending); | 703 | atomic_inc(&io->pending); |
| 707 | 704 | ||
| 708 | /* out of memory -> run queues */ | 705 | /* out of memory -> run queues */ |
| 709 | if (unlikely(remaining)) | 706 | if (unlikely(remaining)) { |
| 707 | /* wait for async crypto then reinitialize pending */ | ||
| 708 | wait_event(cc->writeq, !atomic_read(&io->ctx.pending)); | ||
| 709 | atomic_set(&io->ctx.pending, 1); | ||
| 710 | congestion_wait(WRITE, HZ/100); | 710 | congestion_wait(WRITE, HZ/100); |
| 711 | } | ||
| 711 | } | 712 | } |
| 712 | } | 713 | } |
| 713 | 714 | ||
| @@ -746,7 +747,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) | |||
| 746 | 747 | ||
| 747 | r = crypt_convert(cc, &io->ctx); | 748 | r = crypt_convert(cc, &io->ctx); |
| 748 | 749 | ||
| 749 | if (r != -EINPROGRESS) | 750 | if (atomic_dec_and_test(&io->ctx.pending)) |
| 750 | kcryptd_crypt_read_done(io, r); | 751 | kcryptd_crypt_read_done(io, r); |
| 751 | 752 | ||
| 752 | crypt_dec_pending(io); | 753 | crypt_dec_pending(io); |
| @@ -1047,6 +1048,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1047 | goto bad_crypt_queue; | 1048 | goto bad_crypt_queue; |
| 1048 | } | 1049 | } |
| 1049 | 1050 | ||
| 1051 | init_waitqueue_head(&cc->writeq); | ||
| 1050 | ti->private = cc; | 1052 | ti->private = cc; |
| 1051 | return 0; | 1053 | return 0; |
| 1052 | 1054 | ||
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index b8e342fe7586..8f25f628ef16 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
| @@ -114,7 +114,7 @@ static void dec_count(struct io *io, unsigned int region, int error) | |||
| 114 | wake_up_process(io->sleeper); | 114 | wake_up_process(io->sleeper); |
| 115 | 115 | ||
| 116 | else { | 116 | else { |
| 117 | int r = io->error; | 117 | unsigned long r = io->error; |
| 118 | io_notify_fn fn = io->callback; | 118 | io_notify_fn fn = io->callback; |
| 119 | void *context = io->context; | 119 | void *context = io->context; |
| 120 | 120 | ||
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 51605870f898..762cb086bb7f 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -753,7 +753,7 @@ out: | |||
| 753 | * are in the no-sync state. We have to recover these by | 753 | * are in the no-sync state. We have to recover these by |
| 754 | * recopying from the default mirror to all the others. | 754 | * recopying from the default mirror to all the others. |
| 755 | *---------------------------------------------------------------*/ | 755 | *---------------------------------------------------------------*/ |
| 756 | static void recovery_complete(int read_err, unsigned int write_err, | 756 | static void recovery_complete(int read_err, unsigned long write_err, |
| 757 | void *context) | 757 | void *context) |
| 758 | { | 758 | { |
| 759 | struct region *reg = (struct region *)context; | 759 | struct region *reg = (struct region *)context; |
| @@ -767,7 +767,7 @@ static void recovery_complete(int read_err, unsigned int write_err, | |||
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | if (write_err) { | 769 | if (write_err) { |
| 770 | DMERR_LIMIT("Write error during recovery (error = 0x%x)", | 770 | DMERR_LIMIT("Write error during recovery (error = 0x%lx)", |
| 771 | write_err); | 771 | write_err); |
| 772 | /* | 772 | /* |
| 773 | * Bits correspond to devices (excluding default mirror). | 773 | * Bits correspond to devices (excluding default mirror). |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index ae24eab8cd81..4dc8a43c034b 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -804,7 +804,7 @@ static void commit_callback(void *context, int success) | |||
| 804 | * Called when the copy I/O has finished. kcopyd actually runs | 804 | * Called when the copy I/O has finished. kcopyd actually runs |
| 805 | * this code so don't block. | 805 | * this code so don't block. |
| 806 | */ | 806 | */ |
| 807 | static void copy_callback(int read_err, unsigned int write_err, void *context) | 807 | static void copy_callback(int read_err, unsigned long write_err, void *context) |
| 808 | { | 808 | { |
| 809 | struct dm_snap_pending_exception *pe = context; | 809 | struct dm_snap_pending_exception *pe = context; |
| 810 | struct dm_snapshot *s = pe->snap; | 810 | struct dm_snapshot *s = pe->snap; |
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index f3831f31223e..e76b52ade690 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c | |||
| @@ -169,7 +169,7 @@ struct kcopyd_job { | |||
| 169 | * Error state of the job. | 169 | * Error state of the job. |
| 170 | */ | 170 | */ |
| 171 | int read_err; | 171 | int read_err; |
| 172 | unsigned int write_err; | 172 | unsigned long write_err; |
| 173 | 173 | ||
| 174 | /* | 174 | /* |
| 175 | * Either READ or WRITE | 175 | * Either READ or WRITE |
| @@ -293,7 +293,7 @@ static int run_complete_job(struct kcopyd_job *job) | |||
| 293 | { | 293 | { |
| 294 | void *context = job->context; | 294 | void *context = job->context; |
| 295 | int read_err = job->read_err; | 295 | int read_err = job->read_err; |
| 296 | unsigned int write_err = job->write_err; | 296 | unsigned long write_err = job->write_err; |
| 297 | kcopyd_notify_fn fn = job->fn; | 297 | kcopyd_notify_fn fn = job->fn; |
| 298 | struct kcopyd_client *kc = job->kc; | 298 | struct kcopyd_client *kc = job->kc; |
| 299 | 299 | ||
| @@ -396,7 +396,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *)) | |||
| 396 | if (r < 0) { | 396 | if (r < 0) { |
| 397 | /* error this rogue job */ | 397 | /* error this rogue job */ |
| 398 | if (job->rw == WRITE) | 398 | if (job->rw == WRITE) |
| 399 | job->write_err = (unsigned int) -1; | 399 | job->write_err = (unsigned long) -1L; |
| 400 | else | 400 | else |
| 401 | job->read_err = 1; | 401 | job->read_err = 1; |
| 402 | push(&_complete_jobs, job); | 402 | push(&_complete_jobs, job); |
| @@ -448,8 +448,8 @@ static void dispatch_job(struct kcopyd_job *job) | |||
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | #define SUB_JOB_SIZE 128 | 450 | #define SUB_JOB_SIZE 128 |
| 451 | static void segment_complete(int read_err, | 451 | static void segment_complete(int read_err, unsigned long write_err, |
| 452 | unsigned int write_err, void *context) | 452 | void *context) |
| 453 | { | 453 | { |
| 454 | /* FIXME: tidy this function */ | 454 | /* FIXME: tidy this function */ |
| 455 | sector_t progress = 0; | 455 | sector_t progress = 0; |
diff --git a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h index 4621ea055c0e..4845f2a0c676 100644 --- a/drivers/md/kcopyd.h +++ b/drivers/md/kcopyd.h | |||
| @@ -32,8 +32,8 @@ void kcopyd_client_destroy(struct kcopyd_client *kc); | |||
| 32 | * read_err is a boolean, | 32 | * read_err is a boolean, |
| 33 | * write_err is a bitset, with 1 bit for each destination region | 33 | * write_err is a bitset, with 1 bit for each destination region |
| 34 | */ | 34 | */ |
| 35 | typedef void (*kcopyd_notify_fn)(int read_err, | 35 | typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err, |
| 36 | unsigned int write_err, void *context); | 36 | void *context); |
| 37 | 37 | ||
| 38 | int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, | 38 | int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, |
| 39 | unsigned int num_dests, struct io_region *dests, | 39 | unsigned int num_dests, struct io_region *dests, |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c574cf5efb5c..b162b839a662 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -2348,25 +2348,15 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf, | |||
| 2348 | static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, | 2348 | static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, |
| 2349 | struct stripe_head_state *s, int disks) | 2349 | struct stripe_head_state *s, int disks) |
| 2350 | { | 2350 | { |
| 2351 | int canceled_check = 0; | ||
| 2352 | |||
| 2351 | set_bit(STRIPE_HANDLE, &sh->state); | 2353 | set_bit(STRIPE_HANDLE, &sh->state); |
| 2352 | /* Take one of the following actions: | ||
| 2353 | * 1/ start a check parity operation if (uptodate == disks) | ||
| 2354 | * 2/ finish a check parity operation and act on the result | ||
| 2355 | * 3/ skip to the writeback section if we previously | ||
| 2356 | * initiated a recovery operation | ||
| 2357 | */ | ||
| 2358 | if (s->failed == 0 && | ||
| 2359 | !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) { | ||
| 2360 | if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) { | ||
| 2361 | BUG_ON(s->uptodate != disks); | ||
| 2362 | clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); | ||
| 2363 | sh->ops.count++; | ||
| 2364 | s->uptodate--; | ||
| 2365 | } else if ( | ||
| 2366 | test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) { | ||
| 2367 | clear_bit(STRIPE_OP_CHECK, &sh->ops.ack); | ||
| 2368 | clear_bit(STRIPE_OP_CHECK, &sh->ops.pending); | ||
| 2369 | 2354 | ||
| 2355 | /* complete a check operation */ | ||
| 2356 | if (test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) { | ||
| 2357 | clear_bit(STRIPE_OP_CHECK, &sh->ops.ack); | ||
| 2358 | clear_bit(STRIPE_OP_CHECK, &sh->ops.pending); | ||
| 2359 | if (s->failed == 0) { | ||
| 2370 | if (sh->ops.zero_sum_result == 0) | 2360 | if (sh->ops.zero_sum_result == 0) |
| 2371 | /* parity is correct (on disc, | 2361 | /* parity is correct (on disc, |
| 2372 | * not in buffer any more) | 2362 | * not in buffer any more) |
| @@ -2391,7 +2381,8 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, | |||
| 2391 | s->uptodate++; | 2381 | s->uptodate++; |
| 2392 | } | 2382 | } |
| 2393 | } | 2383 | } |
| 2394 | } | 2384 | } else |
| 2385 | canceled_check = 1; /* STRIPE_INSYNC is not set */ | ||
| 2395 | } | 2386 | } |
| 2396 | 2387 | ||
| 2397 | /* check if we can clear a parity disk reconstruct */ | 2388 | /* check if we can clear a parity disk reconstruct */ |
| @@ -2404,12 +2395,28 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, | |||
| 2404 | clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending); | 2395 | clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending); |
| 2405 | } | 2396 | } |
| 2406 | 2397 | ||
| 2398 | /* start a new check operation if there are no failures, the stripe is | ||
| 2399 | * not insync, and a repair is not in flight | ||
| 2400 | */ | ||
| 2401 | if (s->failed == 0 && | ||
| 2402 | !test_bit(STRIPE_INSYNC, &sh->state) && | ||
| 2403 | !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) { | ||
| 2404 | if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) { | ||
| 2405 | BUG_ON(s->uptodate != disks); | ||
| 2406 | clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); | ||
| 2407 | sh->ops.count++; | ||
| 2408 | s->uptodate--; | ||
| 2409 | } | ||
| 2410 | } | ||
| 2411 | |||
| 2407 | /* Wait for check parity and compute block operations to complete | 2412 | /* Wait for check parity and compute block operations to complete |
| 2408 | * before write-back | 2413 | * before write-back. If a failure occurred while the check operation |
| 2414 | * was in flight we need to cycle this stripe through handle_stripe | ||
| 2415 | * since the parity block may not be uptodate | ||
| 2409 | */ | 2416 | */ |
| 2410 | if (!test_bit(STRIPE_INSYNC, &sh->state) && | 2417 | if (!canceled_check && !test_bit(STRIPE_INSYNC, &sh->state) && |
| 2411 | !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) && | 2418 | !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) && |
| 2412 | !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) { | 2419 | !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) { |
| 2413 | struct r5dev *dev; | 2420 | struct r5dev *dev; |
| 2414 | /* either failed parity check, or recovery is happening */ | 2421 | /* either failed parity check, or recovery is happening */ |
| 2415 | if (s->failed == 0) | 2422 | if (s->failed == 0) |
