diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-06 11:30:03 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-06 11:30:03 -0400 |
| commit | a7c56ebac1bce799b583230595b4de9ccb8162d0 (patch) | |
| tree | 000aa9f3f7aef65ecd918c012c1f9b86445cb135 | |
| parent | 538d2882213ef4f076108f3edda2c39a584c4c2b (diff) | |
| parent | 01f96c0a9922cd9919baf9d16febdf7016177a12 (diff) | |
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md:
md: Avoid waking up a thread after it has been freed.
| -rw-r--r-- | drivers/md/md.c | 22 | ||||
| -rw-r--r-- | drivers/md/md.h | 2 | ||||
| -rw-r--r-- | drivers/md/multipath.c | 3 | ||||
| -rw-r--r-- | drivers/md/raid1.c | 3 | ||||
| -rw-r--r-- | drivers/md/raid10.c | 5 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 6 |
6 files changed, 26 insertions, 15 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 5404b2295820..5c95ccb59500 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -61,6 +61,11 @@ | |||
| 61 | static void autostart_arrays(int part); | 61 | static void autostart_arrays(int part); |
| 62 | #endif | 62 | #endif |
| 63 | 63 | ||
| 64 | /* pers_list is a list of registered personalities protected | ||
| 65 | * by pers_lock. | ||
| 66 | * pers_lock does extra service to protect accesses to | ||
| 67 | * mddev->thread when the mutex cannot be held. | ||
| 68 | */ | ||
| 64 | static LIST_HEAD(pers_list); | 69 | static LIST_HEAD(pers_list); |
| 65 | static DEFINE_SPINLOCK(pers_lock); | 70 | static DEFINE_SPINLOCK(pers_lock); |
| 66 | 71 | ||
| @@ -739,7 +744,12 @@ static void mddev_unlock(mddev_t * mddev) | |||
| 739 | } else | 744 | } else |
| 740 | mutex_unlock(&mddev->reconfig_mutex); | 745 | mutex_unlock(&mddev->reconfig_mutex); |
| 741 | 746 | ||
| 747 | /* was we've dropped the mutex we need a spinlock to | ||
| 748 | * make sur the thread doesn't disappear | ||
| 749 | */ | ||
| 750 | spin_lock(&pers_lock); | ||
| 742 | md_wakeup_thread(mddev->thread); | 751 | md_wakeup_thread(mddev->thread); |
| 752 | spin_unlock(&pers_lock); | ||
| 743 | } | 753 | } |
| 744 | 754 | ||
| 745 | static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) | 755 | static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) |
| @@ -6429,11 +6439,18 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, | |||
| 6429 | return thread; | 6439 | return thread; |
| 6430 | } | 6440 | } |
| 6431 | 6441 | ||
| 6432 | void md_unregister_thread(mdk_thread_t *thread) | 6442 | void md_unregister_thread(mdk_thread_t **threadp) |
| 6433 | { | 6443 | { |
| 6444 | mdk_thread_t *thread = *threadp; | ||
| 6434 | if (!thread) | 6445 | if (!thread) |
| 6435 | return; | 6446 | return; |
| 6436 | dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); | 6447 | dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk)); |
| 6448 | /* Locking ensures that mddev_unlock does not wake_up a | ||
| 6449 | * non-existent thread | ||
| 6450 | */ | ||
| 6451 | spin_lock(&pers_lock); | ||
| 6452 | *threadp = NULL; | ||
| 6453 | spin_unlock(&pers_lock); | ||
| 6437 | 6454 | ||
| 6438 | kthread_stop(thread->tsk); | 6455 | kthread_stop(thread->tsk); |
| 6439 | kfree(thread); | 6456 | kfree(thread); |
| @@ -7340,8 +7357,7 @@ static void reap_sync_thread(mddev_t *mddev) | |||
| 7340 | mdk_rdev_t *rdev; | 7357 | mdk_rdev_t *rdev; |
| 7341 | 7358 | ||
| 7342 | /* resync has finished, collect result */ | 7359 | /* resync has finished, collect result */ |
| 7343 | md_unregister_thread(mddev->sync_thread); | 7360 | md_unregister_thread(&mddev->sync_thread); |
| 7344 | mddev->sync_thread = NULL; | ||
| 7345 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && | 7361 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && |
| 7346 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | 7362 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { |
| 7347 | /* success...*/ | 7363 | /* success...*/ |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 1e586bb4452e..0a309dc29b45 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -560,7 +560,7 @@ extern int register_md_personality(struct mdk_personality *p); | |||
| 560 | extern int unregister_md_personality(struct mdk_personality *p); | 560 | extern int unregister_md_personality(struct mdk_personality *p); |
| 561 | extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev), | 561 | extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev), |
| 562 | mddev_t *mddev, const char *name); | 562 | mddev_t *mddev, const char *name); |
| 563 | extern void md_unregister_thread(mdk_thread_t *thread); | 563 | extern void md_unregister_thread(mdk_thread_t **threadp); |
| 564 | extern void md_wakeup_thread(mdk_thread_t *thread); | 564 | extern void md_wakeup_thread(mdk_thread_t *thread); |
| 565 | extern void md_check_recovery(mddev_t *mddev); | 565 | extern void md_check_recovery(mddev_t *mddev); |
| 566 | extern void md_write_start(mddev_t *mddev, struct bio *bi); | 566 | extern void md_write_start(mddev_t *mddev, struct bio *bi); |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 3535c23af288..d5b5fb300171 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
| @@ -514,8 +514,7 @@ static int multipath_stop (mddev_t *mddev) | |||
| 514 | { | 514 | { |
| 515 | multipath_conf_t *conf = mddev->private; | 515 | multipath_conf_t *conf = mddev->private; |
| 516 | 516 | ||
| 517 | md_unregister_thread(mddev->thread); | 517 | md_unregister_thread(&mddev->thread); |
| 518 | mddev->thread = NULL; | ||
| 519 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 518 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 520 | mempool_destroy(conf->pool); | 519 | mempool_destroy(conf->pool); |
| 521 | kfree(conf->multipaths); | 520 | kfree(conf->multipaths); |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f4622dd8fc59..d9587dffe533 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -2562,8 +2562,7 @@ static int stop(mddev_t *mddev) | |||
| 2562 | raise_barrier(conf); | 2562 | raise_barrier(conf); |
| 2563 | lower_barrier(conf); | 2563 | lower_barrier(conf); |
| 2564 | 2564 | ||
| 2565 | md_unregister_thread(mddev->thread); | 2565 | md_unregister_thread(&mddev->thread); |
| 2566 | mddev->thread = NULL; | ||
| 2567 | if (conf->r1bio_pool) | 2566 | if (conf->r1bio_pool) |
| 2568 | mempool_destroy(conf->r1bio_pool); | 2567 | mempool_destroy(conf->r1bio_pool); |
| 2569 | kfree(conf->mirrors); | 2568 | kfree(conf->mirrors); |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d7a8468ddeab..0cd9672cf9cb 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -2955,7 +2955,7 @@ static int run(mddev_t *mddev) | |||
| 2955 | return 0; | 2955 | return 0; |
| 2956 | 2956 | ||
| 2957 | out_free_conf: | 2957 | out_free_conf: |
| 2958 | md_unregister_thread(mddev->thread); | 2958 | md_unregister_thread(&mddev->thread); |
| 2959 | if (conf->r10bio_pool) | 2959 | if (conf->r10bio_pool) |
| 2960 | mempool_destroy(conf->r10bio_pool); | 2960 | mempool_destroy(conf->r10bio_pool); |
| 2961 | safe_put_page(conf->tmppage); | 2961 | safe_put_page(conf->tmppage); |
| @@ -2973,8 +2973,7 @@ static int stop(mddev_t *mddev) | |||
| 2973 | raise_barrier(conf, 0); | 2973 | raise_barrier(conf, 0); |
| 2974 | lower_barrier(conf); | 2974 | lower_barrier(conf); |
| 2975 | 2975 | ||
| 2976 | md_unregister_thread(mddev->thread); | 2976 | md_unregister_thread(&mddev->thread); |
| 2977 | mddev->thread = NULL; | ||
| 2978 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 2977 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 2979 | if (conf->r10bio_pool) | 2978 | if (conf->r10bio_pool) |
| 2980 | mempool_destroy(conf->r10bio_pool); | 2979 | mempool_destroy(conf->r10bio_pool); |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 43709fa6b6df..ac5e8b57e50f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -4941,8 +4941,7 @@ static int run(mddev_t *mddev) | |||
| 4941 | 4941 | ||
| 4942 | return 0; | 4942 | return 0; |
| 4943 | abort: | 4943 | abort: |
| 4944 | md_unregister_thread(mddev->thread); | 4944 | md_unregister_thread(&mddev->thread); |
| 4945 | mddev->thread = NULL; | ||
| 4946 | if (conf) { | 4945 | if (conf) { |
| 4947 | print_raid5_conf(conf); | 4946 | print_raid5_conf(conf); |
| 4948 | free_conf(conf); | 4947 | free_conf(conf); |
| @@ -4956,8 +4955,7 @@ static int stop(mddev_t *mddev) | |||
| 4956 | { | 4955 | { |
| 4957 | raid5_conf_t *conf = mddev->private; | 4956 | raid5_conf_t *conf = mddev->private; |
| 4958 | 4957 | ||
| 4959 | md_unregister_thread(mddev->thread); | 4958 | md_unregister_thread(&mddev->thread); |
| 4960 | mddev->thread = NULL; | ||
| 4961 | if (mddev->queue) | 4959 | if (mddev->queue) |
| 4962 | mddev->queue->backing_dev_info.congested_fn = NULL; | 4960 | mddev->queue->backing_dev_info.congested_fn = NULL; |
| 4963 | free_conf(conf); | 4961 | free_conf(conf); |
