#ifndef MDASSEMBLE
struct mdinfo *mdi;
#endif
+ int rv = 0;
if (md_get_version(fd) < 9000) {
fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
vers[9] = mdi->text_version[0];
sysfs_set_str(mdi, NULL, "metadata_version", vers);
- return 1;
+ rv = 1;
+ goto out;
}
} else {
char *cp;
sysfs_set_str(mdi, NULL, "metadata_version", vers);
cp = strchr(vers+10, '/');
- if (*cp)
+ if (cp)
*cp = 0;
ping_monitor(vers+10);
if (mdi->array.level <= 0)
sysfs_set_str(mdi, NULL, "array_state", "active");
}
- return 0;
+ goto out;
}
#endif
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
fprintf(stderr, Name ": %s does not appear to be active.\n",
devname);
- return 1;
+ rv = 1;
+ goto out;
}
if (readonly>0) {
if (ioctl(fd, STOP_ARRAY_RO, NULL)) {
fprintf(stderr, Name ": failed to set readonly for %s: %s\n",
devname, strerror(errno));
- return 1;
+ rv = 1;
+ goto out;
}
} else if (readonly < 0) {
if (ioctl(fd, RESTART_ARRAY_RW, NULL)) {
fprintf(stderr, Name ": failed to set writable for %s: %s\n",
devname, strerror(errno));
- return 1;
+ rv = 1;
+ goto out;
}
}
- return 0;
+out:
+#ifndef MDASSEMBLE
+ if (mdi)
+ sysfs_free(mdi);
+#endif
+ return rv;
}
#ifndef MDASSEMBLE
sprintf(pe, "%d", part);
}
n = readlink(path2, link, sizeof(link));
- if (n && (int)strlen(base) == n &&
+ if (n > 0 && (int)strlen(base) == n &&
strncmp(link, base, n) == 0)
unlink(path2);
}
* quiet < 0 means we will try again if it fails.
*/
mdu_param_t param; /* unused */
+ int rv = 0;
if (runstop == -1 && md_get_version(fd) < 9000) {
if (ioctl(fd, STOP_MD, 0)) {
fprintf(stderr, Name
": failed to stop array %s: %s\n",
devname, strerror(errno));
- return 1;
+ rv = 1;
+ goto out;
}
/* Give monitor a chance to act */
": failed to completely stop %s"
": Device is busy\n",
devname);
- return 1;
+ rv = 1;
+ goto out;
}
} else if (mdi &&
mdi->array.major_version == -1 &&
"member %s still active\n",
devname, m->dev);
free_mdstat(mds);
- if (mdi)
- sysfs_free(mdi);
- return 1;
+ rv = 1;
+ goto out;
}
}
"process, mounted filesystem "
"or active volume group?\n");
}
- if (mdi)
- sysfs_free(mdi);
- return 1;
+ rv = 1;
+ goto out;
}
/* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array
* was stopped, so We'll do it here just to be sure. Drop any
map_lock(&map);
map_remove(&map, devnum);
map_unlock(&map);
+ out:
+ if (mdi)
+ sysfs_free(mdi);
}
- return 0;
+ return rv;
}
int Manage_resize(char *devname, int fd, long long size, int raid_disks)
int Manage_subdevs(char *devname, int fd,
struct mddev_dev *devlist, int verbose, int test,
- char *update)
+ char *update, int force)
{
/* do something to each dev.
* devmode can be
if (strcmp(dv->devname, "failed")==0 ||
strcmp(dv->devname, "faulty")==0) {
+ int remaining_disks = array.nr_disks;
if (dv->disposition != 'r') {
fprintf(stderr, Name ": %s only meaningful "
"with -r, not -%c\n",
dv->devname, dv->disposition);
return 1;
}
- for (; j < array.raid_disks + array.nr_disks ; j++) {
+ for (; j < 1024 && remaining_disks > 0; j++) {
unsigned dev;
disc.number = j;
if (ioctl(fd, GET_DISK_INFO, &disc))
continue;
if (disc.major == 0 && disc.minor == 0)
continue;
+ remaining_disks --;
if ((disc.state & 1) == 0) /* faulty */
continue;
dev = makedev(disc.major, disc.minor);
if (next != dv)
continue;
} else if (strcmp(dv->devname, "detached") == 0) {
+ int remaining_disks = array.nr_disks;
if (dv->disposition != 'r' && dv->disposition != 'f') {
fprintf(stderr, Name ": %s only meaningful "
"with -r of -f, not -%c\n",
dv->devname, dv->disposition);
return 1;
}
- for (; j < array.raid_disks + array.nr_disks; j++) {
+ for (; j < 1024 && remaining_disks > 0; j++) {
int sfd;
unsigned dev;
disc.number = j;
continue;
if (disc.major == 0 && disc.minor == 0)
continue;
+ remaining_disks --;
sprintf(dvname,"%d:%d", disc.major, disc.minor);
sfd = dev_open(dvname, O_RDONLY);
if (sfd >= 0) {
if (add_dev == dv->devname) {
if (!get_dev_size(tfd, dv->devname, &ldsize)) {
+ st->ss->free_super(st);
close(tfd);
return 1;
}
} else if (!get_dev_size(tfd, NULL, &ldsize)) {
+ st->ss->free_super(st);
close(tfd);
tfd = -1;
continue;
}
+ if (tst->ss->validate_geometry(
+ tst, array.level, array.layout,
+ array.raid_disks, NULL,
+ ldsize >> 9, NULL, NULL, 0) == 0) {
+ if (!force) {
+ fprintf(stderr, Name
+ ": %s is larger than %s can "
+ "effectively use.\n"
+ " Add --force is you "
+ "really wan to add this device.\n",
+ add_dev, devname);
+ st->ss->free_super(st);
+ close(tfd);
+ return 1;
+ }
+ fprintf(stderr, Name
+ ": %s is larger than %s can "
+ "effectively use.\n"
+ " Adding anyway as --force "
+ "was given.\n",
+ add_dev, devname);
+ }
if (!tst->ss->external &&
array.major_version == 0 &&
md_get_version(fd)%100 < 2) {
close(tfd);
+ st->ss->free_super(st);
tfd = -1;
if (ioctl(fd, HOT_ADD_DISK,
(unsigned long)stb.st_rdev)==0) {
/* FIXME this is a bad test to be using */
if (!tst->sb) {
close(tfd);
+ st->ss->free_super(st);
fprintf(stderr, Name ": cannot load array metadata from %s\n", devname);
return 1;
}
array_size) {
close(tfd);
tfd = -1;
+ st->ss->free_super(st);
if (add_dev != dv->devname)
continue;
fprintf(stderr, Name ": %s not large enough to join array\n",
*/
tst->ss->uuid_from_super(tst, duuid);
- /* re-add doesn't work for version-1 superblocks
- * before 2.6.18 :-(
- */
- if (array.major_version == 1 &&
- get_linux_version() <= 2006018)
- ;
- else if (st->sb) {
+ if (st->sb) {
struct mdinfo mdi;
st->ss->getinfo_super(st, &mdi, NULL);
st->ss->uuid_from_super(st, ouuid);
/* look like it is worth a try. Need to
* make sure kernel will accept it though.
*/
+ /* re-add doesn't work for version-1 superblocks
+ * before 2.6.18 :-(
+ */
+ if (array.major_version == 1 &&
+ get_linux_version() <= 2006018)
+ goto skip_re_add;
disc.number = mdi.disk.number;
if (ioctl(fd, GET_DISK_INFO, &disc) != 0
|| disc.major != 0 || disc.minor != 0
remove_partitions(tfd);
close(tfd);
tfd = -1;
- if (update) {
+ if (update || dv->writemostly > 0) {
int rv = -1;
tfd = dev_open(dv->devname, O_RDWR);
+ if (tfd < 0) {
+ fprintf(stderr, Name ": failed to open %s for"
+ " superblock update during re-add\n", dv->devname);
+ st->ss->free_super(st);
+ return 1;
+ }
- if (tfd >= 0)
+ if (dv->writemostly == 1)
+ rv = st->ss->update_super(
+ st, NULL, "writemostly",
+ devname, verbose, 0, NULL);
+ if (dv->writemostly == 2)
+ rv = st->ss->update_super(
+ st, NULL, "readwrite",
+ devname, verbose, 0, NULL);
+ if (update)
rv = st->ss->update_super(
st, NULL, update,
devname, verbose, 0, NULL);
if (rv != 0) {
fprintf(stderr, Name ": failed to update"
" superblock during re-add\n");
+ st->ss->free_super(st);
return 1;
}
}
if (verbose >= 0)
fprintf(stderr, Name ": re-added %s\n", add_dev);
count++;
+ st->ss->free_super(st);
continue;
}
if (errno == ENOMEM || errno == EROFS) {
fprintf(stderr, Name ": add new device failed for %s: %s\n",
add_dev, strerror(errno));
+ st->ss->free_super(st);
if (add_dev != dv->devname)
continue;
return 1;
sprintf(devname, "%d:%d", major(devid), minor(devid));
devlist.disposition = 'r';
- if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL) == 0) {
+ if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
devlist.disposition = 'a';
- if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL) == 0) {
+ if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL, 0) == 0) {
/* make sure manager is aware of changes */
ping_manager(to_devname);
ping_manager(from_devname);
close(fd2);
return 1;
}
- else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL);
+ else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0);
}
close(fd1);
close(fd2);