/*
* mdadm - manage Linux "md" devices aka RAID arrays.
*
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
*
*
* This program is free software; you can redistribute it and/or modify
st = super_by_fd(fd, &subarray);
if (!st) {
- pr_err("cannot handle arrays with superblock version %d\n", info.array.major_version);
+ pr_err("cannot handle arrays with superblock version %d\n",
+ info.array.major_version);
return 1;
}
free(st);
return 1;
}
- /* now check out all the devices and make sure we can read the superblock */
+ /* now check out all the devices and make sure we can read the
+ * superblock */
for (d=0 ; d < info.array.raid_disks ; d++) {
mdu_disk_info_t disk;
char *dv;
return 0;
}
-int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force)
+int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
{
/*
* First check that array doesn't have a bitmap
return 1;
}
if (bmf.pathname[0]) {
- if (strcmp(file,"none")==0) {
+ if (strcmp(s->bitmap_file,"none")==0) {
if (ioctl(fd, SET_BITMAP_FILE, -1)!= 0) {
pr_err("failed to remove bitmap %s\n",
bmf.pathname);
return 1;
}
if (array.state & (1<<MD_SB_BITMAP_PRESENT)) {
- if (strcmp(file, "none")==0) {
+ if (strcmp(s->bitmap_file, "none")==0) {
array.state &= ~(1<<MD_SB_BITMAP_PRESENT);
if (ioctl(fd, SET_ARRAY_INFO, &array)!= 0) {
pr_err("failed to remove internal bitmap.\n");
return 1;
}
- if (strcmp(file, "none") == 0) {
+ if (strcmp(s->bitmap_file, "none") == 0) {
pr_err("no bitmap found on %s\n", devname);
return 1;
}
free(st);
return 1;
}
- if (strcmp(file, "internal") == 0) {
+ if (strcmp(s->bitmap_file, "internal") == 0) {
int rv;
int d;
int offset_setable = 0;
if (st->ss->load_super(st, fd2, NULL)==0) {
if (st->ss->add_internal_bitmap(
st,
- &chunk, delay, write_behind,
+ &s->bitmap_chunk, c->delay, s->write_behind,
bitmapsize, offset_setable,
major)
)
st->ss->write_bitmap(st, fd2);
else {
- pr_err("failed "
- "to create internal bitmap - chunksize problem.\n");
+ pr_err("failed to create internal bitmap"
+ " - chunksize problem.\n");
close(fd2);
return 1;
}
int max_devs = st->max_devs;
/* try to load a superblock */
- for (d=0; d<max_devs; d++) {
+ for (d = 0; d < max_devs; d++) {
mdu_disk_info_t disk;
char *dv;
int fd2;
(disk.state & (1<<MD_DISK_REMOVED)))
continue;
dv = map_dev(disk.major, disk.minor, 1);
- if (!dv) continue;
+ if (!dv)
+ continue;
fd2 = dev_open(dv, O_RDONLY);
if (fd2 >= 0) {
if (st->ss->load_super(st, fd2, NULL) == 0) {
pr_err("cannot find UUID for array!\n");
return 1;
}
- if (CreateBitmap(file, force, (char*)uuid, chunk,
- delay, write_behind, bitmapsize, major)) {
+ if (CreateBitmap(s->bitmap_file, c->force, (char*)uuid, s->bitmap_chunk,
+ c->delay, s->write_behind, bitmapsize, major)) {
return 1;
}
- bitmap_fd = open(file, O_RDWR);
+ bitmap_fd = open(s->bitmap_file, O_RDWR);
if (bitmap_fd < 0) {
pr_err("weird: %s cannot be opened\n",
- file);
+ s->bitmap_file);
return 1;
}
if (ioctl(fd, SET_BITMAP_FILE, bitmap_fd) < 0) {
{
int i;
int csum = 0;
- for (i=0; i<len; i++)
+ for (i = 0; i < len; i++)
csum = (csum<<3) + buf[0];
return __cpu_to_le32(csum);
}
switch (re->level) {
case 4:
- re->after.layout = 0 ; break;
+ re->after.layout = 0;
+ break;
case 5:
- re->after.layout = ALGORITHM_PARITY_N; break;
+ re->after.layout = ALGORITHM_PARITY_N;
+ break;
}
break;
switch (re->level) {
case 4:
- re->after.layout = 0 ; break;
+ re->after.layout = 0;
+ break;
case 5:
- re->after.layout = ALGORITHM_PARITY_N; break;
+ re->after.layout = ALGORITHM_PARITY_N;
+ break;
}
break;
+ info->delta_disks
- delta_parity);
switch (re->level) {
- case 6: re->parity = 2; break;
+ case 6: re->parity = 2;
+ break;
case 4:
- case 5: re->parity = 1; break;
- default: re->parity = 0; break;
+ case 5: re->parity = 1;
+ break;
+ default: re->parity = 0;
+ break;
}
/* So we have a restripe operation, we need to calculate the number
* of blocks per reshape operation.
char *backup_file,
int verbose, int restart, int freeze_reshape);
-int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
- unsigned long long size,
- int level, char *layout_str, int chunksize, int raid_disks,
+int Grow_reshape(char *devname, int fd,
struct mddev_dev *devlist,
- int assume_clean, int force)
+ struct context *c, struct shape *s)
{
/* Make some changes in the shape of an array.
* The kernel must support the change.
return 1;
}
- if (size > 0 &&
- (chunksize || level!= UnSet || layout_str || raid_disks)) {
+ if (s->size > 0 &&
+ (s->chunk || s->level!= UnSet || s->layout_str || s->raiddisks)) {
pr_err("cannot change component size at the same time "
"as other changes.\n"
" Change size first, then check data is intact before "
return 1;
}
- if (raid_disks && raid_disks < array.raid_disks && array.level > 1 &&
+ if (s->raiddisks && s->raiddisks < array.raid_disks && array.level > 1 &&
get_linux_version() < 2006032 &&
!check_env("MDADM_FORCE_FEWER")) {
pr_err("reducing the number of devices is not safe before Linux 2.6.32\n"
pr_err("Unable to determine metadata format for %s\n", devname);
return 1;
}
- if (raid_disks > st->max_devs) {
+ if (s->raiddisks > st->max_devs) {
pr_err("Cannot increase raid-disks on this array"
" beyond %d\n", st->max_devs);
return 1;
added_disks = 0;
for (dv = devlist; dv; dv = dv->next)
added_disks++;
- if (raid_disks > array.raid_disks &&
- array.spare_disks +added_disks < (raid_disks - array.raid_disks) &&
- !force) {
+ if (s->raiddisks > array.raid_disks &&
+ array.spare_disks +added_disks < (s->raiddisks - array.raid_disks) &&
+ !c->force) {
pr_err("Need %d spare%s to avoid degraded array,"
" and only have %d.\n"
" Use --force to over-ride this check.\n",
- raid_disks - array.raid_disks,
- raid_disks - array.raid_disks == 1 ? "" : "s",
+ s->raiddisks - array.raid_disks,
+ s->raiddisks - array.raid_disks == 1 ? "" : "s",
array.spare_disks + added_disks);
return 1;
}
}
/* ========= set size =============== */
- if (size > 0 && (size == MAX_DISKS || size != (unsigned)array.size)) {
+ if (s->size > 0 && (s->size == MAX_DISKS || s->size != (unsigned)array.size)) {
unsigned long long orig_size = get_component_size(fd)/2;
unsigned long long min_csize;
struct mdinfo *mdi;
if (orig_size == 0)
orig_size = (unsigned) array.size;
- if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL,
- devname, APPLY_METADATA_CHANGES, verbose > 0)) {
+ if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
+ devname, APPLY_METADATA_CHANGES, c->verbose > 0)) {
rv = 1;
goto release;
}
dprintf("Metadata size correction from %llu to "
"%llu (%llu)\n", orig_size, new_size,
new_size * data_disks);
- size = new_size;
+ s->size = new_size;
sysfs_free(sizeinfo);
}
}
rv = 0;
for (mdi = sra->devs; mdi; mdi = mdi->next) {
if (sysfs_set_num(sra, mdi, "size",
- size == MAX_SIZE ? 0 : size) < 0) {
+ s->size == MAX_SIZE ? 0 : s->size) < 0) {
/* Probably kernel refusing to let us
* reduce the size - not an error.
*/
"array members.\n");
goto size_change_error;
}
- if (min_csize && size > min_csize) {
+ if (min_csize && s->size > min_csize) {
pr_err("Cannot safely make this array "
"use more than 2TB per device on this kernel.\n");
rv = 1;
goto size_change_error;
}
- if (min_csize && size == MAX_SIZE) {
+ if (min_csize && s->size == MAX_SIZE) {
/* Don't let the kernel choose a size - it will get
* it wrong
*/
pr_err("Limited v0.90 array to "
"2TB per device\n");
- size = min_csize;
+ s->size = min_csize;
}
if (st->ss->external) {
if (sra->array.level == 0) {
st->update_tail = &st->updates;
}
- array.size = size == MAX_SIZE ? 0 : size;
- if ((unsigned)array.size != size) {
+ if (s->size == MAX_SIZE)
+ s->size = 0;
+ array.size = s->size;
+ if ((unsigned)array.size != s->size) {
/* got truncated to 32bit, write to
* component_size instead
*/
if (sra)
rv = sysfs_set_num(sra, NULL,
- "component_size", size);
+ "component_size", s->size);
else
rv = -1;
} else {
if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
UnSet, NULL, devname,
ROLLBACK_METADATA_CHANGES,
- verbose) == 0)
+ c->verbose) == 0)
sync_metadata(st);
pr_err("Cannot set device size for %s: %s\n",
devname, strerror(err));
rv = 1;
goto release;
}
- if (assume_clean) {
+ if (s->assume_clean) {
/* This will fail on kernels newer than 3.0 unless
* a backport has been arranged.
*/
pr_err("--assume-clean not support with --grow on this kernel\n");
}
ioctl(fd, GET_ARRAY_INFO, &array);
- size = get_component_size(fd)/2;
- if (size == 0)
- size = array.size;
- if (verbose >= 0) {
- if (size == orig_size)
+ s->size = get_component_size(fd)/2;
+ if (s->size == 0)
+ s->size = array.size;
+ if (c->verbose >= 0) {
+ if (s->size == orig_size)
pr_err("component size of %s "
"unchanged at %lluK\n",
- devname, size);
+ devname, s->size);
else
pr_err("component size of %s "
"has been set to %lluK\n",
- devname, size);
+ devname, s->size);
}
changed = 1;
} else if (array.level != LEVEL_CONTAINER) {
- size = get_component_size(fd)/2;
- if (size == 0)
- size = array.size;
+ s->size = get_component_size(fd)/2;
+ if (s->size == 0)
+ s->size = array.size;
}
/* See if there is anything else to do */
- if ((level == UnSet || level == array.level) &&
- (layout_str == NULL) &&
- (chunksize == 0 || chunksize == array.chunk_size) &&
- (raid_disks == 0 || raid_disks == array.raid_disks)) {
+ if ((s->level == UnSet || s->level == array.level) &&
+ (s->layout_str == NULL) &&
+ (s->chunk == 0 || s->chunk == array.chunk_size) &&
+ (s->raiddisks == 0 || s->raiddisks == array.raid_disks)) {
/* Nothing more to do */
- if (!changed && verbose >= 0)
+ if (!changed && c->verbose >= 0)
pr_err("%s: no change requested\n",
devname);
goto release;
* - far_copies == 1
* - near_copies == 2
*/
- if ((level == 0 && array.level == 10 && sra &&
+ if ((s->level == 0 && array.level == 10 && sra &&
array.layout == ((1 << 8) + 2) && !(array.raid_disks & 1)) ||
- (level == 0 && array.level == 1 && sra)) {
+ (s->level == 0 && array.level == 1 && sra)) {
int err;
err = remove_disks_for_takeover(st, sra, array.layout);
if (err) {
info.array = array;
sysfs_init(&info, fd, NoMdDev);
strcpy(info.text_version, sra->text_version);
- info.component_size = size*2;
- info.new_level = level;
- info.new_chunk = chunksize * 1024;
+ info.component_size = s->size*2;
+ info.new_level = s->level;
+ info.new_chunk = s->chunk * 1024;
if (info.array.level == LEVEL_CONTAINER) {
info.delta_disks = UnSet;
- info.array.raid_disks = raid_disks;
- } else if (raid_disks)
- info.delta_disks = raid_disks - info.array.raid_disks;
+ info.array.raid_disks = s->raiddisks;
+ } else if (s->raiddisks)
+ info.delta_disks = s->raiddisks - info.array.raid_disks;
else
info.delta_disks = UnSet;
- if (layout_str == NULL) {
+ if (s->layout_str == NULL) {
info.new_layout = UnSet;
if (info.array.level == 6 &&
(info.new_level == 6 || info.new_level == UnSet) &&
rv = 1;
goto release;
}
- } else if (strcmp(layout_str, "normalise") == 0 ||
- strcmp(layout_str, "normalize") == 0) {
+ } else if (strcmp(s->layout_str, "normalise") == 0 ||
+ strcmp(s->layout_str, "normalize") == 0) {
/* If we have a -6 RAID6 layout, remove the '-6'. */
info.new_layout = UnSet;
if (info.array.level == 6 && info.new_level == UnSet) {
}
} else {
pr_err("%s is only meaningful when reshaping"
- " a RAID6 array.\n", layout_str);
+ " a RAID6 array.\n", s->layout_str);
rv = 1;
goto release;
}
- } else if (strcmp(layout_str, "preserve") == 0) {
+ } else if (strcmp(s->layout_str, "preserve") == 0) {
/* This means that a non-standard RAID6 layout
* is OK.
* In particular:
info.new_layout = map_name(r6layout, l);
} else {
pr_err("%s in only meaningful when reshaping"
- " to RAID6\n", layout_str);
+ " to RAID6\n", s->layout_str);
rv = 1;
goto release;
}
l = info.array.level;
switch (l) {
case 5:
- info.new_layout = map_name(r5layout, layout_str);
+ info.new_layout = map_name(r5layout, s->layout_str);
break;
case 6:
- info.new_layout = map_name(r6layout, layout_str);
+ info.new_layout = map_name(r6layout, s->layout_str);
break;
case 10:
- info.new_layout = parse_layout_10(layout_str);
+ info.new_layout = parse_layout_10(s->layout_str);
break;
case LEVEL_FAULTY:
- info.new_layout = parse_layout_faulty(layout_str);
+ info.new_layout = parse_layout_faulty(s->layout_str);
break;
default:
pr_err("layout not meaningful"
if (info.new_layout == UnSet) {
pr_err("layout %s not understood"
" for this level\n",
- layout_str);
+ s->layout_str);
rv = 1;
goto release;
}
}
if (array.level == LEVEL_FAULTY) {
- if (level != UnSet && level != array.level) {
+ if (s->level != UnSet && s->level != array.level) {
pr_err("cannot change level of Faulty device\n");
rv =1 ;
}
- if (chunksize) {
+ if (s->chunk) {
pr_err("cannot set chunksize of Faulty device\n");
rv =1 ;
}
- if (raid_disks && raid_disks != 1) {
+ if (s->raiddisks && s->raiddisks != 1) {
pr_err("cannot set raid_disks of Faulty device\n");
rv =1 ;
}
- if (layout_str) {
+ if (s->layout_str) {
if (ioctl(fd, GET_ARRAY_INFO, &array) != 0) {
dprintf("Cannot get array information.\n");
goto release;
if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) {
pr_err("failed to set new layout\n");
rv = 1;
- } else if (verbose >= 0)
+ } else if (c->verbose >= 0)
printf("layout for %s set to %d\n",
devname, array.layout);
}
* performed at the level of the container
*/
rv = reshape_container(container, devname, -1, st, &info,
- force, backup_file, verbose, 0, 0);
+ c->force, c->backup_file, c->verbose, 0, 0);
frozen = 0;
} else {
/* get spare devices from external metadata
if (reshape_super(st, -1, info.new_level,
info.new_layout, info.new_chunk,
info.array.raid_disks, info.delta_disks,
- backup_file, devname, APPLY_METADATA_CHANGES,
- verbose)) {
+ c->backup_file, devname, APPLY_METADATA_CHANGES,
+ c->verbose)) {
rv = 1;
goto release;
}
sync_metadata(st);
- rv = reshape_array(container, fd, devname, st, &info, force,
- devlist, backup_file, verbose, 0, 0, 0);
+ rv = reshape_array(container, fd, devname, st, &info, c->force,
+ devlist, c->backup_file, c->verbose, 0, 0, 0);
frozen = 0;
}
release:
}
}
for (j=0; j<info->array.raid_disks; j++) {
- if (fdlist[j] < 0) continue;
+ if (fdlist[j] < 0)
+ continue;
if (st->ss->load_super(st, fdlist[j], NULL))
continue;
st->ss->getinfo_super(st, &dinfo, NULL);