#include "md_p.h"
#include <ctype.h>
-int Create(struct supertype *st, char *mddev, int mdfd,
+int Create(struct supertype *st, char *mddev,
int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
char *name, char *homehost, int *uuid,
int subdevs, mddev_dev_t devlist,
int runstop, int verbose, int force, int assume_clean,
- char *bitmap_file, int bitmap_chunk, int write_behind, int delay)
+ char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof)
{
/*
* Create a new raid array.
* if runstop==run, or raiddisks disks were used,
* RUN_ARRAY
*/
+ int mdfd;
unsigned long long minsize=0, maxsize=0;
char *mindisc = NULL;
char *maxdisc = NULL;
struct mdinfo info, *infos;
int did_default = 0;
unsigned long safe_mode_delay = 0;
+ char chosen_name[1024];
+ struct map_ent *map = NULL;
int major_num = BITMAP_MAJOR_HI;
memset(&info, 0, sizeof(info));
- vers = md_get_version(mdfd);
- if (vers < 9000) {
- fprintf(stderr, Name ": Create requires md driver version 0.90.0 or later\n");
- return 1;
- } else {
- mdu_array_info_t inf;
- memset(&inf, 0, sizeof(inf));
- ioctl(mdfd, GET_ARRAY_INFO, &inf);
- if (inf.working_disks != 0) {
- fprintf(stderr, Name ": another array by this name"
- " is already running.\n");
- return 1;
- }
- }
if (level == UnSet) {
/* "ddf" and "imsm" metadata only supports one level - should possibly
* push this into metadata handler??
}
if (size && freesize < size) {
- fprintf(stderr, Name ": %s is smaller that given size."
+ fprintf(stderr, Name ": %s is smaller than given size."
" %lluK < %lluK + metadata\n",
dname, freesize, size);
fail = 1;
* as missing, so that a reconstruct happens (faster than re-parity)
* FIX: Can we do this for raid6 as well?
*/
- if (assume_clean==0 && force == 0 && first_missing >= raiddisks) {
+ if (st->ss->external == 0 &&
+ assume_clean==0 && force == 0 && first_missing >= raiddisks) {
switch ( level ) {
case 4:
case 5:
return 1;
}
+ /* We need to create the device */
+ map_lock(&map);
+ mdfd = create_mddev(mddev, name, autof, LOCAL, chosen_name);
+ if (mdfd < 0)
+ 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;
+ } else {
+ mdu_array_info_t inf;
+ memset(&inf, 0, sizeof(inf));
+ ioctl(mdfd, GET_ARRAY_INFO, &inf);
+ if (inf.working_disks != 0) {
+ fprintf(stderr, Name ": another array by this name"
+ " is already running.\n");
+ goto abort;
+ }
+ }
+
/* Ok, lets try some ioctls */
info.array.level = level;
* /dev/md/home -> home
* /dev/mdhome -> home
*/
+ /* FIXME compare this with rules in create_mddev */
name = strrchr(mddev, '/');
if (name) {
name++;
}
}
if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid))
- return 1;
+ goto abort;
total_slots = info.array.nr_disks;
sysfs_init(&info, mdfd, 0);
" %s metadata\n", info.text_version);
}
+ map_update(&map, fd2devnum(mdfd), info.text_version,
+ info.uuid, chosen_name);
+ map_unlock(&map);
+
if (bitmap_file && vers < 9003) {
major_num = BITMAP_MAJOR_HOSTENDIAN;
#ifdef __BIG_ENDIAN
if (bitmap_file && strcmp(bitmap_file, "internal")==0) {
if ((vers%100) < 2) {
fprintf(stderr, Name ": internal bitmaps not supported by this kernel.\n");
- return 1;
+ goto abort;
}
if (!st->ss->add_internal_bitmap(st, &bitmap_chunk,
delay, write_behind,
bitmapsize, 1, major_num)) {
fprintf(stderr, Name ": Given bitmap chunk size not supported.\n");
- return 1;
+ goto abort;
}
bitmap_file = NULL;
}
if (container_fd < 0) {
fprintf(stderr, Name ": Cannot get exclusive "
"open on container - weird.\n");
- return 1;
+ goto abort;
}
if (mdmon_running(st->container_dev)) {
if (verbose)
if (rv) {
fprintf(stderr, Name ": failed to set array info for %s: %s\n",
mddev, strerror(errno));
- return 1;
+ goto abort;
}
if (bitmap_file) {
delay, write_behind,
bitmapsize,
major_num)) {
- return 1;
+ goto abort;
}
bitmap_fd = open(bitmap_file, O_RDWR);
if (bitmap_fd < 0) {
fprintf(stderr, Name ": weird: %s cannot be openned\n",
bitmap_file);
- return 1;
+ goto abort;
}
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
fprintf(stderr, Name ": Cannot set bitmap file for %s: %s\n",
mddev, strerror(errno));
- return 1;
+ goto abort;
}
}
fprintf(stderr, Name ": failed to open %s "
"after earlier success - aborting\n",
dv->devname);
- return 1;
+ goto abort;
}
fstat(fd, &stb);
inf->disk.major = major(stb.st_rdev);
"failed: %s\n",
dv->devname, strerror(errno));
st->ss->free_super(st);
- return 1;
+ goto abort;
}
break;
}
free(infos);
st->ss->free_super(st);
- /* param is not actually used */
- if (level == LEVEL_CONTAINER)
- /* No need to start */
+ if (level == LEVEL_CONTAINER) {
+ /* No need to start. But we should signal udev to
+ * create links */
+ sysfs_uevent(&info, "change");
;
- else if (runstop == 1 || subdevs >= raiddisks) {
+ } else if (runstop == 1 || subdevs >= raiddisks) {
if (st->ss->external) {
switch(level) {
case LEVEL_LINEAR:
}
sysfs_set_safemode(&info, safe_mode_delay);
} else {
+ /* param is not actually used */
mdu_param_t param;
if (ioctl(mdfd, RUN_ARRAY, ¶m)) {
fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
strerror(errno));
Manage_runstop(mddev, mdfd, -1, 0);
- return 1;
+ goto abort;
}
}
if (verbose >= 0)
ping_monitor(devnum2devname(st->container_dev));
close(container_fd);
}
+ wait_for(chosen_name);
} else {
fprintf(stderr, Name ": not starting array - not enough devices.\n");
}
+ close(mdfd);
return 0;
+
+ abort:
+ if (mdfd >= 0)
+ close(mdfd);
+ return 1;
}