Commit 48df498d authored by Guoqing Jiang's avatar Guoqing Jiang Committed by Shaohua Li

md: move bitmap_destroy to the beginning of __md_stop

Since we have switched to sync way to handle METADATA_UPDATED
msg for md-cluster, then process_metadata_update is depended
on mddev->thread->wqueue.

With the new change, clustered raid could possible hang if
array received a METADATA_UPDATED msg after array unregistered
mddev->thread, so we need to stop clustered raid (bitmap_destroy
-> bitmap_free -> md_cluster_stop) earlier than unregister
thread (mddev_detach -> md_unregister_thread).

And this change should be safe for non-clustered raid since
all writes are stopped before the destroy. Also in md_run,
we activate the personality (pers->run()) before activating
the bitmap (bitmap_create()). So it is pleasingly symmetric
to stop the bitmap (bitmap_destroy()) before stopping the
personality (__md_stop() calls pers->free()), we achieve this
by move bitmap_destroy to the beginning of __md_stop.

But we don't want to break the codes for waiting behind IO as
Shaohua mentioned, so introduce bitmap_wait_behind_writes to
call the codes, and call the new fun in both mddev_detach and
bitmap_destroy, then we will not break original behind IO code
and also fit the new condition well.
Signed-off-by: default avatarGuoqing Jiang <gqjiang@suse.com>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent ea17481f
...@@ -1764,6 +1764,20 @@ void bitmap_free(struct bitmap *bitmap) ...@@ -1764,6 +1764,20 @@ void bitmap_free(struct bitmap *bitmap)
} }
EXPORT_SYMBOL(bitmap_free); EXPORT_SYMBOL(bitmap_free);
void bitmap_wait_behind_writes(struct mddev *mddev)
{
struct bitmap *bitmap = mddev->bitmap;
/* wait for behind writes to complete */
if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
pr_debug("md:%s: behind writes in progress - waiting to stop.\n",
mdname(mddev));
/* need to kick something here to make sure I/O goes? */
wait_event(bitmap->behind_wait,
atomic_read(&bitmap->behind_writes) == 0);
}
}
void bitmap_destroy(struct mddev *mddev) void bitmap_destroy(struct mddev *mddev)
{ {
struct bitmap *bitmap = mddev->bitmap; struct bitmap *bitmap = mddev->bitmap;
...@@ -1771,6 +1785,8 @@ void bitmap_destroy(struct mddev *mddev) ...@@ -1771,6 +1785,8 @@ void bitmap_destroy(struct mddev *mddev)
if (!bitmap) /* there was no bitmap */ if (!bitmap) /* there was no bitmap */
return; return;
bitmap_wait_behind_writes(mddev);
mutex_lock(&mddev->bitmap_info.mutex); mutex_lock(&mddev->bitmap_info.mutex);
spin_lock(&mddev->lock); spin_lock(&mddev->lock);
mddev->bitmap = NULL; /* disconnect from the md device */ mddev->bitmap = NULL; /* disconnect from the md device */
......
...@@ -271,6 +271,7 @@ struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot); ...@@ -271,6 +271,7 @@ struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot);
int bitmap_copy_from_slot(struct mddev *mddev, int slot, int bitmap_copy_from_slot(struct mddev *mddev, int slot,
sector_t *lo, sector_t *hi, bool clear_bits); sector_t *lo, sector_t *hi, bool clear_bits);
void bitmap_free(struct bitmap *bitmap); void bitmap_free(struct bitmap *bitmap);
void bitmap_wait_behind_writes(struct mddev *mddev);
#endif #endif
#endif #endif
...@@ -5675,15 +5675,7 @@ EXPORT_SYMBOL_GPL(md_stop_writes); ...@@ -5675,15 +5675,7 @@ EXPORT_SYMBOL_GPL(md_stop_writes);
static void mddev_detach(struct mddev *mddev) static void mddev_detach(struct mddev *mddev)
{ {
struct bitmap *bitmap = mddev->bitmap; bitmap_wait_behind_writes(mddev);
/* wait for behind writes to complete */
if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
pr_debug("md:%s: behind writes in progress - waiting to stop.\n",
mdname(mddev));
/* need to kick something here to make sure I/O goes? */
wait_event(bitmap->behind_wait,
atomic_read(&bitmap->behind_writes) == 0);
}
if (mddev->pers && mddev->pers->quiesce) { if (mddev->pers && mddev->pers->quiesce) {
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
...@@ -5696,6 +5688,7 @@ static void mddev_detach(struct mddev *mddev) ...@@ -5696,6 +5688,7 @@ static void mddev_detach(struct mddev *mddev)
static void __md_stop(struct mddev *mddev) static void __md_stop(struct mddev *mddev)
{ {
struct md_personality *pers = mddev->pers; struct md_personality *pers = mddev->pers;
bitmap_destroy(mddev);
mddev_detach(mddev); mddev_detach(mddev);
/* Ensure ->event_work is done */ /* Ensure ->event_work is done */
flush_workqueue(md_misc_wq); flush_workqueue(md_misc_wq);
...@@ -5716,7 +5709,6 @@ void md_stop(struct mddev *mddev) ...@@ -5716,7 +5709,6 @@ void md_stop(struct mddev *mddev)
* This is called from dm-raid * This is called from dm-raid
*/ */
__md_stop(mddev); __md_stop(mddev);
bitmap_destroy(mddev);
if (mddev->bio_set) if (mddev->bio_set)
bioset_free(mddev->bio_set); bioset_free(mddev->bio_set);
} }
...@@ -5854,7 +5846,6 @@ static int do_md_stop(struct mddev *mddev, int mode, ...@@ -5854,7 +5846,6 @@ static int do_md_stop(struct mddev *mddev, int mode,
if (mode == 0) { if (mode == 0) {
pr_info("md: %s stopped.\n", mdname(mddev)); pr_info("md: %s stopped.\n", mdname(mddev));
bitmap_destroy(mddev);
if (mddev->bitmap_info.file) { if (mddev->bitmap_info.file) {
struct file *f = mddev->bitmap_info.file; struct file *f = mddev->bitmap_info.file;
spin_lock(&mddev->lock); spin_lock(&mddev->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment