mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02: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:
parent
180b82c1c7
commit
fb8cc3b0d9
|
|
@ -388,6 +388,9 @@ All md devices contain:
|
||||||
bitmap
|
bitmap
|
||||||
The default internal bitmap
|
The default internal bitmap
|
||||||
|
|
||||||
|
If bitmap_type is not none, then additional bitmap attributes bitmap/xxx or
|
||||||
|
llbitmap/xxx will be created after md device KOBJ_CHANGE event.
|
||||||
|
|
||||||
If bitmap_type is bitmap, then the md device will also contain:
|
If bitmap_type is bitmap, then the md device will also contain:
|
||||||
|
|
||||||
bitmap/location
|
bitmap/location
|
||||||
|
|
|
||||||
|
|
@ -678,9 +678,11 @@ static void no_op(struct percpu_ref *r) {}
|
||||||
|
|
||||||
static bool mddev_set_bitmap_ops(struct mddev *mddev)
|
static bool mddev_set_bitmap_ops(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
|
struct bitmap_operations *old = mddev->bitmap_ops;
|
||||||
struct md_submodule_head *head;
|
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;
|
return true;
|
||||||
|
|
||||||
xa_lock(&md_submodule);
|
xa_lock(&md_submodule);
|
||||||
|
|
@ -698,6 +700,18 @@ static bool mddev_set_bitmap_ops(struct mddev *mddev)
|
||||||
|
|
||||||
mddev->bitmap_ops = (void *)head;
|
mddev->bitmap_ops = (void *)head;
|
||||||
xa_unlock(&md_submodule);
|
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;
|
return true;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
@ -707,28 +721,26 @@ static bool mddev_set_bitmap_ops(struct mddev *mddev)
|
||||||
|
|
||||||
static void mddev_clear_bitmap_ops(struct mddev *mddev)
|
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;
|
mddev->bitmap_ops = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mddev_init(struct mddev *mddev)
|
int mddev_init(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
if (!IS_ENABLED(CONFIG_MD_BITMAP)) {
|
if (!IS_ENABLED(CONFIG_MD_BITMAP))
|
||||||
mddev->bitmap_id = ID_BITMAP_NONE;
|
mddev->bitmap_id = ID_BITMAP_NONE;
|
||||||
} else {
|
else
|
||||||
mddev->bitmap_id = ID_BITMAP;
|
mddev->bitmap_id = ID_BITMAP;
|
||||||
if (!mddev_set_bitmap_ops(mddev))
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (percpu_ref_init(&mddev->active_io, active_io_release,
|
if (percpu_ref_init(&mddev->active_io, active_io_release,
|
||||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
|
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL))
|
||||||
mddev_clear_bitmap_ops(mddev);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
if (percpu_ref_init(&mddev->writes_pending, no_op,
|
if (percpu_ref_init(&mddev->writes_pending, no_op,
|
||||||
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
|
PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
|
||||||
mddev_clear_bitmap_ops(mddev);
|
|
||||||
percpu_ref_exit(&mddev->active_io);
|
percpu_ref_exit(&mddev->active_io);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
@ -766,7 +778,6 @@ EXPORT_SYMBOL_GPL(mddev_init);
|
||||||
|
|
||||||
void mddev_destroy(struct mddev *mddev)
|
void mddev_destroy(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
mddev_clear_bitmap_ops(mddev);
|
|
||||||
percpu_ref_exit(&mddev->active_io);
|
percpu_ref_exit(&mddev->active_io);
|
||||||
percpu_ref_exit(&mddev->writes_pending);
|
percpu_ref_exit(&mddev->writes_pending);
|
||||||
}
|
}
|
||||||
|
|
@ -6196,11 +6207,6 @@ struct mddev *md_alloc(dev_t dev, char *name)
|
||||||
return ERR_PTR(error);
|
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);
|
kobject_uevent(&mddev->kobj, KOBJ_ADD);
|
||||||
mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
|
mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
|
||||||
mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
|
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 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 md_run(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -6443,9 +6469,9 @@ int md_run(struct mddev *mddev)
|
||||||
(unsigned long long)pers->size(mddev, 0, 0) / 2);
|
(unsigned long long)pers->size(mddev, 0, 0) / 2);
|
||||||
err = -EINVAL;
|
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)) {
|
(mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
|
||||||
err = mddev->bitmap_ops->create(mddev);
|
err = md_bitmap_create(mddev);
|
||||||
if (err)
|
if (err)
|
||||||
pr_warn("%s: failed to create bitmap (%d)\n",
|
pr_warn("%s: failed to create bitmap (%d)\n",
|
||||||
mdname(mddev), err);
|
mdname(mddev), err);
|
||||||
|
|
@ -6518,8 +6544,7 @@ int md_run(struct mddev *mddev)
|
||||||
pers->free(mddev, mddev->private);
|
pers->free(mddev, mddev->private);
|
||||||
mddev->private = NULL;
|
mddev->private = NULL;
|
||||||
put_pers(pers);
|
put_pers(pers);
|
||||||
if (md_bitmap_registered(mddev))
|
md_bitmap_destroy(mddev);
|
||||||
mddev->bitmap_ops->destroy(mddev);
|
|
||||||
abort:
|
abort:
|
||||||
bioset_exit(&mddev->io_clone_set);
|
bioset_exit(&mddev->io_clone_set);
|
||||||
exit_sync_set:
|
exit_sync_set:
|
||||||
|
|
@ -6542,7 +6567,7 @@ int do_md_run(struct mddev *mddev)
|
||||||
if (md_bitmap_registered(mddev)) {
|
if (md_bitmap_registered(mddev)) {
|
||||||
err = mddev->bitmap_ops->load(mddev);
|
err = mddev->bitmap_ops->load(mddev);
|
||||||
if (err) {
|
if (err) {
|
||||||
mddev->bitmap_ops->destroy(mddev);
|
md_bitmap_destroy(mddev);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6740,8 +6765,7 @@ static void __md_stop(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
struct md_personality *pers = mddev->pers;
|
struct md_personality *pers = mddev->pers;
|
||||||
|
|
||||||
if (md_bitmap_registered(mddev))
|
md_bitmap_destroy(mddev);
|
||||||
mddev->bitmap_ops->destroy(mddev);
|
|
||||||
mddev_detach(mddev);
|
mddev_detach(mddev);
|
||||||
spin_lock(&mddev->lock);
|
spin_lock(&mddev->lock);
|
||||||
mddev->pers = NULL;
|
mddev->pers = NULL;
|
||||||
|
|
@ -7518,16 +7542,16 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
|
||||||
err = 0;
|
err = 0;
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
err = mddev->bitmap_ops->create(mddev);
|
err = md_bitmap_create(mddev);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = mddev->bitmap_ops->load(mddev);
|
err = mddev->bitmap_ops->load(mddev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mddev->bitmap_ops->destroy(mddev);
|
md_bitmap_destroy(mddev);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
} else if (fd < 0) {
|
} 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);
|
rv = update_raid_disks(mddev, info->raid_disks);
|
||||||
|
|
||||||
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
|
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) {
|
if (mddev->pers->quiesce == NULL || mddev->thread == NULL) {
|
||||||
rv = -EINVAL;
|
rv = -EINVAL;
|
||||||
goto err;
|
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.default_offset;
|
||||||
mddev->bitmap_info.space =
|
mddev->bitmap_info.space =
|
||||||
mddev->bitmap_info.default_space;
|
mddev->bitmap_info.default_space;
|
||||||
rv = mddev->bitmap_ops->create(mddev);
|
rv = md_bitmap_create(mddev);
|
||||||
if (!rv)
|
if (!rv)
|
||||||
rv = mddev->bitmap_ops->load(mddev);
|
rv = mddev->bitmap_ops->load(mddev);
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
mddev->bitmap_ops->destroy(mddev);
|
md_bitmap_destroy(mddev);
|
||||||
} else {
|
} else {
|
||||||
struct md_bitmap_stats stats;
|
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);
|
put_cluster_ops(mddev);
|
||||||
mddev->safemode_delay = DEFAULT_SAFEMODE_DELAY;
|
mddev->safemode_delay = DEFAULT_SAFEMODE_DELAY;
|
||||||
}
|
}
|
||||||
mddev->bitmap_ops->destroy(mddev);
|
md_bitmap_destroy(mddev);
|
||||||
mddev->bitmap_info.offset = 0;
|
mddev->bitmap_info.offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user