Create.c (mdadm-4.1) | : | Create.c (mdadm-4.2) | ||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
* | * | |||
* Author: Neil Brown | * Author: Neil Brown | |||
* Email: <neilb@suse.de> | * Email: <neilb@suse.de> | |||
*/ | */ | |||
#include "mdadm.h" | #include "mdadm.h" | |||
#include "md_u.h" | #include "md_u.h" | |||
#include "md_p.h" | #include "md_p.h" | |||
#include <ctype.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) | static int default_layout(struct supertype *st, int level, int verbose) | |||
{ | { | |||
int layout = UnSet; | int layout = UnSet; | |||
if (st && st->ss->default_geometry) | if (st && st->ss->default_geometry) | |||
st->ss->default_geometry(st, &level, &layout, NULL); | st->ss->default_geometry(st, &level, &layout, NULL); | |||
if (layout == UnSet) | if (layout == UnSet) | |||
switch(level) { | switch(level) { | |||
default: /* no layout */ | default: /* no layout */ | |||
layout = 0; | layout = 0; | |||
break; | break; | |||
case 0: | ||||
layout = RAID0_ORIG_LAYOUT; | ||||
break; | ||||
case 10: | case 10: | |||
layout = 0x102; /* near=2, far=1 */ | layout = 0x102; /* near=2, far=1 */ | |||
if (verbose > 0) | if (verbose > 0) | |||
pr_err("layout defaults to n2\n"); | pr_err("layout defaults to n2\n"); | |||
break; | break; | |||
case 5: | case 5: | |||
case 6: | case 6: | |||
layout = map_name(r5layout, "default"); | layout = map_name(r5layout, "default"); | |||
if (verbose > 0) | if (verbose > 0) | |||
pr_err("layout defaults to %s\n", map_num(r5layou t, layout)); | pr_err("layout defaults to %s\n", map_num(r5layou t, layout)); | |||
skipping to change at line 141 | skipping to change at line 156 | |||
} | } | |||
if (s->raiddisks < 4 && s->level == 6) { | if (s->raiddisks < 4 && s->level == 6) { | |||
pr_err("at least 4 raid-devices needed for level 6\n"); | pr_err("at least 4 raid-devices needed for level 6\n"); | |||
return 1; | return 1; | |||
} | } | |||
if (s->raiddisks > 256 && s->level == 6) { | if (s->raiddisks > 256 && s->level == 6) { | |||
pr_err("no more than 256 raid-devices supported for level 6\n"); | pr_err("no more than 256 raid-devices supported for level 6\n"); | |||
return 1; | return 1; | |||
} | } | |||
if (s->raiddisks < 2 && s->level >= 4) { | if (s->raiddisks < 2 && s->level >= 4) { | |||
pr_err("at least 2 raid-devices needed for level 4 or 5\n"); | pr_err("at least 2 raid-devices needed for level %d\n", s->level) ; | |||
return 1; | return 1; | |||
} | } | |||
if (s->level <= 0 && s->sparedisks) { | if (s->level <= 0 && s->sparedisks) { | |||
pr_err("This level does not support spare devices\n"); | pr_err("This level does not support spare devices\n"); | |||
return 1; | return 1; | |||
} | } | |||
if (subdevs == 1 && strcmp(devlist->devname, "missing") != 0) { | if (subdevs == 1 && strcmp(devlist->devname, "missing") != 0) { | |||
/* If given a single device, it might be a container, and we can | /* If given a single device, it might be a container, and we can | |||
* extract a device list from there | * extract a device list from there | |||
skipping to change at line 242 | skipping to change at line 257 | |||
s->chunk = 64; | s->chunk = 64; | |||
if (c->verbose > 0) | if (c->verbose > 0) | |||
pr_err("chunk size defaults to 64K\n"); | pr_err("chunk size defaults to 64K\n"); | |||
} | } | |||
break; | break; | |||
case 1: | case 1: | |||
case LEVEL_FAULTY: | case LEVEL_FAULTY: | |||
case LEVEL_MULTIPATH: | case LEVEL_MULTIPATH: | |||
case LEVEL_CONTAINER: | case LEVEL_CONTAINER: | |||
if (s->chunk) { | if (s->chunk) { | |||
s->chunk = 0; | pr_err("specifying chunk size is forbidden for this level | |||
if (c->verbose > 0) | \n"); | |||
pr_err("chunk size ignored for this level\n"); | return 1; | |||
} | } | |||
break; | break; | |||
default: | default: | |||
pr_err("unknown level %d\n", s->level); | pr_err("unknown level %d\n", s->level); | |||
return 1; | return 1; | |||
} | } | |||
if (s->size == MAX_SIZE) | if (s->size == MAX_SIZE) | |||
/* use '0' to mean 'max' now... */ | /* use '0' to mean 'max' now... */ | |||
s->size = 0; | s->size = 0; | |||
if (s->size && s->chunk && s->chunk != UnSet) | 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; | newsize = s->size * 2; | |||
if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddis ks, | if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddis ks, | |||
&s->chunk, s->size*2, | &s->chunk, s->size*2, | |||
data_offset, NULL, | data_offset, NULL, | |||
&newsize, s->consistency_policy, | &newsize, s->consistency_policy, | |||
c->verbose >= 0)) | c->verbose >= 0)) | |||
return 1; | return 1; | |||
if (s->chunk && s->chunk != UnSet) { | if (s->chunk && s->chunk != UnSet) { | |||
newsize &= ~(unsigned long long)(s->chunk*2 - 1); | newsize &= ~(unsigned long long)(s->chunk*2 - 1); | |||
if (do_default_chunk) { | if (do_default_chunk) { | |||
/* default chunk was just set */ | /* default chunk was just set */ | |||
if (c->verbose > 0) | 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); | if (round_size_and_verify(&s->size, s->chunk)) | |||
return 1; | ||||
do_default_chunk = 0; | do_default_chunk = 0; | |||
} | } | |||
} | } | |||
if (s->size == 0) { | if (s->size == 0) { | |||
s->size = newsize / 2; | s->size = newsize / 2; | |||
if (s->level == 1) | if (s->level == 1) | |||
/* If this is ever reshaped to RAID5, we will | /* If this is ever reshaped to RAID5, we will | |||
* need a chunksize. So round it off a bit | * need a chunksize. So round it off a bit | |||
* now just to be safe | * now just to be safe | |||
skipping to change at line 416 | skipping to change at line 434 | |||
goto skip_size_check; /* skip write journal for size che ck */ | goto skip_size_check; /* skip write journal for size che ck */ | |||
freesize /= 2; /* convert to K */ | freesize /= 2; /* convert to K */ | |||
if (s->chunk && s->chunk != UnSet) { | if (s->chunk && s->chunk != UnSet) { | |||
/* round to chunk size */ | /* round to chunk size */ | |||
freesize = freesize & ~(s->chunk-1); | freesize = freesize & ~(s->chunk-1); | |||
if (do_default_chunk) { | if (do_default_chunk) { | |||
/* default chunk was just set */ | /* default chunk was just set */ | |||
if (c->verbose > 0) | 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); | if (round_size_and_verify(&s->size, s->chunk)) | |||
return 1; | ||||
do_default_chunk = 0; | do_default_chunk = 0; | |||
} | } | |||
} | } | |||
if (!freesize) { | if (!freesize) { | |||
pr_err("no free space left on %s\n", dname); | pr_err("no free space left on %s\n", dname); | |||
fail = 1; | fail = 1; | |||
continue; | continue; | |||
} | } | |||
if (s->size && freesize < s->size) { | if (s->size && freesize < s->size) { | |||
skipping to change at line 523 | skipping to change at line 542 | |||
* need a chunksize. So round it off a bit | * need a chunksize. So round it off a bit | |||
* now just to be safe | * now just to be safe | |||
*/ | */ | |||
s->size &= ~(64ULL-1); | s->size &= ~(64ULL-1); | |||
if (c->verbose > 0) | if (c->verbose > 0) | |||
pr_err("size set to %lluK\n", s->size); | pr_err("size set to %lluK\n", s->size); | |||
} | } | |||
} | } | |||
if (!s->bitmap_file && | if (!s->bitmap_file && | |||
!st->ss->external && | ||||
s->level >= 1 && | s->level >= 1 && | |||
st->ss->add_internal_bitmap && | st->ss->add_internal_bitmap && | |||
s->journaldisks == 0 && | ||||
(s->consistency_policy != CONSISTENCY_POLICY_RESYNC && | (s->consistency_policy != CONSISTENCY_POLICY_RESYNC && | |||
s->consistency_policy != CONSISTENCY_POLICY_PPL) && | s->consistency_policy != CONSISTENCY_POLICY_PPL) && | |||
(s->write_behind || s->size > 100*1024*1024ULL)) { | (s->write_behind || s->size > 100*1024*1024ULL)) { | |||
if (c->verbose > 0) | if (c->verbose > 0) | |||
pr_err("automatically enabling write-intent bitmap on lar ge array\n"); | pr_err("automatically enabling write-intent bitmap on lar ge array\n"); | |||
s->bitmap_file = "internal"; | s->bitmap_file = "internal"; | |||
} | } | |||
if (s->bitmap_file && strcmp(s->bitmap_file, "none") == 0) | if (s->bitmap_file && strcmp(s->bitmap_file, "none") == 0) | |||
s->bitmap_file = NULL; | s->bitmap_file = NULL; | |||
skipping to change at line 826 | skipping to change at line 847 | |||
st->ss->uuid_from_super(st, uuid); | st->ss->uuid_from_super(st, uuid); | |||
if (CreateBitmap(s->bitmap_file, c->force, (char*)uuid, s->bitmap _chunk, | if (CreateBitmap(s->bitmap_file, c->force, (char*)uuid, s->bitmap _chunk, | |||
c->delay, s->write_behind, | c->delay, s->write_behind, | |||
bitmapsize, | bitmapsize, | |||
major_num)) { | major_num)) { | |||
goto abort_locked; | goto abort_locked; | |||
} | } | |||
bitmap_fd = open(s->bitmap_file, O_RDWR); | bitmap_fd = open(s->bitmap_file, O_RDWR); | |||
if (bitmap_fd < 0) { | if (bitmap_fd < 0) { | |||
pr_err("weird: %s cannot be openned\n", | pr_err("weird: %s cannot be opened\n", | |||
s->bitmap_file); | s->bitmap_file); | |||
goto abort_locked; | goto abort_locked; | |||
} | } | |||
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { | if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { | |||
pr_err("Cannot set bitmap file for %s: %s\n", | pr_err("Cannot set bitmap file for %s: %s\n", | |||
mddev, strerror(errno)); | mddev, strerror(errno)); | |||
goto abort_locked; | goto abort_locked; | |||
} | } | |||
} | } | |||
skipping to change at line 881 | skipping to change at line 902 | |||
if (dv->disposition == 'j') { | if (dv->disposition == 'j') { | |||
inf->disk.raid_disk = MD_DISK_ROLE_JOURNA L; | inf->disk.raid_disk = MD_DISK_ROLE_JOURNA L; | |||
inf->disk.state = (1<<MD_DISK_JOURNAL); | inf->disk.state = (1<<MD_DISK_JOURNAL); | |||
raid_disk_num--; | raid_disk_num--; | |||
} else if (inf->disk.raid_disk < s->raiddisks) | } else if (inf->disk.raid_disk < s->raiddisks) | |||
inf->disk.state = (1<<MD_DISK_ACTIVE) | | inf->disk.state = (1<<MD_DISK_ACTIVE) | | |||
(1<<MD_DISK_SYNC); | (1<<MD_DISK_SYNC); | |||
else | else | |||
inf->disk.state = 0; | inf->disk.state = 0; | |||
if (dv->writemostly == FlagSet) | if (dv->writemostly == FlagSet) { | |||
inf->disk.state |= (1<<MD_DISK_WRITEMOSTL | if (major_num == BITMAP_MAJOR_CLUSTERED) | |||
Y); | { | |||
pr_err("Can not set %s --write-mo | ||||
stly with a clustered bitmap\n",dv->devname); | ||||
goto abort_locked; | ||||
} else | ||||
inf->disk.state |= (1<<MD_DISK_WR | ||||
ITEMOSTLY); | ||||
} | ||||
if (dv->failfast == FlagSet) | if (dv->failfast == FlagSet) | |||
inf->disk.state |= (1<<MD_DISK_FAILFAST); | inf->disk.state |= (1<<MD_DISK_FAILFAST); | |||
if (have_container) | if (have_container) | |||
fd = -1; | fd = -1; | |||
else { | else { | |||
if (st->ss->external && | if (st->ss->external && | |||
st->container_devnm[0]) | st->container_devnm[0]) | |||
fd = open(dv->devname, O_RDWR); | fd = open(dv->devname, O_RDWR); | |||
else | else | |||
skipping to change at line 936 | skipping to change at line 962 | |||
} | } | |||
break; | break; | |||
case 2: | case 2: | |||
inf->errors = 0; | inf->errors = 0; | |||
rv = add_disk(mdfd, st, &info, inf); | rv = add_disk(mdfd, st, &info, inf); | |||
if (rv) { | 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)); | dv->devname, strerror(errno)); | |||
if (errno == EINVAL && | ||||
info.array.level == 0) { | ||||
pr_err("Possibly your kernel does | ||||
n't support RAID0 layouts.\n"); | ||||
pr_err("Either upgrade, or use -- | ||||
layout=dangerous\n"); | ||||
} | ||||
goto abort_locked; | goto abort_locked; | |||
} | } | |||
break; | break; | |||
} | } | |||
if (!have_container && | if (!have_container && | |||
dv == moved_disk && dnum != insert_point) break; | dv == moved_disk && dnum != insert_point) break; | |||
} | } | |||
if (pass == 1) { | if (pass == 1) { | |||
struct mdinfo info_new; | struct mdinfo info_new; | |||
struct map_ent *me = NULL; | struct map_ent *me = NULL; | |||
skipping to change at line 966 | skipping to change at line 997 | |||
map_update(&map, fd2devnm(mdfd), | map_update(&map, fd2devnm(mdfd), | |||
info_new.text_version, | info_new.text_version, | |||
info_new.uuid, chosen_name); | info_new.uuid, chosen_name); | |||
me = map_by_devnm(&map, st->container_devnm); | me = map_by_devnm(&map, st->container_devnm); | |||
} | } | |||
if (st->ss->write_init_super(st)) { | if (st->ss->write_init_super(st)) { | |||
st->ss->free_super(st); | st->ss->free_super(st); | |||
goto abort_locked; | goto abort_locked; | |||
} | } | |||
/* | ||||
* Before activating the array, perform extra steps | ||||
* required to configure the internal write-intent | ||||
* bitmap. | ||||
*/ | ||||
if (info_new.consistency_policy == | ||||
CONSISTENCY_POLICY_BITMAP && | ||||
st->ss->set_bitmap && | ||||
st->ss->set_bitmap(st, &info)) { | ||||
st->ss->free_super(st); | ||||
goto abort_locked; | ||||
} | ||||
/* update parent container uuid */ | /* update parent container uuid */ | |||
if (me) { | if (me) { | |||
char *path = xstrdup(me->path); | char *path = xstrdup(me->path); | |||
st->ss->getinfo_super(st, &info_new, NULL); | st->ss->getinfo_super(st, &info_new, NULL); | |||
map_update(&map, st->container_devnm, | map_update(&map, st->container_devnm, | |||
info_new.text_version, | info_new.text_version, | |||
info_new.uuid, path); | info_new.uuid, path); | |||
free(path); | free(path); | |||
skipping to change at line 1032 | skipping to change at line 1075 | |||
strerror(errno)); | strerror(errno)); | |||
ioctl(mdfd, STOP_ARRAY, NULL); | ioctl(mdfd, STOP_ARRAY, NULL); | |||
goto abort; | goto abort; | |||
} | } | |||
} else { | } else { | |||
/* param is not actually used */ | /* param is not actually used */ | |||
mdu_param_t param; | mdu_param_t param; | |||
if (ioctl(mdfd, RUN_ARRAY, ¶m)) { | if (ioctl(mdfd, RUN_ARRAY, ¶m)) { | |||
pr_err("RUN_ARRAY failed: %s\n", | pr_err("RUN_ARRAY failed: %s\n", | |||
strerror(errno)); | 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_siz e-1)) { | if (info.array.chunk_size & (info.array.chunk_siz e-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); | ioctl(mdfd, STOP_ARRAY, NULL); | |||
goto abort; | goto abort; | |||
} | } | |||
/* if start_ro module parameter is set, array is | /* if start_ro module parameter is set, array is | |||
* auto-read-only, which is bad as the resync won't | * auto-read-only, which is bad as the resync won't | |||
* start. So lets make it read-write now. | * start. So lets make it read-write now. | |||
*/ | */ | |||
skipping to change at line 1057 | skipping to change at line 1103 | |||
if (need_mdmon) | if (need_mdmon) | |||
start_mdmon(st->container_devnm); | start_mdmon(st->container_devnm); | |||
ping_monitor(st->container_devnm); | ping_monitor(st->container_devnm); | |||
close(container_fd); | close(container_fd); | |||
} | } | |||
wait_for(chosen_name, mdfd); | wait_for(chosen_name, mdfd); | |||
} else { | } else { | |||
pr_err("not starting array - not enough devices.\n"); | 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(); | udev_unblock(); | |||
close(mdfd); | ||||
sysfs_uevent(&info, "change"); | ||||
return 0; | return 0; | |||
abort: | abort: | |||
udev_unblock(); | udev_unblock(); | |||
map_lock(&map); | map_lock(&map); | |||
abort_locked: | abort_locked: | |||
map_remove(&map, fd2devnm(mdfd)); | map_remove(&map, fd2devnm(mdfd)); | |||
map_unlock(&map); | map_unlock(&map); | |||
if (mdfd >= 0) | if (mdfd >= 0) | |||
End of changes. 17 change blocks. | ||||
16 lines changed or deleted | 65 lines changed or added |