int Create(struct supertype *st, char *mddev,
- int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
+ int chunk, int level, int layout, unsigned long long size,
+ int raiddisks, int sparedisks,
char *name, char *homehost, int *uuid,
int subdevs, struct mddev_dev *devlist,
int runstop, int verbose, int force, int assume_clean,
- char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof)
+ char *bitmap_file, int bitmap_chunk, int write_behind,
+ int delay, int autof)
{
/*
* Create a new raid array.
struct mdinfo info, *infos;
int did_default = 0;
int do_default_layout = 0;
+ int do_default_chunk = 0;
unsigned long safe_mode_delay = 0;
char chosen_name[1024];
struct map_ent *map = NULL;
case 10:
case 6:
case 0:
- if (chunk == 0) {
- if (st && st->ss->default_geometry)
- st->ss->default_geometry(st, NULL, NULL, &chunk);
- chunk = chunk ? : 512;
- if (verbose > 0)
- fprintf(stderr, Name ": chunk size defaults to %dK\n", chunk);
+ if (chunk == 0 || chunk == UnSet) {
+ chunk = UnSet;
+ do_default_chunk = 1;
+ /* chunk will be set later */
}
break;
case LEVEL_LINEAR:
return 1;
}
- if (size && chunk)
+ if (size && chunk && chunk != UnSet)
size &= ~(unsigned long long)(chunk - 1);
newsize = size * 2;
if (st && ! st->ss->validate_geometry(st, level, layout, raiddisks,
- chunk, size*2, NULL, &newsize, verbose>=0))
+ &chunk, size*2, NULL, &newsize, verbose>=0))
return 1;
+
+ if (chunk) {
+ newsize &= ~(unsigned long long)(chunk*2 - 1);
+ size &= ~(unsigned long long)(chunk - 1);
+ }
if (size == 0) {
size = newsize / 2;
if (size && verbose > 0)
layout = default_layout(st, level, verbose);
if (st && !st->ss->validate_geometry
(st, level, layout, raiddisks,
- chunk, size*2, dname, &freesize,
- verbose > 0))
+ &chunk, size*2, dname, &freesize,
+ verbose > 0)) {
+ free(st);
st = NULL;
+ chunk = do_default_chunk ? 0 : chunk;
+ }
}
if (!st) {
layout = default_layout(st, level, verbose);
if (!st->ss->validate_geometry(st, level, layout,
raiddisks,
- chunk, size*2, dname,
+ &chunk, size*2, dname,
&freesize,
verbose >= 0)) {
continue;
}
}
+ if (verbose > 0 && do_default_chunk) {
+ do_default_chunk = 0;
+ fprintf(stderr, Name ": chunk size "
+ "defaults to %dK\n", chunk);
+ }
freesize /= 2; /* convert to K */
if (chunk) {
if (strcmp(st->ss->name, "1.x") == 0 &&
st->minor_version >= 1)
/* metadata at front */
- warn |= check_partitions(fd, dname, 0);
- else if (level == 1 || level == LEVEL_CONTAINER)
+ warn |= check_partitions(fd, dname, 0, 0);
+ else if (level == 1 || level == LEVEL_CONTAINER
+ || (level == 0 && raiddisks == 1))
/* partitions could be meaningful */
- warn |= check_partitions(fd, dname, freesize*2);
+ warn |= check_partitions(fd, dname, freesize*2, size*2);
else
/* partitions cannot be meaningful */
- warn |= check_partitions(fd, dname, 0);
+ warn |= check_partitions(fd, dname, 0, 0);
if (strcmp(st->ss->name, "1.x") == 0 &&
st->minor_version >= 1 &&
did_default &&
close(fd);
}
}
+ if (raiddisks + sparedisks > st->max_devs) {
+ fprintf(stderr, Name ": Too many devices:"
+ " %s metadata only supports %d\n",
+ st->ss->name, st->max_devs);
+ return 1;
+ }
if (have_container)
info.array.working_disks = raiddisks;
if (fail) {
/* size is meaningful */
if (!st->ss->validate_geometry(st, level, layout,
raiddisks,
- chunk, minsize*2,
+ &chunk, minsize*2,
NULL, NULL, 0)) {
fprintf(stderr, Name ": devices too large for RAID level %d\n", level);
return 1;
Name ": ADD_NEW_DISK for %s "
"failed: %s\n",
dv->devname, strerror(errno));
- st->ss->free_super(st);
goto abort;
}
break;
map_unlock(&map);
flush_metadata_updates(st);
+ st->ss->free_super(st);
}
}
free(infos);
- st->ss->free_super(st);
if (level == LEVEL_CONTAINER) {
/* No need to start. But we should signal udev to
wait_for(chosen_name, mdfd);
} else if (runstop == 1 || subdevs >= raiddisks) {
if (st->ss->external) {
+ int err;
switch(level) {
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
case 0:
- sysfs_set_str(&info, NULL, "array_state",
- "active");
+ err = sysfs_set_str(&info, NULL, "array_state",
+ "active");
need_mdmon = 0;
break;
default:
- sysfs_set_str(&info, NULL, "array_state",
- "readonly");
+ err = sysfs_set_str(&info, NULL, "array_state",
+ "readonly");
break;
}
sysfs_set_safemode(&info, safe_mode_delay);
+ if (err) {
+ fprintf(stderr, Name ": failed to"
+ " activate array.\n");
+ ioctl(mdfd, STOP_ARRAY, NULL);
+ goto abort;
+ }
} else {
/* param is not actually used */
mdu_param_t param;