public inbox for linux-raid@vger.kernel.org
 help / color / mirror / Atom feed
From: Su Yue <glass.su@suse.com>
To: linux-raid@vger.kernel.org
Cc: song@kernel.org, xni@redhat.com, linan122@huawei.com,
	yukuai@fnnas.com, heming.zhao@suse.com, l@damenly.org,
	Su Yue <glass.su@suse.com>
Subject: [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing
Date: Tue,  3 Mar 2026 11:37:29 +0800	[thread overview]
Message-ID: <20260303033731.83885-2-glass.su@suse.com> (raw)
In-Reply-To: <20260303033731.83885-1-glass.su@suse.com>

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


  reply	other threads:[~2026-03-03  3:37 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-03  3:37 [PATCH 0/3] md: bitmap grow fixes Su Yue
2026-03-03  3:37 ` Su Yue [this message]
2026-03-04  2:30   ` [PATCH 1/3] md: restore bitmap/location to fix wrong bitmap offset while growing 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260303033731.83885-2-glass.su@suse.com \
    --to=glass.su@suse.com \
    --cc=heming.zhao@suse.com \
    --cc=l@damenly.org \
    --cc=linan122@huawei.com \
    --cc=linux-raid@vger.kernel.org \
    --cc=song@kernel.org \
    --cc=xni@redhat.com \
    --cc=yukuai@fnnas.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox