]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdadm: block update=ppl for non raid456 levels
authorLukasz Florczak <lukasz.florczak@linux.intel.com>
Wed, 15 Jun 2022 12:28:39 +0000 (14:28 +0200)
committerJes Sorensen <jsorensen@fb.com>
Fri, 24 Jun 2022 18:09:38 +0000 (14:09 -0400)
Option ppl should be used only for raid levels 4, 5 and 6. Cancel update
for other levels.

Applied globally for imsm and ddf format.

Additionally introduce is_level456() helper function.

Signed-off-by: Lukasz Florczak <lukasz.florczak@linux.intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
Assemble.c
Grow.c
Manage.c
mdadm.h
super0.c
super1.c

index 4b213560cd2b1ba72a999cbcbf92d78cadfcbb33..6df6bfbcfa3e23ba58fba3fe2128345f18398783 100644 (file)
@@ -906,8 +906,7 @@ static int force_array(struct mdinfo *content,
                                 * devices in RAID4 or last devices in RAID4/5/6.
                                 */
                                delta = devices[j].i.delta_disks;
-                               if (devices[j].i.array.level >= 4 &&
-                                   devices[j].i.array.level <= 6 &&
+                               if (is_level456(devices[j].i.array.level) &&
                                    i/2 >= content->array.raid_disks - delta)
                                        /* OK */;
                                else if (devices[j].i.array.level == 4 &&
@@ -1226,8 +1225,7 @@ static int start_array(int mdfd,
                                fprintf(stderr, ".\n");
                        }
                        if (content->reshape_active &&
-                           content->array.level >= 4 &&
-                           content->array.level <= 6) {
+                           is_level456(content->array.level)) {
                                /* might need to increase the size
                                 * of the stripe cache - default is 256
                                 */
@@ -1974,7 +1972,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
        int start_reshape;
        char *avail;
        int err;
-       int is_raid456, is_clean, all_disks;
+       int is_clean, all_disks;
+       bool is_raid456;
 
        if (sysfs_init(content, mdfd, NULL)) {
                pr_err("Unable to initialize sysfs\n");
@@ -2107,7 +2106,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
                content->array.state |= 1;
        }
 
-       is_raid456 = (content->array.level >= 4 && content->array.level <= 6);
+       is_raid456 = is_level456(content->array.level);
        is_clean = content->array.state & 1;
 
        if (enough(content->array.level, content->array.raid_disks,
diff --git a/Grow.c b/Grow.c
index f6efbc48dafd53c149c2664d5808e356f3bf6b62..8c520d428ed24a6d3b46fa645dd2f7771445ddc7 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -2944,7 +2944,7 @@ static int impose_level(int fd, int level, char *devname, int verbose)
        }
 
        md_get_array_info(fd, &array);
-       if (level == 0 && (array.level >= 4 && array.level <= 6)) {
+       if (level == 0 && is_level456(array.level)) {
                /* To convert to RAID0 we need to fail and
                 * remove any non-data devices. */
                int found = 0;
index f789e0c176e5797fdac9c20d3a45def95ced07b8..e5e6abe4d0adabc80d3fcaf3c3a11930578e27d7 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -307,7 +307,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
         *  - unfreeze reshape
         *  - wait on 'sync_completed' for that point to be reached.
         */
-       if (mdi && (mdi->array.level >= 4 && mdi->array.level <= 6) &&
+       if (mdi && is_level456(mdi->array.level) &&
            sysfs_attribute_available(mdi, NULL, "sync_action") &&
            sysfs_attribute_available(mdi, NULL, "reshape_direction") &&
            sysfs_get_str(mdi, NULL, "sync_action", buf, 20) > 0 &&
@@ -1679,6 +1679,7 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
 {
        struct supertype supertype, *st = &supertype;
        int fd, rv = 2;
+       struct mdinfo *info = NULL;
 
        memset(st, 0, sizeof(*st));
 
@@ -1696,6 +1697,13 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
        if (mdmon_running(st->devnm))
                st->update_tail = &st->updates;
 
+       info = st->ss->container_content(st, subarray);
+
+       if (strncmp(update, "ppl", 3) == 0 && !is_level456(info->array.level)) {
+               pr_err("RWH policy ppl is supported only for raid4, raid5 and raid6.\n");
+               goto free_super;
+       }
+
        rv = st->ss->update_subarray(st, subarray, update, ident);
 
        if (rv) {
@@ -1711,7 +1719,9 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
                pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
                       subarray, dev);
 
- free_super:
+free_super:
+       if (info)
+               free(info);
        st->ss->free_super(st);
        close(fd);
 
diff --git a/mdadm.h b/mdadm.h
index d53df1697f889e878b59e5966e2a48c7bf803331..974415b9e663a1ced039f1986ed54491777968ff 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -796,6 +796,17 @@ static inline int is_fd_valid(int fd)
        return (fd > -1);
 }
 
+/**
+ * is_level456() - check whether given level is between inclusive 4 and 6.
+ * @level: level to check.
+ *
+ * Return: true if condition is met, false otherwise
+ */
+static inline bool is_level456(int level)
+{
+       return (level >= 4 && level <= 6);
+}
+
 /**
  * close_fd() - verify, close and unset file descriptor.
  * @fd: pointer to file descriptor.
index 61c9ec1dcc4ccfb8900cf83de62d45ad957ad2e9..37f595ed9e6027881a7738d5d95bc4a8e2499290 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -683,7 +683,7 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
                        int parity = sb->level == 6 ? 2 : 1;
                        rv = 0;
 
-                       if (sb->level >= 4 && sb->level <= 6 &&
+                       if (is_level456(sb->level) &&
                            sb->reshape_position % (
                                    sb->new_chunk/512 *
                                    (sb->raid_disks - sb->delta_disks - parity))) {
index 3a0c69fdedba74f63d79ef553d181f996dbcc28d..71af860c0e3ec9d4a5e2ea6ca1c4ad1a4c44c453 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1530,8 +1530,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                         * So we reject a revert-reshape unless the
                         * alignment is good.
                         */
-                       if (__le32_to_cpu(sb->level) >= 4 &&
-                           __le32_to_cpu(sb->level) <= 6) {
+                       if (is_level456(__le32_to_cpu(sb->level))) {
                                reshape_sectors =
                                        __le64_to_cpu(sb->reshape_position);
                                reshape_chunk = __le32_to_cpu(sb->new_chunk);