diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 16f5c21963db..25247a852912 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -679,14 +679,9 @@ get_active_stripe(struct r5conf *conf, sector_t sector, | |||
679 | init_stripe(sh, sector, previous); | 679 | init_stripe(sh, sector, previous); |
680 | atomic_inc(&sh->count); | 680 | atomic_inc(&sh->count); |
681 | } | 681 | } |
682 | } else { | 682 | } else if (!atomic_inc_not_zero(&sh->count)) { |
683 | spin_lock(&conf->device_lock); | 683 | spin_lock(&conf->device_lock); |
684 | if (atomic_read(&sh->count)) { | 684 | if (!atomic_read(&sh->count)) { |
685 | BUG_ON(!list_empty(&sh->lru) | ||
686 | && !test_bit(STRIPE_EXPANDING, &sh->state) | ||
687 | && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state) | ||
688 | ); | ||
689 | } else { | ||
690 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 685 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
691 | atomic_inc(&conf->active_stripes); | 686 | atomic_inc(&conf->active_stripes); |
692 | BUG_ON(list_empty(&sh->lru) && | 687 | BUG_ON(list_empty(&sh->lru) && |
@@ -4552,6 +4547,8 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4552 | struct stripe_head *sh; | 4547 | struct stripe_head *sh; |
4553 | const int rw = bio_data_dir(bi); | 4548 | const int rw = bio_data_dir(bi); |
4554 | int remaining; | 4549 | int remaining; |
4550 | DEFINE_WAIT(w); | ||
4551 | bool do_prepare; | ||
4555 | 4552 | ||
4556 | if (unlikely(bi->bi_rw & REQ_FLUSH)) { | 4553 | if (unlikely(bi->bi_rw & REQ_FLUSH)) { |
4557 | md_flush_request(mddev, bi); | 4554 | md_flush_request(mddev, bi); |
@@ -4575,15 +4572,18 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4575 | bi->bi_next = NULL; | 4572 | bi->bi_next = NULL; |
4576 | bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ | 4573 | bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ |
4577 | 4574 | ||
4575 | prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); | ||
4578 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { | 4576 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { |
4579 | DEFINE_WAIT(w); | ||
4580 | int previous; | 4577 | int previous; |
4581 | int seq; | 4578 | int seq; |
4582 | 4579 | ||
4580 | do_prepare = false; | ||
4583 | retry: | 4581 | retry: |
4584 | seq = read_seqcount_begin(&conf->gen_lock); | 4582 | seq = read_seqcount_begin(&conf->gen_lock); |
4585 | previous = 0; | 4583 | previous = 0; |
4586 | prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); | 4584 | if (do_prepare) |
4585 | prepare_to_wait(&conf->wait_for_overlap, &w, | ||
4586 | TASK_UNINTERRUPTIBLE); | ||
4587 | if (unlikely(conf->reshape_progress != MaxSector)) { | 4587 | if (unlikely(conf->reshape_progress != MaxSector)) { |
4588 | /* spinlock is needed as reshape_progress may be | 4588 | /* spinlock is needed as reshape_progress may be |
4589 | * 64bit on a 32bit platform, and so it might be | 4589 | * 64bit on a 32bit platform, and so it might be |
@@ -4604,6 +4604,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4604 | : logical_sector >= conf->reshape_safe) { | 4604 | : logical_sector >= conf->reshape_safe) { |
4605 | spin_unlock_irq(&conf->device_lock); | 4605 | spin_unlock_irq(&conf->device_lock); |
4606 | schedule(); | 4606 | schedule(); |
4607 | do_prepare = true; | ||
4607 | goto retry; | 4608 | goto retry; |
4608 | } | 4609 | } |
4609 | } | 4610 | } |
@@ -4640,6 +4641,7 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4640 | if (must_retry) { | 4641 | if (must_retry) { |
4641 | release_stripe(sh); | 4642 | release_stripe(sh); |
4642 | schedule(); | 4643 | schedule(); |
4644 | do_prepare = true; | ||
4643 | goto retry; | 4645 | goto retry; |
4644 | } | 4646 | } |
4645 | } | 4647 | } |
@@ -4663,8 +4665,10 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4663 | prepare_to_wait(&conf->wait_for_overlap, | 4665 | prepare_to_wait(&conf->wait_for_overlap, |
4664 | &w, TASK_INTERRUPTIBLE); | 4666 | &w, TASK_INTERRUPTIBLE); |
4665 | if (logical_sector >= mddev->suspend_lo && | 4667 | if (logical_sector >= mddev->suspend_lo && |
4666 | logical_sector < mddev->suspend_hi) | 4668 | logical_sector < mddev->suspend_hi) { |
4667 | schedule(); | 4669 | schedule(); |
4670 | do_prepare = true; | ||
4671 | } | ||
4668 | goto retry; | 4672 | goto retry; |
4669 | } | 4673 | } |
4670 | 4674 | ||
@@ -4677,9 +4681,9 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4677 | md_wakeup_thread(mddev->thread); | 4681 | md_wakeup_thread(mddev->thread); |
4678 | release_stripe(sh); | 4682 | release_stripe(sh); |
4679 | schedule(); | 4683 | schedule(); |
4684 | do_prepare = true; | ||
4680 | goto retry; | 4685 | goto retry; |
4681 | } | 4686 | } |
4682 | finish_wait(&conf->wait_for_overlap, &w); | ||
4683 | set_bit(STRIPE_HANDLE, &sh->state); | 4687 | set_bit(STRIPE_HANDLE, &sh->state); |
4684 | clear_bit(STRIPE_DELAYED, &sh->state); | 4688 | clear_bit(STRIPE_DELAYED, &sh->state); |
4685 | if ((bi->bi_rw & REQ_SYNC) && | 4689 | if ((bi->bi_rw & REQ_SYNC) && |
@@ -4689,10 +4693,10 @@ static void make_request(struct mddev *mddev, struct bio * bi) | |||
4689 | } else { | 4693 | } else { |
4690 | /* cannot get stripe for read-ahead, just give-up */ | 4694 | /* cannot get stripe for read-ahead, just give-up */ |
4691 | clear_bit(BIO_UPTODATE, &bi->bi_flags); | 4695 | clear_bit(BIO_UPTODATE, &bi->bi_flags); |
4692 | finish_wait(&conf->wait_for_overlap, &w); | ||
4693 | break; | 4696 | break; |
4694 | } | 4697 | } |
4695 | } | 4698 | } |
4699 | finish_wait(&conf->wait_for_overlap, &w); | ||
4696 | 4700 | ||
4697 | remaining = raid5_dec_bi_active_stripes(bi); | 4701 | remaining = raid5_dec_bi_active_stripes(bi); |
4698 | if (remaining == 0) { | 4702 | if (remaining == 0) { |