It is not currently possible to create a RAID0 with 0.90 metadata.
This is because 0.90 cannot specify the layout of RAID0 (it is
traditionally ignored) and different kernels do different things with
RAID0 layouts.
However it should be possible to use --layout=dangerous as that
acknowledges the risk.
It also should be possible to create a RAID0 with all devices the same
size because in that case all layouts are identical.
The metadata handler can only check that all devices are the same size
quite late - in write_init_super(). By that time the default is
currently set - set to a value that super0 cannot handle.
So this patch delays the setting of the default value and leave it for
the metadata handler (or for the Build handler).
super1 selects ORIG in that case.
intel and ddf don't support non-uniform RAID0 so they don't need any
change.
super0 now checks the sizes of devices if the default RAID0 layout was
requested and rejects the request in they are not the same.
validiate_geometry0 now allows "dangerous" layouts for raid0.
Signed-off-by: NeilBrown <neil@brown.name>
s->chunk = 64;
array.chunk_size = s->chunk*1024;
array.layout = s->layout;
+
+ if (array.level == 0 && array.layout == UnSet)
+ /* Raid0 leaves default to metadata handler. That is us. */
+ array.layout = RAID0_ORIG_LAYOUT;
if (md_set_array_info(mdfd, &array)) {
pr_err("md_set_array_info() failed for %s: %s\n", chosen_name, strerror(errno));
goto abort;
layout = 0;
break;
case 0:
- layout = RAID0_ORIG_LAYOUT;
+ /* Leave unset - metadata handlers choose default */
break;
case 10:
layout = 0x102; /* near=2, far=1 */
{ "alternate", RAID0_ALT_MULTIZONE_LAYOUT},
{ "1", 1}, /* aka ORIG */
{ "2", 2}, /* aka ALT */
- { "dangerous", 0},
+ { "dangerous", RAID0_DANGEROUS_LAYOUT},
{ NULL, UnSet},
};
#endif
enum r0layout {
+ RAID0_DANGEROUS_LAYOUT = 0, /* layout depends on kernel version */
RAID0_ORIG_LAYOUT = 1,
RAID0_ALT_MULTIZONE_LAYOUT = 2,
};
int fd;
char *devname;
mdu_disk_info_t disk;
+ unsigned long long dev_size;
struct devinfo *next;
};
di->devname = devname;
di->disk = *dinfo;
di->next = NULL;
+
+ if (is_fd_valid(fd))
+ get_dev_size(fd, NULL, &di->dev_size);
+
*dip = di;
return 0;
int rv = 0;
struct devinfo *di;
+ if (sb->level == 0 && sb->layout == UnSet) {
+ /* Without requesting a dangerous (0) layout
+ * we can only allow this RAID0 if all devices are
+ * the same size
+ */
+ unsigned long long chunks = 0;
+ unsigned long chunk_sectors = sb->chunk_size >> 9;
+
+ for (di = st->info; di; di = di->next) {
+ unsigned long long this_chunks;
+
+ this_chunks = st->ss->avail_size(st, di->dev_size, 0) / chunk_sectors;
+
+ if (chunks == 0) {
+ chunks = this_chunks;
+ continue;
+ }
+
+ if (this_chunks != chunks) {
+ pr_err("Need explicit layout=dangerous to create 0.90 raid0 on non-uniform sized devices\n");
+ return 1;
+ }
+ }
+ /* looks safe */
+ sb->layout = 0;
+ }
+
for (di = st->info ; di && ! rv ; di = di->next) {
if (di->disk.state & (1 << MD_DISK_FAULTY))
if (*chunk == UnSet)
*chunk = DEFAULT_CHUNK;
- if (level == 0 && layout != UnSet) {
+ if (level == 0 && layout != UnSet && layout != RAID0_DANGEROUS_LAYOUT) {
if (verbose)
pr_err("0.90 metadata does not support layouts for RAID0\n");
return 0;
sizeof(sb->set_name) - namelen);
}
+ if (info->level == 0 && info->layout == UnSet)
+ /* Metadata chooses default layout for RAID0 */
+ info->layout = RAID0_ORIG_LAYOUT;
+
sb->ctime = __cpu_to_le64((unsigned long long)time(0));
sb->level = __cpu_to_le32(info->level);
sb->layout = __cpu_to_le32(info->layout);
testdev $md0 3 $mdsize2_l 512
mdadm -S $md0
-# verify raid0 with layouts fail for 0.90
-mdadm -CR $md0 -e0.90 -l0 -n4 $dev0 $dev1 $dev2 $dev3
+# verify raid0 with explicit layouts fail for 0.90
+mdadm -CR $md0 -e0.90 -l0 --layout=original -n4 $dev0 $dev1 $dev2 $dev3
check opposite_result
# now with no superblock