mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
md/md-bitmap: delay registration of bitmap_ops until creating bitmap
Currently bitmap_ops is registered while allocating mddev, this is fine when there is only one bitmap_ops. Delay setting bitmap_ops until creating bitmap, so that user can choose which bitmap to use before running the array. Link: https://lore.kernel.org/linux-raid/20250721171557.34587-7-yukuai@kernel.org Signed-off-by: Yu Kuai <yukuai3@huawei.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Li Nan <linan122@huawei.com> Reviewed-by: Xiao Ni <xni@redhat.com>
This commit is contained in:
@@ -678,9 +678,11 @@ static void no_op(struct percpu_ref *r) {}
|
||||
|
||||
static bool mddev_set_bitmap_ops(struct mddev *mddev)
|
||||
{
|
||||
struct bitmap_operations *old = mddev->bitmap_ops;
|
||||
struct md_submodule_head *head;
|
||||
|
||||
if (mddev->bitmap_id == ID_BITMAP_NONE)
|
||||
if (mddev->bitmap_id == ID_BITMAP_NONE ||
|
||||
(old && old->head.id == mddev->bitmap_id))
|
||||
return true;
|
||||
|
||||
xa_lock(&md_submodule);
|
||||
@@ -698,6 +700,18 @@ static bool mddev_set_bitmap_ops(struct mddev *mddev)
|
||||
|
||||
mddev->bitmap_ops = (void *)head;
|
||||
xa_unlock(&md_submodule);
|
||||
|
||||
if (!mddev_is_dm(mddev) && mddev->bitmap_ops->group) {
|
||||
if (sysfs_create_group(&mddev->kobj, mddev->bitmap_ops->group))
|
||||
pr_warn("md: cannot register extra bitmap attributes for %s\n",
|
||||
mdname(mddev));
|
||||
else
|
||||
/*
|
||||
* Inform user with KOBJ_CHANGE about new bitmap
|
||||
* attributes.
|
||||
*/
|
||||
kobject_uevent(&mddev->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
return true;
|
||||
|
||||
err:
|
||||
@@ -707,28 +721,26 @@ err:
|
||||
|
||||
static void mddev_clear_bitmap_ops(struct mddev *mddev)
|
||||
{
|
||||
if (!mddev_is_dm(mddev) && mddev->bitmap_ops &&
|
||||
mddev->bitmap_ops->group)
|
||||
sysfs_remove_group(&mddev->kobj, mddev->bitmap_ops->group);
|
||||
|
||||
mddev->bitmap_ops = NULL;
|
||||
}
|
||||
|
||||
int mddev_init(struct mddev *mddev)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_MD_BITMAP)) {
|
||||
if (!IS_ENABLED(CONFIG_MD_BITMAP))
|
||||
mddev->bitmap_id = ID_BITMAP_NONE;
|
||||
} else {
|
||||
else
|
||||
mddev->bitmap_id = ID_BITMAP;
|
||||
if (!mddev_set_bitmap_ops(mddev))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (percpu_ref_init(&mddev->active_io, active_io_release,
|
||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
|
||||
mddev_clear_bitmap_ops(mddev);
|
||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (percpu_ref_init(&mddev->writes_pending, no_op,
|
||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
|
||||
mddev_clear_bitmap_ops(mddev);
|
||||
percpu_ref_exit(&mddev->active_io);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -766,7 +778,6 @@ EXPORT_SYMBOL_GPL(mddev_init);
|
||||
|
||||
void mddev_destroy(struct mddev *mddev)
|
||||
{
|
||||
mddev_clear_bitmap_ops(mddev);
|
||||
percpu_ref_exit(&mddev->active_io);
|
||||
percpu_ref_exit(&mddev->writes_pending);
|
||||
}
|
||||
@@ -6196,11 +6207,6 @@ struct mddev *md_alloc(dev_t dev, char *name)
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
if (md_bitmap_registered(mddev) && mddev->bitmap_ops->group)
|
||||
if (sysfs_create_group(&mddev->kobj, mddev->bitmap_ops->group))
|
||||
pr_warn("md: cannot register extra bitmap attributes for %s\n",
|
||||
mdname(mddev));
|
||||
|
||||
kobject_uevent(&mddev->kobj, KOBJ_ADD);
|
||||
mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
|
||||
mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
|
||||
@@ -6279,6 +6285,26 @@ static void md_safemode_timeout(struct timer_list *t)
|
||||
|
||||
static int start_dirty_degraded;
|
||||
|
||||
static int md_bitmap_create(struct mddev *mddev)
|
||||
{
|
||||
if (mddev->bitmap_id == ID_BITMAP_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mddev_set_bitmap_ops(mddev))
|
||||
return -ENOENT;
|
||||
|
||||
return mddev->bitmap_ops->create(mddev);
|
||||
}
|
||||
|
||||
static void md_bitmap_destroy(struct mddev *mddev)
|
||||
{
|
||||
if (!md_bitmap_registered(mddev))
|
||||
return;
|
||||
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
mddev_clear_bitmap_ops(mddev);
|
||||
}
|
||||
|
||||
int md_run(struct mddev *mddev)
|
||||
{
|
||||
int err;
|
||||
@@ -6443,9 +6469,9 @@ int md_run(struct mddev *mddev)
|
||||
(unsigned long long)pers->size(mddev, 0, 0) / 2);
|
||||
err = -EINVAL;
|
||||
}
|
||||
if (err == 0 && pers->sync_request && md_bitmap_registered(mddev) &&
|
||||
if (err == 0 && pers->sync_request &&
|
||||
(mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
|
||||
err = mddev->bitmap_ops->create(mddev);
|
||||
err = md_bitmap_create(mddev);
|
||||
if (err)
|
||||
pr_warn("%s: failed to create bitmap (%d)\n",
|
||||
mdname(mddev), err);
|
||||
@@ -6518,8 +6544,7 @@ bitmap_abort:
|
||||
pers->free(mddev, mddev->private);
|
||||
mddev->private = NULL;
|
||||
put_pers(pers);
|
||||
if (md_bitmap_registered(mddev))
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
abort:
|
||||
bioset_exit(&mddev->io_clone_set);
|
||||
exit_sync_set:
|
||||
@@ -6542,7 +6567,7 @@ int do_md_run(struct mddev *mddev)
|
||||
if (md_bitmap_registered(mddev)) {
|
||||
err = mddev->bitmap_ops->load(mddev);
|
||||
if (err) {
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -6740,8 +6765,7 @@ static void __md_stop(struct mddev *mddev)
|
||||
{
|
||||
struct md_personality *pers = mddev->pers;
|
||||
|
||||
if (md_bitmap_registered(mddev))
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev_detach(mddev);
|
||||
spin_lock(&mddev->lock);
|
||||
mddev->pers = NULL;
|
||||
@@ -7518,16 +7542,16 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
|
||||
err = 0;
|
||||
if (mddev->pers) {
|
||||
if (fd >= 0) {
|
||||
err = mddev->bitmap_ops->create(mddev);
|
||||
err = md_bitmap_create(mddev);
|
||||
if (!err)
|
||||
err = mddev->bitmap_ops->load(mddev);
|
||||
|
||||
if (err) {
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
fd = -1;
|
||||
}
|
||||
} else if (fd < 0) {
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7812,14 +7836,6 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
||||
rv = update_raid_disks(mddev, info->raid_disks);
|
||||
|
||||
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
|
||||
/*
|
||||
* Metadata says bitmap existed, however kernel can't find
|
||||
* registered bitmap.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!md_bitmap_registered(mddev))) {
|
||||
rv = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (mddev->pers->quiesce == NULL || mddev->thread == NULL) {
|
||||
rv = -EINVAL;
|
||||
goto err;
|
||||
@@ -7842,12 +7858,12 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
||||
mddev->bitmap_info.default_offset;
|
||||
mddev->bitmap_info.space =
|
||||
mddev->bitmap_info.default_space;
|
||||
rv = mddev->bitmap_ops->create(mddev);
|
||||
rv = md_bitmap_create(mddev);
|
||||
if (!rv)
|
||||
rv = mddev->bitmap_ops->load(mddev);
|
||||
|
||||
if (rv)
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
} else {
|
||||
struct md_bitmap_stats stats;
|
||||
|
||||
@@ -7873,7 +7889,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
||||
put_cluster_ops(mddev);
|
||||
mddev->safemode_delay = DEFAULT_SAFEMODE_DELAY;
|
||||
}
|
||||
mddev->bitmap_ops->destroy(mddev);
|
||||
md_bitmap_destroy(mddev);
|
||||
mddev->bitmap_info.offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user