diff options
Diffstat (limited to 'drivers/md/raid5.c')
| -rw-r--r-- | drivers/md/raid5.c | 61 |
1 files changed, 26 insertions, 35 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e867ee42b152..f301e6ae220c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -27,12 +27,12 @@ | |||
| 27 | * | 27 | * |
| 28 | * We group bitmap updates into batches. Each batch has a number. | 28 | * We group bitmap updates into batches. Each batch has a number. |
| 29 | * We may write out several batches at once, but that isn't very important. | 29 | * We may write out several batches at once, but that isn't very important. |
| 30 | * conf->bm_write is the number of the last batch successfully written. | 30 | * conf->seq_write is the number of the last batch successfully written. |
| 31 | * conf->bm_flush is the number of the last batch that was closed to | 31 | * conf->seq_flush is the number of the last batch that was closed to |
| 32 | * new additions. | 32 | * new additions. |
| 33 | * When we discover that we will need to write to any block in a stripe | 33 | * When we discover that we will need to write to any block in a stripe |
| 34 | * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq | 34 | * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq |
| 35 | * the number of the batch it will be in. This is bm_flush+1. | 35 | * the number of the batch it will be in. This is seq_flush+1. |
| 36 | * When we are ready to do a write, if that batch hasn't been written yet, | 36 | * When we are ready to do a write, if that batch hasn't been written yet, |
| 37 | * we plug the array and queue the stripe for later. | 37 | * we plug the array and queue the stripe for later. |
| 38 | * When an unplug happens, we increment bm_flush, thus closing the current | 38 | * When an unplug happens, we increment bm_flush, thus closing the current |
| @@ -199,14 +199,12 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) | |||
| 199 | BUG_ON(!list_empty(&sh->lru)); | 199 | BUG_ON(!list_empty(&sh->lru)); |
| 200 | BUG_ON(atomic_read(&conf->active_stripes)==0); | 200 | BUG_ON(atomic_read(&conf->active_stripes)==0); |
| 201 | if (test_bit(STRIPE_HANDLE, &sh->state)) { | 201 | if (test_bit(STRIPE_HANDLE, &sh->state)) { |
| 202 | if (test_bit(STRIPE_DELAYED, &sh->state)) { | 202 | if (test_bit(STRIPE_DELAYED, &sh->state)) |
| 203 | list_add_tail(&sh->lru, &conf->delayed_list); | 203 | list_add_tail(&sh->lru, &conf->delayed_list); |
| 204 | plugger_set_plug(&conf->plug); | 204 | else if (test_bit(STRIPE_BIT_DELAY, &sh->state) && |
| 205 | } else if (test_bit(STRIPE_BIT_DELAY, &sh->state) && | 205 | sh->bm_seq - conf->seq_write > 0) |
| 206 | sh->bm_seq - conf->seq_write > 0) { | ||
| 207 | list_add_tail(&sh->lru, &conf->bitmap_list); | 206 | list_add_tail(&sh->lru, &conf->bitmap_list); |
| 208 | plugger_set_plug(&conf->plug); | 207 | else { |
| 209 | } else { | ||
| 210 | clear_bit(STRIPE_BIT_DELAY, &sh->state); | 208 | clear_bit(STRIPE_BIT_DELAY, &sh->state); |
| 211 | list_add_tail(&sh->lru, &conf->handle_list); | 209 | list_add_tail(&sh->lru, &conf->handle_list); |
| 212 | } | 210 | } |
| @@ -461,7 +459,7 @@ get_active_stripe(raid5_conf_t *conf, sector_t sector, | |||
| 461 | < (conf->max_nr_stripes *3/4) | 459 | < (conf->max_nr_stripes *3/4) |
| 462 | || !conf->inactive_blocked), | 460 | || !conf->inactive_blocked), |
| 463 | conf->device_lock, | 461 | conf->device_lock, |
| 464 | md_raid5_kick_device(conf)); | 462 | ); |
| 465 | conf->inactive_blocked = 0; | 463 | conf->inactive_blocked = 0; |
| 466 | } else | 464 | } else |
| 467 | init_stripe(sh, sector, previous); | 465 | init_stripe(sh, sector, previous); |
| @@ -1470,7 +1468,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) | |||
| 1470 | wait_event_lock_irq(conf->wait_for_stripe, | 1468 | wait_event_lock_irq(conf->wait_for_stripe, |
| 1471 | !list_empty(&conf->inactive_list), | 1469 | !list_empty(&conf->inactive_list), |
| 1472 | conf->device_lock, | 1470 | conf->device_lock, |
| 1473 | blk_flush_plug(current)); | 1471 | ); |
| 1474 | osh = get_free_stripe(conf); | 1472 | osh = get_free_stripe(conf); |
| 1475 | spin_unlock_irq(&conf->device_lock); | 1473 | spin_unlock_irq(&conf->device_lock); |
| 1476 | atomic_set(&nsh->count, 1); | 1474 | atomic_set(&nsh->count, 1); |
| @@ -3623,8 +3621,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf) | |||
| 3623 | atomic_inc(&conf->preread_active_stripes); | 3621 | atomic_inc(&conf->preread_active_stripes); |
| 3624 | list_add_tail(&sh->lru, &conf->hold_list); | 3622 | list_add_tail(&sh->lru, &conf->hold_list); |
| 3625 | } | 3623 | } |
| 3626 | } else | 3624 | } |
| 3627 | plugger_set_plug(&conf->plug); | ||
| 3628 | } | 3625 | } |
| 3629 | 3626 | ||
| 3630 | static void activate_bit_delay(raid5_conf_t *conf) | 3627 | static void activate_bit_delay(raid5_conf_t *conf) |
| @@ -3641,21 +3638,6 @@ static void activate_bit_delay(raid5_conf_t *conf) | |||
| 3641 | } | 3638 | } |
| 3642 | } | 3639 | } |
| 3643 | 3640 | ||
| 3644 | void md_raid5_kick_device(raid5_conf_t *conf) | ||
| 3645 | { | ||
| 3646 | blk_flush_plug(current); | ||
| 3647 | raid5_activate_delayed(conf); | ||
| 3648 | md_wakeup_thread(conf->mddev->thread); | ||
| 3649 | } | ||
| 3650 | EXPORT_SYMBOL_GPL(md_raid5_kick_device); | ||
| 3651 | |||
| 3652 | static void raid5_unplug(struct plug_handle *plug) | ||
| 3653 | { | ||
| 3654 | raid5_conf_t *conf = container_of(plug, raid5_conf_t, plug); | ||
| 3655 | |||
| 3656 | md_raid5_kick_device(conf); | ||
| 3657 | } | ||
| 3658 | |||
| 3659 | int md_raid5_congested(mddev_t *mddev, int bits) | 3641 | int md_raid5_congested(mddev_t *mddev, int bits) |
| 3660 | { | 3642 | { |
| 3661 | raid5_conf_t *conf = mddev->private; | 3643 | raid5_conf_t *conf = mddev->private; |
| @@ -3945,6 +3927,7 @@ static int make_request(mddev_t *mddev, struct bio * bi) | |||
| 3945 | struct stripe_head *sh; | 3927 | struct stripe_head *sh; |
| 3946 | const int rw = bio_data_dir(bi); | 3928 | const int rw = bio_data_dir(bi); |
| 3947 | int remaining; | 3929 | int remaining; |
| 3930 | int plugged; | ||
| 3948 | 3931 | ||
| 3949 | if (unlikely(bi->bi_rw & REQ_FLUSH)) { | 3932 | if (unlikely(bi->bi_rw & REQ_FLUSH)) { |
| 3950 | md_flush_request(mddev, bi); | 3933 | md_flush_request(mddev, bi); |
| @@ -3963,6 +3946,7 @@ static int make_request(mddev_t *mddev, struct bio * bi) | |||
| 3963 | bi->bi_next = NULL; | 3946 | bi->bi_next = NULL; |
| 3964 | bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ | 3947 | bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ |
| 3965 | 3948 | ||
| 3949 | plugged = mddev_check_plugged(mddev); | ||
| 3966 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { | 3950 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { |
| 3967 | DEFINE_WAIT(w); | 3951 | DEFINE_WAIT(w); |
| 3968 | int disks, data_disks; | 3952 | int disks, data_disks; |
| @@ -4057,7 +4041,7 @@ static int make_request(mddev_t *mddev, struct bio * bi) | |||
| 4057 | * add failed due to overlap. Flush everything | 4041 | * add failed due to overlap. Flush everything |
| 4058 | * and wait a while | 4042 | * and wait a while |
| 4059 | */ | 4043 | */ |
| 4060 | md_raid5_kick_device(conf); | 4044 | md_wakeup_thread(mddev->thread); |
| 4061 | release_stripe(sh); | 4045 | release_stripe(sh); |
| 4062 | schedule(); | 4046 | schedule(); |
| 4063 | goto retry; | 4047 | goto retry; |
| @@ -4077,6 +4061,9 @@ static int make_request(mddev_t *mddev, struct bio * bi) | |||
| 4077 | } | 4061 | } |
| 4078 | 4062 | ||
| 4079 | } | 4063 | } |
| 4064 | if (!plugged) | ||
| 4065 | md_wakeup_thread(mddev->thread); | ||
| 4066 | |||
| 4080 | spin_lock_irq(&conf->device_lock); | 4067 | spin_lock_irq(&conf->device_lock); |
| 4081 | remaining = raid5_dec_bi_phys_segments(bi); | 4068 | remaining = raid5_dec_bi_phys_segments(bi); |
| 4082 | spin_unlock_irq(&conf->device_lock); | 4069 | spin_unlock_irq(&conf->device_lock); |
| @@ -4478,24 +4465,30 @@ static void raid5d(mddev_t *mddev) | |||
| 4478 | struct stripe_head *sh; | 4465 | struct stripe_head *sh; |
| 4479 | raid5_conf_t *conf = mddev->private; | 4466 | raid5_conf_t *conf = mddev->private; |
| 4480 | int handled; | 4467 | int handled; |
| 4468 | struct blk_plug plug; | ||
| 4481 | 4469 | ||
| 4482 | pr_debug("+++ raid5d active\n"); | 4470 | pr_debug("+++ raid5d active\n"); |
| 4483 | 4471 | ||
| 4484 | md_check_recovery(mddev); | 4472 | md_check_recovery(mddev); |
| 4485 | 4473 | ||
| 4474 | blk_start_plug(&plug); | ||
| 4486 | handled = 0; | 4475 | handled = 0; |
| 4487 | spin_lock_irq(&conf->device_lock); | 4476 | spin_lock_irq(&conf->device_lock); |
| 4488 | while (1) { | 4477 | while (1) { |
| 4489 | struct bio *bio; | 4478 | struct bio *bio; |
| 4490 | 4479 | ||
| 4491 | if (conf->seq_flush != conf->seq_write) { | 4480 | if (atomic_read(&mddev->plug_cnt) == 0 && |
| 4492 | int seq = conf->seq_flush; | 4481 | !list_empty(&conf->bitmap_list)) { |
| 4482 | /* Now is a good time to flush some bitmap updates */ | ||
| 4483 | conf->seq_flush++; | ||
| 4493 | spin_unlock_irq(&conf->device_lock); | 4484 | spin_unlock_irq(&conf->device_lock); |
| 4494 | bitmap_unplug(mddev->bitmap); | 4485 | bitmap_unplug(mddev->bitmap); |
| 4495 | spin_lock_irq(&conf->device_lock); | 4486 | spin_lock_irq(&conf->device_lock); |
| 4496 | conf->seq_write = seq; | 4487 | conf->seq_write = conf->seq_flush; |
| 4497 | activate_bit_delay(conf); | 4488 | activate_bit_delay(conf); |
| 4498 | } | 4489 | } |
| 4490 | if (atomic_read(&mddev->plug_cnt) == 0) | ||
| 4491 | raid5_activate_delayed(conf); | ||
| 4499 | 4492 | ||
| 4500 | while ((bio = remove_bio_from_retry(conf))) { | 4493 | while ((bio = remove_bio_from_retry(conf))) { |
| 4501 | int ok; | 4494 | int ok; |
| @@ -4525,6 +4518,7 @@ static void raid5d(mddev_t *mddev) | |||
| 4525 | spin_unlock_irq(&conf->device_lock); | 4518 | spin_unlock_irq(&conf->device_lock); |
| 4526 | 4519 | ||
| 4527 | async_tx_issue_pending_all(); | 4520 | async_tx_issue_pending_all(); |
| 4521 | blk_finish_plug(&plug); | ||
| 4528 | 4522 | ||
| 4529 | pr_debug("--- raid5d inactive\n"); | 4523 | pr_debug("--- raid5d inactive\n"); |
| 4530 | } | 4524 | } |
| @@ -5141,8 +5135,6 @@ static int run(mddev_t *mddev) | |||
| 5141 | mdname(mddev)); | 5135 | mdname(mddev)); |
| 5142 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); | 5136 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); |
| 5143 | 5137 | ||
| 5144 | plugger_init(&conf->plug, raid5_unplug); | ||
| 5145 | mddev->plug = &conf->plug; | ||
| 5146 | if (mddev->queue) { | 5138 | if (mddev->queue) { |
| 5147 | int chunk_size; | 5139 | int chunk_size; |
| 5148 | /* read-ahead size must cover two whole stripes, which | 5140 | /* read-ahead size must cover two whole stripes, which |
| @@ -5192,7 +5184,6 @@ static int stop(mddev_t *mddev) | |||
| 5192 | mddev->thread = NULL; | 5184 | mddev->thread = NULL; |
| 5193 | if (mddev->queue) | 5185 | if (mddev->queue) |
| 5194 | mddev->queue->backing_dev_info.congested_fn = NULL; | 5186 | mddev->queue->backing_dev_info.congested_fn = NULL; |
| 5195 | plugger_flush(&conf->plug); /* the unplug fn references 'conf'*/ | ||
| 5196 | free_conf(conf); | 5187 | free_conf(conf); |
| 5197 | mddev->private = NULL; | 5188 | mddev->private = NULL; |
| 5198 | mddev->to_remove = &raid5_attrs_group; | 5189 | mddev->to_remove = &raid5_attrs_group; |
