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 /drivers | |
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.
Diffstat (limited to 'drivers')
-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); |