* [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
* 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-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
* 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
* [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
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