* [PATCH 0/3] md: bitmap grow fixes
@ 2026-03-03 3:37 Su Yue
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Su Yue @ 2026-03-03 3:37 UTC (permalink / raw)
To: linux-raid; +Cc: song, xni, linan122, yukuai, heming.zhao, l, Su Yue
Hi, This series is to fixes bugs exposed by mdadm/clustermd-autotest.
The bugs are not cluster md only but also bitmap related.
I'll find time to add test cases to mdadm. Thanks.
Su Yue (3):
md: restore bitmap/location to fix wrong bitmap offset while growing
md: call md_bitmap_create,destroy in location_store
md: remove member group from bitmap_operations
drivers/md/md-bitmap.c | 45 +++++++++++++++++++++++++++++++++++-----
drivers/md/md-bitmap.h | 5 ++++-
drivers/md/md-llbitmap.c | 13 +++++++++++-
drivers/md/md.c | 20 ++++++++++++------
drivers/md/md.h | 2 ++
5 files changed, 72 insertions(+), 13 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-03 3:37 [PATCH 0/3] md: bitmap grow fixes Su Yue
@ 2026-03-03 3:37 ` Su Yue
2026-03-04 2:30 ` Yu Kuai
` (2 more replies)
2026-03-03 3:37 ` [PATCH 2/3] md: call md_bitmap_create,destroy in location_store Su Yue
2026-03-03 3:37 ` [PATCH 3/3] md: remove member group from bitmap_operations Su Yue
2 siblings, 3 replies; 12+ messages in thread
From: Su Yue @ 2026-03-03 3:37 UTC (permalink / raw)
To: linux-raid; +Cc: song, xni, linan122, yukuai, heming.zhao, l, Su Yue
Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and clustered have
the sysfs file bitmap/location.
After the commit, if bitmap is none, bitmap/location doesn't exist anymore.
It breaks 'grow' behavior of a md array of madam with MD_FEATURE_BITMAP_OFFSET.
Take level=mirror and metadata=1.2 as an example:
$ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2 --level=mirror \
--metadata=1.2 /dev/vdd /dev/vde
$ mdadm --grow /dev/md0 --bitmap=internal
$ cat /sys/block/md0/md/bitmap/location
Before:+8
After: +2
While growing bitmap from none to internal, clustered and llbitmap,
mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location first.
1)If bitmap/location exists, it sets bitmap/location after getinfo_super().
2)If bitmap/location doesn't exist, mdadm just calls md_set_array_info() then
mddev->bitmap_info.default_offset will be used.
Situation can be worse if growing none to clustered, bitmap offset of the node
calling `madm --grow` will be changed but the other node are reading bitmap sb from
the old location.
Here restore sysfs file bitmap/location for ID_BITMAP_NONE and ID_BITMAP.
And it d adds the entry for llbitmap too.
New attribute_group md_bitmap_common_group is introduced and created in
md_alloc() as before commit fb8cc3b0d9db.
Add New operations register_group and unregister_group to struct bitmap_operations.
Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
Signed-off-by: Su Yue <glass.su@suse.com>
---
drivers/md/md-bitmap.c | 32 +++++++++++++++++++++++++++++++-
drivers/md/md-bitmap.h | 5 +++++
drivers/md/md-llbitmap.c | 13 +++++++++++++
drivers/md/md.c | 16 ++++++++++++----
4 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 83378c033c72..8ff1dc94ed78 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -2956,7 +2956,6 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
behind_writes_used_show, behind_writes_used_reset);
static struct attribute *md_bitmap_attrs[] = {
- &bitmap_location.attr,
&bitmap_space.attr,
&bitmap_timeout.attr,
&bitmap_backlog.attr,
@@ -2967,11 +2966,40 @@ static struct attribute *md_bitmap_attrs[] = {
NULL
};
+static struct attribute *md_bitmap_common_attrs[] = {
+ &bitmap_location.attr,
+ NULL
+};
+
static struct attribute_group md_bitmap_group = {
.name = "bitmap",
.attrs = md_bitmap_attrs,
};
+static struct attribute_group md_bitmap_common_group = {
+ .name = "bitmap",
+ .attrs = md_bitmap_common_attrs,
+};
+
+int md_sysfs_create_common_group(struct mddev *mddev)
+{
+ return sysfs_create_group(&mddev->kobj, &md_bitmap_common_group);
+}
+
+static int bitmap_register_group(struct mddev *mddev)
+{
+ /*
+ * md_bitmap_group and md_bitmap_common_group are using same name
+ * 'bitmap'.
+ */
+ return sysfs_merge_group(&mddev->kobj, &md_bitmap_group);
+}
+
+static void bitmap_unregister_group(struct mddev *mddev)
+{
+ sysfs_unmerge_group(&mddev->kobj, &md_bitmap_group);
+}
+
static struct bitmap_operations bitmap_ops = {
.head = {
.type = MD_BITMAP,
@@ -3013,6 +3041,8 @@ static struct bitmap_operations bitmap_ops = {
.set_pages = bitmap_set_pages,
.free = md_bitmap_free,
+ .register_group = bitmap_register_group,
+ .unregister_group = bitmap_unregister_group,
.group = &md_bitmap_group,
};
diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
index b42a28fa83a0..371791e9011d 100644
--- a/drivers/md/md-bitmap.h
+++ b/drivers/md/md-bitmap.h
@@ -125,6 +125,9 @@ struct bitmap_operations {
void (*set_pages)(void *data, unsigned long pages);
void (*free)(void *data);
+ int (*register_group)(struct mddev *mddev);
+ void (*unregister_group)(struct mddev *mddev);
+
struct attribute_group *group;
};
@@ -169,6 +172,8 @@ static inline void md_bitmap_end_sync(struct mddev *mddev, sector_t offset,
mddev->bitmap_ops->end_sync(mddev, offset, blocks);
}
+int md_sysfs_create_common_group(struct mddev *mddev);
+
#ifdef CONFIG_MD_BITMAP
int md_bitmap_init(void);
void md_bitmap_exit(void);
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index bf398d7476b3..24ff5f7f8751 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -1561,6 +1561,16 @@ static struct attribute_group md_llbitmap_group = {
.attrs = md_llbitmap_attrs,
};
+static int llbitmap_register_group(struct mddev *mddev)
+{
+ return sysfs_create_group(&mddev->kobj, &md_llbitmap_group);
+}
+
+static void llbitmap_unregister_group(struct mddev *mddev)
+{
+ sysfs_remove_group(&mddev->kobj, &md_llbitmap_group);
+}
+
static struct bitmap_operations llbitmap_ops = {
.head = {
.type = MD_BITMAP,
@@ -1597,6 +1607,9 @@ static struct bitmap_operations llbitmap_ops = {
.dirty_bits = llbitmap_dirty_bits,
.write_all = llbitmap_write_all,
+ .register_group = llbitmap_register_group,
+ .unregister_group = llbitmap_unregister_group,
+
.group = &md_llbitmap_group,
};
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3ce6f9e9d38e..ab969e950ea8 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -703,8 +703,8 @@ 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))
+ if (!mddev_is_dm(mddev) && mddev->bitmap_ops->register_group) {
+ if (mddev->bitmap_ops->register_group(mddev))
pr_warn("md: cannot register extra bitmap attributes for %s\n",
mdname(mddev));
else
@@ -724,8 +724,8 @@ static bool mddev_set_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->unregister_group)
+ mddev->bitmap_ops->unregister_group(mddev);
mddev->bitmap_ops = NULL;
}
@@ -6369,6 +6369,14 @@ struct mddev *md_alloc(dev_t dev, char *name)
return ERR_PTR(error);
}
+ /*
+ * md_sysfs_remove_common_group is not needed because mddev_delayed_delete
+ * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
+ */
+ if (md_sysfs_create_common_group(mddev))
+ pr_warn("md: cannot register common 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");
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/3] md: call md_bitmap_create,destroy in location_store
2026-03-03 3:37 [PATCH 0/3] md: bitmap grow fixes Su Yue
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
@ 2026-03-03 3:37 ` Su Yue
2026-03-03 3:37 ` [PATCH 3/3] md: remove member group from bitmap_operations Su Yue
2 siblings, 0 replies; 12+ messages in thread
From: Su Yue @ 2026-03-03 3:37 UTC (permalink / raw)
To: linux-raid; +Cc: song, xni, linan122, yukuai, heming.zhao, l, Su Yue
If commit
'md: restore bitmap/location to fix wrong bitmap offset while growing'
is applied, mdadm will call update_array_info() while growing bitmap from
none to internal via location_store(). md_bitmap_create() is needed to set
mddev->bitmap_ops otherwise mddev->bitmap_ops->get_stats() in
update_array_info() will trigger kernel NULL pointer dereference.
Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
Signed-off-by: Su Yue <glass.su@suse.com>
---
drivers/md/md-bitmap.c | 12 +++++++++---
drivers/md/md.c | 4 ++--
drivers/md/md.h | 2 ++
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 8ff1dc94ed78..8abec00496b4 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -2618,7 +2618,7 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
goto out;
}
- bitmap_destroy(mddev);
+ md_bitmap_destroy(mddev);
mddev->bitmap_info.offset = 0;
if (mddev->bitmap_info.file) {
struct file *f = mddev->bitmap_info.file;
@@ -2653,15 +2653,21 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
goto out;
}
+ /*
+ * lockless bitmap shoudle have set bitmap_id
+ * using bitmap_type, so always ID_BITMAP.
+ */
+ if (mddev->bitmap_id == ID_BITMAP_NONE)
+ mddev->bitmap_id = ID_BITMAP;
mddev->bitmap_info.offset = offset;
- rv = bitmap_create(mddev);
+ rv = md_bitmap_create(mddev);
if (rv)
goto out;
rv = bitmap_load(mddev);
if (rv) {
mddev->bitmap_info.offset = 0;
- bitmap_destroy(mddev);
+ md_bitmap_destroy(mddev);
goto out;
}
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ab969e950ea8..80beaff5ad39 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6455,7 +6455,7 @@ static void md_safemode_timeout(struct timer_list *t)
static int start_dirty_degraded;
-static int md_bitmap_create(struct mddev *mddev)
+int md_bitmap_create(struct mddev *mddev)
{
if (mddev->bitmap_id == ID_BITMAP_NONE)
return -EINVAL;
@@ -6466,7 +6466,7 @@ static int md_bitmap_create(struct mddev *mddev)
return mddev->bitmap_ops->create(mddev);
}
-static void md_bitmap_destroy(struct mddev *mddev)
+void md_bitmap_destroy(struct mddev *mddev)
{
if (!md_bitmap_registered(mddev))
return;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index ac84289664cd..ed69244af00d 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -895,6 +895,8 @@ static inline void safe_put_page(struct page *p)
int register_md_submodule(struct md_submodule_head *msh);
void unregister_md_submodule(struct md_submodule_head *msh);
+int md_bitmap_create(struct mddev *mddev);
+void md_bitmap_destroy(struct mddev *mddev);
extern struct md_thread *md_register_thread(
void (*run)(struct md_thread *thread),
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] md: remove member group from bitmap_operations
2026-03-03 3:37 [PATCH 0/3] md: bitmap grow fixes Su Yue
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
2026-03-03 3:37 ` [PATCH 2/3] md: call md_bitmap_create,destroy in location_store Su Yue
@ 2026-03-03 3:37 ` Su Yue
2 siblings, 0 replies; 12+ messages in thread
From: Su Yue @ 2026-03-03 3:37 UTC (permalink / raw)
To: linux-raid; +Cc: song, xni, linan122, yukuai, heming.zhao, l, Su Yue
The member is unused now so remove it.
Signed-off-by: Su Yue <glass.su@suse.com>
---
drivers/md/md-bitmap.c | 1 -
drivers/md/md-bitmap.h | 2 --
drivers/md/md-llbitmap.c | 2 --
3 files changed, 5 deletions(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 8abec00496b4..bb04e3c17043 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -3049,7 +3049,6 @@ static struct bitmap_operations bitmap_ops = {
.register_group = bitmap_register_group,
.unregister_group = bitmap_unregister_group,
- .group = &md_bitmap_group,
};
int md_bitmap_init(void)
diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
index 371791e9011d..c81489aaa767 100644
--- a/drivers/md/md-bitmap.h
+++ b/drivers/md/md-bitmap.h
@@ -127,8 +127,6 @@ struct bitmap_operations {
int (*register_group)(struct mddev *mddev);
void (*unregister_group)(struct mddev *mddev);
-
- struct attribute_group *group;
};
/* the bitmap API */
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index 24ff5f7f8751..78f5fafd59ba 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -1609,8 +1609,6 @@ static struct bitmap_operations llbitmap_ops = {
.register_group = llbitmap_register_group,
.unregister_group = llbitmap_unregister_group,
-
- .group = &md_llbitmap_group,
};
int md_llbitmap_init(void)
--
2.53.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
@ 2026-03-04 2:30 ` Yu Kuai
2026-03-04 3:14 ` Su Yue
2026-03-05 22:38 ` kernel test robot
2026-03-05 22:50 ` kernel test robot
2 siblings, 1 reply; 12+ messages in thread
From: Yu Kuai @ 2026-03-04 2:30 UTC (permalink / raw)
To: Su Yue, linux-raid, yukuai; +Cc: song, xni, linan122, heming.zhao, l
Hi,
在 2026/3/3 11:37, Su Yue 写道:
> Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
> if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and clustered have
> the sysfs file bitmap/location.
>
> After the commit, if bitmap is none, bitmap/location doesn't exist anymore.
> It breaks 'grow' behavior of a md array of madam with MD_FEATURE_BITMAP_OFFSET.
> Take level=mirror and metadata=1.2 as an example:
>
> $ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2 --level=mirror \
> --metadata=1.2 /dev/vdd /dev/vde
> $ mdadm --grow /dev/md0 --bitmap=internal
> $ cat /sys/block/md0/md/bitmap/location
> Before:+8
> After: +2
>
> While growing bitmap from none to internal, clustered and llbitmap,
> mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location first.
> 1)If bitmap/location exists, it sets bitmap/location after getinfo_super().
> 2)If bitmap/location doesn't exist, mdadm just calls md_set_array_info() then
> mddev->bitmap_info.default_offset will be used.
> Situation can be worse if growing none to clustered, bitmap offset of the node
> calling `madm --grow` will be changed but the other node are reading bitmap sb from
> the old location.
Now that we have a new sysfs attribute bitmap_type, can we fix this by:
- in the kernel, allow writing to this file in this case;
- in mdadm and the grow case above, write to this file first, and change
bitmap_type from none to bitmap(For llbitmap, there is still more work to do).
>
> Here restore sysfs file bitmap/location for ID_BITMAP_NONE and ID_BITMAP.
> And it d adds the entry for llbitmap too.
>
> New attribute_group md_bitmap_common_group is introduced and created in
> md_alloc() as before commit fb8cc3b0d9db.
> Add New operations register_group and unregister_group to struct bitmap_operations.
>
> Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
> Signed-off-by: Su Yue <glass.su@suse.com>
> ---
> drivers/md/md-bitmap.c | 32 +++++++++++++++++++++++++++++++-
> drivers/md/md-bitmap.h | 5 +++++
> drivers/md/md-llbitmap.c | 13 +++++++++++++
> drivers/md/md.c | 16 ++++++++++++----
> 4 files changed, 61 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
> index 83378c033c72..8ff1dc94ed78 100644
> --- a/drivers/md/md-bitmap.c
> +++ b/drivers/md/md-bitmap.c
> @@ -2956,7 +2956,6 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
> behind_writes_used_show, behind_writes_used_reset);
>
> static struct attribute *md_bitmap_attrs[] = {
> - &bitmap_location.attr,
> &bitmap_space.attr,
> &bitmap_timeout.attr,
> &bitmap_backlog.attr,
> @@ -2967,11 +2966,40 @@ static struct attribute *md_bitmap_attrs[] = {
> NULL
> };
>
> +static struct attribute *md_bitmap_common_attrs[] = {
> + &bitmap_location.attr,
> + NULL
> +};
> +
> static struct attribute_group md_bitmap_group = {
> .name = "bitmap",
> .attrs = md_bitmap_attrs,
> };
>
> +static struct attribute_group md_bitmap_common_group = {
> + .name = "bitmap",
> + .attrs = md_bitmap_common_attrs,
> +};
> +
> +int md_sysfs_create_common_group(struct mddev *mddev)
> +{
> + return sysfs_create_group(&mddev->kobj, &md_bitmap_common_group);
> +}
> +
> +static int bitmap_register_group(struct mddev *mddev)
> +{
> + /*
> + * md_bitmap_group and md_bitmap_common_group are using same name
> + * 'bitmap'.
> + */
> + return sysfs_merge_group(&mddev->kobj, &md_bitmap_group);
> +}
> +
> +static void bitmap_unregister_group(struct mddev *mddev)
> +{
> + sysfs_unmerge_group(&mddev->kobj, &md_bitmap_group);
> +}
> +
> static struct bitmap_operations bitmap_ops = {
> .head = {
> .type = MD_BITMAP,
> @@ -3013,6 +3041,8 @@ static struct bitmap_operations bitmap_ops = {
> .set_pages = bitmap_set_pages,
> .free = md_bitmap_free,
>
> + .register_group = bitmap_register_group,
> + .unregister_group = bitmap_unregister_group,
> .group = &md_bitmap_group,
> };
>
> diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
> index b42a28fa83a0..371791e9011d 100644
> --- a/drivers/md/md-bitmap.h
> +++ b/drivers/md/md-bitmap.h
> @@ -125,6 +125,9 @@ struct bitmap_operations {
> void (*set_pages)(void *data, unsigned long pages);
> void (*free)(void *data);
>
> + int (*register_group)(struct mddev *mddev);
> + void (*unregister_group)(struct mddev *mddev);
> +
> struct attribute_group *group;
> };
>
> @@ -169,6 +172,8 @@ static inline void md_bitmap_end_sync(struct mddev *mddev, sector_t offset,
> mddev->bitmap_ops->end_sync(mddev, offset, blocks);
> }
>
> +int md_sysfs_create_common_group(struct mddev *mddev);
> +
> #ifdef CONFIG_MD_BITMAP
> int md_bitmap_init(void);
> void md_bitmap_exit(void);
> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
> index bf398d7476b3..24ff5f7f8751 100644
> --- a/drivers/md/md-llbitmap.c
> +++ b/drivers/md/md-llbitmap.c
> @@ -1561,6 +1561,16 @@ static struct attribute_group md_llbitmap_group = {
> .attrs = md_llbitmap_attrs,
> };
>
> +static int llbitmap_register_group(struct mddev *mddev)
> +{
> + return sysfs_create_group(&mddev->kobj, &md_llbitmap_group);
> +}
> +
> +static void llbitmap_unregister_group(struct mddev *mddev)
> +{
> + sysfs_remove_group(&mddev->kobj, &md_llbitmap_group);
> +}
> +
> static struct bitmap_operations llbitmap_ops = {
> .head = {
> .type = MD_BITMAP,
> @@ -1597,6 +1607,9 @@ static struct bitmap_operations llbitmap_ops = {
> .dirty_bits = llbitmap_dirty_bits,
> .write_all = llbitmap_write_all,
>
> + .register_group = llbitmap_register_group,
> + .unregister_group = llbitmap_unregister_group,
> +
> .group = &md_llbitmap_group,
> };
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 3ce6f9e9d38e..ab969e950ea8 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -703,8 +703,8 @@ 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))
> + if (!mddev_is_dm(mddev) && mddev->bitmap_ops->register_group) {
> + if (mddev->bitmap_ops->register_group(mddev))
> pr_warn("md: cannot register extra bitmap attributes for %s\n",
> mdname(mddev));
> else
> @@ -724,8 +724,8 @@ static bool mddev_set_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->unregister_group)
> + mddev->bitmap_ops->unregister_group(mddev);
>
> mddev->bitmap_ops = NULL;
> }
> @@ -6369,6 +6369,14 @@ struct mddev *md_alloc(dev_t dev, char *name)
> return ERR_PTR(error);
> }
>
> + /*
> + * md_sysfs_remove_common_group is not needed because mddev_delayed_delete
> + * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
> + */
> + if (md_sysfs_create_common_group(mddev))
> + pr_warn("md: cannot register common 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");
--
Thansk,
Kuai
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-04 2:30 ` Yu Kuai
@ 2026-03-04 3:14 ` Su Yue
2026-03-05 17:57 ` Yu Kuai
0 siblings, 1 reply; 12+ messages in thread
From: Su Yue @ 2026-03-04 3:14 UTC (permalink / raw)
To: Yu Kuai; +Cc: Su Yue, linux-raid, song, xni, linan122, heming.zhao
On Wed 04 Mar 2026 at 10:30, "Yu Kuai" <yukuai@fnnas.com> wrote:
> Hi,
>
> 在 2026/3/3 11:37, Su Yue 写道:
>> Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration
>> of bitmap_ops until creating bitmap")
>> if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and
>> clustered have
>> the sysfs file bitmap/location.
>>
>> After the commit, if bitmap is none, bitmap/location doesn't
>> exist anymore.
>> It breaks 'grow' behavior of a md array of madam with
>> MD_FEATURE_BITMAP_OFFSET.
>> Take level=mirror and metadata=1.2 as an example:
>>
>> $ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2
>> --level=mirror \
>> --metadata=1.2 /dev/vdd /dev/vde
>> $ mdadm --grow /dev/md0 --bitmap=internal
>> $ cat /sys/block/md0/md/bitmap/location
>> Before:+8
>> After: +2
>>
>> While growing bitmap from none to internal, clustered and
>> llbitmap,
>> mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location
>> first.
>> 1)If bitmap/location exists, it sets bitmap/location after
>> getinfo_super().
>> 2)If bitmap/location doesn't exist, mdadm just calls
>> md_set_array_info() then
>> mddev->bitmap_info.default_offset will be used.
>> Situation can be worse if growing none to clustered, bitmap
>> offset of the node
>> calling `madm --grow` will be changed but the other node are
>> reading bitmap sb from
>> the old location.
>
> Now that we have a new sysfs attribute bitmap_type, can we fix
> this by:
> - in the kernel, allow writing to this file in this case;
> - in mdadm and the grow case above, write to this file first,
> and change
> bitmap_type from none to bitmap(For llbitmap, there is still
> more work to do).
>
Yes. It's indeed feasible. But how about old versions mdadm? We
can't require
users' madadm + kernel combinations for old feature. Kernel part
should keep
compatibility with userspace. sysfs changes and broken haviros are
not ideal
especially userspace depends on it unless there's a strong reason.
That's why linux/Documentation/ABI exists.
--
Su
>>
>> Here restore sysfs file bitmap/location for ID_BITMAP_NONE and
>> ID_BITMAP.
>> And it d adds the entry for llbitmap too.
>>
>> New attribute_group md_bitmap_common_group is introduced and
>> created in
>> md_alloc() as before commit fb8cc3b0d9db.
>> Add New operations register_group and unregister_group to
>> struct bitmap_operations.
>>
>> Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of
>> bitmap_ops until creating bitmap")
>> Signed-off-by: Su Yue <glass.su@suse.com>
>> ---
>> drivers/md/md-bitmap.c | 32
>> +++++++++++++++++++++++++++++++-
>> drivers/md/md-bitmap.h | 5 +++++
>> drivers/md/md-llbitmap.c | 13 +++++++++++++
>> drivers/md/md.c | 16 ++++++++++++----
>> 4 files changed, 61 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
>> index 83378c033c72..8ff1dc94ed78 100644
>> --- a/drivers/md/md-bitmap.c
>> +++ b/drivers/md/md-bitmap.c
>> @@ -2956,7 +2956,6 @@ __ATTR(max_backlog_used, S_IRUGO |
>> S_IWUSR,
>> behind_writes_used_show, behind_writes_used_reset);
>>
>> static struct attribute *md_bitmap_attrs[] = {
>> - &bitmap_location.attr,
>> &bitmap_space.attr,
>> &bitmap_timeout.attr,
>> &bitmap_backlog.attr,
>> @@ -2967,11 +2966,40 @@ static struct attribute
>> *md_bitmap_attrs[] = {
>> NULL
>> };
>>
>> +static struct attribute *md_bitmap_common_attrs[] = {
>> + &bitmap_location.attr,
>> + NULL
>> +};
>> +
>> static struct attribute_group md_bitmap_group = {
>> .name = "bitmap",
>> .attrs = md_bitmap_attrs,
>> };
>>
>> +static struct attribute_group md_bitmap_common_group = {
>> + .name = "bitmap",
>> + .attrs = md_bitmap_common_attrs,
>> +};
>> +
>> +int md_sysfs_create_common_group(struct mddev *mddev)
>> +{
>> + return sysfs_create_group(&mddev->kobj,
>> &md_bitmap_common_group);
>> +}
>> +
>> +static int bitmap_register_group(struct mddev *mddev)
>> +{
>> + /*
>> + * md_bitmap_group and md_bitmap_common_group are using
>> same name
>> + * 'bitmap'.
>> + */
>> + return sysfs_merge_group(&mddev->kobj, &md_bitmap_group);
>> +}
>> +
>> +static void bitmap_unregister_group(struct mddev *mddev)
>> +{
>> + sysfs_unmerge_group(&mddev->kobj, &md_bitmap_group);
>> +}
>> +
>> static struct bitmap_operations bitmap_ops = {
>> .head = {
>> .type = MD_BITMAP,
>> @@ -3013,6 +3041,8 @@ static struct bitmap_operations
>> bitmap_ops = {
>> .set_pages = bitmap_set_pages,
>> .free = md_bitmap_free,
>>
>> + .register_group = bitmap_register_group,
>> + .unregister_group = bitmap_unregister_group,
>> .group = &md_bitmap_group,
>> };
>>
>> diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
>> index b42a28fa83a0..371791e9011d 100644
>> --- a/drivers/md/md-bitmap.h
>> +++ b/drivers/md/md-bitmap.h
>> @@ -125,6 +125,9 @@ struct bitmap_operations {
>> void (*set_pages)(void *data, unsigned long pages);
>> void (*free)(void *data);
>>
>> + int (*register_group)(struct mddev *mddev);
>> + void (*unregister_group)(struct mddev *mddev);
>> +
>> struct attribute_group *group;
>> };
>>
>> @@ -169,6 +172,8 @@ static inline void
>> md_bitmap_end_sync(struct mddev *mddev, sector_t offset,
>> mddev->bitmap_ops->end_sync(mddev, offset, blocks);
>> }
>>
>> +int md_sysfs_create_common_group(struct mddev *mddev);
>> +
>> #ifdef CONFIG_MD_BITMAP
>> int md_bitmap_init(void);
>> void md_bitmap_exit(void);
>> diff --git a/drivers/md/md-llbitmap.c
>> b/drivers/md/md-llbitmap.c
>> index bf398d7476b3..24ff5f7f8751 100644
>> --- a/drivers/md/md-llbitmap.c
>> +++ b/drivers/md/md-llbitmap.c
>> @@ -1561,6 +1561,16 @@ static struct attribute_group
>> md_llbitmap_group = {
>> .attrs = md_llbitmap_attrs,
>> };
>>
>> +static int llbitmap_register_group(struct mddev *mddev)
>> +{
>> + return sysfs_create_group(&mddev->kobj,
>> &md_llbitmap_group);
>> +}
>> +
>> +static void llbitmap_unregister_group(struct mddev *mddev)
>> +{
>> + sysfs_remove_group(&mddev->kobj, &md_llbitmap_group);
>> +}
>> +
>> static struct bitmap_operations llbitmap_ops = {
>> .head = {
>> .type = MD_BITMAP,
>> @@ -1597,6 +1607,9 @@ static struct bitmap_operations
>> llbitmap_ops = {
>> .dirty_bits = llbitmap_dirty_bits,
>> .write_all = llbitmap_write_all,
>>
>> + .register_group = llbitmap_register_group,
>> + .unregister_group = llbitmap_unregister_group,
>> +
>> .group = &md_llbitmap_group,
>> };
>>
>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>> index 3ce6f9e9d38e..ab969e950ea8 100644
>> --- a/drivers/md/md.c
>> +++ b/drivers/md/md.c
>> @@ -703,8 +703,8 @@ 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))
>> + if (!mddev_is_dm(mddev) &&
>> mddev->bitmap_ops->register_group) {
>> + if (mddev->bitmap_ops->register_group(mddev))
>> pr_warn("md: cannot register extra bitmap
>> attributes for %s\n",
>> mdname(mddev));
>> else
>> @@ -724,8 +724,8 @@ static bool mddev_set_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->unregister_group)
>> + mddev->bitmap_ops->unregister_group(mddev);
>>
>> mddev->bitmap_ops = NULL;
>> }
>> @@ -6369,6 +6369,14 @@ struct mddev *md_alloc(dev_t dev, char
>> *name)
>> return ERR_PTR(error);
>> }
>>
>> + /*
>> + * md_sysfs_remove_common_group is not needed because
>> mddev_delayed_delete
>> + * calls kobject_put(&mddev->kobj) if mddev is to be
>> deleted.
>> + */
>> + if (md_sysfs_create_common_group(mddev))
>> + pr_warn("md: cannot register common 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");
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-04 3:14 ` Su Yue
@ 2026-03-05 17:57 ` Yu Kuai
2026-03-15 8:56 ` Glass Su
0 siblings, 1 reply; 12+ messages in thread
From: Yu Kuai @ 2026-03-05 17:57 UTC (permalink / raw)
To: Su Yue, yukuai; +Cc: Su Yue, linux-raid, song, xni, linan122, heming.zhao
Hi,
在 2026/3/4 11:14, Su Yue 写道:
> On Wed 04 Mar 2026 at 10:30, "Yu Kuai" <yukuai@fnnas.com> wrote:
>
>> Hi,
>>
>> 在 2026/3/3 11:37, Su Yue 写道:
>>> Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration of
>>> bitmap_ops until creating bitmap")
>>> if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and
>>> clustered have
>>> the sysfs file bitmap/location.
>>>
>>> After the commit, if bitmap is none, bitmap/location doesn't exist
>>> anymore.
>>> It breaks 'grow' behavior of a md array of madam with
>>> MD_FEATURE_BITMAP_OFFSET.
>>> Take level=mirror and metadata=1.2 as an example:
>>>
>>> $ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2
>>> --level=mirror \
>>> --metadata=1.2 /dev/vdd /dev/vde
>>> $ mdadm --grow /dev/md0 --bitmap=internal
>>> $ cat /sys/block/md0/md/bitmap/location
>>> Before:+8
>>> After: +2
>>>
>>> While growing bitmap from none to internal, clustered and llbitmap,
>>> mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location first.
>>> 1)If bitmap/location exists, it sets bitmap/location after
>>> getinfo_super().
>>> 2)If bitmap/location doesn't exist, mdadm just calls
>>> md_set_array_info() then
>>> mddev->bitmap_info.default_offset will be used.
>>> Situation can be worse if growing none to clustered, bitmap offset
>>> of the node
>>> calling `madm --grow` will be changed but the other node are reading
>>> bitmap sb from
>>> the old location.
>>
>> Now that we have a new sysfs attribute bitmap_type, can we fix this by:
>> - in the kernel, allow writing to this file in this case;
>> - in mdadm and the grow case above, write to this file first, and change
>> bitmap_type from none to bitmap(For llbitmap, there is still more
>> work to do).
>>
> Yes. It's indeed feasible. But how about old versions mdadm? We can't
> require
> users' madadm + kernel combinations for old feature. Kernel part
> should keep
> compatibility with userspace. sysfs changes and broken haviros are not
> ideal
> especially userspace depends on it unless there's a strong reason.
> That's why linux/Documentation/ABI exists.
Okay, I can accept keep this old behavior.
However, instead of introducing a new common_group with the same name "bitmap",
I'll prefer to introducing a separate bitmap_ops for none bitmap as well, and
you can define the attrs that are necessary.
For llbitmap, I think it's fine, we don't need this old sysfs attr anyway. I'll
support to convert from none/bitmap to llbitmap by writing the new bitmap_type
file.
>
> --
> Su
>
>>>
>>> Here restore sysfs file bitmap/location for ID_BITMAP_NONE and
>>> ID_BITMAP.
>>> And it d adds the entry for llbitmap too.
>>>
>>> New attribute_group md_bitmap_common_group is introduced and created in
>>> md_alloc() as before commit fb8cc3b0d9db.
>>> Add New operations register_group and unregister_group to struct
>>> bitmap_operations.
>>>
>>> Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops
>>> until creating bitmap")
>>> Signed-off-by: Su Yue <glass.su@suse.com>
>>> ---
>>> drivers/md/md-bitmap.c | 32 +++++++++++++++++++++++++++++++-
>>> drivers/md/md-bitmap.h | 5 +++++
>>> drivers/md/md-llbitmap.c | 13 +++++++++++++
>>> drivers/md/md.c | 16 ++++++++++++----
>>> 4 files changed, 61 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
>>> index 83378c033c72..8ff1dc94ed78 100644
>>> --- a/drivers/md/md-bitmap.c
>>> +++ b/drivers/md/md-bitmap.c
>>> @@ -2956,7 +2956,6 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
>>> behind_writes_used_show, behind_writes_used_reset);
>>>
>>> static struct attribute *md_bitmap_attrs[] = {
>>> - &bitmap_location.attr,
>>> &bitmap_space.attr,
>>> &bitmap_timeout.attr,
>>> &bitmap_backlog.attr,
>>> @@ -2967,11 +2966,40 @@ static struct attribute *md_bitmap_attrs[] = {
>>> NULL
>>> };
>>>
>>> +static struct attribute *md_bitmap_common_attrs[] = {
>>> + &bitmap_location.attr,
>>> + NULL
>>> +};
>>> +
>>> static struct attribute_group md_bitmap_group = {
>>> .name = "bitmap",
>>> .attrs = md_bitmap_attrs,
>>> };
>>>
>>> +static struct attribute_group md_bitmap_common_group = {
>>> + .name = "bitmap",
>>> + .attrs = md_bitmap_common_attrs,
>>> +};
>>> +
>>> +int md_sysfs_create_common_group(struct mddev *mddev)
>>> +{
>>> + return sysfs_create_group(&mddev->kobj, &md_bitmap_common_group);
>>> +}
>>> +
>>> +static int bitmap_register_group(struct mddev *mddev)
>>> +{
>>> + /*
>>> + * md_bitmap_group and md_bitmap_common_group are using same name
>>> + * 'bitmap'.
>>> + */
>>> + return sysfs_merge_group(&mddev->kobj, &md_bitmap_group);
>>> +}
>>> +
>>> +static void bitmap_unregister_group(struct mddev *mddev)
>>> +{
>>> + sysfs_unmerge_group(&mddev->kobj, &md_bitmap_group);
>>> +}
>>> +
>>> static struct bitmap_operations bitmap_ops = {
>>> .head = {
>>> .type = MD_BITMAP,
>>> @@ -3013,6 +3041,8 @@ static struct bitmap_operations bitmap_ops = {
>>> .set_pages = bitmap_set_pages,
>>> .free = md_bitmap_free,
>>>
>>> + .register_group = bitmap_register_group,
>>> + .unregister_group = bitmap_unregister_group,
>>> .group = &md_bitmap_group,
>>> };
>>>
>>> diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
>>> index b42a28fa83a0..371791e9011d 100644
>>> --- a/drivers/md/md-bitmap.h
>>> +++ b/drivers/md/md-bitmap.h
>>> @@ -125,6 +125,9 @@ struct bitmap_operations {
>>> void (*set_pages)(void *data, unsigned long pages);
>>> void (*free)(void *data);
>>>
>>> + int (*register_group)(struct mddev *mddev);
>>> + void (*unregister_group)(struct mddev *mddev);
>>> +
>>> struct attribute_group *group;
>>> };
>>>
>>> @@ -169,6 +172,8 @@ static inline void md_bitmap_end_sync(struct
>>> mddev *mddev, sector_t offset,
>>> mddev->bitmap_ops->end_sync(mddev, offset, blocks);
>>> }
>>>
>>> +int md_sysfs_create_common_group(struct mddev *mddev);
>>> +
>>> #ifdef CONFIG_MD_BITMAP
>>> int md_bitmap_init(void);
>>> void md_bitmap_exit(void);
>>> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
>>> index bf398d7476b3..24ff5f7f8751 100644
>>> --- a/drivers/md/md-llbitmap.c
>>> +++ b/drivers/md/md-llbitmap.c
>>> @@ -1561,6 +1561,16 @@ static struct attribute_group
>>> md_llbitmap_group = {
>>> .attrs = md_llbitmap_attrs,
>>> };
>>>
>>> +static int llbitmap_register_group(struct mddev *mddev)
>>> +{
>>> + return sysfs_create_group(&mddev->kobj, &md_llbitmap_group);
>>> +}
>>> +
>>> +static void llbitmap_unregister_group(struct mddev *mddev)
>>> +{
>>> + sysfs_remove_group(&mddev->kobj, &md_llbitmap_group);
>>> +}
>>> +
>>> static struct bitmap_operations llbitmap_ops = {
>>> .head = {
>>> .type = MD_BITMAP,
>>> @@ -1597,6 +1607,9 @@ static struct bitmap_operations llbitmap_ops = {
>>> .dirty_bits = llbitmap_dirty_bits,
>>> .write_all = llbitmap_write_all,
>>>
>>> + .register_group = llbitmap_register_group,
>>> + .unregister_group = llbitmap_unregister_group,
>>> +
>>> .group = &md_llbitmap_group,
>>> };
>>>
>>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>>> index 3ce6f9e9d38e..ab969e950ea8 100644
>>> --- a/drivers/md/md.c
>>> +++ b/drivers/md/md.c
>>> @@ -703,8 +703,8 @@ 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))
>>> + if (!mddev_is_dm(mddev) && mddev->bitmap_ops->register_group) {
>>> + if (mddev->bitmap_ops->register_group(mddev))
>>> pr_warn("md: cannot register extra bitmap attributes
>>> for %s\n",
>>> mdname(mddev));
>>> else
>>> @@ -724,8 +724,8 @@ static bool mddev_set_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->unregister_group)
>>> + mddev->bitmap_ops->unregister_group(mddev);
>>>
>>> mddev->bitmap_ops = NULL;
>>> }
>>> @@ -6369,6 +6369,14 @@ struct mddev *md_alloc(dev_t dev, char *name)
>>> return ERR_PTR(error);
>>> }
>>>
>>> + /*
>>> + * md_sysfs_remove_common_group is not needed because
>>> mddev_delayed_delete
>>> + * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
>>> + */
>>> + if (md_sysfs_create_common_group(mddev))
>>> + pr_warn("md: cannot register common 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");
--
Thansk,
Kuai
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
2026-03-04 2:30 ` Yu Kuai
@ 2026-03-05 22:38 ` kernel test robot
2026-03-05 22:50 ` kernel test robot
2 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-03-05 22:38 UTC (permalink / raw)
To: Su Yue, linux-raid
Cc: oe-kbuild-all, song, xni, linan122, yukuai, heming.zhao, l,
Su Yue
Hi Su,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v7.0-rc2 next-20260305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Su-Yue/md-restore-bitmap-location-to-fix-wrong-bitmap-offset-while-growing/20260303-114108
base: linus/master
patch link: https://lore.kernel.org/r/20260303033731.83885-2-glass.su%40suse.com
patch subject: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
config: i386-randconfig-r064-20260305 (https://download.01.org/0day-ci/archive/20260306/202603060651.tJ5tGHRo-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260306/202603060651.tJ5tGHRo-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603060651.tJ5tGHRo-lkp@intel.com/
All errors (new ones prefixed by >>):
>> ld.lld: error: undefined symbol: md_sysfs_create_common_group
>>> referenced by md.c:6376 (drivers/md/md.c:6376)
>>> drivers/md/md.o:(md_alloc) in archive vmlinux.a
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
2026-03-04 2:30 ` Yu Kuai
2026-03-05 22:38 ` kernel test robot
@ 2026-03-05 22:50 ` kernel test robot
2026-03-06 4:25 ` Glass Su
2 siblings, 1 reply; 12+ messages in thread
From: kernel test robot @ 2026-03-05 22:50 UTC (permalink / raw)
To: Su Yue, linux-raid
Cc: oe-kbuild-all, song, xni, linan122, yukuai, heming.zhao, l,
Su Yue
Hi Su,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v7.0-rc2 next-20260305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Su-Yue/md-restore-bitmap-location-to-fix-wrong-bitmap-offset-while-growing/20260303-114108
base: linus/master
patch link: https://lore.kernel.org/r/20260303033731.83885-2-glass.su%40suse.com
patch subject: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
config: i386-randconfig-051-20260305 (https://download.01.org/0day-ci/archive/20260306/202603060614.AZY6J9w9-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260306/202603060614.AZY6J9w9-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603060614.AZY6J9w9-lkp@intel.com/
All errors (new ones prefixed by >>):
ld: drivers/md/md.o: in function `md_alloc':
>> drivers/md/md.c:6376:(.text+0xb36c): undefined reference to `md_sysfs_create_common_group'
vim +6376 drivers/md/md.c
6276
6277 struct mddev *md_alloc(dev_t dev, char *name)
6278 {
6279 /*
6280 * If dev is zero, name is the name of a device to allocate with
6281 * an arbitrary minor number. It will be "md_???"
6282 * If dev is non-zero it must be a device number with a MAJOR of
6283 * MD_MAJOR or mdp_major. In this case, if "name" is NULL, then
6284 * the device is being created by opening a node in /dev.
6285 * If "name" is not NULL, the device is being created by
6286 * writing to /sys/module/md_mod/parameters/new_array.
6287 */
6288 static DEFINE_MUTEX(disks_mutex);
6289 struct mddev *mddev;
6290 struct gendisk *disk;
6291 int partitioned;
6292 int shift;
6293 int unit;
6294 int error;
6295
6296 /*
6297 * Wait for any previous instance of this device to be completely
6298 * removed (mddev_delayed_delete).
6299 */
6300 flush_workqueue(md_misc_wq);
6301
6302 mutex_lock(&disks_mutex);
6303 mddev = mddev_alloc(dev);
6304 if (IS_ERR(mddev)) {
6305 error = PTR_ERR(mddev);
6306 goto out_unlock;
6307 }
6308
6309 partitioned = (MAJOR(mddev->unit) != MD_MAJOR);
6310 shift = partitioned ? MdpMinorShift : 0;
6311 unit = MINOR(mddev->unit) >> shift;
6312
6313 if (name && !dev) {
6314 /* Need to ensure that 'name' is not a duplicate.
6315 */
6316 struct mddev *mddev2;
6317 spin_lock(&all_mddevs_lock);
6318
6319 list_for_each_entry(mddev2, &all_mddevs, all_mddevs)
6320 if (mddev2->gendisk &&
6321 strcmp(mddev2->gendisk->disk_name, name) == 0) {
6322 spin_unlock(&all_mddevs_lock);
6323 error = -EEXIST;
6324 goto out_free_mddev;
6325 }
6326 spin_unlock(&all_mddevs_lock);
6327 }
6328 if (name && dev)
6329 /*
6330 * Creating /dev/mdNNN via "newarray", so adjust hold_active.
6331 */
6332 mddev->hold_active = UNTIL_STOP;
6333
6334 disk = blk_alloc_disk(NULL, NUMA_NO_NODE);
6335 if (IS_ERR(disk)) {
6336 error = PTR_ERR(disk);
6337 goto out_free_mddev;
6338 }
6339
6340 disk->major = MAJOR(mddev->unit);
6341 disk->first_minor = unit << shift;
6342 disk->minors = 1 << shift;
6343 if (name)
6344 strcpy(disk->disk_name, name);
6345 else if (partitioned)
6346 sprintf(disk->disk_name, "md_d%d", unit);
6347 else
6348 sprintf(disk->disk_name, "md%d", unit);
6349 disk->fops = &md_fops;
6350 disk->private_data = mddev;
6351
6352 disk->events |= DISK_EVENT_MEDIA_CHANGE;
6353 mddev->gendisk = disk;
6354 error = add_disk(disk);
6355 if (error)
6356 goto out_put_disk;
6357
6358 kobject_init(&mddev->kobj, &md_ktype);
6359 error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md");
6360 if (error) {
6361 /*
6362 * The disk is already live at this point. Clear the hold flag
6363 * and let mddev_put take care of the deletion, as it isn't any
6364 * different from a normal close on last release now.
6365 */
6366 mddev->hold_active = 0;
6367 mutex_unlock(&disks_mutex);
6368 mddev_put(mddev);
6369 return ERR_PTR(error);
6370 }
6371
6372 /*
6373 * md_sysfs_remove_common_group is not needed because mddev_delayed_delete
6374 * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
6375 */
> 6376 if (md_sysfs_create_common_group(mddev))
6377 pr_warn("md: cannot register common bitmap attributes for %s\n",
6378 mdname(mddev));
6379
6380 kobject_uevent(&mddev->kobj, KOBJ_ADD);
6381 mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
6382 mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
6383 mutex_unlock(&disks_mutex);
6384 return mddev;
6385
6386 out_put_disk:
6387 put_disk(disk);
6388 out_free_mddev:
6389 mddev_free(mddev);
6390 out_unlock:
6391 mutex_unlock(&disks_mutex);
6392 return ERR_PTR(error);
6393 }
6394
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-05 22:50 ` kernel test robot
@ 2026-03-06 4:25 ` Glass Su
0 siblings, 0 replies; 12+ messages in thread
From: Glass Su @ 2026-03-06 4:25 UTC (permalink / raw)
To: kernel test robot
Cc: linux-raid, oe-kbuild-all, song, xni, linan122, yukuai,
Heming Zhao, Su Yue
> On Mar 6, 2026, at 06:50, kernel test robot <lkp@intel.com> wrote:
>
> Hi Su,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on linus/master]
> [also build test ERROR on v7.0-rc2 next-20260305]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Su-Yue/md-restore-bitmap-location-to-fix-wrong-bitmap-offset-while-growing/20260303-114108
> base: linus/master
> patch link: https://lore.kernel.org/r/20260303033731.83885-2-glass.su%40suse.com
> patch subject: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
> config: i386-randconfig-051-20260305 (https://download.01.org/0day-ci/archive/20260306/202603060614.AZY6J9w9-lkp@intel.com/config)
> compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260306/202603060614.AZY6J9w9-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202603060614.AZY6J9w9-lkp@intel.com/
>
> All errors (new ones prefixed by >>):
>
> ld: drivers/md/md.o: in function `md_alloc':
>>> drivers/md/md.c:6376:(.text+0xb36c): undefined reference to `md_sysfs_create_common_group'
Forget to test it with
# CONFIG_MD_BITMAP is not set
Anyway, I will do revision as Yu Kuai’s suggestion.
—
Su
>
>
> vim +6376 drivers/md/md.c
>
> 6276
> 6277 struct mddev *md_alloc(dev_t dev, char *name)
> 6278 {
> 6279 /*
> 6280 * If dev is zero, name is the name of a device to allocate with
> 6281 * an arbitrary minor number. It will be "md_???"
> 6282 * If dev is non-zero it must be a device number with a MAJOR of
> 6283 * MD_MAJOR or mdp_major. In this case, if "name" is NULL, then
> 6284 * the device is being created by opening a node in /dev.
> 6285 * If "name" is not NULL, the device is being created by
> 6286 * writing to /sys/module/md_mod/parameters/new_array.
> 6287 */
> 6288 static DEFINE_MUTEX(disks_mutex);
> 6289 struct mddev *mddev;
> 6290 struct gendisk *disk;
> 6291 int partitioned;
> 6292 int shift;
> 6293 int unit;
> 6294 int error;
> 6295
> 6296 /*
> 6297 * Wait for any previous instance of this device to be completely
> 6298 * removed (mddev_delayed_delete).
> 6299 */
> 6300 flush_workqueue(md_misc_wq);
> 6301
> 6302 mutex_lock(&disks_mutex);
> 6303 mddev = mddev_alloc(dev);
> 6304 if (IS_ERR(mddev)) {
> 6305 error = PTR_ERR(mddev);
> 6306 goto out_unlock;
> 6307 }
> 6308
> 6309 partitioned = (MAJOR(mddev->unit) != MD_MAJOR);
> 6310 shift = partitioned ? MdpMinorShift : 0;
> 6311 unit = MINOR(mddev->unit) >> shift;
> 6312
> 6313 if (name && !dev) {
> 6314 /* Need to ensure that 'name' is not a duplicate.
> 6315 */
> 6316 struct mddev *mddev2;
> 6317 spin_lock(&all_mddevs_lock);
> 6318
> 6319 list_for_each_entry(mddev2, &all_mddevs, all_mddevs)
> 6320 if (mddev2->gendisk &&
> 6321 strcmp(mddev2->gendisk->disk_name, name) == 0) {
> 6322 spin_unlock(&all_mddevs_lock);
> 6323 error = -EEXIST;
> 6324 goto out_free_mddev;
> 6325 }
> 6326 spin_unlock(&all_mddevs_lock);
> 6327 }
> 6328 if (name && dev)
> 6329 /*
> 6330 * Creating /dev/mdNNN via "newarray", so adjust hold_active.
> 6331 */
> 6332 mddev->hold_active = UNTIL_STOP;
> 6333
> 6334 disk = blk_alloc_disk(NULL, NUMA_NO_NODE);
> 6335 if (IS_ERR(disk)) {
> 6336 error = PTR_ERR(disk);
> 6337 goto out_free_mddev;
> 6338 }
> 6339
> 6340 disk->major = MAJOR(mddev->unit);
> 6341 disk->first_minor = unit << shift;
> 6342 disk->minors = 1 << shift;
> 6343 if (name)
> 6344 strcpy(disk->disk_name, name);
> 6345 else if (partitioned)
> 6346 sprintf(disk->disk_name, "md_d%d", unit);
> 6347 else
> 6348 sprintf(disk->disk_name, "md%d", unit);
> 6349 disk->fops = &md_fops;
> 6350 disk->private_data = mddev;
> 6351
> 6352 disk->events |= DISK_EVENT_MEDIA_CHANGE;
> 6353 mddev->gendisk = disk;
> 6354 error = add_disk(disk);
> 6355 if (error)
> 6356 goto out_put_disk;
> 6357
> 6358 kobject_init(&mddev->kobj, &md_ktype);
> 6359 error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md");
> 6360 if (error) {
> 6361 /*
> 6362 * The disk is already live at this point. Clear the hold flag
> 6363 * and let mddev_put take care of the deletion, as it isn't any
> 6364 * different from a normal close on last release now.
> 6365 */
> 6366 mddev->hold_active = 0;
> 6367 mutex_unlock(&disks_mutex);
> 6368 mddev_put(mddev);
> 6369 return ERR_PTR(error);
> 6370 }
> 6371
> 6372 /*
> 6373 * md_sysfs_remove_common_group is not needed because mddev_delayed_delete
> 6374 * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
> 6375 */
>> 6376 if (md_sysfs_create_common_group(mddev))
> 6377 pr_warn("md: cannot register common bitmap attributes for %s\n",
> 6378 mdname(mddev));
> 6379
> 6380 kobject_uevent(&mddev->kobj, KOBJ_ADD);
> 6381 mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
> 6382 mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
> 6383 mutex_unlock(&disks_mutex);
> 6384 return mddev;
> 6385
> 6386 out_put_disk:
> 6387 put_disk(disk);
> 6388 out_free_mddev:
> 6389 mddev_free(mddev);
> 6390 out_unlock:
> 6391 mutex_unlock(&disks_mutex);
> 6392 return ERR_PTR(error);
> 6393 }
> 6394
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-05 17:57 ` Yu Kuai
@ 2026-03-15 8:56 ` Glass Su
2026-03-15 18:12 ` Yu Kuai
0 siblings, 1 reply; 12+ messages in thread
From: Glass Su @ 2026-03-15 8:56 UTC (permalink / raw)
To: yukuai; +Cc: Su Yue, linux-raid, song, xni, linan122, Heming Zhao
[-- Attachment #1: Type: text/plain, Size: 5392 bytes --]
> On Mar 6, 2026, at 01:57, Yu Kuai <yukuai@fnnas.com> wrote:
>
> Hi,
>
> 在 2026/3/4 11:14, Su Yue 写道:
>> On Wed 04 Mar 2026 at 10:30, "Yu Kuai" <yukuai@fnnas.com> wrote:
>>
>>> Hi,
>>>
>>> 在 2026/3/3 11:37, Su Yue 写道:
>>>> Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration of
>>>> bitmap_ops until creating bitmap")
>>>> if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and
>>>> clustered have
>>>> the sysfs file bitmap/location.
>>>>
>>>> After the commit, if bitmap is none, bitmap/location doesn't exist
>>>> anymore.
>>>> It breaks 'grow' behavior of a md array of madam with
>>>> MD_FEATURE_BITMAP_OFFSET.
>>>> Take level=mirror and metadata=1.2 as an example:
>>>>
>>>> $ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2
>>>> --level=mirror \
>>>> --metadata=1.2 /dev/vdd /dev/vde
>>>> $ mdadm --grow /dev/md0 --bitmap=internal
>>>> $ cat /sys/block/md0/md/bitmap/location
>>>> Before:+8
>>>> After: +2
>>>>
>>>> While growing bitmap from none to internal, clustered and llbitmap,
>>>> mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location first.
>>>> 1)If bitmap/location exists, it sets bitmap/location after
>>>> getinfo_super().
>>>> 2)If bitmap/location doesn't exist, mdadm just calls
>>>> md_set_array_info() then
>>>> mddev->bitmap_info.default_offset will be used.
>>>> Situation can be worse if growing none to clustered, bitmap offset
>>>> of the node
>>>> calling `madm --grow` will be changed but the other node are reading
>>>> bitmap sb from
>>>> the old location.
>>>
>>> Now that we have a new sysfs attribute bitmap_type, can we fix this by:
>>> - in the kernel, allow writing to this file in this case;
>>> - in mdadm and the grow case above, write to this file first, and change
>>> bitmap_type from none to bitmap(For llbitmap, there is still more
>>> work to do).
>>>
>> Yes. It's indeed feasible. But how about old versions mdadm? We can't
>> require
>> users' madadm + kernel combinations for old feature. Kernel part
>> should keep
>> compatibility with userspace. sysfs changes and broken haviros are not
>> ideal
>> especially userspace depends on it unless there's a strong reason.
>> That's why linux/Documentation/ABI exists.
>
> Okay, I can accept keep this old behavior.
>
> However, instead of introducing a new common_group with the same name "bitmap",
> I'll prefer to introducing a separate bitmap_ops for none bitmap as well, and
> you can define the attrs that are necessary.
>
After a try, the thing I realized is that a common group is unavoidable for bitmap and none bitmap.
mdadm writes to /sys/block/md0/md/bitmap/location, if remove_files() called by sysfs_remove_group()/
sysfs_update_group() on same kernfs node, recursive locks will be triggered:
[ 139.516750] ============================================
[ 139.517363] WARNING: possible recursive locking detected
[ 139.517953] 7.0.0-rc1-custom+ #282 Tainted: G OE
[ 139.518628] --------------------------------------------
[ 139.519233] mdadm/2346 is trying to acquire lock:
[ 139.519836] ffff8e6b24d85000 (kn->active#116){++++}-{0:0}, at: __kernfs_remove+0xd1/0x3e0
[ 139.520848]
but task is already holding lock:
[ 139.521561] ffff8e6b24d85000 (kn->active#116){++++}-{0:0}, at: kernfs_fop_write_iter+0x12d/0x250
[ 139.522603]
other info that might help us debug this:
[ 139.523383] Possible unsafe locking scenario:
[ 139.524169] CPU0
[ 139.524430] ----
[ 139.524682] lock(kn->active#116);
[ 139.525047] lock(kn->active#116);
[ 139.525398]
*** DEADLOCK ***
[ 139.525990] May be due to missing lock nesting notation
[ 139.526658] 4 locks held by mdadm/2346:
[ 139.527049] #0: ffff8e6acd5ec420 (sb_writers#5){.+.+}-{0:0}, at: ksys_write+0x6c/0xe0
[ 139.527838] #1: ffff8e6acd54fa88 (&of->mutex){+.+.}-{4:4}, at: kernfs_fop_write_iter+0x118/0x250
[ 139.528713] #2: ffff8e6b24d85000 (kn->active#116){++++}-{0:0}, at: kernfs_fop_write_iter+0x12d/0x250
[ 139.529594] #3: ffff8e6b26b51370 (&mddev->reconfig_mutex){+.+.}-{4:4}, at: location_store+0x6c/0x360 [md_mod]
[ 139.530535] dump_stack_lvl+0x68/0x90
[ 139.530540] print_deadlock_bug.cold+0xc0/0xcd
[ 139.530549] __lock_acquire+0x1324/0x2250
[ 139.530556] lock_acquire+0xc6/0x2f0
[ 139.530564] kernfs_drain+0x1eb/0x200
[ 139.530568] __kernfs_remove+0xd1/0x3e0
[ 139.530570] kernfs_remove_by_name_ns+0x5e/0xb0
[ 139.530572] internal_create_group+0x221/0x4d0
[ 139.530578] md_bitmap_create+0x122/0x130 [md_mod]
[ 139.530586] location_store+0x1e9/0x360 [md_mod]
[ 139.530594] md_attr_store+0xb8/0x1a0 [md_mod]
[ 139.530602] kernfs_fop_write_iter+0x176/0x250
[ 139.530605] vfs_write+0x21b/0x560
[ 139.530609] ksys_write+0x6c/0xe0
[ 139.530611] do_syscall_64+0x10f/0x5f0
[ 139.530623] entry_SYSCALL_64_after_hwframe+0x76/0x7e
The patch implemented by separated bitmap_ops is attached. This version looks pretty similar to the first
version because of the reason listed above and IMO ungraceful. Dummy ops and functions are a little unnecessary.
I would like to ask your opinion since you are the maintainer even though I prefer v1 version + (remove the location entry for llbitmap).
Thanks.
[-- Attachment #2: 000-md-add-dummy-bitmap-ops-for-none-to-fix-wrong-bitmap.patch --]
[-- Type: application/octet-stream, Size: 7408 bytes --]
From 1dd81c439b0097d0a9a5975682801ce75448e108 Mon Sep 17 00:00:00 2001
From: Su Yue <glass.su@suse.com>
Date: Sat, 7 Mar 2026 12:30:36 +0800
Subject: [PATCH 1/2] md: add dummy bitmap ops for none to fix wrong bitmap
offset
Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and clustered have
the sysfs file bitmap/location.
After the commit, if bitmap is none, bitmap/location doesn't exist anymore.
It breaks 'grow' behavior of a md array of madam with MD_FEATURE_BITMAP_OFFSET.
Take level=mirror and metadata=1.2 as an example:
$ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2 --level=mirror \
--metadata=1.2 /dev/vdd /dev/vde
$ mdadm --grow /dev/md0 --bitmap=internal
$ cat /sys/block/md0/md/bitmap/location
Before:+8
After: +2
While growing bitmap from none to internal, clustered and llbitmap,
mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location first.
1)If bitmap/location exists, it sets bitmap/location after getinfo_super().
2)If bitmap/location doesn't exist, mdadm just calls md_set_array_info() then
mddev->bitmap_info.default_offset will be used.
Situation can be worse if growing none to clustered, bitmap offset of the node
calling `madm --grow` will be changed but the other node are reading bitmap sb from
the old location.
Here introducing a dummy bitmap_operations for ID_BITMAP_NONE to restore sysfs
file bitmap/location for ID_BITMAP_NONE and ID_BITMAP.
Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops until creating bitmap")
Signed-off-by: Su Yue <glass.su@suse.com>
---
drivers/md/md-bitmap.c | 48 ++++++++++++++++++++++++++++++++++++++++--
drivers/md/md.c | 46 ++++++++++++++++++++++++++++------------
2 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 83378c033c72..d5354cf35a65 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -240,6 +240,11 @@ static bool bitmap_enabled(void *data, bool flush)
bitmap->storage.filemap != NULL;
}
+static bool dummy_bitmap_enabled(void *data, bool flush)
+{
+ return false;
+}
+
/*
* check a page and, if necessary, allocate it (or hijack it if the alloc fails)
*
@@ -2201,6 +2206,11 @@ static int bitmap_create(struct mddev *mddev)
return 0;
}
+static int dummy_bitmap_create(struct mddev *mddev)
+{
+ return 0;
+}
+
static int bitmap_load(struct mddev *mddev)
{
int err = 0;
@@ -2956,7 +2966,7 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
behind_writes_used_show, behind_writes_used_reset);
static struct attribute *md_bitmap_attrs[] = {
- &bitmap_location.attr,
+// &bitmap_location.attr,
&bitmap_space.attr,
&bitmap_timeout.attr,
&bitmap_backlog.attr,
@@ -2972,6 +2982,17 @@ static struct attribute_group md_bitmap_group = {
.attrs = md_bitmap_attrs,
};
+/* Only necessary attrs for compatibility */
+static struct attribute *md_dummy_bitmap_attrs[] = {
+ &bitmap_location.attr,
+ NULL
+};
+
+static struct attribute_group md_dummy_bitmap_group = {
+ .name = "bitmap",
+ .attrs = md_dummy_bitmap_attrs,
+};
+
static struct bitmap_operations bitmap_ops = {
.head = {
.type = MD_BITMAP,
@@ -3016,18 +3037,41 @@ static struct bitmap_operations bitmap_ops = {
.group = &md_bitmap_group,
};
+static struct bitmap_operations dummy_bitmap_ops = {
+ .head = {
+ .type = MD_BITMAP,
+ .id = ID_BITMAP_NONE,
+ .name = "none",
+ },
+
+ .enabled = dummy_bitmap_enabled,
+ .create = dummy_bitmap_create,
+ .destroy = bitmap_destroy,
+ .load = bitmap_load,
+ .get_stats = bitmap_get_stats,
+ .free = md_bitmap_free,
+ .group = &md_dummy_bitmap_group,
+};
+
int md_bitmap_init(void)
{
+ int ret;
+
md_bitmap_wq = alloc_workqueue("md_bitmap", WQ_MEM_RECLAIM | WQ_UNBOUND,
0);
if (!md_bitmap_wq)
return -ENOMEM;
- return register_md_submodule(&bitmap_ops.head);
+ ret = register_md_submodule(&bitmap_ops.head);
+ if (ret)
+ return ret;
+
+ return register_md_submodule(&dummy_bitmap_ops.head);
}
void md_bitmap_exit(void)
{
destroy_workqueue(md_bitmap_wq);
unregister_md_submodule(&bitmap_ops.head);
+ unregister_md_submodule(&dummy_bitmap_ops.head);
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3ce6f9e9d38e..94ded8efb725 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -682,9 +682,9 @@ static bool mddev_set_bitmap_ops(struct mddev *mddev)
{
struct bitmap_operations *old = mddev->bitmap_ops;
struct md_submodule_head *head;
+ int err = 0;
- if (mddev->bitmap_id == ID_BITMAP_NONE ||
- (old && old->head.id == mddev->bitmap_id))
+ if (old && old->head.id == mddev->bitmap_id)
return true;
xa_lock(&md_submodule);
@@ -704,13 +704,24 @@ static bool mddev_set_bitmap_ops(struct mddev *mddev)
xa_unlock(&md_submodule);
if (!mddev_is_dm(mddev) && mddev->bitmap_ops->group) {
- if (sysfs_create_group(&mddev->kobj, mddev->bitmap_ops->group))
+
+ if (old && old->head.id == ID_BITMAP_NONE) {
+ if (head->id == ID_BITMAP) {
+ err = sysfs_merge_group(&mddev->kobj, mddev->bitmap_ops->group);
+ } else if (head->id == ID_LLBITMAP) {
+ sysfs_remove_group(&mddev->kobj, mddev->bitmap_ops->group);
+ err = sysfs_create_group(&mddev->kobj, mddev->bitmap_ops->group);
+ }
+ } else {
+ err = sysfs_create_group(&mddev->kobj, mddev->bitmap_ops->group);
+ }
+
+ if (err)
pr_warn("md: cannot register extra bitmap attributes for %s\n",
mdname(mddev));
else
/*
- * Inform user with KOBJ_CHANGE about new bitmap
- * attributes.
+ * Inform user with KOBJ_CHANGE about bitmap attributes changes.
*/
kobject_uevent(&mddev->kobj, KOBJ_CHANGE);
}
@@ -723,11 +734,20 @@ static bool mddev_set_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);
+ if (mddev_is_dm(mddev) || !mddev->bitmap_ops)
+ return;
- mddev->bitmap_ops = NULL;
+ if (mddev->bitmap_ops->head.id == ID_BITMAP_NONE)
+ return;
+
+ if (mddev->bitmap_ops->group)
+ sysfs_remove_group(&mddev->kobj, mddev->bitmap_ops->group);
+ /*
+ * group of ID_BITMAP_NONE is removed when new bitmap is
+ * creating in mddev_set_bitmap_ops().
+ */
+ mddev->bitmap_id = ID_BITMAP_NONE;
+ md_bitmap_create(mddev);
}
int mddev_init(struct mddev *mddev)
@@ -6449,9 +6469,6 @@ 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;
@@ -6610,8 +6627,9 @@ int md_run(struct mddev *mddev)
(unsigned long long)pers->size(mddev, 0, 0) / 2);
err = -EINVAL;
}
- if (err == 0 && pers->sync_request &&
- (mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
+ if (err == 0 && pers->sync_request) {
+ if (mddev->bitmap_info.offset == 0)
+ mddev->bitmap_id = ID_BITMAP_NONE;
err = md_bitmap_create(mddev);
if (err)
pr_warn("%s: failed to create bitmap (%d)\n",
--
2.53.0
[-- Attachment #3: Type: text/plain, Size: 7309 bytes --]
—
Su
> For llbitmap, I think it's fine, we don't need this old sysfs attr anyway. I'll
> support to convert from none/bitmap to llbitmap by writing the new bitmap_type
> file.
>
>
>>
>> --
>> Su
>>
>>>>
>>>> Here restore sysfs file bitmap/location for ID_BITMAP_NONE and
>>>> ID_BITMAP.
>>>> And it d adds the entry for llbitmap too.
>>>>
>>>> New attribute_group md_bitmap_common_group is introduced and created in
>>>> md_alloc() as before commit fb8cc3b0d9db.
>>>> Add New operations register_group and unregister_group to struct
>>>> bitmap_operations.
>>>>
>>>> Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops
>>>> until creating bitmap")
>>>> Signed-off-by: Su Yue <glass.su@suse.com>
>>>> ---
>>>> drivers/md/md-bitmap.c | 32 +++++++++++++++++++++++++++++++-
>>>> drivers/md/md-bitmap.h | 5 +++++
>>>> drivers/md/md-llbitmap.c | 13 +++++++++++++
>>>> drivers/md/md.c | 16 ++++++++++++----
>>>> 4 files changed, 61 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
>>>> index 83378c033c72..8ff1dc94ed78 100644
>>>> --- a/drivers/md/md-bitmap.c
>>>> +++ b/drivers/md/md-bitmap.c
>>>> @@ -2956,7 +2956,6 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
>>>> behind_writes_used_show, behind_writes_used_reset);
>>>>
>>>> static struct attribute *md_bitmap_attrs[] = {
>>>> - &bitmap_location.attr,
>>>> &bitmap_space.attr,
>>>> &bitmap_timeout.attr,
>>>> &bitmap_backlog.attr,
>>>> @@ -2967,11 +2966,40 @@ static struct attribute *md_bitmap_attrs[] = {
>>>> NULL
>>>> };
>>>>
>>>> +static struct attribute *md_bitmap_common_attrs[] = {
>>>> + &bitmap_location.attr,
>>>> + NULL
>>>> +};
>>>> +
>>>> static struct attribute_group md_bitmap_group = {
>>>> .name = "bitmap",
>>>> .attrs = md_bitmap_attrs,
>>>> };
>>>>
>>>> +static struct attribute_group md_bitmap_common_group = {
>>>> + .name = "bitmap",
>>>> + .attrs = md_bitmap_common_attrs,
>>>> +};
>>>> +
>>>> +int md_sysfs_create_common_group(struct mddev *mddev)
>>>> +{
>>>> + return sysfs_create_group(&mddev->kobj, &md_bitmap_common_group);
>>>> +}
>>>> +
>>>> +static int bitmap_register_group(struct mddev *mddev)
>>>> +{
>>>> + /*
>>>> + * md_bitmap_group and md_bitmap_common_group are using same name
>>>> + * 'bitmap'.
>>>> + */
>>>> + return sysfs_merge_group(&mddev->kobj, &md_bitmap_group);
>>>> +}
>>>> +
>>>> +static void bitmap_unregister_group(struct mddev *mddev)
>>>> +{
>>>> + sysfs_unmerge_group(&mddev->kobj, &md_bitmap_group);
>>>> +}
>>>> +
>>>> static struct bitmap_operations bitmap_ops = {
>>>> .head = {
>>>> .type = MD_BITMAP,
>>>> @@ -3013,6 +3041,8 @@ static struct bitmap_operations bitmap_ops = {
>>>> .set_pages = bitmap_set_pages,
>>>> .free = md_bitmap_free,
>>>>
>>>> + .register_group = bitmap_register_group,
>>>> + .unregister_group = bitmap_unregister_group,
>>>> .group = &md_bitmap_group,
>>>> };
>>>>
>>>> diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
>>>> index b42a28fa83a0..371791e9011d 100644
>>>> --- a/drivers/md/md-bitmap.h
>>>> +++ b/drivers/md/md-bitmap.h
>>>> @@ -125,6 +125,9 @@ struct bitmap_operations {
>>>> void (*set_pages)(void *data, unsigned long pages);
>>>> void (*free)(void *data);
>>>>
>>>> + int (*register_group)(struct mddev *mddev);
>>>> + void (*unregister_group)(struct mddev *mddev);
>>>> +
>>>> struct attribute_group *group;
>>>> };
>>>>
>>>> @@ -169,6 +172,8 @@ static inline void md_bitmap_end_sync(struct
>>>> mddev *mddev, sector_t offset,
>>>> mddev->bitmap_ops->end_sync(mddev, offset, blocks);
>>>> }
>>>>
>>>> +int md_sysfs_create_common_group(struct mddev *mddev);
>>>> +
>>>> #ifdef CONFIG_MD_BITMAP
>>>> int md_bitmap_init(void);
>>>> void md_bitmap_exit(void);
>>>> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
>>>> index bf398d7476b3..24ff5f7f8751 100644
>>>> --- a/drivers/md/md-llbitmap.c
>>>> +++ b/drivers/md/md-llbitmap.c
>>>> @@ -1561,6 +1561,16 @@ static struct attribute_group
>>>> md_llbitmap_group = {
>>>> .attrs = md_llbitmap_attrs,
>>>> };
>>>>
>>>> +static int llbitmap_register_group(struct mddev *mddev)
>>>> +{
>>>> + return sysfs_create_group(&mddev->kobj, &md_llbitmap_group);
>>>> +}
>>>> +
>>>> +static void llbitmap_unregister_group(struct mddev *mddev)
>>>> +{
>>>> + sysfs_remove_group(&mddev->kobj, &md_llbitmap_group);
>>>> +}
>>>> +
>>>> static struct bitmap_operations llbitmap_ops = {
>>>> .head = {
>>>> .type = MD_BITMAP,
>>>> @@ -1597,6 +1607,9 @@ static struct bitmap_operations llbitmap_ops = {
>>>> .dirty_bits = llbitmap_dirty_bits,
>>>> .write_all = llbitmap_write_all,
>>>>
>>>> + .register_group = llbitmap_register_group,
>>>> + .unregister_group = llbitmap_unregister_group,
>>>> +
>>>> .group = &md_llbitmap_group,
>>>> };
>>>>
>>>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>>>> index 3ce6f9e9d38e..ab969e950ea8 100644
>>>> --- a/drivers/md/md.c
>>>> +++ b/drivers/md/md.c
>>>> @@ -703,8 +703,8 @@ 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))
>>>> + if (!mddev_is_dm(mddev) && mddev->bitmap_ops->register_group) {
>>>> + if (mddev->bitmap_ops->register_group(mddev))
>>>> pr_warn("md: cannot register extra bitmap attributes
>>>> for %s\n",
>>>> mdname(mddev));
>>>> else
>>>> @@ -724,8 +724,8 @@ static bool mddev_set_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->unregister_group)
>>>> + mddev->bitmap_ops->unregister_group(mddev);
>>>>
>>>> mddev->bitmap_ops = NULL;
>>>> }
>>>> @@ -6369,6 +6369,14 @@ struct mddev *md_alloc(dev_t dev, char *name)
>>>> return ERR_PTR(error);
>>>> }
>>>>
>>>> + /*
>>>> + * md_sysfs_remove_common_group is not needed because
>>>> mddev_delayed_delete
>>>> + * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
>>>> + */
>>>> + if (md_sysfs_create_common_group(mddev))
>>>> + pr_warn("md: cannot register common 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");
>
> --
> Thansk,
> Kuai
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
2026-03-15 8:56 ` Glass Su
@ 2026-03-15 18:12 ` Yu Kuai
0 siblings, 0 replies; 12+ messages in thread
From: Yu Kuai @ 2026-03-15 18:12 UTC (permalink / raw)
To: Glass Su, yukuai; +Cc: Su Yue, linux-raid, song, xni, linan122, Heming Zhao
Hi,
在 2026/3/15 16:56, Glass Su 写道:
>
>> On Mar 6, 2026, at 01:57, Yu Kuai <yukuai@fnnas.com> wrote:
>>
>> Hi,
>>
>> 在 2026/3/4 11:14, Su Yue 写道:
>>> On Wed 04 Mar 2026 at 10:30, "Yu Kuai" <yukuai@fnnas.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> 在 2026/3/3 11:37, Su Yue 写道:
>>>>> Before commit fb8cc3b0d9db ("md/md-bitmap: delay registration of
>>>>> bitmap_ops until creating bitmap")
>>>>> if CONFIG_MD_BITMAP is enabled, both bitmap none, internal and
>>>>> clustered have
>>>>> the sysfs file bitmap/location.
>>>>>
>>>>> After the commit, if bitmap is none, bitmap/location doesn't exist
>>>>> anymore.
>>>>> It breaks 'grow' behavior of a md array of madam with
>>>>> MD_FEATURE_BITMAP_OFFSET.
>>>>> Take level=mirror and metadata=1.2 as an example:
>>>>>
>>>>> $ mdadm --create /dev/md0 -f --bitmap=none --raid-devices=2
>>>>> --level=mirror \
>>>>> --metadata=1.2 /dev/vdd /dev/vde
>>>>> $ mdadm --grow /dev/md0 --bitmap=internal
>>>>> $ cat /sys/block/md0/md/bitmap/location
>>>>> Before:+8
>>>>> After: +2
>>>>>
>>>>> While growing bitmap from none to internal, clustered and llbitmap,
>>>>> mdadm/Grow.c:Grow_addbitmap() tries to detect bitmap/location first.
>>>>> 1)If bitmap/location exists, it sets bitmap/location after
>>>>> getinfo_super().
>>>>> 2)If bitmap/location doesn't exist, mdadm just calls
>>>>> md_set_array_info() then
>>>>> mddev->bitmap_info.default_offset will be used.
>>>>> Situation can be worse if growing none to clustered, bitmap offset
>>>>> of the node
>>>>> calling `madm --grow` will be changed but the other node are reading
>>>>> bitmap sb from
>>>>> the old location.
>>>> Now that we have a new sysfs attribute bitmap_type, can we fix this by:
>>>> - in the kernel, allow writing to this file in this case;
>>>> - in mdadm and the grow case above, write to this file first, and change
>>>> bitmap_type from none to bitmap(For llbitmap, there is still more
>>>> work to do).
>>>>
>>> Yes. It's indeed feasible. But how about old versions mdadm? We can't
>>> require
>>> users' madadm + kernel combinations for old feature. Kernel part
>>> should keep
>>> compatibility with userspace. sysfs changes and broken haviros are not
>>> ideal
>>> especially userspace depends on it unless there's a strong reason.
>>> That's why linux/Documentation/ABI exists.
>> Okay, I can accept keep this old behavior.
>>
>> However, instead of introducing a new common_group with the same name "bitmap",
>> I'll prefer to introducing a separate bitmap_ops for none bitmap as well, and
>> you can define the attrs that are necessary.
>>
> After a try, the thing I realized is that a common group is unavoidable for bitmap and none bitmap.
>
> mdadm writes to /sys/block/md0/md/bitmap/location, if remove_files() called by sysfs_remove_group()/
> sysfs_update_group() on same kernfs node, recursive locks will be triggered:
>
> [ 139.516750] ============================================
> [ 139.517363] WARNING: possible recursive locking detected
> [ 139.517953] 7.0.0-rc1-custom+ #282 Tainted: G OE
> [ 139.518628] --------------------------------------------
> [ 139.519233] mdadm/2346 is trying to acquire lock:
> [ 139.519836] ffff8e6b24d85000 (kn->active#116){++++}-{0:0}, at: __kernfs_remove+0xd1/0x3e0
> [ 139.520848]
> but task is already holding lock:
> [ 139.521561] ffff8e6b24d85000 (kn->active#116){++++}-{0:0}, at: kernfs_fop_write_iter+0x12d/0x250
> [ 139.522603]
> other info that might help us debug this:
> [ 139.523383] Possible unsafe locking scenario:
>
> [ 139.524169] CPU0
> [ 139.524430] ----
> [ 139.524682] lock(kn->active#116);
> [ 139.525047] lock(kn->active#116);
> [ 139.525398]
> *** DEADLOCK ***
>
> [ 139.525990] May be due to missing lock nesting notation
>
> [ 139.526658] 4 locks held by mdadm/2346:
> [ 139.527049] #0: ffff8e6acd5ec420 (sb_writers#5){.+.+}-{0:0}, at: ksys_write+0x6c/0xe0
> [ 139.527838] #1: ffff8e6acd54fa88 (&of->mutex){+.+.}-{4:4}, at: kernfs_fop_write_iter+0x118/0x250
> [ 139.528713] #2: ffff8e6b24d85000 (kn->active#116){++++}-{0:0}, at: kernfs_fop_write_iter+0x12d/0x250
> [ 139.529594] #3: ffff8e6b26b51370 (&mddev->reconfig_mutex){+.+.}-{4:4}, at: location_store+0x6c/0x360 [md_mod]
>
> [ 139.530535] dump_stack_lvl+0x68/0x90
> [ 139.530540] print_deadlock_bug.cold+0xc0/0xcd
> [ 139.530549] __lock_acquire+0x1324/0x2250
> [ 139.530556] lock_acquire+0xc6/0x2f0
> [ 139.530564] kernfs_drain+0x1eb/0x200
> [ 139.530568] __kernfs_remove+0xd1/0x3e0
> [ 139.530570] kernfs_remove_by_name_ns+0x5e/0xb0
> [ 139.530572] internal_create_group+0x221/0x4d0
> [ 139.530578] md_bitmap_create+0x122/0x130 [md_mod]
> [ 139.530586] location_store+0x1e9/0x360 [md_mod]
> [ 139.530594] md_attr_store+0xb8/0x1a0 [md_mod]
> [ 139.530602] kernfs_fop_write_iter+0x176/0x250
> [ 139.530605] vfs_write+0x21b/0x560
> [ 139.530609] ksys_write+0x6c/0xe0
> [ 139.530611] do_syscall_64+0x10f/0x5f0
> [ 139.530623] entry_SYSCALL_64_after_hwframe+0x76/0x7e
>
> The patch implemented by separated bitmap_ops is attached. This version looks pretty similar to the first
> version because of the reason listed above and IMO ungraceful. Dummy ops and functions are a little unnecessary.
>
> I would like to ask your opinion since you are the maintainer even though I prefer v1 version + (remove the location entry for llbitmap).
Hi, I don't think you'll need to remove and recreate sysfs entry here, looks like
this problem is introduced by patch 2?
1) split bitmap group into a common group that contain location attr; and a internal
bitmap group(the name is NULL), for example:
struct attribute_group *none_bitmap_group[] = {
&common_bitmap_group,
NULL
};
struct attribute_group *internal_bitmap_group[] = {
&common_bitmap_group,
&internal_bitmap_group,
NULL,
};
2) create none bitmap with common group only, and create internal bitmap with common group and
internal bitmap group; Notice we should convert to user sysfs_create_groups().
3) while growing from none to bitmap, create internal bitmap group attrs
4) while growing from bitmap to none, remove internal bitmap group attrs
> Thanks.
>
>
>
> —
> Su
>
>
>
>> For llbitmap, I think it's fine, we don't need this old sysfs attr anyway. I'll
>> support to convert from none/bitmap to llbitmap by writing the new bitmap_type
>> file.
>>
>>
>>> --
>>> Su
>>>
>>>>> Here restore sysfs file bitmap/location for ID_BITMAP_NONE and
>>>>> ID_BITMAP.
>>>>> And it d adds the entry for llbitmap too.
>>>>>
>>>>> New attribute_group md_bitmap_common_group is introduced and created in
>>>>> md_alloc() as before commit fb8cc3b0d9db.
>>>>> Add New operations register_group and unregister_group to struct
>>>>> bitmap_operations.
>>>>>
>>>>> Fixes: fb8cc3b0d9db ("md/md-bitmap: delay registration of bitmap_ops
>>>>> until creating bitmap")
>>>>> Signed-off-by: Su Yue <glass.su@suse.com>
>>>>> ---
>>>>> drivers/md/md-bitmap.c | 32 +++++++++++++++++++++++++++++++-
>>>>> drivers/md/md-bitmap.h | 5 +++++
>>>>> drivers/md/md-llbitmap.c | 13 +++++++++++++
>>>>> drivers/md/md.c | 16 ++++++++++++----
>>>>> 4 files changed, 61 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
>>>>> index 83378c033c72..8ff1dc94ed78 100644
>>>>> --- a/drivers/md/md-bitmap.c
>>>>> +++ b/drivers/md/md-bitmap.c
>>>>> @@ -2956,7 +2956,6 @@ __ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
>>>>> behind_writes_used_show, behind_writes_used_reset);
>>>>>
>>>>> static struct attribute *md_bitmap_attrs[] = {
>>>>> - &bitmap_location.attr,
>>>>> &bitmap_space.attr,
>>>>> &bitmap_timeout.attr,
>>>>> &bitmap_backlog.attr,
>>>>> @@ -2967,11 +2966,40 @@ static struct attribute *md_bitmap_attrs[] = {
>>>>> NULL
>>>>> };
>>>>>
>>>>> +static struct attribute *md_bitmap_common_attrs[] = {
>>>>> + &bitmap_location.attr,
>>>>> + NULL
>>>>> +};
>>>>> +
>>>>> static struct attribute_group md_bitmap_group = {
>>>>> .name = "bitmap",
>>>>> .attrs = md_bitmap_attrs,
>>>>> };
>>>>>
>>>>> +static struct attribute_group md_bitmap_common_group = {
>>>>> + .name = "bitmap",
>>>>> + .attrs = md_bitmap_common_attrs,
>>>>> +};
>>>>> +
>>>>> +int md_sysfs_create_common_group(struct mddev *mddev)
>>>>> +{
>>>>> + return sysfs_create_group(&mddev->kobj, &md_bitmap_common_group);
>>>>> +}
>>>>> +
>>>>> +static int bitmap_register_group(struct mddev *mddev)
>>>>> +{
>>>>> + /*
>>>>> + * md_bitmap_group and md_bitmap_common_group are using same name
>>>>> + * 'bitmap'.
>>>>> + */
>>>>> + return sysfs_merge_group(&mddev->kobj, &md_bitmap_group);
>>>>> +}
>>>>> +
>>>>> +static void bitmap_unregister_group(struct mddev *mddev)
>>>>> +{
>>>>> + sysfs_unmerge_group(&mddev->kobj, &md_bitmap_group);
>>>>> +}
>>>>> +
>>>>> static struct bitmap_operations bitmap_ops = {
>>>>> .head = {
>>>>> .type = MD_BITMAP,
>>>>> @@ -3013,6 +3041,8 @@ static struct bitmap_operations bitmap_ops = {
>>>>> .set_pages = bitmap_set_pages,
>>>>> .free = md_bitmap_free,
>>>>>
>>>>> + .register_group = bitmap_register_group,
>>>>> + .unregister_group = bitmap_unregister_group,
>>>>> .group = &md_bitmap_group,
>>>>> };
>>>>>
>>>>> diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
>>>>> index b42a28fa83a0..371791e9011d 100644
>>>>> --- a/drivers/md/md-bitmap.h
>>>>> +++ b/drivers/md/md-bitmap.h
>>>>> @@ -125,6 +125,9 @@ struct bitmap_operations {
>>>>> void (*set_pages)(void *data, unsigned long pages);
>>>>> void (*free)(void *data);
>>>>>
>>>>> + int (*register_group)(struct mddev *mddev);
>>>>> + void (*unregister_group)(struct mddev *mddev);
>>>>> +
>>>>> struct attribute_group *group;
>>>>> };
>>>>>
>>>>> @@ -169,6 +172,8 @@ static inline void md_bitmap_end_sync(struct
>>>>> mddev *mddev, sector_t offset,
>>>>> mddev->bitmap_ops->end_sync(mddev, offset, blocks);
>>>>> }
>>>>>
>>>>> +int md_sysfs_create_common_group(struct mddev *mddev);
>>>>> +
>>>>> #ifdef CONFIG_MD_BITMAP
>>>>> int md_bitmap_init(void);
>>>>> void md_bitmap_exit(void);
>>>>> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
>>>>> index bf398d7476b3..24ff5f7f8751 100644
>>>>> --- a/drivers/md/md-llbitmap.c
>>>>> +++ b/drivers/md/md-llbitmap.c
>>>>> @@ -1561,6 +1561,16 @@ static struct attribute_group
>>>>> md_llbitmap_group = {
>>>>> .attrs = md_llbitmap_attrs,
>>>>> };
>>>>>
>>>>> +static int llbitmap_register_group(struct mddev *mddev)
>>>>> +{
>>>>> + return sysfs_create_group(&mddev->kobj, &md_llbitmap_group);
>>>>> +}
>>>>> +
>>>>> +static void llbitmap_unregister_group(struct mddev *mddev)
>>>>> +{
>>>>> + sysfs_remove_group(&mddev->kobj, &md_llbitmap_group);
>>>>> +}
>>>>> +
>>>>> static struct bitmap_operations llbitmap_ops = {
>>>>> .head = {
>>>>> .type = MD_BITMAP,
>>>>> @@ -1597,6 +1607,9 @@ static struct bitmap_operations llbitmap_ops = {
>>>>> .dirty_bits = llbitmap_dirty_bits,
>>>>> .write_all = llbitmap_write_all,
>>>>>
>>>>> + .register_group = llbitmap_register_group,
>>>>> + .unregister_group = llbitmap_unregister_group,
>>>>> +
>>>>> .group = &md_llbitmap_group,
>>>>> };
>>>>>
>>>>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>>>>> index 3ce6f9e9d38e..ab969e950ea8 100644
>>>>> --- a/drivers/md/md.c
>>>>> +++ b/drivers/md/md.c
>>>>> @@ -703,8 +703,8 @@ 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))
>>>>> + if (!mddev_is_dm(mddev) && mddev->bitmap_ops->register_group) {
>>>>> + if (mddev->bitmap_ops->register_group(mddev))
>>>>> pr_warn("md: cannot register extra bitmap attributes
>>>>> for %s\n",
>>>>> mdname(mddev));
>>>>> else
>>>>> @@ -724,8 +724,8 @@ static bool mddev_set_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->unregister_group)
>>>>> + mddev->bitmap_ops->unregister_group(mddev);
>>>>>
>>>>> mddev->bitmap_ops = NULL;
>>>>> }
>>>>> @@ -6369,6 +6369,14 @@ struct mddev *md_alloc(dev_t dev, char *name)
>>>>> return ERR_PTR(error);
>>>>> }
>>>>>
>>>>> + /*
>>>>> + * md_sysfs_remove_common_group is not needed because
>>>>> mddev_delayed_delete
>>>>> + * calls kobject_put(&mddev->kobj) if mddev is to be deleted.
>>>>> + */
>>>>> + if (md_sysfs_create_common_group(mddev))
>>>>> + pr_warn("md: cannot register common 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");
>> --
>> Thansk,
>> Kuai
>
--
Thansk,
Kuai
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-03-15 18:12 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-03 3:37 [PATCH 0/3] md: bitmap grow fixes Su Yue
2026-03-03 3:37 ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing Su Yue
2026-03-04 2:30 ` Yu Kuai
2026-03-04 3:14 ` Su Yue
2026-03-05 17:57 ` Yu Kuai
2026-03-15 8:56 ` Glass Su
2026-03-15 18:12 ` Yu Kuai
2026-03-05 22:38 ` kernel test robot
2026-03-05 22:50 ` kernel test robot
2026-03-06 4:25 ` Glass Su
2026-03-03 3:37 ` [PATCH 2/3] md: call md_bitmap_create,destroy in location_store Su Yue
2026-03-03 3:37 ` [PATCH 3/3] md: remove member group from bitmap_operations Su Yue
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox