diff options
author | NeilBrown <neilb@suse.de> | 2011-09-21 07:30:20 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-09-21 07:30:20 +0200 |
commit | 01f96c0a9922cd9919baf9d16febdf7016177a12 (patch) | |
tree | a877fe509c4ef0db5252b7192df56009c1d06d6f /drivers/md/raid1.c | |
parent | md: Fix handling for devices from 2TB to 4TB in 0.90 metadata. (diff) | |
download | linux-01f96c0a9922cd9919baf9d16febdf7016177a12.tar.xz linux-01f96c0a9922cd9919baf9d16febdf7016177a12.zip |
md: Avoid waking up a thread after it has been freed.
Two related problems:
1/ some error paths call "md_unregister_thread(mddev->thread)"
without subsequently clearing ->thread. A subsequent call
to mddev_unlock will try to wake the thread, and crash.
2/ Most calls to md_wakeup_thread are protected against the thread
disappeared either by:
- holding the ->mutex
- having an active request, so something else must be keeping
the array active.
However mddev_unlock calls md_wakeup_thread after dropping the
mutex and without any certainty of an active request, so the
->thread could theoretically disappear.
So we need a spinlock to provide some protections.
So change md_unregister_thread to take a pointer to the thread
pointer, and ensure that it always does the required locking, and
clears the pointer properly.
Reported-by: "Moshe Melnikov" <moshe@zadarastorage.com>
Signed-off-by: NeilBrown <neilb@suse.de>
cc: stable@kernel.org
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 3 |
1 files changed, 1 insertions, 2 deletions
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) raise_barrier(conf); lower_barrier(conf); - md_unregister_thread(mddev->thread); - mddev->thread = NULL; + md_unregister_thread(&mddev->thread); if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); kfree(conf->mirrors); |