" between different architectures. Consider upgrading the Linux kernel.\n");
}
+ /*
+ * We only ever get called if s->bitmap_file is != NULL, so this check
+ * is just here to quiet down static code checkers.
+ */
+ if (!s->bitmap_file)
+ return 1;
+
+ if (strcmp(s->bitmap_file, "clustered") == 0)
+ major = BITMAP_MAJOR_CLUSTERED;
+
if (ioctl(fd, GET_BITMAP_FILE, &bmf) != 0) {
if (errno == ENOMEM)
pr_err("Memory allocation failure.\n");
return 1;
}
if (bmf.pathname[0]) {
- if (strcmp(s->bitmap_file,"none")==0) {
- if (ioctl(fd, SET_BITMAP_FILE, -1)!= 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;
pr_err("cannot get array status for %s\n", devname);
return 1;
}
- if (array.state & (1<<MD_SB_BITMAP_PRESENT)) {
+ if (array.state & (1 << MD_SB_BITMAP_PRESENT)) {
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");
+ array.state &= ~(1 << MD_SB_BITMAP_PRESENT);
+ if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) {
+ if (array.state & (1 << MD_SB_CLUSTERED))
+ pr_err("failed to remove clustered bitmap.\n");
+ else
+ pr_err("failed to remove internal bitmap.\n");
return 1;
}
return 0;
}
- pr_err("%s bitmap already present on %s\n", s->bitmap_file, devname);
+ pr_err("bitmap already present on %s\n", devname);
return 1;
}
bitmapsize = array.size;
bitmapsize <<= 1;
if (get_dev_size(fd, NULL, &array_size) &&
- array_size > (0x7fffffffULL<<9)) {
+ array_size > (0x7fffffffULL << 9)) {
/* Array is big enough that we cannot trust array.size
* try other approaches
*/
}
if (array.level == 10) {
- int ncopies = (array.layout&255)*((array.layout>>8)&255);
+ int ncopies;
+
+ ncopies = (array.layout & 255) * ((array.layout >> 8) & 255);
bitmapsize = bitmapsize * array.raid_disks / ncopies;
}
mdi = sysfs_read(fd, NULL, GET_BITMAP_LOCATION);
if (mdi)
offset_setable = 1;
- for (d=0; d< st->max_devs; d++) {
+ for (d = 0; d < st->max_devs; d++) {
mdu_disk_info_t disk;
char *dv;
+ int fd2;
+
disk.number = d;
if (ioctl(fd, GET_DISK_INFO, &disk) < 0)
continue;
- if (disk.major == 0 &&
- disk.minor == 0)
+ if (disk.major == 0 && disk.minor == 0)
continue;
- if ((disk.state & (1<<MD_DISK_SYNC))==0)
+ if ((disk.state & (1 << MD_DISK_SYNC)) == 0)
continue;
dv = map_dev(disk.major, disk.minor, 1);
- if (dv) {
- int fd2 = dev_open(dv, O_RDWR);
- if (fd2 < 0)
- continue;
- if (st->ss->load_super(st, fd2, NULL)==0) {
- if (st->ss->add_internal_bitmap(
- st,
- &s->bitmap_chunk, c->delay, s->write_behind,
- bitmapsize, offset_setable,
- major)
- )
- st->ss->write_bitmap(st, fd2, NoUpdate);
- else {
- pr_err("failed to create internal bitmap - chunksize problem.\n");
- close(fd2);
- return 1;
- }
+ if (!dv)
+ continue;
+ fd2 = dev_open(dv, O_RDWR);
+ if (fd2 < 0)
+ continue;
+ rv = st->ss->load_super(st, fd2, NULL);
+ if (!rv) {
+ rv = st->ss->add_internal_bitmap(
+ st, &s->bitmap_chunk, c->delay,
+ s->write_behind, bitmapsize,
+ offset_setable, major);
+ if (!rv) {
+ st->ss->write_bitmap(st, fd2,
+ NodeNumUpdate);
+ } else {
+ pr_err("failed to create internal bitmap - chunksize problem.\n");
}
- close(fd2);
+ } else {
+ pr_err("failed to load super-block.\n");
}
+ close(fd2);
+ if (rv)
+ return 1;
}
if (offset_setable) {
st->ss->getinfo_super(st, mdi, NULL);
mdi->bitmap_offset);
} else {
if (strcmp(s->bitmap_file, "clustered") == 0)
- array.state |= (1<<MD_SB_CLUSTERED);
- array.state |= (1<<MD_SB_BITMAP_PRESENT);
+ array.state |= (1 << MD_SB_CLUSTERED);
+ array.state |= (1 << MD_SB_BITMAP_PRESENT);
rv = ioctl(fd, SET_ARRAY_INFO, &array);
}
if (rv < 0) {
disk.number = d;
if (ioctl(fd, GET_DISK_INFO, &disk) < 0)
continue;
- if ((disk.major==0 && disk.minor==0) ||
- (disk.state & (1<<MD_DISK_REMOVED)))
+ if ((disk.major==0 && disk.minor == 0) ||
+ (disk.state & (1 << MD_DISK_REMOVED)))
continue;
dv = map_dev(disk.major, disk.minor, 1);
if (!dv)
pr_err("cannot find UUID for array!\n");
return 1;
}
- if (CreateBitmap(s->bitmap_file, c->force, (char*)uuid, s->bitmap_chunk,
- c->delay, s->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(s->bitmap_file, O_RDWR);
if (bitmap_fd < 0) {
- pr_err("weird: %s cannot be opened\n",
- s->bitmap_file);
+ pr_err("weird: %s cannot be opened\n", s->bitmap_file);
return 1;
}
if (ioctl(fd, SET_BITMAP_FILE, bitmap_fd) < 0) {
void abort_reshape(struct mdinfo *sra)
{
sysfs_set_str(sra, NULL, "sync_action", "idle");
+ /*
+ * Prior to kernel commit: 23ddff3792f6 ("md: allow suspend_lo and
+ * suspend_hi to decrease as well as increase.")
+ * you could only increase suspend_{lo,hi} unless the region they
+ * covered was empty. So to reset to 0, you need to push suspend_lo
+ * up past suspend_hi first. So to maximize the chance of mdadm
+ * working on all kernels, we want to keep doing that.
+ */
sysfs_set_num(sra, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL);
sysfs_set_num(sra, NULL, "suspend_hi", 0);
sysfs_set_num(sra, NULL, "suspend_lo", 0);
re->level = 1;
return NULL;
}
+ if (info->array.raid_disks != 2 &&
+ info->new_level == 5)
+ return "Can only convert a 2-device array to RAID5";
if (info->array.raid_disks == 2 &&
info->new_level == 5) {
pr_err("Cannot increase raid-disks on this array beyond %d\n", st->max_devs);
return 1;
}
+ if (s->level == 0 &&
+ (array.state & (1<<MD_SB_BITMAP_PRESENT)) &&
+ !(array.state & (1<<MD_SB_CLUSTERED))) {
+ 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;
+ }
+ }
/* in the external case we need to check that the requested reshape is
* supported, and perform an initial check that the container holds the
* number of devices (On-Line Capacity Expansion) must be
* performed at the level of the container
*/
+ if (fd > 0) {
+ close(fd);
+ fd = -1;
+ }
rv = reshape_container(container, devname, -1, st, &info,
c->force, c->backup_file, c->verbose, 0, 0, 0);
frozen = 0;
* array. Now that the array has been changed to the right
* level and frozen, we can safely add them.
*/
- if (devlist)
- Manage_subdevs(devname, fd, devlist, verbose,
- 0,NULL, 0);
+ if (devlist) {
+ if (Manage_subdevs(devname, fd, devlist, verbose,
+ 0, NULL, 0))
+ goto release;
+ }
if (reshape.backup_blocks == 0 && data_offset != INVALID_SECTORS)
reshape.backup_blocks = reshape.before.data_disks * info->array.chunk_size/512;
int fd;
struct mdstat_ent *mdstat;
char *adev;
- int devid;
+ dev_t devid;
sysfs_free(cc);
* sometimes they aren't... So allow considerable flexability in matching, and allow
* this test to be overridden by an environment variable.
*/
- if (info->array.utime > (int)__le64_to_cpu(bsb.mtime) + 2*60*60 ||
- info->array.utime < (int)__le64_to_cpu(bsb.mtime) - 10*60) {
+ if(time_after(info->array.utime, (unsigned int)__le64_to_cpu(bsb.mtime) + 2*60*60) ||
+ time_before(info->array.utime, (unsigned int)__le64_to_cpu(bsb.mtime) - 10*60)) {
if (check_env("MDADM_GROW_ALLOW_OLD")) {
pr_err("accepting backup with timestamp %lu for array with timestamp %lu\n",
(unsigned long)__le64_to_cpu(bsb.mtime),
struct mdinfo *cc = NULL;
struct mdstat_ent *mdstat = NULL;
int cfd = -1;
- int fd2 = -1;
+ int fd2;
dprintf("Grow continue from command line called for %s\n",
devname);
dprintf("Grow continue is run for ");
if (st->ss->external == 0) {
int d;
+ int cnt = 5;
dprintf_cont("native array (%s)\n", devname);
if (ioctl(fd, GET_ARRAY_INFO, &array.array) < 0) {
pr_err("%s is not an active md array - aborting\n", devname);
* FIXME we should really get what we need from
* sysfs
*/
- for (d = 0; d < MAX_DISKS; d++) {
- mdu_disk_info_t disk;
- char *dv;
- int err;
- disk.number = d;
- if (ioctl(fd, GET_DISK_INFO, &disk) < 0)
- continue;
- if (disk.major == 0 && disk.minor == 0)
- continue;
- if ((disk.state & (1 << MD_DISK_ACTIVE)) == 0)
- continue;
- dv = map_dev(disk.major, disk.minor, 1);
- if (!dv)
- continue;
- fd2 = dev_open(dv, O_RDONLY);
- if (fd2 < 0)
- continue;
- err = st->ss->load_super(st, fd2, NULL);
- close(fd2);
- /* invalidate fd2 to avoid possible double close() */
- fd2 = -1;
- if (err)
- continue;
- break;
- }
- if (d == MAX_DISKS) {
- pr_err("Unable to load metadata for %s\n",
- devname);
- ret_val = 1;
- goto Grow_continue_command_exit;
- }
- st->ss->getinfo_super(st, content, NULL);
+ do {
+ for (d = 0; d < MAX_DISKS; d++) {
+ mdu_disk_info_t disk;
+ char *dv;
+ int err;
+ disk.number = d;
+ if (ioctl(fd, GET_DISK_INFO, &disk) < 0)
+ continue;
+ if (disk.major == 0 && disk.minor == 0)
+ continue;
+ if ((disk.state & (1 << MD_DISK_ACTIVE)) == 0)
+ continue;
+ dv = map_dev(disk.major, disk.minor, 1);
+ if (!dv)
+ continue;
+ fd2 = dev_open(dv, O_RDONLY);
+ if (fd2 < 0)
+ continue;
+ err = st->ss->load_super(st, fd2, NULL);
+ close(fd2);
+ if (err)
+ continue;
+ break;
+ }
+ if (d == MAX_DISKS) {
+ pr_err("Unable to load metadata for %s\n",
+ devname);
+ ret_val = 1;
+ goto Grow_continue_command_exit;
+ }
+ st->ss->getinfo_super(st, content, NULL);
+ if (!content->reshape_active)
+ sleep(3);
+ else
+ break;
+ } while (cnt-- > 0);
} else {
char *container;
sysfs_init(content, fd2, mdstat->devnm);
+ close(fd2);
+
/* start mdmon in case it is not running
*/
if (!mdmon_running(container))
ret_val = Grow_continue(fd, st, content, backup_file, 1, 0);
Grow_continue_command_exit:
- if (fd2 > -1)
- close(fd2);
if (cfd > -1)
close(cfd);
st->ss->free_super(st);