diff mbox series

[md-6.12,1/1] md: add new_level sysfs interface

Message ID 20240828021828.63447-1-xni@redhat.com (mailing list archive)
State Superseded
Headers show
Series [md-6.12,1/1] md: add new_level sysfs interface | expand

Checks

Context Check Description
mdraidci/vmtest-md-6_11-PR success PR summary
mdraidci/vmtest-md-6_11-VM_Test-0 success Logs for build-kernel

Commit Message

Xiao Ni Aug. 28, 2024, 2:18 a.m. UTC
This interface is used to updating new level during reshape progress.
Now it doesn't update new level during reshape. So it can't know the
new level when systemd service mdadm-grow-continue runs. And it can't
finally change to new level.

Signed-off-by: Xiao Ni <xni@redhat.com>
---
 drivers/md/md.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Comments

Paul Menzel Aug. 28, 2024, 5:19 a.m. UTC | #1
Dear Xiao,


Thank you for your patch.

Am 28.08.24 um 04:18 schrieb Xiao Ni:
> This interface is used to updating new level during reshape progress.

to update

> Now it doesn't update new level during reshape. So it can't know the
> new level when systemd service mdadm-grow-continue runs. And it can't
> finally change to new level.

How can this be tested?

> Signed-off-by: Xiao Ni <xni@redhat.com>
> ---
>   drivers/md/md.c | 29 +++++++++++++++++++++++++++++
>   1 file changed, 29 insertions(+)
> 
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index d3a837506a36..c639eca03df9 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -4141,6 +4141,34 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
>   static struct md_sysfs_entry md_level =
>   __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
>   
> +static ssize_t
> +new_level_show(struct mddev *mddev, char *page)
> +{
> +	return sprintf(page, "%d\n", mddev->new_level);
> +}
> +
> +static ssize_t
> +new_level_store(struct mddev *mddev, const char *buf, size_t len)
> +{
> +	unsigned int n;
> +	int err;
> +
> +	err = kstrtouint(buf, 10, &n);
> +	if (err < 0)
> +		return err;
> +	err = mddev_lock(mddev);
> +	if (err)
> +		return err;
> +
> +	mddev->new_level = n;
> +	md_update_sb(mddev, 1);
> +
> +	mddev_unlock(mddev);
> +	return err ?: len;

Can `err` be set? Why return `len` if it’s not modified?

> +}
> +static struct md_sysfs_entry md_new_level =
> +__ATTR(new_level, 0664, new_level_show, new_level_store);
> +
>   static ssize_t
>   layout_show(struct mddev *mddev, char *page)
>   {
> @@ -5666,6 +5694,7 @@ __ATTR(serialize_policy, S_IRUGO | S_IWUSR, serialize_policy_show,
>   
>   static struct attribute *md_default_attrs[] = {
>   	&md_level.attr,
> +	&md_new_level.attr,
>   	&md_layout.attr,
>   	&md_raid_disks.attr,
>   	&md_uuid.attr,


Kind regards,

Paul
Xiao Ni Aug. 28, 2024, 1:56 p.m. UTC | #2
On Wed, Aug 28, 2024 at 8:33 PM Paul Menzel <pmenzel@molgen.mpg.de> wrote:
>
> Dear Xiao,
>
>
> Thank you for your reply. Was it intentional, that you only replied to
> me off-list?

Hi Paul

I made a mistake. Thanks for reminding me.

>
> Am 28.08.24 um 10:44 schrieb Xiao Ni:
> > On Wed, Aug 28, 2024 at 1:19 PM Paul Menzel wrote:
>
> >> Am 28.08.24 um 04:18 schrieb Xiao Ni:
>
> […]
>
> >> How can this be tested?
> >
> > mdadm -CR /dev/md0 -l6 -n4 /dev/loop[0-3]
> > mdadm --wait /dev/md0
> > mdadm /dev/md0 --grow -l5 --backup=backup
> > cat /proc/mdstat
> > Personalities : [raid6] [raid5] [raid4] [raid0] [raid1] [raid10]
> > md0 : active raid6 loop3[3] loop2[2] loop1[1] loop0[0]
> >        98304 blocks super 1.2 level 6, 512k chunk, algorithm 18 [4/4] [UUUU]
> >
> > unused devices: <none>
> >
> > There is a tests directory in mdadm. The case 07changelevels have this
> > test. Now it can't run successfully. This patch is used to fix this.
>
> It’d be great if you mentioned this in the commit message. That this
> test fails, and now it works. Please also mention, if this was a
> regression. (I guess it is, as the test should have been passed, when it
> was added?)

Ok, I'll add them to the commit message. The test cases was created in
2009. So yes, it must be a regression, but it's hard to see what
changes cause the regression.

>
> >>> Signed-off-by: Xiao Ni <xni@redhat.com>
> >>> ---
> >>>    drivers/md/md.c | 29 +++++++++++++++++++++++++++++
> >>>    1 file changed, 29 insertions(+)
> >>>
> >>> diff --git a/drivers/md/md.c b/drivers/md/md.c
> >>> index d3a837506a36..c639eca03df9 100644
> >>> --- a/drivers/md/md.c
> >>> +++ b/drivers/md/md.c
> >>> @@ -4141,6 +4141,34 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
> >>>    static struct md_sysfs_entry md_level =
> >>>    __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
> >>>
> >>> +static ssize_t
> >>> +new_level_show(struct mddev *mddev, char *page)
> >>> +{
> >>> +     return sprintf(page, "%d\n", mddev->new_level);
> >>> +}
> >>> +
> >>> +static ssize_t
> >>> +new_level_store(struct mddev *mddev, const char *buf, size_t len)
> >>> +{
> >>> +     unsigned int n;
> >>> +     int err;
> >>> +
> >>> +     err = kstrtouint(buf, 10, &n);
> >>> +     if (err < 0)
> >>> +             return err;
> >>> +     err = mddev_lock(mddev);
> >>> +     if (err)
> >>> +             return err;
> >>> +
> >>> +     mddev->new_level = n;
> >>> +     md_update_sb(mddev, 1);
> >>> +
> >>> +     mddev_unlock(mddev);
> >>> +     return err ?: len;
> >>
> >> Can `err` be set? Why return `len` if it’s not modified?
> >
> > err is the return value from kstrtouint and mddev_lock. And len is the
> > input value of the buf length. If it can be set successfully, it
> > returns len. It's same with other sysfs functions. For example,
> > raid_disks_store, layout_store and so on.
>
> At least `layout_store` modifies `err` later on. In your new function,
> if there is an error the function returns, so there is no need to check it.

Ah I know what you mean. I'll fix this.
>
> Where is `len` used in your new function? It’s only in the function
> signature. A colleague also didn’t spot it.

Hmm, functions raid_disks_store, layout_store, chunk_size_sotre don't
use len too. So what's your suggestion here?

Best Regards
Xiao
>
>
> Kind regards,
>
> Paul
>
>
> >>> +}
> >>> +static struct md_sysfs_entry md_new_level =
> >>> +__ATTR(new_level, 0664, new_level_show, new_level_store);
> >>> +
> >>>    static ssize_t
> >>>    layout_show(struct mddev *mddev, char *page)
> >>>    {
> >>> @@ -5666,6 +5694,7 @@ __ATTR(serialize_policy, S_IRUGO | S_IWUSR, serialize_policy_show,
> >>>
> >>>    static struct attribute *md_default_attrs[] = {
> >>>        &md_level.attr,
> >>> +     &md_new_level.attr,
> >>>        &md_layout.attr,
> >>>        &md_raid_disks.attr,
> >>>        &md_uuid.attr,
>
Mariusz Tkaczyk Sept. 2, 2024, 10:13 a.m. UTC | #3
On Wed, 28 Aug 2024 10:18:28 +0800
Xiao Ni <xni@redhat.com> wrote:

> This interface is used to updating new level during reshape progress.
> Now it doesn't update new level during reshape. So it can't know the
> new level when systemd service mdadm-grow-continue runs. And it can't
> finally change to new level.
> 
> Signed-off-by: Xiao Ni <xni@redhat.com>
> ---
>  drivers/md/md.c | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index d3a837506a36..c639eca03df9 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -4141,6 +4141,34 @@ level_store(struct mddev *mddev, const char *buf,
> size_t len) static struct md_sysfs_entry md_level =
>  __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
>  
> +static ssize_t
> +new_level_show(struct mddev *mddev, char *page)
> +{
> +	return sprintf(page, "%d\n", mddev->new_level);
> +}
> +
> +static ssize_t
> +new_level_store(struct mddev *mddev, const char *buf, size_t len)
> +{
> +	unsigned int n;
> +	int err;
> +
> +	err = kstrtouint(buf, 10, &n);
> +	if (err < 0)
> +		return err;
> +	err = mddev_lock(mddev);
> +	if (err)
> +		return err;
> +
> +	mddev->new_level = n;
> +	md_update_sb(mddev, 1);

I don't see any code behind mddev->new_level handling so I suspect that
md_update_sb() does nothing in this case. Is there something I'm missing?

Thanks,
Mariusz

> +
> +	mddev_unlock(mddev);
> +	return err ?: len;
> +}
> +static struct md_sysfs_entry md_new_level =
> +__ATTR(new_level, 0664, new_level_show, new_level_store);
> +
>  static ssize_t
>  layout_show(struct mddev *mddev, char *page)
>  {
> @@ -5666,6 +5694,7 @@ __ATTR(serialize_policy, S_IRUGO | S_IWUSR,
> serialize_policy_show, 
>  static struct attribute *md_default_attrs[] = {
>  	&md_level.attr,
> +	&md_new_level.attr,
>  	&md_layout.attr,
>  	&md_raid_disks.attr,
>  	&md_uuid.attr,
Xiao Ni Sept. 3, 2024, 12:18 a.m. UTC | #4
On Mon, Sep 2, 2024 at 6:14 PM Mariusz Tkaczyk
<mariusz.tkaczyk@linux.intel.com> wrote:
>
> On Wed, 28 Aug 2024 10:18:28 +0800
> Xiao Ni <xni@redhat.com> wrote:
>
> > This interface is used to updating new level during reshape progress.
> > Now it doesn't update new level during reshape. So it can't know the
> > new level when systemd service mdadm-grow-continue runs. And it can't
> > finally change to new level.
> >
> > Signed-off-by: Xiao Ni <xni@redhat.com>
> > ---
> >  drivers/md/md.c | 29 +++++++++++++++++++++++++++++
> >  1 file changed, 29 insertions(+)
> >
> > diff --git a/drivers/md/md.c b/drivers/md/md.c
> > index d3a837506a36..c639eca03df9 100644
> > --- a/drivers/md/md.c
> > +++ b/drivers/md/md.c
> > @@ -4141,6 +4141,34 @@ level_store(struct mddev *mddev, const char *buf,
> > size_t len) static struct md_sysfs_entry md_level =
> >  __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
> >
> > +static ssize_t
> > +new_level_show(struct mddev *mddev, char *page)
> > +{
> > +     return sprintf(page, "%d\n", mddev->new_level);
> > +}
> > +
> > +static ssize_t
> > +new_level_store(struct mddev *mddev, const char *buf, size_t len)
> > +{
> > +     unsigned int n;
> > +     int err;
> > +
> > +     err = kstrtouint(buf, 10, &n);
> > +     if (err < 0)
> > +             return err;
> > +     err = mddev_lock(mddev);
> > +     if (err)
> > +             return err;
> > +
> > +     mddev->new_level = n;
> > +     md_update_sb(mddev, 1);
>
> I don't see any code behind mddev->new_level handling so I suspect that
> md_update_sb() does nothing in this case. Is there something I'm missing?

You mean the calling path md_update_sb->sync_sbs->super_1_sync?

Best Regards
Xiao
>
> Thanks,
> Mariusz
>
> > +
> > +     mddev_unlock(mddev);
> > +     return err ?: len;
> > +}
> > +static struct md_sysfs_entry md_new_level =
> > +__ATTR(new_level, 0664, new_level_show, new_level_store);
> > +
> >  static ssize_t
> >  layout_show(struct mddev *mddev, char *page)
> >  {
> > @@ -5666,6 +5694,7 @@ __ATTR(serialize_policy, S_IRUGO | S_IWUSR,
> > serialize_policy_show,
> >  static struct attribute *md_default_attrs[] = {
> >       &md_level.attr,
> > +     &md_new_level.attr,
> >       &md_layout.attr,
> >       &md_raid_disks.attr,
> >       &md_uuid.attr,
>
>
Mariusz Tkaczyk Sept. 3, 2024, 7:17 a.m. UTC | #5
On Tue, 3 Sep 2024 08:18:19 +0800
Xiao Ni <xni@redhat.com> wrote:

> On Mon, Sep 2, 2024 at 6:14 PM Mariusz Tkaczyk
> <mariusz.tkaczyk@linux.intel.com> wrote:
> >
> > On Wed, 28 Aug 2024 10:18:28 +0800
> > Xiao Ni <xni@redhat.com> wrote:
> >  
> > > This interface is used to updating new level during reshape progress.
> > > Now it doesn't update new level during reshape. So it can't know the
> > > new level when systemd service mdadm-grow-continue runs. And it can't
> > > finally change to new level.
> > >
> > > Signed-off-by: Xiao Ni <xni@redhat.com>
> > > ---
> > >  drivers/md/md.c | 29 +++++++++++++++++++++++++++++
> > >  1 file changed, 29 insertions(+)
> > >
> > > diff --git a/drivers/md/md.c b/drivers/md/md.c
> > > index d3a837506a36..c639eca03df9 100644
> > > --- a/drivers/md/md.c
> > > +++ b/drivers/md/md.c
> > > @@ -4141,6 +4141,34 @@ level_store(struct mddev *mddev, const char *buf,
> > > size_t len) static struct md_sysfs_entry md_level =
> > >  __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
> > >
> > > +static ssize_t
> > > +new_level_show(struct mddev *mddev, char *page)
> > > +{
> > > +     return sprintf(page, "%d\n", mddev->new_level);
> > > +}
> > > +
> > > +static ssize_t
> > > +new_level_store(struct mddev *mddev, const char *buf, size_t len)
> > > +{
> > > +     unsigned int n;
> > > +     int err;
> > > +
> > > +     err = kstrtouint(buf, 10, &n);
> > > +     if (err < 0)
> > > +             return err;
> > > +     err = mddev_lock(mddev);
> > > +     if (err)
> > > +             return err;
> > > +
> > > +     mddev->new_level = n;
> > > +     md_update_sb(mddev, 1);  
> >
> > I don't see any code behind mddev->new_level handling so I suspect that
> > md_update_sb() does nothing in this case. Is there something I'm missing?  
> 
> You mean the calling path md_update_sb->sync_sbs->super_1_sync?
> 

No, I missed that mddev->new_level is a exiting property and it is already
implemented in kernel. Now, I understand that it is super0 metadata property
and you just presented it. This is fine.

What I can see is that calling md_update_super() in case of
external might be unnecessary but it is fine anyway I think.

maybe: if (!mddev->external)
               md_update_sb(mddev, 1);

but I don't see it used in the code anywhere. metadata update path is
still black box to me. Maybe Kuai can comment?

Thanks,
Mariusz
diff mbox series

Patch

diff --git a/drivers/md/md.c b/drivers/md/md.c
index d3a837506a36..c639eca03df9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4141,6 +4141,34 @@  level_store(struct mddev *mddev, const char *buf, size_t len)
 static struct md_sysfs_entry md_level =
 __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store);
 
+static ssize_t
+new_level_show(struct mddev *mddev, char *page)
+{
+	return sprintf(page, "%d\n", mddev->new_level);
+}
+
+static ssize_t
+new_level_store(struct mddev *mddev, const char *buf, size_t len)
+{
+	unsigned int n;
+	int err;
+
+	err = kstrtouint(buf, 10, &n);
+	if (err < 0)
+		return err;
+	err = mddev_lock(mddev);
+	if (err)
+		return err;
+
+	mddev->new_level = n;
+	md_update_sb(mddev, 1);
+
+	mddev_unlock(mddev);
+	return err ?: len;
+}
+static struct md_sysfs_entry md_new_level =
+__ATTR(new_level, 0664, new_level_show, new_level_store);
+
 static ssize_t
 layout_show(struct mddev *mddev, char *page)
 {
@@ -5666,6 +5694,7 @@  __ATTR(serialize_policy, S_IRUGO | S_IWUSR, serialize_policy_show,
 
 static struct attribute *md_default_attrs[] = {
 	&md_level.attr,
+	&md_new_level.attr,
 	&md_layout.attr,
 	&md_raid_disks.attr,
 	&md_uuid.attr,