|
@@ -374,6 +374,8 @@ static void release_inactive_stripe_list(struct r5conf *conf,
|
|
|
|
|
|
if (do_wakeup) {
|
|
if (do_wakeup) {
|
|
wake_up(&conf->wait_for_stripe);
|
|
wake_up(&conf->wait_for_stripe);
|
|
|
|
+ if (atomic_read(&conf->active_stripes) == 0)
|
|
|
|
+ wake_up(&conf->wait_for_quiescent);
|
|
if (conf->retry_read_aligned)
|
|
if (conf->retry_read_aligned)
|
|
md_wakeup_thread(conf->mddev->thread);
|
|
md_wakeup_thread(conf->mddev->thread);
|
|
}
|
|
}
|
|
@@ -667,7 +669,7 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
|
|
spin_lock_irq(conf->hash_locks + hash);
|
|
spin_lock_irq(conf->hash_locks + hash);
|
|
|
|
|
|
do {
|
|
do {
|
|
- wait_event_lock_irq(conf->wait_for_stripe,
|
|
|
|
|
|
+ wait_event_lock_irq(conf->wait_for_quiescent,
|
|
conf->quiesce == 0 || noquiesce,
|
|
conf->quiesce == 0 || noquiesce,
|
|
*(conf->hash_locks + hash));
|
|
*(conf->hash_locks + hash));
|
|
sh = __find_stripe(conf, sector, conf->generation - previous);
|
|
sh = __find_stripe(conf, sector, conf->generation - previous);
|
|
@@ -4760,7 +4762,7 @@ static void raid5_align_endio(struct bio *bi, int error)
|
|
raid_bi, 0);
|
|
raid_bi, 0);
|
|
bio_endio(raid_bi, 0);
|
|
bio_endio(raid_bi, 0);
|
|
if (atomic_dec_and_test(&conf->active_aligned_reads))
|
|
if (atomic_dec_and_test(&conf->active_aligned_reads))
|
|
- wake_up(&conf->wait_for_stripe);
|
|
|
|
|
|
+ wake_up(&conf->wait_for_quiescent);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4855,7 +4857,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
|
|
align_bi->bi_iter.bi_sector += rdev->data_offset;
|
|
align_bi->bi_iter.bi_sector += rdev->data_offset;
|
|
|
|
|
|
spin_lock_irq(&conf->device_lock);
|
|
spin_lock_irq(&conf->device_lock);
|
|
- wait_event_lock_irq(conf->wait_for_stripe,
|
|
|
|
|
|
+ wait_event_lock_irq(conf->wait_for_quiescent,
|
|
conf->quiesce == 0,
|
|
conf->quiesce == 0,
|
|
conf->device_lock);
|
|
conf->device_lock);
|
|
atomic_inc(&conf->active_aligned_reads);
|
|
atomic_inc(&conf->active_aligned_reads);
|
|
@@ -5699,7 +5701,7 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
|
|
bio_endio(raid_bio, 0);
|
|
bio_endio(raid_bio, 0);
|
|
}
|
|
}
|
|
if (atomic_dec_and_test(&conf->active_aligned_reads))
|
|
if (atomic_dec_and_test(&conf->active_aligned_reads))
|
|
- wake_up(&conf->wait_for_stripe);
|
|
|
|
|
|
+ wake_up(&conf->wait_for_quiescent);
|
|
return handled;
|
|
return handled;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6433,6 +6435,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
|
|
goto abort;
|
|
goto abort;
|
|
spin_lock_init(&conf->device_lock);
|
|
spin_lock_init(&conf->device_lock);
|
|
seqcount_init(&conf->gen_lock);
|
|
seqcount_init(&conf->gen_lock);
|
|
|
|
+ init_waitqueue_head(&conf->wait_for_quiescent);
|
|
init_waitqueue_head(&conf->wait_for_stripe);
|
|
init_waitqueue_head(&conf->wait_for_stripe);
|
|
init_waitqueue_head(&conf->wait_for_overlap);
|
|
init_waitqueue_head(&conf->wait_for_overlap);
|
|
INIT_LIST_HEAD(&conf->handle_list);
|
|
INIT_LIST_HEAD(&conf->handle_list);
|
|
@@ -7466,7 +7469,7 @@ static void raid5_quiesce(struct mddev *mddev, int state)
|
|
* active stripes can drain
|
|
* active stripes can drain
|
|
*/
|
|
*/
|
|
conf->quiesce = 2;
|
|
conf->quiesce = 2;
|
|
- wait_event_cmd(conf->wait_for_stripe,
|
|
|
|
|
|
+ wait_event_cmd(conf->wait_for_quiescent,
|
|
atomic_read(&conf->active_stripes) == 0 &&
|
|
atomic_read(&conf->active_stripes) == 0 &&
|
|
atomic_read(&conf->active_aligned_reads) == 0,
|
|
atomic_read(&conf->active_aligned_reads) == 0,
|
|
unlock_all_device_hash_locks_irq(conf),
|
|
unlock_all_device_hash_locks_irq(conf),
|
|
@@ -7480,7 +7483,7 @@ static void raid5_quiesce(struct mddev *mddev, int state)
|
|
case 0: /* re-enable writes */
|
|
case 0: /* re-enable writes */
|
|
lock_all_device_hash_locks_irq(conf);
|
|
lock_all_device_hash_locks_irq(conf);
|
|
conf->quiesce = 0;
|
|
conf->quiesce = 0;
|
|
- wake_up(&conf->wait_for_stripe);
|
|
|
|
|
|
+ wake_up(&conf->wait_for_quiescent);
|
|
wake_up(&conf->wait_for_overlap);
|
|
wake_up(&conf->wait_for_overlap);
|
|
unlock_all_device_hash_locks_irq(conf);
|
|
unlock_all_device_hash_locks_irq(conf);
|
|
break;
|
|
break;
|