summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-09 11:16:53 +1100
committerNeilBrown <neilb@suse.de>2009-03-09 11:16:53 +1100
commitb640a252ee4d0c7be9ab31d9300aec00571b6238 (patch)
tree12ca36b06babede8272f5e4eeab26e74e974e0dc
parente8e1c176d86433b6d5ebab246257e6f506402fa4 (diff)
downloadmdadm-b640a252ee4d0c7be9ab31d9300aec00571b6238.tar.gz
mdadm-b640a252ee4d0c7be9ab31d9300aec00571b6238.tar.xz
mdadm-b640a252ee4d0c7be9ab31d9300aec00571b6238.zip
Support new raid6 layouts needed for DDF
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>
-rw-r--r--ReadMe.c53
-rw-r--r--mdadm.c9
-rw-r--r--mdadm.h40
-rw-r--r--super-ddf.c39
4 files changed, 120 insertions, 21 deletions
diff --git a/ReadMe.c b/ReadMe.c
index ea977d2..dd53c48 100644
--- 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 72e7926..1fef4b9 100644
--- 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 f8f3685..f580e3e 100644
--- 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
+
diff --git a/super-ddf.c b/super-ddf.c
index 6c75998..b021801 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -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,