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>
This commit is contained in:
NeilBrown 2009-03-09 11:16:53 +11:00
parent e8e1c176d8
commit b640a252ee
4 changed files with 119 additions and 20 deletions

View File

@ -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},
{ "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},
{ "default", 2},
{ "la", 0},
{ "ra", 1},
{ "ls", 2},
{ "rs", 3},
{ NULL, 0}
};

View File

@ -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 */

40
mdadm.h
View File

@ -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

View 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,