From b578481ca382959da894ebdd91c5e5f45d50374d Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 15 May 2006 02:46:54 +0000 Subject: [PATCH] Support new offset layout for raid10 Requires 2.6.18. Signed-off-by: Neil Brown --- ChangeLog | 1 + Detail.c | 8 +++++--- md.4 | 10 +++++++++- mdadm.8 | 14 +++++++++++--- mdadm.c | 8 +++++--- super0.c | 12 ++++++++---- super1.c | 9 ++++++--- 7 files changed, 45 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 28e6240f..8e1d951c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ Changes Prior to this release - Arrange that SparesMissing (which is similar in import to DegradedArray) generates an Email. - Assume "DEVICE partitions" if no DEVICE line is given. + - Support new 'offset' layout for raid10. Changes Prior to 2.4.1 release - Honour --write-mostly when adding to an array without persistent diff --git a/Detail.c b/Detail.c index 8fa044a5..882ec078 100644 --- a/Detail.c +++ b/Detail.c @@ -205,8 +205,9 @@ int Detail(char *dev, int brief, int test) printf(" Layout : %s\n", c?c:"-unknown-"); } if (array.level == 10) { - printf(" Layout : near=%d, far=%d\n", - array.layout&255, (array.layout>>8)&255); + printf(" Layout : near=%d, %s=%d\n", + array.layout&255, (array.layout&0x10000)?"offset":"far", + (array.layout>>8)&255); } switch (array.level) { case 0: @@ -254,8 +255,9 @@ This is pretty boring c?c:"-unknown-"); } if (info.new_level == 10) { - printf(" New Layout : near=%d, far=%d\n", + printf(" New Layout : near=%d, %s=%d\n", info.new_layout&255, + (info.new_layout&0x10000)?"offset":"far", (info.new_layout>>8)&255); } } diff --git a/md.4 b/md.4 index d76dd8c1..d22ded42 100644 --- a/md.4 +++ b/md.4 @@ -203,7 +203,8 @@ drives. When configuring a RAID10 array it is necessary to specify the number of replicas of each data block that are required (this will normally -be 2) and whether the replicas should be 'near' or 'far'. +be 2) and whether the replicas should be 'near', 'offset' or 'far'. +(Note that the 'offset' layout is only available from 2.6.18). When 'near' replicas are chosen, the multiple copies of a given chunk are laid out consecutively across the stripes of the array, so the two @@ -220,6 +221,13 @@ of any given block are on different drives. The 'far' arrangement can give sequential read performance equal to that of a RAID0 array, but at the cost of degraded write performance. +When 'offset' replicas are chosen, the multiple copies of a given +chunk are laid out on consecutive drives and at consecutive offsets. +Effectively each stripe is duplicated and the copies are offset by one +device. This should give similar read characteristics to 'far' if a +suitably large chunk size is used, but without as much seeking for +writes. + It should be noted that the number of devices in a RAID10 array need not be a multiple of the number of replica of each data block, those there must be at least as many devices as replicas. diff --git a/mdadm.8 b/mdadm.8 index e3052dcd..4ec2f76a 100644 --- a/mdadm.8 +++ b/mdadm.8 @@ -398,12 +398,20 @@ and "flush" will clear any persistent faults. To set the parity with "--grow", the level of the array ("faulty") must be specified before the fault mode is specified. -Finally, the layout options for RAID10 are either 'n' or 'p' followed +Finally, the layout options for RAID10 are one of 'n', 'o' or 'p' followed by a small number. The default is 'n2'. .I n -signals 'near' copies (multiple copies of one data block are at -similar offsets in different devices) while +signals 'near' copies. Multiple copies of one data block are at +similar offsets in different devices. + +.I o +signals 'offset' copies. Rather than the chunks being duplicated +within a stripe, whole stripes are duplicated but are rotated by one +device so duplicate blocks are on different devices. Thus subsequent +copies of a block are in the next drive, and are one chunk further +down. + .I f signals 'far' copies (multiple copies have very different offsets). See md(4) for more diff --git a/mdadm.c b/mdadm.c index 05784e1d..f3104747 100644 --- a/mdadm.c +++ b/mdadm.c @@ -403,16 +403,18 @@ int main(int argc, char *argv[]) break; case 10: - /* 'f' or 'n' followed by a number <= raid_disks */ - if ((optarg[0] != 'n' && optarg[0] != 'f') || + /* 'f', 'o' or 'n' followed by a number <= raid_disks */ + if ((optarg[0] != 'n' && optarg[0] != 'f' && optarg[0] != 'o') || (copies = strtoul(optarg+1, &cp, 10)) < 1 || copies > 200 || *cp) { - fprintf(stderr, Name ": layout for raid10 must be 'nNN' or 'fNN' where NN is a number, not %s\n", optarg); + fprintf(stderr, Name ": layout for raid10 must be 'nNN', 'oNN' or 'fNN' where NN is a number, not %s\n", optarg); exit(2); } if (optarg[0] == 'n') layout = 256 + copies; + else if (optarg[0] == 'o') + layout = 0x10000 + (copies<<8) + 1; else layout = 1 + (copies<<8); break; diff --git a/super0.c b/super0.c index 49474d07..8bded15c 100644 --- a/super0.c +++ b/super0.c @@ -141,8 +141,10 @@ static void examine_super0(void *sbv) printf(" New Layout : %s\n", c?c:"-unknown-"); } if (sb->level == 10) { - printf(" New Layout : near=%d, far=%d\n", - sb->new_layout&255, (sb->new_layout>>8)&255); + printf(" New Layout : near=%d, %s=%d\n", + sb->new_layout&255, + (sb->new_layout&0x10000)?"offset":"far", + (sb->new_layout>>8)&255); } } if (sb->new_chunk != sb->chunk_size) @@ -170,8 +172,10 @@ static void examine_super0(void *sbv) printf(" Layout : %s\n", c?c:"-unknown-"); } if (sb->level == 10) { - printf(" Layout : near=%d, far=%d\n", - sb->layout&255, (sb->layout>>8)&255); + printf(" Layout : near=%d, %s=%d\n", + sb->layout&255, + (sb->layout&0x10000)?"offset":"far", + (sb->layout>>8)&255); } switch(sb->level) { case 0: diff --git a/super1.c b/super1.c index 1ab07769..77b5485d 100644 --- a/super1.c +++ b/super1.c @@ -218,8 +218,9 @@ static void examine_super1(void *sbv) printf(" New Layout : %s\n", c?c:"-unknown-"); } if (__le32_to_cpu(sb->level) == 10) { - printf(" New Layout : near=%d, far=%d\n", + printf(" New Layout : near=%d, %s=%d\n", __le32_to_cpu(sb->new_layout)&255, + (__le32_to_cpu(sb->new_layout)&0x10000)?"offset":"far", (__le32_to_cpu(sb->new_layout)>>8)&255); } } @@ -250,8 +251,10 @@ static void examine_super1(void *sbv) } if (__le32_to_cpu(sb->level) == 10) { int lo = __le32_to_cpu(sb->layout); - printf(" Layout : near=%d, far=%d\n", - lo&255, (lo>>8)&255); + printf(" Layout : near=%d, %s=%d\n", + lo&255, + (lo&0x10000)?"offset":"far", + (lo>>8)&255); } switch(__le32_to_cpu(sb->level)) { case 0: -- 2.39.2