&chunk, size*2, NULL, &newsize, verbose>=0))
return 1;
- if (chunk) {
+ if (chunk && chunk != UnSet) {
newsize &= ~(unsigned long long)(chunk*2 - 1);
- size &= ~(unsigned long long)(chunk - 1);
+ if (do_default_chunk) {
+ /* default chunk was just set */
+ if (verbose > 0)
+ fprintf(stderr, Name ": chunk size "
+ "defaults to %dK\n", chunk);
+ size &= ~(unsigned long long)(chunk - 1);
+ do_default_chunk = 0;
+ }
}
+
if (size == 0) {
size = newsize / 2;
+ if (level == 1)
+ /* If this is ever reshaped to RAID5, we will
+ * need a chunksize. So round it off a bit
+ * now just to be safe
+ */
+ size &= ~(64ULL-1);
+
if (size && verbose > 0)
fprintf(stderr, Name ": setting size to %lluK\n",
(unsigned long long)size);
for (dv=devlist; dv && !have_container; dv=dv->next, dnum++) {
char *dname = dv->devname;
unsigned long long freesize;
+ int dfd;
+
if (strcasecmp(dname, "missing")==0) {
if (first_missing > dnum)
first_missing = dnum;
missing_disks ++;
continue;
}
+ dfd = open(dname, O_RDONLY);
+ if (dfd < 0) {
+ fprintf(stderr, Name ": cannot open %s: %s\n",
+ dname, strerror(errno));
+ exit(2);
+ }
+ if (fstat(dfd, &stb) != 0 ||
+ (stb.st_mode & S_IFMT) != S_IFBLK) {
+ close(dfd);
+ fprintf(stderr, Name ": %s is not a block device\n",
+ dname);
+ exit(2);
+ }
+ close(dfd);
info.array.working_disks++;
if (dnum < raiddisks)
info.array.active_disks++;
char *name = "default";
for(i=0; !st && superlist[i]; i++) {
st = superlist[i]->match_metadata_desc(name);
+ if (!st)
+ continue;
if (do_default_layout)
layout = default_layout(st, level, verbose);
- if (st && !st->ss->validate_geometry
- (st, level, layout, raiddisks,
- &chunk, size*2, dname, &freesize,
- verbose > 0)) {
+ switch (st->ss->validate_geometry(
+ st, level, layout, raiddisks,
+ &chunk, size*2, dname, &freesize,
+ verbose > 0)) {
+ case -1: /* Not valid, message printed, and not
+ * worth checking any further */
+ exit(2);
+ break;
+ case 0: /* Geometry not valid */
free(st);
st = NULL;
- chunk = do_default_chunk ? 0 : chunk;
+ chunk = do_default_chunk ? UnSet : chunk;
+ break;
+ case 1: /* All happy */
+ break;
}
}
if (!st) {
+ int dfd = open(dname, O_RDONLY|O_EXCL);
+ if (dfd < 0) {
+ fprintf(stderr, Name ": cannot open %s: %s\n",
+ dname, strerror(errno));
+ exit(2);
+ }
fprintf(stderr, Name ": device %s not suitable "
"for any style of array\n",
dname);
did_default = 1;
} else {
if (do_default_layout)
- layout = default_layout(st, level, verbose);
+ layout = default_layout(st, level, 0);
if (!st->ss->validate_geometry(st, level, layout,
raiddisks,
&chunk, size*2, dname,
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 (chunk && chunk != UnSet) {
/* round to chunk size */
freesize = freesize & ~(chunk-1);
+ if (do_default_chunk) {
+ /* default chunk was just set */
+ if (verbose > 0)
+ fprintf(stderr, Name ": chunk size "
+ "defaults to %dK\n", chunk);
+ size &= ~(unsigned long long)(chunk - 1);
+ do_default_chunk = 0;
+ }
}
if (size && freesize < size) {
if (strcmp(st->ss->name, "1.x") == 0 &&
st->minor_version >= 1)
/* metadata at front */
- warn |= check_partitions(fd, dname, 0);
+ 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 &&
return 1;
}
size = minsize;
+ if (level == 1)
+ /* If this is ever reshaped to RAID5, we will
+ * need a chunksize. So round it off a bit
+ * now just to be safe
+ */
+ size &= ~(64ULL-1);
if (verbose > 0)
fprintf(stderr, Name ": size set to %lluK\n", size);
}
/* We need to create the device */
map_lock(&map);
mdfd = create_mddev(mddev, name, autof, LOCAL, chosen_name);
- if (mdfd < 0)
+ if (mdfd < 0) {
+ map_unlock(&map);
return 1;
+ }
+ /* verify if chosen_name is not in use,
+ * it could be in conflict with already existing device
+ * e.g. container, array
+ */
+ if (strncmp(chosen_name, "/dev/md/", 8) == 0
+ && map_by_name(&map, chosen_name+8) != NULL) {
+ fprintf(stderr, Name ": Array name %s is in use already.\n",
+ chosen_name);
+ close(mdfd);
+ map_unlock(&map);
+ return 1;
+ }
mddev = chosen_name;
vers = md_get_version(mdfd);
if (vers < 9000) {
fprintf(stderr, Name ": Create requires md driver version 0.90.0 or later\n");
- goto abort;
+ goto abort_locked;
} else {
mdu_array_info_t inf;
memset(&inf, 0, sizeof(inf));
if (inf.working_disks != 0) {
fprintf(stderr, Name ": another array by this name"
" is already running.\n");
- goto abort;
+ goto abort_locked;
}
}
}
}
if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid))
- goto abort;
+ goto abort_locked;
total_slots = info.array.nr_disks;
- sysfs_init(&info, mdfd, 0);
st->ss->getinfo_super(st, &info, NULL);
+ sysfs_init(&info, mdfd, 0);
if (did_default && verbose >= 0) {
if (is_subarray(info.text_version)) {
}
infos = malloc(sizeof(*infos) * total_slots);
+ if (!infos) {
+ fprintf(stderr, Name ": Unable to allocate memory\n");
+ goto abort;
+ }
for (pass=1; pass <=2 ; pass++) {
struct mddev_dev *moved_disk = NULL; /* the disk that was moved out of the insert point */
break;
case 2:
inf->errors = 0;
- rv = 0;
rv = add_disk(mdfd, st, &info, inf);
me = map_by_devnum(&map, st->container_dev);
}
- st->ss->write_init_super(st);
+ if (st->ss->write_init_super(st)) {
+ st->ss->free_super(st);
+ goto abort_locked;
+ }
/* update parent container uuid */
if (me) {
if (ioctl(mdfd, RUN_ARRAY, ¶m)) {
fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
strerror(errno));
+ if (info.array.chunk_size & (info.array.chunk_size-1)) {
+ fprintf(stderr, " : Problem may be that "
+ "chunk size is not a power of 2\n");
+ }
ioctl(mdfd, STOP_ARRAY, NULL);
goto abort;
}
if (need_mdmon)
start_mdmon(st->container_dev);
- ping_monitor(devnum2devname(st->container_dev));
+ ping_monitor_by_id(st->container_dev);
close(container_fd);
}
wait_for(chosen_name, mdfd);
abort:
map_lock(&map);
+ abort_locked:
map_remove(&map, fd2devnum(mdfd));
map_unlock(&map);