X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Create.c;h=2721884efabce46ee4e00b2e04f4f27d3a80b7c2;hb=2dd271fe7041c2f7036939cf6917c0578b92fefe;hp=9247d46bbfac8545a12233cf0c2205aa188becba;hpb=6f02172d2e9cbef03da07a16c9fffe46062d09e6;p=thirdparty%2Fmdadm.git diff --git a/Create.c b/Create.c index 9247d46b..2721884e 100644 --- a/Create.c +++ b/Create.c @@ -87,7 +87,7 @@ int Create(struct supertype *st, char *mddev, unsigned long long minsize=0, maxsize=0; char *mindisc = NULL; char *maxdisc = NULL; - int dnum; + int dnum, raid_disk_num; struct mddev_dev *dv; int fail=0, warn=0; struct stat stb; @@ -114,6 +114,13 @@ int Create(struct supertype *st, char *mddev, unsigned long long newsize; int major_num = BITMAP_MAJOR_HI; + if (s->bitmap_file && strcmp(s->bitmap_file, "clustered") == 0) { + major_num = BITMAP_MAJOR_CLUSTERED; + if (c->nodes <= 1) { + pr_err("At least 2 nodes are needed for cluster-md\n"); + return 1; + } + } memset(&info, 0, sizeof(info)); if (s->level == UnSet && st && st->ss->default_geometry) @@ -177,15 +184,14 @@ int Create(struct supertype *st, char *mddev, close(fd); } if (st && st->ss->external && s->sparedisks) { - pr_err("This metadata type does not support " - "spare disks at create time\n"); + pr_err("This metadata type does not support spare disks at create time\n"); return 1; } - if (subdevs > s->raiddisks+s->sparedisks) { + if (subdevs > s->raiddisks+s->sparedisks+s->journaldisks) { pr_err("You have listed more devices (%d) than are in the array(%d)!\n", subdevs, s->raiddisks+s->sparedisks); return 1; } - if (!have_container && subdevs < s->raiddisks+s->sparedisks) { + if (!have_container && subdevs < s->raiddisks+s->sparedisks+s->journaldisks) { pr_err("You haven't given enough devices (real or missing) to create this array\n"); return 1; } @@ -261,8 +267,7 @@ int Create(struct supertype *st, char *mddev, if (do_default_chunk) { /* default chunk was just set */ if (c->verbose > 0) - pr_err("chunk size " - "defaults to %dK\n", s->chunk); + pr_err("chunk size defaults to %dK\n", s->chunk); s->size &= ~(unsigned long long)(s->chunk - 1); do_default_chunk = 0; } @@ -285,6 +290,12 @@ int Create(struct supertype *st, char *mddev, info.array.active_disks = 0; info.array.working_disks = 0; dnum = 0; + for (dv = devlist; dv ; dv = dv->next) + if (data_offset == VARIABLE_OFFSET) + dv->data_offset = INVALID_SECTORS; + else + dv->data_offset = data_offset; + for (dv=devlist; dv && !have_container; dv=dv->next, dnum++) { char *dname = dv->devname; unsigned long long freesize; @@ -324,7 +335,7 @@ int Create(struct supertype *st, char *mddev, } close(dfd); info.array.working_disks++; - if (dnum < s->raiddisks) + if (dnum < s->raiddisks && dv->disposition != 'j') info.array.active_disks++; if (st == NULL) { struct createinfo *ci = conf_get_create_info(); @@ -369,8 +380,7 @@ int Create(struct supertype *st, char *mddev, dname, strerror(errno)); exit(2); } - pr_err("device %s not suitable " - "for any style of array\n", + pr_err("device %s not suitable for any style of array\n", dname); exit(2); } @@ -387,14 +397,16 @@ int Create(struct supertype *st, char *mddev, dname, &freesize, c->verbose >= 0)) { - pr_err("%s is not suitable for " - "this array.\n", + pr_err("%s is not suitable for this array.\n", dname); fail = 1; continue; } } + if (dv->disposition == 'j') + goto skip_size_check; /* skip write journal for size check */ + freesize /= 2; /* convert to K */ if (s->chunk && s->chunk != UnSet) { /* round to chunk size */ @@ -402,8 +414,7 @@ int Create(struct supertype *st, char *mddev, if (do_default_chunk) { /* default chunk was just set */ if (c->verbose > 0) - pr_err("chunk size " - "defaults to %dK\n", s->chunk); + pr_err("chunk size defaults to %dK\n", s->chunk); s->size &= ~(unsigned long long)(s->chunk - 1); do_default_chunk = 0; } @@ -415,8 +426,7 @@ int Create(struct supertype *st, char *mddev, } if (s->size && freesize < s->size) { - pr_err("%s is smaller than given size." - " %lluK < %lluK + metadata\n", + pr_err("%s is smaller than given size. %lluK < %lluK + metadata\n", dname, freesize, s->size); fail = 1; continue; @@ -429,6 +439,7 @@ int Create(struct supertype *st, char *mddev, mindisc = dname; minsize = freesize; } + skip_size_check: if (c->runstop != 1 || c->verbose >= 0) { int fd = open(dname, O_RDONLY); if (fd <0 ) { @@ -467,8 +478,7 @@ int Create(struct supertype *st, char *mddev, } } if (s->raiddisks + s->sparedisks > st->max_devs) { - pr_err("Too many devices:" - " %s metadata only supports %d\n", + pr_err("Too many devices: %s metadata only supports %d\n", st->ss->name, st->max_devs); return 1; } @@ -509,6 +519,7 @@ int Create(struct supertype *st, char *mddev, if (!s->bitmap_file && s->level >= 1 && + st->ss->add_internal_bitmap && (s->write_behind || s->size > 100*1024*1024ULL)) { if (c->verbose > 0) pr_err("automatically enabling write-intent bitmap on large array\n"); @@ -531,6 +542,8 @@ int Create(struct supertype *st, char *mddev, st->ss->name); warn = 1; } + st->nodes = c->nodes; + st->cluster_name = c->homecluster; if (warn) { if (c->runstop!= 1) { @@ -611,8 +624,7 @@ int Create(struct supertype *st, char *mddev, memset(&inf, 0, sizeof(inf)); ioctl(mdfd, GET_ARRAY_INFO, &inf); if (inf.working_disks != 0) { - pr_err("another array by this name" - " is already running.\n"); + pr_err("another array by this name is already running.\n"); goto abort_locked; } } @@ -734,13 +746,14 @@ int Create(struct supertype *st, char *mddev, mdi?mdi->text_version:"managed", devnm); sysfs_free(mdi); } else - pr_err("Defaulting to version" - " %s metadata\n", info.text_version); + pr_err("Defaulting to version %s metadata\n", info.text_version); } map_update(&map, fd2devnm(mdfd), info.text_version, info.uuid, chosen_name); - map_unlock(&map); + /* Keep map locked until devices have been added to array + * to stop another mdadm from finding and using those devices. + */ if (s->bitmap_file && vers < 9003) { major_num = BITMAP_MAJOR_HOSTENDIAN; @@ -750,21 +763,22 @@ int Create(struct supertype *st, char *mddev, #endif } - if (s->bitmap_file && strcmp(s->bitmap_file, "internal")==0) { + if (s->bitmap_file && (strcmp(s->bitmap_file, "internal")==0 || + strcmp(s->bitmap_file, "clustered")==0)) { if ((vers%100) < 2) { pr_err("internal bitmaps not supported by this kernel.\n"); - goto abort; + goto abort_locked; } if (!st->ss->add_internal_bitmap) { pr_err("internal bitmaps not supported with %s metadata\n", st->ss->name); - goto abort; + goto abort_locked; } - if (!st->ss->add_internal_bitmap(st, &s->bitmap_chunk, - c->delay, s->write_behind, - bitmapsize, 1, major_num)) { + if (st->ss->add_internal_bitmap(st, &s->bitmap_chunk, + c->delay, s->write_behind, + bitmapsize, 1, major_num)) { pr_err("Given bitmap chunk size not supported.\n"); - goto abort; + goto abort_locked; } s->bitmap_file = NULL; } @@ -788,14 +802,12 @@ int Create(struct supertype *st, char *mddev, */ container_fd = open_dev_excl(st->container_devnm); if (container_fd < 0) { - pr_err("Cannot get exclusive " - "open on container - weird.\n"); - goto abort; + pr_err("Cannot get exclusive open on container - weird.\n"); + goto abort_locked; } if (mdmon_running(st->container_devnm)) { if (c->verbose) - pr_err("reusing mdmon " - "for %s.\n", + pr_err("reusing mdmon for %s.\n", st->container_devnm); st->update_tail = &st->updates; } else @@ -805,7 +817,7 @@ int Create(struct supertype *st, char *mddev, if (rv) { pr_err("failed to set array info for %s: %s\n", mddev, strerror(errno)); - goto abort; + goto abort_locked; } if (s->bitmap_file) { @@ -816,18 +828,18 @@ int Create(struct supertype *st, char *mddev, c->delay, s->write_behind, bitmapsize, major_num)) { - goto abort; + goto abort_locked; } bitmap_fd = open(s->bitmap_file, O_RDWR); if (bitmap_fd < 0) { pr_err("weird: %s cannot be openned\n", s->bitmap_file); - goto abort; + goto abort_locked; } if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { pr_err("Cannot set bitmap file for %s: %s\n", mddev, strerror(errno)); - goto abort; + goto abort_locked; } } @@ -836,7 +848,7 @@ int Create(struct supertype *st, char *mddev, for (pass=1; pass <=2 ; pass++) { struct mddev_dev *moved_disk = NULL; /* the disk that was moved out of the insert point */ - for (dnum=0, dv = devlist ; dv ; + for (dnum=0, raid_disk_num=0, dv = devlist ; dv ; dv=(dv->next)?(dv->next):moved_disk, dnum++) { int fd; struct stat stb; @@ -845,11 +857,14 @@ int Create(struct supertype *st, char *mddev, if (dnum >= total_slots) abort(); if (dnum == insert_point) { + raid_disk_num += 1; moved_disk = dv; continue; } - if (strcasecmp(dv->devname, "missing")==0) + if (strcasecmp(dv->devname, "missing")==0) { + raid_disk_num += 1; continue; + } if (have_container) moved_disk = NULL; if (have_container && dnum < info.array.raid_disks - 1) @@ -861,15 +876,22 @@ int Create(struct supertype *st, char *mddev, *inf = info; inf->disk.number = dnum; - inf->disk.raid_disk = dnum; - if (inf->disk.raid_disk < s->raiddisks) + inf->disk.raid_disk = raid_disk_num++; + + if (dv->disposition == 'j') { + inf->disk.raid_disk = MD_DISK_ROLE_JOURNAL; + inf->disk.state = (1<disk.raid_disk < s->raiddisks) inf->disk.state = (1<disk.state = 0; - if (dv->writemostly == 1) + if (dv->writemostly == FlagSet) inf->disk.state |= (1<failfast == FlagSet) + inf->disk.state |= (1<devname, O_RDWR|O_EXCL); if (fd < 0) { - pr_err("failed to open %s " - "after earlier success - aborting\n", + pr_err("failed to open %s after earlier success - aborting\n", dv->devname); - goto abort; + goto abort_locked; } fstat(fd, &stb); inf->disk.major = major(stb.st_rdev); @@ -896,7 +917,7 @@ int Create(struct supertype *st, char *mddev, fd, dv->devname, dv->data_offset)) { ioctl(mdfd, STOP_ARRAY, NULL); - goto abort; + goto abort_locked; } st->ss->getinfo_super(st, inf, NULL); safe_mode_delay = inf->safe_mode_delay; @@ -919,10 +940,9 @@ int Create(struct supertype *st, char *mddev, rv = add_disk(mdfd, st, &info, inf); if (rv) { - pr_err("ADD_NEW_DISK for %s " - "failed: %s\n", + pr_err("ADD_NEW_DISK for %s failed: %s\n", dv->devname, strerror(errno)); - goto abort; + goto abort_locked; } break; } @@ -939,7 +959,6 @@ int Create(struct supertype *st, char *mddev, * the subarray cursor such that ->getinfo_super once * again returns container info. */ - map_lock(&map); st->ss->getinfo_super(st, &info_new, NULL); if (st->ss->external && s->level != LEVEL_CONTAINER && !same_uuid(info_new.uuid, info.uuid, 0)) { @@ -964,12 +983,12 @@ int Create(struct supertype *st, char *mddev, info_new.uuid, path); free(path); } - map_unlock(&map); flush_metadata_updates(st); st->ss->free_super(st); } } + map_unlock(&map); free(infos); if (s->level == LEVEL_CONTAINER) { @@ -999,8 +1018,7 @@ int Create(struct supertype *st, char *mddev, } sysfs_set_safemode(&info, safe_mode_delay); if (err) { - pr_err("failed to" - " activate array.\n"); + pr_err("failed to activate array.\n"); ioctl(mdfd, STOP_ARRAY, NULL); goto abort; } @@ -1021,8 +1039,7 @@ int Create(struct supertype *st, char *mddev, pr_err("RUN_ARRAY failed: %s\n", strerror(errno)); 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"); + cont_err("Problem may be that chunk size is not a power of 2\n"); } ioctl(mdfd, STOP_ARRAY, NULL); goto abort;