]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Support new raid6 layouts needed for DDF
authorNeilBrown <neilb@suse.de>
Mon, 9 Mar 2009 00:16:53 +0000 (11:16 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 9 Mar 2009 00:16:53 +0000 (11:16 +1100)
DDF raid6 layouts are subtly different from the standard 'md' layouts.
From 2.6.30 the kernel knows about these.
Teach mdadm about them, and also allow 'ddf' to set an appropriate default.

Signed-off-by: NeilBrown <neilb@suse.de>
ReadMe.c
mdadm.c
mdadm.h
super-ddf.c

index ea977d22763c54ce0e5d4be8d0cdfe38d30ad720..dd53c48f71381c6ccaaab23303a7af32bb5d4aa0 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -584,16 +584,49 @@ char Help_config[] =
 /* name/number mappings */
 
 mapping_t r5layout[] = {
-       { "left-asymmetric", 0},
-       { "right-asymmetric", 1},
-       { "left-symmetric", 2},
-       { "right-symmetric", 3},
-
-       { "default", 2},
-       { "la", 0},
-       { "ra", 1},
-       { "ls", 2},
-       { "rs", 3},
+       { "left-asymmetric", ALGORITHM_LEFT_ASYMMETRIC},
+       { "right-asymmetric", ALGORITHM_RIGHT_ASYMMETRIC},
+       { "left-symmetric", ALGORITHM_LEFT_SYMMETRIC},
+       { "right-symmetric", ALGORITHM_RIGHT_SYMMETRIC},
+
+       { "default", ALGORITHM_LEFT_SYMMETRIC},
+       { "la", ALGORITHM_LEFT_ASYMMETRIC},
+       { "ra", ALGORITHM_RIGHT_ASYMMETRIC},
+       { "ls", ALGORITHM_LEFT_SYMMETRIC},
+       { "rs", ALGORITHM_RIGHT_SYMMETRIC},
+
+       { "parity-first", ALGORITHM_PARITY_0},
+       { "parity-last", ALGORITHM_PARITY_N},
+       { "ddf-zero-restart", ALGORITHM_RIGHT_ASYMMETRIC},
+       { "ddf-N-restart", ALGORITHM_LEFT_ASYMMETRIC},
+       { "ddf-N-continue", ALGORITHM_LEFT_SYMMETRIC},
+
+       { NULL, 0}
+};
+mapping_t r6layout[] = {
+       { "left-asymmetric", ALGORITHM_LEFT_ASYMMETRIC},
+       { "right-asymmetric", ALGORITHM_RIGHT_ASYMMETRIC},
+       { "left-symmetric", ALGORITHM_LEFT_SYMMETRIC},
+       { "right-symmetric", ALGORITHM_RIGHT_SYMMETRIC},
+
+       { "default", ALGORITHM_LEFT_SYMMETRIC},
+       { "la", ALGORITHM_LEFT_ASYMMETRIC},
+       { "ra", ALGORITHM_RIGHT_ASYMMETRIC},
+       { "ls", ALGORITHM_LEFT_SYMMETRIC},
+       { "rs", ALGORITHM_RIGHT_SYMMETRIC},
+
+       { "parity-first", ALGORITHM_PARITY_0},
+       { "parity-last", ALGORITHM_PARITY_N},
+       { "ddf-zero-restart", ALGORITHM_ROTATING_ZERO_RESTART},
+       { "ddf-N-restart", ALGORITHM_ROTATING_N_RESTART},
+       { "ddf-N-continue", ALGORITHM_ROTATING_N_CONTINUE},
+
+       { "left-asymmetric-6", ALGORITHM_LEFT_ASYMMETRIC_6},
+       { "right-asymmetric-6", ALGORITHM_RIGHT_ASYMMETRIC_6},
+       { "left-symmetric-6", ALGORITHM_LEFT_SYMMETRIC_6},
+       { "right-symmetric-6", ALGORITHM_RIGHT_SYMMETRIC_6},
+       { "parity-first-6", ALGORITHM_PARITY_0_6},
+
        { NULL, 0}
 };
 
diff --git a/mdadm.c b/mdadm.c
index 72e7926f0ed8417d85355fa10b90e69f5d345d64..1fef4b998524cfac4382644624e19683be6cc389 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -437,7 +437,6 @@ int main(int argc, char *argv[])
                                exit(2);
 
                        case 5:
-                       case 6:
                                layout = map_name(r5layout, optarg);
                                if (layout==UnSet) {
                                        fprintf(stderr, Name ": layout %s not understood for raid5.\n",
@@ -445,6 +444,14 @@ int main(int argc, char *argv[])
                                        exit(2);
                                }
                                break;
+                       case 6:
+                               layout = map_name(r6layout, optarg);
+                               if (layout==UnSet) {
+                                       fprintf(stderr, Name ": layout %s not understood for raid6.\n",
+                                               optarg);
+                                       exit(2);
+                               }
+                               break;
 
                        case 10:
                                /* 'f', 'o' or 'n' followed by a number <= raid_disks */
diff --git a/mdadm.h b/mdadm.h
index f8f3685963ecc980967457213ee795b15a434709..f580e3e807388ead74966e25ffc20f0ff8577252 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -394,7 +394,7 @@ extern int restore_stripes(int *dest, unsigned long long *offsets,
 
 extern char *map_num(mapping_t *map, int num);
 extern int map_name(mapping_t *map, char *name);
-extern mapping_t r5layout[], pers[], modes[], faultylayout[];
+extern mapping_t r5layout[], r6layout[], pers[], modes[], faultylayout[];
 
 extern char *map_dev(int major, int minor, int create);
 
@@ -937,8 +937,44 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
 #define makedev(M,m) (((M)<<8) | (m))
 #endif
 
-/* for raid5 */
+/* for raid4/5/6 */
 #define ALGORITHM_LEFT_ASYMMETRIC      0
 #define ALGORITHM_RIGHT_ASYMMETRIC     1
 #define ALGORITHM_LEFT_SYMMETRIC       2
 #define ALGORITHM_RIGHT_SYMMETRIC      3
+
+/* Define non-rotating (raid4) algorithms.  These allow
+ * conversion of raid4 to raid5.
+ */
+#define ALGORITHM_PARITY_0             4 /* P or P,Q are initial devices */
+#define ALGORITHM_PARITY_N             5 /* P or P,Q are final devices. */
+
+/* DDF RAID6 layouts differ from md/raid6 layouts in two ways.
+ * Firstly, the exact positioning of the parity block is slightly
+ * different between the 'LEFT_*' modes of md and the "_N_*" modes
+ * of DDF.
+ * Secondly, or order of datablocks over which the Q syndrome is computed
+ * is different.
+ * Consequently we have different layouts for DDF/raid6 than md/raid6.
+ * These layouts are from the DDFv1.2 spec.
+ * Interestingly DDFv1.2-Errata-A does not specify N_CONTINUE but
+ * leaves RLQ=3 as 'Vendor Specific'
+ */
+
+#define ALGORITHM_ROTATING_ZERO_RESTART        8 /* DDF PRL=6 RLQ=1 */
+#define ALGORITHM_ROTATING_N_RESTART   9 /* DDF PRL=6 RLQ=2 */
+#define ALGORITHM_ROTATING_N_CONTINUE  10 /*DDF PRL=6 RLQ=3 */
+
+
+/* For every RAID5 algorithm we define a RAID6 algorithm
+ * with exactly the same layout for data and parity, and
+ * with the Q block always on the last device (N-1).
+ * This allows trivial conversion from RAID5 to RAID6
+ */
+#define ALGORITHM_LEFT_ASYMMETRIC_6    16
+#define ALGORITHM_RIGHT_ASYMMETRIC_6   17
+#define ALGORITHM_LEFT_SYMMETRIC_6     18
+#define ALGORITHM_RIGHT_SYMMETRIC_6    19
+#define ALGORITHM_PARITY_0_6           20
+#define ALGORITHM_PARITY_N_6           ALGORITHM_PARITY_N
+
index 6c75998e90703566b79b6d787d65276a6a24264b..b0218016e25a2c75efb5548fbd048b37e09b1494 100644 (file)
@@ -1759,20 +1759,25 @@ static int layout_to_rlq(int level, int layout, int raiddisks)
                }
                break;
        case 5:
-       case 6:
                switch(layout) {
                case ALGORITHM_LEFT_ASYMMETRIC:
                        return DDF_RAID5_N_RESTART;
                case ALGORITHM_RIGHT_ASYMMETRIC:
-                       if (level == 5)
-                               return DDF_RAID5_0_RESTART;
-                       else
-                               return DDF_RAID6_0_RESTART;
+                       return DDF_RAID5_0_RESTART;
                case ALGORITHM_LEFT_SYMMETRIC:
                        return DDF_RAID5_N_CONTINUE;
                case ALGORITHM_RIGHT_SYMMETRIC:
                        return -1; /* not mentioned in standard */
                }
+       case 6:
+               switch(layout) {
+               case ALGORITHM_ROTATING_N_RESTART:
+                       return DDF_RAID5_N_RESTART;
+               case ALGORITHM_ROTATING_ZERO_RESTART:
+                       return DDF_RAID6_0_RESTART;
+               case ALGORITHM_ROTATING_N_CONTINUE:
+                       return DDF_RAID5_N_CONTINUE;
+               }
        }
        return -1;
 }
@@ -1807,11 +1812,11 @@ static int rlq_to_layout(int rlq, int prl, int raiddisks)
        case DDF_RAID6:
                switch(rlq) {
                case DDF_RAID5_N_RESTART:
-                       return ALGORITHM_LEFT_ASYMMETRIC;
+                       return ALGORITHM_ROTATING_N_RESTART;
                case DDF_RAID6_0_RESTART:
-                       return ALGORITHM_RIGHT_ASYMMETRIC;
+                       return ALGORITHM_ROTATING_ZERO_RESTART;
                case DDF_RAID5_N_CONTINUE:
-                       return ALGORITHM_LEFT_SYMMETRIC;
+                       return ALGORITHM_ROTATING_N_CONTINUE;
                default:
                        return -1;
                }
@@ -3537,6 +3542,23 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
 }
 #endif /* MDASSEMBLE */
 
+static int ddf_level_to_layout(int level)
+{
+       switch(level) {
+       case 0:
+       case 1:
+               return 0;
+       case 5:
+               return ALGORITHM_LEFT_SYMMETRIC;
+       case 6:
+               return ALGORITHM_ROTATING_N_CONTINUE;
+       case 10:
+               return 0x102;
+       default:
+               return UnSet;
+       }
+}
+
 struct superswitch super_ddf = {
 #ifndef        MDASSEMBLE
        .examine_super  = examine_super_ddf,
@@ -3562,6 +3584,7 @@ struct superswitch super_ddf = {
        .free_super     = free_super_ddf,
        .match_metadata_desc = match_metadata_desc_ddf,
        .container_content = container_content_ddf,
+       .default_layout = ddf_level_to_layout,
 
        .external       = 1,