summaryrefslogtreecommitdiffstats
path: root/Manage.c
diff options
context:
space:
mode:
Diffstat (limited to 'Manage.c')
-rw-r--r--Manage.c187
1 files changed, 83 insertions, 104 deletions
diff --git a/Manage.c b/Manage.c
index f0304e1..b9e55c4 100644
--- a/Manage.c
+++ b/Manage.c
@@ -26,6 +26,8 @@
#include "md_u.h"
#include "md_p.h"
#include "udev.h"
+#include "xmalloc.h"
+
#include <ctype.h>
int Manage_ro(char *devname, int fd, int readonly)
@@ -238,13 +240,14 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
"array_state",
"inactive")) < 0 &&
errno == EBUSY) {
+ err = errno;
sleep_for(0, MSEC_TO_NSEC(200), true);
count--;
}
if (err) {
if (verbose >= 0)
pr_err("failed to stop array %s: %s\n",
- devname, strerror(errno));
+ devname, strerror(err));
rv = 1;
goto out;
}
@@ -276,10 +279,8 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
*/
mds = mdstat_read(0, 0);
for (m = mds; m; m = m->next)
- if (m->metadata_version &&
- strncmp(m->metadata_version, "external:", 9)==0 &&
- metadata_container_matches(m->metadata_version+9,
- devnm)) {
+ if (is_mdstat_ent_external(m) &&
+ metadata_container_matches(m->metadata_version + 9, devnm)) {
if (verbose >= 0)
pr_err("Cannot stop container %s: member %s still active\n",
devname, m->devnm);
@@ -440,14 +441,15 @@ done:
count = 25; err = 0;
while (count && fd >= 0 &&
(err = ioctl(fd, STOP_ARRAY, NULL)) < 0 && errno == EBUSY) {
+ err = errno;
sleep_for(0, MSEC_TO_NSEC(200), true);
count --;
}
if (fd >= 0 && err) {
if (verbose >= 0) {
pr_err("failed to stop array %s: %s\n",
- devname, strerror(errno));
- if (errno == EBUSY)
+ devname, strerror(err));
+ if (err == EBUSY)
cont_err("Perhaps a running process, mounted filesystem or active volume group?\n");
}
rv = 1;
@@ -791,6 +793,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
int j;
mdu_disk_info_t disc;
struct map_ent *map = NULL;
+ bool add_new_super = false;
if (!get_dev_size(tfd, dv->devname, &ldsize)) {
if (dv->disposition == 'M')
@@ -1009,6 +1012,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
goto unlock;
if (tst->ss->write_init_super(tst))
goto unlock;
+ add_new_super = true;
} else if (dv->disposition == 'A') {
/* this had better be raid1.
* As we are "--re-add"ing we must find a spare slot
@@ -1076,6 +1080,8 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
map_unlock(&map);
return 1;
unlock:
+ if (add_new_super)
+ Kill(dv->devname, tst, 0, -1, 0);
map_unlock(&map);
return -1;
}
@@ -1439,29 +1445,25 @@ int Manage_subdevs(char *devname, int fd,
for (dv = devlist; dv; dv = dv->next) {
dev_t rdev = 0; /* device to add/remove etc */
- int rv;
- int mj,mn;
+ int rv, err = 0;
+ int mj, mn;
raid_slot = -1;
if (dv->disposition == 'c') {
- rv = parse_cluster_confirm_arg(dv->devname,
- &dv->devname,
- &raid_slot);
+ rv = parse_cluster_confirm_arg(dv->devname, &dv->devname, &raid_slot);
if (rv) {
pr_err("Could not get the devname of cluster\n");
goto abort;
}
}
- if (strcmp(dv->devname, "failed") == 0 ||
- strcmp(dv->devname, "faulty") == 0) {
+ if (strcmp(dv->devname, "failed") == 0 || strcmp(dv->devname, "faulty") == 0) {
if (dv->disposition != 'A' && dv->disposition != 'r') {
pr_err("%s only meaningful with -r or --re-add, not -%c\n",
dv->devname, dv->disposition);
goto abort;
}
- add_faulty(dv, fd, (dv->disposition == 'A'
- ? 'F' : 'r'));
+ add_faulty(dv, fd, (dv->disposition == 'A' ? 'F' : 'r'));
continue;
}
if (strcmp(dv->devname, "detached") == 0) {
@@ -1477,6 +1479,7 @@ int Manage_subdevs(char *devname, int fd,
if (strcmp(dv->devname, "missing") == 0) {
struct mddev_dev *add_devlist;
struct mddev_dev **dp;
+
if (dv->disposition == 'c') {
rv = ioctl(fd, CLUSTERED_DISK_NACK, NULL);
break;
@@ -1491,7 +1494,7 @@ int Manage_subdevs(char *devname, int fd,
pr_err("no devices to scan for missing members.\n");
continue;
}
- for (dp = &add_devlist; *dp; dp = & (*dp)->next)
+ for (dp = &add_devlist; *dp; dp = &(*dp)->next)
/* 'M' (for 'missing') is like 'A' without errors */
(*dp)->disposition = 'M';
*dp = dv->next;
@@ -1499,74 +1502,50 @@ int Manage_subdevs(char *devname, int fd,
continue;
}
- if (strncmp(dv->devname, "set-", 4) == 0 &&
- strlen(dv->devname) == 5) {
+ if (strncmp(dv->devname, "set-", 4) == 0 && strlen(dv->devname) == 5) {
int copies;
- if (dv->disposition != 'r' &&
- dv->disposition != 'f') {
- pr_err("'%s' only meaningful with -r or -f\n",
- dv->devname);
+ if (dv->disposition != 'r' && dv->disposition != 'f') {
+ pr_err("'%s' only meaningful with -r or -f\n", dv->devname);
goto abort;
}
+
if (array.level != 10) {
- pr_err("'%s' only meaningful with RAID10 arrays\n",
- dv->devname);
+ pr_err("'%s' only meaningful with RAID10 arrays\n", dv->devname);
goto abort;
}
- copies = ((array.layout & 0xff) *
- ((array.layout >> 8) & 0xff));
- if (array.raid_disks % copies != 0 ||
- dv->devname[4] < 'A' ||
- dv->devname[4] >= 'A' + copies ||
- copies > 26) {
- pr_err("'%s' not meaningful with this array\n",
- dv->devname);
+
+ copies = ((array.layout & 0xff) * ((array.layout >> 8) & 0xff));
+
+ if (array.raid_disks % copies != 0 || dv->devname[4] < 'A' ||
+ dv->devname[4] >= 'A' + copies || copies > 26) {
+ pr_err("'%s' not meaningful with this array\n", dv->devname);
goto abort;
}
add_set(dv, fd, dv->devname[4]);
continue;
}
- if (strchr(dv->devname, '/') == NULL &&
- strchr(dv->devname, ':') == NULL &&
+ if (!strchr(dv->devname, '/') && !strchr(dv->devname, ':') &&
strlen(dv->devname) < 50) {
- /* Assume this is a kernel-internal name like 'sda1' */
- int found = 0;
- char dname[55];
- if (dv->disposition != 'r' && dv->disposition != 'f' &&
- dv->disposition != 'I') {
+ char *array_devnm = fd2devnm(fd);
+
+ /* This is a kernel-internal name like 'sda1' */
+
+ if (!strchr("rfI", dv->disposition)) {
pr_err("%s only meaningful with -r, -f or -I, not -%c\n",
dv->devname, dv->disposition);
goto abort;
}
- sprintf(dname, "dev-%s", dv->devname);
- sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev");
- if (sysfd >= 0) {
- char dn[SYSFS_MAX_BUF_SIZE];
- if (sysfs_fd_get_str(sysfd, dn, sizeof(dn)) > 0 &&
- sscanf(dn, "%d:%d", &mj,&mn) == 2) {
- rdev = makedev(mj,mn);
- found = 1;
- }
- close_fd(&sysfd);
- sysfd = -1;
- }
- if (!found) {
- sysfd = sysfs_open(fd2devnm(fd), dname, "state");
- if (sysfd < 0) {
- pr_err("%s does not appear to be a component of %s\n",
- dv->devname, devname);
+ sysfd = sysfs_open_memb_attr(array_devnm, dv->devname, "state", O_RDWR);
+ if (!is_fd_valid(sysfd)) {
+ pr_err("%s does not appear to be a component of %s\n", dv->devname,
+ devname);
goto abort;
}
- }
- } else if ((dv->disposition == 'r' ||
- dv->disposition == 'f') &&
- get_maj_min(dv->devname, &mj, &mn)) {
- /* for 'fail' and 'remove', the device might
- * not exist.
- */
+ } else if (strchr("rf", dv->disposition) && get_maj_min(dv->devname, &mj, &mn)) {
+ /* for 'fail' and 'remove', the device might not exist. */
rdev = makedev(mj, mn);
} else {
tfd = dev_open(dv->devname, O_RDONLY);
@@ -1575,6 +1554,7 @@ int Manage_subdevs(char *devname, int fd,
close_fd(&tfd);
} else {
int open_err = errno;
+
if (!stat_is_blkdev(dv->devname, &rdev)) {
if (dv->disposition == 'M')
/* non-fatal. Also improbable */
@@ -1590,16 +1570,15 @@ int Manage_subdevs(char *devname, int fd,
if (dv->disposition == 'M')
/* non-fatal */
continue;
- pr_err("Cannot open %s: %s\n",
- dv->devname, strerror(open_err));
+ pr_err("Cannot open %s: %s\n", dv->devname,
+ strerror(open_err));
goto abort;
}
}
}
- switch(dv->disposition){
+ switch (dv->disposition) {
default:
- pr_err("internal error - devmode[%s]=%d\n",
- dv->devname, dv->disposition);
+ pr_err("internal error - devmode[%s]=%d\n", dv->devname, dv->disposition);
goto abort;
case 'a':
case 'S': /* --add-spare */
@@ -1615,12 +1594,11 @@ int Manage_subdevs(char *devname, int fd,
}
/* Let's first try to write re-add to sysfs */
- if (rdev != 0 &&
- (dv->disposition == 'A' || dv->disposition == 'F')) {
+ if (rdev != 0 && (dv->disposition == 'A' || dv->disposition == 'F')) {
sysfs_init_dev(&devinfo, rdev);
if (sysfs_set_str(&info, &devinfo, "state", "re-add") == 0) {
- pr_err("re-add %s to %s succeed\n",
- dv->devname, info.sys_name);
+ pr_err("re-add %s to %s succeed\n", dv->devname,
+ info.sys_name);
break;
}
}
@@ -1651,8 +1629,7 @@ int Manage_subdevs(char *devname, int fd,
else
frozen = -1;
}
- rv = Manage_add(fd, tfd, dv, tst, &array,
- force, verbose, devname, update,
+ rv = Manage_add(fd, tfd, dv, tst, &array, force, verbose, devname, update,
rdev, array_size, raid_slot);
close_fd(&tfd);
if (rv < 0)
@@ -1667,12 +1644,10 @@ int Manage_subdevs(char *devname, int fd,
pr_err("Cannot remove disks from a \'member\' array, perform this operation on the parent container\n");
rv = -1;
} else
- rv = Manage_remove(tst, fd, dv, sysfd,
- rdev, verbose, force,
+ rv = Manage_remove(tst, fd, dv, sysfd, rdev, verbose, force,
devname);
- if (sysfd >= 0)
- close_fd(&sysfd);
- sysfd = -1;
+ close_fd(&sysfd);
+
if (rv < 0)
goto abort;
if (rv > 0)
@@ -1686,23 +1661,31 @@ int Manage_subdevs(char *devname, int fd,
close_fd(&sysfd);
goto abort;
}
- case 'I': /* incremental fail */
- if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
- (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
- rdev))) {
- if (errno == EBUSY)
- busy = 1;
- pr_err("set device faulty failed for %s: %s\n",
- dv->devname, strerror(errno));
- close_fd(&sysfd);
- goto abort;
+ case 'I':
+ if (is_fd_valid(sysfd)) {
+ static const char val[] = "faulty";
+
+ rv = sysfs_write_descriptor(sysfd, val, strlen(val), &err);
+ } else {
+ rv = ioctl(fd, SET_DISK_FAULTY, rdev);
+ if (rv)
+ err = errno;
}
+
close_fd(&sysfd);
- count++;
- if (verbose >= 0)
- pr_err("set %s faulty in %s\n",
- dv->devname, devname);
- break;
+
+ if (rv == MDADM_STATUS_SUCCESS) {
+ count++;
+
+ pr_vrb("set %s faulty in %s\n", dv->devname, devname);
+ break;
+ }
+
+ if (err == EBUSY)
+ busy = 1;
+
+ pr_err("set device faulty failed for %s: %s\n", dv->devname, strerror(err));
+ goto abort;
case 'R': /* Mark as replaceable */
if (subarray) {
pr_err("Cannot replace disks in a \'member\' array, perform this operation on the parent container\n");
@@ -1714,9 +1697,7 @@ int Manage_subdevs(char *devname, int fd,
else
frozen = -1;
}
- rv = Manage_replace(tst, fd, dv,
- rdev, verbose,
- devname);
+ rv = Manage_replace(tst, fd, dv, rdev, verbose, devname);
}
if (rv < 0)
goto abort;
@@ -1724,12 +1705,10 @@ int Manage_subdevs(char *devname, int fd,
count++;
break;
case 'W': /* --with device that doesn't match */
- pr_err("No matching --replace device for --with %s\n",
- dv->devname);
+ pr_err("No matching --replace device for --with %s\n", dv->devname);
goto abort;
case 'w': /* --with device which was matched */
- rv = Manage_with(tst, fd, dv,
- rdev, verbose, devname);
+ rv = Manage_with(tst, fd, dv, rdev, verbose, devname);
if (rv < 0)
goto abort;
break;
@@ -1737,7 +1716,7 @@ int Manage_subdevs(char *devname, int fd,
}
free(tst);
if (frozen > 0)
- sysfs_set_str(&info, NULL, "sync_action","idle");
+ sysfs_set_str(&info, NULL, "sync_action", "idle");
if (test && count == 0)
return 2;
return 0;
@@ -1745,7 +1724,7 @@ int Manage_subdevs(char *devname, int fd,
abort:
free(tst);
if (frozen > 0)
- sysfs_set_str(&info, NULL, "sync_action","idle");
+ sysfs_set_str(&info, NULL, "sync_action", "idle");
return !test && busy ? 2 : 1;
}