summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--Detail.c8
-rw-r--r--md.410
-rw-r--r--mdadm.814
-rw-r--r--mdadm.c8
-rw-r--r--super0.c12
-rw-r--r--super1.c9
7 files changed, 45 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 28e6240..8e1d951 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 8fa044a..882ec07 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 d76dd8c..d22ded4 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 e3052dc..4ec2f76 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 05784e1..f310474 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 49474d0..8bded15 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 1ab0776..77b5485 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: