Commit 11d3a9f6 authored by Guoqing Jiang's avatar Guoqing Jiang Committed by Song Liu

md: prepare for enable raid1 io serialization

1. The related resources (spin_lock, list and waitqueue) are needed for
address raid1 reorder overlap issue too, in this case, rdev is set to
NULL for mddev_create/destroy_serial_pool which implies all rdevs need
to handle these resources.

And also add "is_suspend" to mddev_destroy_serial_pool since it will
be called under suspended situation, which also makes both create and
destroy pool have same arguments.

2. Introduce rdevs_init_serial which is called if raid1 io serialization
is enabled since all rdevs need to init related stuffs.

3. rdev_init_serial and clear_bit(CollisionCheck, &rdev->flags) should
be called between suspend and resume.

No need to export mddev_create_serial_pool since it is only called in
md-mod module.
Signed-off-by: default avatarGuoqing Jiang <guoqing.jiang@cloud.ionos.com>
Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
parent 3e173ab5
...@@ -127,9 +127,6 @@ static inline int speed_max(struct mddev *mddev) ...@@ -127,9 +127,6 @@ static inline int speed_max(struct mddev *mddev)
static int rdev_init_serial(struct md_rdev *rdev) static int rdev_init_serial(struct md_rdev *rdev)
{ {
if (rdev->bdev->bd_queue->nr_hw_queues == 1)
return 0;
spin_lock_init(&rdev->serial_list_lock); spin_lock_init(&rdev->serial_list_lock);
INIT_LIST_HEAD(&rdev->serial_list); INIT_LIST_HEAD(&rdev->serial_list);
init_waitqueue_head(&rdev->serial_io_wait); init_waitqueue_head(&rdev->serial_io_wait);
...@@ -138,17 +135,29 @@ static int rdev_init_serial(struct md_rdev *rdev) ...@@ -138,17 +135,29 @@ static int rdev_init_serial(struct md_rdev *rdev)
return 1; return 1;
} }
static void rdevs_init_serial(struct mddev *mddev)
{
struct md_rdev *rdev;
rdev_for_each(rdev, mddev) {
if (test_bit(CollisionCheck, &rdev->flags))
continue;
rdev_init_serial(rdev);
}
}
/* /*
* Create serial_info_pool if rdev is the first multi-queue device flaged * Create serial_info_pool for raid1 under conditions:
* with writemostly, also write-behind mode is enabled. * 1. rdev is the first multi-queue device flaged with writemostly,
* also write-behind mode is enabled.
* 2. rdev is NULL, means want to enable serialization for all rdevs.
*/ */
void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev, void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev,
bool is_suspend) bool is_suspend)
{ {
if (mddev->bitmap_info.max_write_behind == 0) if (rdev && (mddev->bitmap_info.max_write_behind == 0 ||
return; rdev->bdev->bd_queue->nr_hw_queues == 1 ||
!test_bit(WriteMostly, &rdev->flags)))
if (!test_bit(WriteMostly, &rdev->flags) || !rdev_init_serial(rdev))
return; return;
if (mddev->serial_info_pool == NULL) { if (mddev->serial_info_pool == NULL) {
...@@ -156,6 +165,10 @@ void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev, ...@@ -156,6 +165,10 @@ void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev,
if (!is_suspend) if (!is_suspend)
mddev_suspend(mddev); mddev_suspend(mddev);
if (!rdev)
rdevs_init_serial(mddev);
else
rdev_init_serial(rdev);
noio_flag = memalloc_noio_save(); noio_flag = memalloc_noio_save();
mddev->serial_info_pool = mddev->serial_info_pool =
mempool_create_kmalloc_pool(NR_SERIAL_INFOS, mempool_create_kmalloc_pool(NR_SERIAL_INFOS,
...@@ -167,15 +180,16 @@ void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev, ...@@ -167,15 +180,16 @@ void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev,
mddev_resume(mddev); mddev_resume(mddev);
} }
} }
EXPORT_SYMBOL_GPL(mddev_create_serial_pool);
/* /*
* Destroy serial_info_pool if rdev is the last device flaged with * Destroy serial_info_pool if rdev is the last device flaged with
* CollisionCheck. * CollisionCheck, or rdev is NULL when we disable serialization
* for normal raid1.
*/ */
static void mddev_destroy_serial_pool(struct mddev *mddev, struct md_rdev *rdev) static void mddev_destroy_serial_pool(struct mddev *mddev, struct md_rdev *rdev,
bool is_suspend)
{ {
if (!test_and_clear_bit(CollisionCheck, &rdev->flags)) if (rdev && !test_bit(CollisionCheck, &rdev->flags))
return; return;
if (mddev->serial_info_pool) { if (mddev->serial_info_pool) {
...@@ -185,16 +199,27 @@ static void mddev_destroy_serial_pool(struct mddev *mddev, struct md_rdev *rdev) ...@@ -185,16 +199,27 @@ static void mddev_destroy_serial_pool(struct mddev *mddev, struct md_rdev *rdev)
/* /*
* Check if other rdevs need serial_info_pool. * Check if other rdevs need serial_info_pool.
*/ */
rdev_for_each(temp, mddev) if (!is_suspend)
mddev_suspend(mddev);
rdev_for_each(temp, mddev) {
if (!rdev) {
clear_bit(CollisionCheck, &temp->flags);
continue;
}
if (temp != rdev && if (temp != rdev &&
test_bit(CollisionCheck, &temp->flags)) test_bit(CollisionCheck, &temp->flags))
num++; num++;
if (!num) { }
mddev_suspend(rdev->mddev);
if (rdev)
clear_bit(CollisionCheck, &rdev->flags);
if (!rdev || !num) {
mempool_destroy(mddev->serial_info_pool); mempool_destroy(mddev->serial_info_pool);
mddev->serial_info_pool = NULL; mddev->serial_info_pool = NULL;
mddev_resume(rdev->mddev);
} }
if (!is_suspend)
mddev_resume(mddev);
} }
} }
...@@ -2377,7 +2402,7 @@ static void unbind_rdev_from_array(struct md_rdev *rdev) ...@@ -2377,7 +2402,7 @@ static void unbind_rdev_from_array(struct md_rdev *rdev)
bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk); bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
list_del_rcu(&rdev->same_set); list_del_rcu(&rdev->same_set);
pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b)); pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b));
mddev_destroy_serial_pool(rdev->mddev, rdev); mddev_destroy_serial_pool(rdev->mddev, rdev, false);
rdev->mddev = NULL; rdev->mddev = NULL;
sysfs_remove_link(&rdev->kobj, "block"); sysfs_remove_link(&rdev->kobj, "block");
sysfs_put(rdev->sysfs_state); sysfs_put(rdev->sysfs_state);
...@@ -2893,7 +2918,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) ...@@ -2893,7 +2918,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
mddev_create_serial_pool(rdev->mddev, rdev, false); mddev_create_serial_pool(rdev->mddev, rdev, false);
err = 0; err = 0;
} else if (cmd_match(buf, "-writemostly")) { } else if (cmd_match(buf, "-writemostly")) {
mddev_destroy_serial_pool(rdev->mddev, rdev); mddev_destroy_serial_pool(rdev->mddev, rdev, false);
clear_bit(WriteMostly, &rdev->flags); clear_bit(WriteMostly, &rdev->flags);
err = 0; err = 0;
} else if (cmd_match(buf, "blocked")) { } else if (cmd_match(buf, "blocked")) {
......
...@@ -738,7 +738,7 @@ extern void md_reload_sb(struct mddev *mddev, int raid_disk); ...@@ -738,7 +738,7 @@ extern void md_reload_sb(struct mddev *mddev, int raid_disk);
extern void md_update_sb(struct mddev *mddev, int force); extern void md_update_sb(struct mddev *mddev, int force);
extern void md_kick_rdev_from_array(struct md_rdev * rdev); extern void md_kick_rdev_from_array(struct md_rdev * rdev);
extern void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev, extern void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev,
bool is_suspend); bool is_suspend);
struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr); struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr);
struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev); struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev);
......
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