2024-02-01 06:58:07

by Li Nan

[permalink] [raw]
Subject: [PATCH v5 0/8] bugfix of MD_CLOSING and clean up md_ioctl()

From: Li Nan <[email protected]>

Changes in v5:
- add patches 1-4 to clean up md_ioct(), pathc 4 can help us clean up
local variable 'clear_md_closing'.
- in patches 5 and 7, clean up local variable 'clear_md_closing'.

By the way, md_ioctl() is not readable now, I wanna to re-write it later
to make it only have one 'switch' like other drivers.

Li Nan (8):
md: merge the check of capabilities into md_ioctl_valid()
md: changed the switch of RAID_VERSION to if
md: clean up invalid BUG_ON in md_ioctl
md: return directly before setting did_set_md_closing
md: Don't clear MD_CLOSING when the raid is about to stop
md: factor out a helper to sync mddev
md: sync blockdev before stopping raid or setting readonly
md: check mddev->pers before calling md_set_readonly()

drivers/md/md.c | 149 ++++++++++++++++++++++++++----------------------
1 file changed, 80 insertions(+), 69 deletions(-)

--
2.39.2



2024-02-01 07:02:34

by Li Nan

[permalink] [raw]
Subject: [PATCH v5 1/8] md: merge the check of capabilities into md_ioctl_valid()

From: Li Nan <[email protected]>

There is no functional change. Just to make code cleaner.

Signed-off-by: Li Nan <[email protected]>
---
drivers/md/md.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index e351e6c51cc7..1b509fb82040 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7545,16 +7545,17 @@ static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}

-static inline bool md_ioctl_valid(unsigned int cmd)
+static inline int md_ioctl_valid(unsigned int cmd)
{
switch (cmd) {
- case ADD_NEW_DISK:
case GET_ARRAY_INFO:
- case GET_BITMAP_FILE:
case GET_DISK_INFO:
+ case RAID_VERSION:
+ return 0;
+ case ADD_NEW_DISK:
+ case GET_BITMAP_FILE:
case HOT_ADD_DISK:
case HOT_REMOVE_DISK:
- case RAID_VERSION:
case RESTART_ARRAY_RW:
case RUN_ARRAY:
case SET_ARRAY_INFO:
@@ -7563,9 +7564,11 @@ static inline bool md_ioctl_valid(unsigned int cmd)
case STOP_ARRAY:
case STOP_ARRAY_RO:
case CLUSTERED_DISK_NACK:
- return true;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return 0;
default:
- return false;
+ return -ENOTTY;
}
}

@@ -7625,18 +7628,9 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
struct mddev *mddev = NULL;
bool did_set_md_closing = false;

- if (!md_ioctl_valid(cmd))
- return -ENOTTY;
-
- switch (cmd) {
- case RAID_VERSION:
- case GET_ARRAY_INFO:
- case GET_DISK_INFO:
- break;
- default:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- }
+ err = md_ioctl_valid(cmd);
+ if (err)
+ return err;

/*
* Commands dealing with the RAID driver but not any
--
2.39.2


2024-02-01 07:03:57

by Li Nan

[permalink] [raw]
Subject: [PATCH v5 5/8] md: Don't clear MD_CLOSING when the raid is about to stop

From: Li Nan <[email protected]>

The raid should not be opened anymore when it is about to be stopped.
However, other processes can open it again if the flag MD_CLOSING is
cleared before exiting. From now on, this flag will not be cleared when
the raid will be stopped.

Fixes: 065e519e71b2 ("md: MD_CLOSING needs to be cleared after called md_set_readonly or do_md_stop")
Signed-off-by: Li Nan <[email protected]>
---
drivers/md/md.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5442e8e3c161..deee004b8f22 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6247,7 +6247,15 @@ static void md_clean(struct mddev *mddev)
mddev->persistent = 0;
mddev->level = LEVEL_NONE;
mddev->clevel[0] = 0;
- mddev->flags = 0;
+ /*
+ * Don't clear MD_CLOSING, or mddev can be opened again.
+ * 'hold_active != 0' means mddev is still in the creation
+ * process and will be used later.
+ */
+ if (mddev->hold_active)
+ mddev->flags = 0;
+ else
+ mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
mddev->sb_flags = 0;
mddev->ro = MD_RDWR;
mddev->metadata_type[0] = 0;
@@ -7626,7 +7634,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
int err = 0;
void __user *argp = (void __user *)arg;
struct mddev *mddev = NULL;
- bool did_set_md_closing = false;

err = md_ioctl_valid(cmd);
if (err)
@@ -7687,7 +7694,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
mutex_unlock(&mddev->open_mutex);
return -EBUSY;
}
- did_set_md_closing = true;
mutex_unlock(&mddev->open_mutex);
sync_blockdev(bdev);
}
@@ -7829,7 +7835,7 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
mddev_unlock(mddev);

out:
- if(did_set_md_closing)
+ if (cmd == STOP_ARRAY_RO || (err && cmd == STOP_ARRAY))
clear_bit(MD_CLOSING, &mddev->flags);
return err;
}
--
2.39.2


2024-02-02 01:17:37

by Yu Kuai

[permalink] [raw]
Subject: Re: [PATCH v5 1/8] md: merge the check of capabilities into md_ioctl_valid()

?? 2024/02/01 14:33, [email protected] д??:
> From: Li Nan <[email protected]>
>
> There is no functional change. Just to make code cleaner.
>
> Signed-off-by: Li Nan <[email protected]>

LGTM
Reviewed-by: Yu Kuai <[email protected]>

> ---
> drivers/md/md.c | 30 ++++++++++++------------------
> 1 file changed, 12 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index e351e6c51cc7..1b509fb82040 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -7545,16 +7545,17 @@ static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
> return 0;
> }
>
> -static inline bool md_ioctl_valid(unsigned int cmd)
> +static inline int md_ioctl_valid(unsigned int cmd)
> {
> switch (cmd) {
> - case ADD_NEW_DISK:
> case GET_ARRAY_INFO:
> - case GET_BITMAP_FILE:
> case GET_DISK_INFO:
> + case RAID_VERSION:
> + return 0;
> + case ADD_NEW_DISK:
> + case GET_BITMAP_FILE:
> case HOT_ADD_DISK:
> case HOT_REMOVE_DISK:
> - case RAID_VERSION:
> case RESTART_ARRAY_RW:
> case RUN_ARRAY:
> case SET_ARRAY_INFO:
> @@ -7563,9 +7564,11 @@ static inline bool md_ioctl_valid(unsigned int cmd)
> case STOP_ARRAY:
> case STOP_ARRAY_RO:
> case CLUSTERED_DISK_NACK:
> - return true;
> + if (!capable(CAP_SYS_ADMIN))
> + return -EACCES;
> + return 0;
> default:
> - return false;
> + return -ENOTTY;
> }
> }
>
> @@ -7625,18 +7628,9 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
> struct mddev *mddev = NULL;
> bool did_set_md_closing = false;
>
> - if (!md_ioctl_valid(cmd))
> - return -ENOTTY;
> -
> - switch (cmd) {
> - case RAID_VERSION:
> - case GET_ARRAY_INFO:
> - case GET_DISK_INFO:
> - break;
> - default:
> - if (!capable(CAP_SYS_ADMIN))
> - return -EACCES;
> - }
> + err = md_ioctl_valid(cmd);
> + if (err)
> + return err;
>
> /*
> * Commands dealing with the RAID driver but not any
>


2024-02-02 01:26:48

by Yu Kuai

[permalink] [raw]
Subject: Re: [PATCH v5 5/8] md: Don't clear MD_CLOSING when the raid is about to stop

?? 2024/02/01 14:34, [email protected] д??:
> From: Li Nan <[email protected]>
>
> The raid should not be opened anymore when it is about to be stopped.
> However, other processes can open it again if the flag MD_CLOSING is
> cleared before exiting. From now on, this flag will not be cleared when
> the raid will be stopped.
>
> Fixes: 065e519e71b2 ("md: MD_CLOSING needs to be cleared after called md_set_readonly or do_md_stop")
> Signed-off-by: Li Nan <[email protected]>

LGTM
Reviewed-by: Yu Kuai <[email protected]>

> ---
> drivers/md/md.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index 5442e8e3c161..deee004b8f22 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -6247,7 +6247,15 @@ static void md_clean(struct mddev *mddev)
> mddev->persistent = 0;
> mddev->level = LEVEL_NONE;
> mddev->clevel[0] = 0;
> - mddev->flags = 0;
> + /*
> + * Don't clear MD_CLOSING, or mddev can be opened again.
> + * 'hold_active != 0' means mddev is still in the creation
> + * process and will be used later.
> + */
> + if (mddev->hold_active)
> + mddev->flags = 0;
> + else
> + mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
> mddev->sb_flags = 0;
> mddev->ro = MD_RDWR;
> mddev->metadata_type[0] = 0;
> @@ -7626,7 +7634,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
> int err = 0;
> void __user *argp = (void __user *)arg;
> struct mddev *mddev = NULL;
> - bool did_set_md_closing = false;
>
> err = md_ioctl_valid(cmd);
> if (err)
> @@ -7687,7 +7694,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
> mutex_unlock(&mddev->open_mutex);
> return -EBUSY;
> }
> - did_set_md_closing = true;
> mutex_unlock(&mddev->open_mutex);
> sync_blockdev(bdev);
> }
> @@ -7829,7 +7835,7 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
> mddev_unlock(mddev);
>
> out:
> - if(did_set_md_closing)
> + if (cmd == STOP_ARRAY_RO || (err && cmd == STOP_ARRAY))
> clear_bit(MD_CLOSING, &mddev->flags);
> return err;
> }
>