diff options
author | NeilBrown <neilb@suse.de> | 2011-09-21 15:30:20 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-09-21 15:30:20 +1000 |
commit | 01f96c0a9922cd9919baf9d16febdf7016177a12 (patch) | |
tree | a877fe509c4ef0db5252b7192df56009c1d06d6f /drivers/md/multipath.c | |
parent | 27a7b260f71439c40546b43588448faac01adb93 (diff) |
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/multipath.c')
-rw-r--r-- | drivers/md/multipath.c | 3 |
1 files changed, 1 insertions, 2 deletions
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) { multipath_conf_t *conf = mddev->private; - md_unregister_thread(mddev->thread); - mddev->thread = NULL; + md_unregister_thread(&mddev->thread); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ mempool_destroy(conf->pool); kfree(conf->multipaths); |