mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-19 02:34:01 +08:00
md: introduce mddev_create/destroy_wb_pool for the change of member device
Previously, we called rdev_init_wb to avoid potential data inconsistency when array is created. Now, we need to call the function and create mempool if a device is added or just be flaged as "writemostly". So mddev_create_wb_pool is introduced and called accordingly. And for safety reason, we mark implicit GFP_NOIO allocation scope for create mempool during mddev_suspend/mddev_resume. And mempool should be removed conversely after remove a member device or its's "writemostly" flag, which is done by call mddev_destroy_wb_pool. Reviewed-by: NeilBrown <neilb@suse.com> Signed-off-by: Guoqing Jiang <gqjiang@suse.com> Signed-off-by: Song Liu <songliubraving@fb.com>
This commit is contained in:
parent
3e148a3209
commit
963c555e75
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/sched/mm.h>
|
||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
@ -137,6 +138,64 @@ static int rdev_init_wb(struct md_rdev *rdev)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create wb_info_pool if rdev is the first multi-queue device flaged
|
||||||
|
* with writemostly, also write-behind mode is enabled.
|
||||||
|
*/
|
||||||
|
void mddev_create_wb_pool(struct mddev *mddev, struct md_rdev *rdev,
|
||||||
|
bool is_suspend)
|
||||||
|
{
|
||||||
|
if (mddev->bitmap_info.max_write_behind == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!test_bit(WriteMostly, &rdev->flags) || !rdev_init_wb(rdev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mddev->wb_info_pool == NULL) {
|
||||||
|
unsigned int noio_flag;
|
||||||
|
|
||||||
|
if (!is_suspend)
|
||||||
|
mddev_suspend(mddev);
|
||||||
|
noio_flag = memalloc_noio_save();
|
||||||
|
mddev->wb_info_pool = mempool_create_kmalloc_pool(NR_WB_INFOS,
|
||||||
|
sizeof(struct wb_info));
|
||||||
|
memalloc_noio_restore(noio_flag);
|
||||||
|
if (!mddev->wb_info_pool)
|
||||||
|
pr_err("can't alloc memory pool for writemostly\n");
|
||||||
|
if (!is_suspend)
|
||||||
|
mddev_resume(mddev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mddev_create_wb_pool);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destroy wb_info_pool if rdev is the last device flaged with WBCollisionCheck.
|
||||||
|
*/
|
||||||
|
static void mddev_destroy_wb_pool(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
|
{
|
||||||
|
if (!test_and_clear_bit(WBCollisionCheck, &rdev->flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mddev->wb_info_pool) {
|
||||||
|
struct md_rdev *temp;
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if other rdevs need wb_info_pool.
|
||||||
|
*/
|
||||||
|
rdev_for_each(temp, mddev)
|
||||||
|
if (temp != rdev &&
|
||||||
|
test_bit(WBCollisionCheck, &temp->flags))
|
||||||
|
num++;
|
||||||
|
if (!num) {
|
||||||
|
mddev_suspend(rdev->mddev);
|
||||||
|
mempool_destroy(mddev->wb_info_pool);
|
||||||
|
mddev->wb_info_pool = NULL;
|
||||||
|
mddev_resume(rdev->mddev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct ctl_table_header *raid_table_header;
|
static struct ctl_table_header *raid_table_header;
|
||||||
|
|
||||||
static struct ctl_table raid_table[] = {
|
static struct ctl_table raid_table[] = {
|
||||||
@ -2223,6 +2282,9 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev)
|
|||||||
rdev->mddev = mddev;
|
rdev->mddev = mddev;
|
||||||
pr_debug("md: bind<%s>\n", b);
|
pr_debug("md: bind<%s>\n", b);
|
||||||
|
|
||||||
|
if (mddev->raid_disks)
|
||||||
|
mddev_create_wb_pool(mddev, rdev, false);
|
||||||
|
|
||||||
if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b)))
|
if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -2259,6 +2321,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_wb_pool(rdev->mddev, rdev);
|
||||||
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);
|
||||||
@ -2771,8 +2834,10 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|||||||
}
|
}
|
||||||
} else if (cmd_match(buf, "writemostly")) {
|
} else if (cmd_match(buf, "writemostly")) {
|
||||||
set_bit(WriteMostly, &rdev->flags);
|
set_bit(WriteMostly, &rdev->flags);
|
||||||
|
mddev_create_wb_pool(rdev->mddev, rdev, false);
|
||||||
err = 0;
|
err = 0;
|
||||||
} else if (cmd_match(buf, "-writemostly")) {
|
} else if (cmd_match(buf, "-writemostly")) {
|
||||||
|
mddev_destroy_wb_pool(rdev->mddev, rdev);
|
||||||
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")) {
|
||||||
|
@ -730,6 +730,8 @@ extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
|
|||||||
extern void md_reload_sb(struct mddev *mddev, int raid_disk);
|
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_wb_pool(struct mddev *mddev, struct md_rdev *rdev,
|
||||||
|
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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user