#include "md_p.h"
#include <ctype.h>
+static int round_size_and_verify(unsigned long long *size, int chunk)
+{
+ if (*size == 0)
+ return 0;
+ *size &= ~(unsigned long long)(chunk - 1);
+ if (*size == 0) {
+ pr_err("Size cannot be smaller than chunk.\n");
+ return 1;
+ }
+ return 0;
+}
+
static int default_layout(struct supertype *st, int level, int verbose)
{
int layout = UnSet;
default: /* no layout */
layout = 0;
break;
+ case 0:
+ layout = RAID0_ORIG_LAYOUT;
+ break;
case 10:
layout = 0x102; /* near=2, far=1 */
if (verbose > 0)
char *maxdisc = NULL;
int dnum, raid_disk_num;
struct mddev_dev *dv;
+ dev_t rdev;
int fail = 0, warn = 0;
- struct stat stb;
int first_missing = subdevs * 2;
int second_missing = subdevs * 2;
int missing_disks = 0;
pr_err("unknown level %d\n", s->level);
return 1;
}
+
if (s->size == MAX_SIZE)
/* use '0' to mean 'max' now... */
s->size = 0;
if (s->size && s->chunk && s->chunk != UnSet)
- s->size &= ~(unsigned long long)(s->chunk - 1);
+ if (round_size_and_verify(&s->size, s->chunk))
+ return 1;
+
newsize = s->size * 2;
if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks,
&s->chunk, s->size*2,
/* default chunk was just set */
if (c->verbose > 0)
pr_err("chunk size defaults to %dK\n", s->chunk);
- s->size &= ~(unsigned long long)(s->chunk - 1);
+ if (round_size_and_verify(&s->size, s->chunk))
+ return 1;
do_default_chunk = 0;
}
}
dname, strerror(errno));
exit(2);
}
- if (fstat(dfd, &stb) != 0 ||
- (stb.st_mode & S_IFMT) != S_IFBLK) {
+ if (!fstat_is_blkdev(dfd, dname, NULL)) {
close(dfd);
- pr_err("%s is not a block device\n",
- dname);
exit(2);
}
close(dfd);
/* default chunk was just set */
if (c->verbose > 0)
pr_err("chunk size defaults to %dK\n", s->chunk);
- s->size &= ~(unsigned long long)(s->chunk - 1);
+ if (round_size_and_verify(&s->size, s->chunk))
+ return 1;
do_default_chunk = 0;
}
}
close(fd);
}
}
+ if (missing_disks == dnum && !have_container) {
+ pr_err("Subdevs can't be all missing\n");
+ return 1;
+ }
if (s->raiddisks + s->sparedisks > st->max_devs) {
pr_err("Too many devices: %s metadata only supports %d\n",
st->ss->name, st->max_devs);
if (!s->bitmap_file &&
s->level >= 1 &&
st->ss->add_internal_bitmap &&
+ s->journaldisks == 0 &&
(s->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
s->consistency_policy != CONSISTENCY_POLICY_PPL) &&
(s->write_behind || s->size > 100*1024*1024ULL)) {
* with, but it chooses to trust me instead. Sigh
*/
info.array.md_minor = 0;
- if (fstat(mdfd, &stb) == 0)
- info.array.md_minor = minor(stb.st_rdev);
+ if (fstat_is_blkdev(mdfd, mddev, &rdev))
+ info.array.md_minor = minor(rdev);
info.array.not_persistent = 0;
if (((s->level == 4 || s->level == 5) &&
}
bitmap_fd = open(s->bitmap_file, O_RDWR);
if (bitmap_fd < 0) {
- pr_err("weird: %s cannot be openned\n",
+ pr_err("weird: %s cannot be opened\n",
s->bitmap_file);
goto abort_locked;
}
for (dnum = 0, raid_disk_num = 0, dv = devlist; dv;
dv = (dv->next) ? (dv->next) : moved_disk, dnum++) {
int fd;
- struct stat stb2;
struct mdinfo *inf = &infos[dnum];
if (dnum >= total_slots)
dv->devname);
goto abort_locked;
}
- fstat(fd, &stb2);
- inf->disk.major = major(stb2.st_rdev);
- inf->disk.minor = minor(stb2.st_rdev);
+ if (!fstat_is_blkdev(fd, dv->devname, &rdev))
+ return 1;
+ inf->disk.major = major(rdev);
+ inf->disk.minor = minor(rdev);
}
if (fd >= 0)
remove_partitions(fd);
if (!have_container) {
/* getinfo_super might have lost these ... */
- inf->disk.major = major(stb2.st_rdev);
- inf->disk.minor = minor(stb2.st_rdev);
+ inf->disk.major = major(rdev);
+ inf->disk.minor = minor(rdev);
}
break;
case 2:
if (rv) {
pr_err("ADD_NEW_DISK for %s failed: %s\n",
dv->devname, strerror(errno));
+ if (errno == EINVAL &&
+ info.array.level == 0) {
+ pr_err("Possibly your kernel doesn't support RAID0 layouts.\n");
+ pr_err("Either upgrade, or use --layout=dangerous\n");
+ }
goto abort_locked;
}
break;
if (ioctl(mdfd, RUN_ARRAY, ¶m)) {
pr_err("RUN_ARRAY failed: %s\n",
strerror(errno));
+ if (errno == 524 /* ENOTSUP */ &&
+ info.array.level == 0)
+ cont_err("Please use --layout=original or --layout=alternate\n");
if (info.array.chunk_size & (info.array.chunk_size-1)) {
cont_err("Problem may be that chunk size is not a power of 2\n");
}
} else {
pr_err("not starting array - not enough devices.\n");
}
- close(mdfd);
- /* Give udev a moment to process the Change event caused
- * by the close.
- */
- usleep(100*1000);
udev_unblock();
+ close(mdfd);
+ sysfs_uevent(&info, "change");
return 0;
abort: