goto out;
}
- if (get_linux_version() < 2006028) {
- /* 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
- * partitions as well...
- */
- if (fd >= 0)
- ioctl(fd, BLKRRPART, 0);
- if (mdi)
- sysfs_uevent(mdi, "change");
- }
-
if (devnm[0] && use_udev()) {
struct map_ent *mp = map_by_devnm(&map, devnm);
remove_devices(devnm, mp ? mp->path : NULL);
int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
struct supertype *dev_st, struct supertype *tst,
- unsigned long rdev,
- char *update, char *devname, int verbose,
- mdu_array_info_t *array)
+ unsigned long rdev, enum update_opt update,
+ char *devname, int verbose, mdu_array_info_t *array)
{
struct mdinfo mdi;
int duuid[4];
* though.
*/
mdu_disk_info_t disc;
- /* 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 (md_get_disk_info(fd, &disc) != 0 ||
disc.major != 0 || disc.minor != 0)
if (dv->writemostly == FlagSet)
rv = dev_st->ss->update_super(
- dev_st, NULL, "writemostly",
+ dev_st, NULL, UOPT_SPEC_WRITEMOSTLY,
devname, verbose, 0, NULL);
if (dv->writemostly == FlagClear)
rv = dev_st->ss->update_super(
- dev_st, NULL, "readwrite",
+ dev_st, NULL, UOPT_SPEC_READWRITE,
devname, verbose, 0, NULL);
if (dv->failfast == FlagSet)
rv = dev_st->ss->update_super(
- dev_st, NULL, "failfast",
+ dev_st, NULL, UOPT_SPEC_FAILFAST,
devname, verbose, 0, NULL);
if (dv->failfast == FlagClear)
rv = dev_st->ss->update_super(
- dev_st, NULL, "nofailfast",
+ dev_st, NULL, UOPT_SPEC_NOFAILFAST,
devname, verbose, 0, NULL);
if (update)
rv = dev_st->ss->update_super(
int Manage_add(int fd, int tfd, struct mddev_dev *dv,
struct supertype *tst, mdu_array_info_t *array,
int force, int verbose, char *devname,
- char *update, unsigned long rdev, unsigned long long array_size,
- int raid_slot)
+ enum update_opt update, unsigned long rdev,
+ unsigned long long array_size, int raid_slot)
{
unsigned long long ldsize;
struct supertype *dev_st;
sysfs_free(mdi);
bool is_enough = enough(array->level, array->raid_disks,
- array->layout, (array->state & 1),
- avail);
+ array->layout, 1, avail);
free(avail);
return is_enough;
}
+/**
+ * Manage_subdevs() - Execute operation depending on devmode.
+ *
+ * @devname: name of the device.
+ * @fd: file descriptor.
+ * @devlist: list of sub-devices to manage.
+ * @verbose: verbose level.
+ * @test: test flag.
+ * @update: type of update.
+ * @force: force flag.
+ *
+ * This function executes operation defined by devmode
+ * for each dev from devlist.
+ * Devmode can be:
+ * 'a' - add the device
+ * 'S' - add the device as a spare - don't try re-add
+ * 'j' - add the device as a journal device
+ * 'A' - re-add the device
+ * 'r' - remove the device: HOT_REMOVE_DISK
+ * device can be 'faulty' or 'detached' in which case all
+ * matching devices are removed.
+ * 'f' - set the device faulty SET_DISK_FAULTY
+ * device can be 'detached' in which case any device that
+ * is inaccessible will be marked faulty.
+ * 'I' - remove device by using incremental fail
+ * which is executed when device is removed surprisingly.
+ * 'R' - mark this device as wanting replacement.
+ * 'W' - this device is added if necessary and activated as
+ * a replacement for a previous 'R' device.
+ * -----
+ * 'w' - 'W' will be changed to 'w' when it is paired with
+ * a 'R' device. If a 'W' is found while walking the list
+ * it must be unpaired, and is an error.
+ * 'M' - this is created by a 'missing' target. It is a slight
+ * variant on 'A'
+ * 'F' - Another variant of 'A', where the device was faulty
+ * so must be removed from the array first.
+ * 'c' - confirm the device as found (for clustered environments)
+ *
+ * For 'f' and 'r', the device can also be a kernel-internal
+ * name such as 'sdb'.
+ *
+ * Return: 0 on success, otherwise 1 or 2.
+ */
int Manage_subdevs(char *devname, int fd,
struct mddev_dev *devlist, int verbose, int test,
- char *update, int force)
+ enum update_opt update, int force)
{
- /* Do something to each dev.
- * devmode can be
- * 'a' - add the device
- * 'S' - add the device as a spare - don't try re-add
- * 'j' - add the device as a journal device
- * 'A' - re-add the device
- * 'r' - remove the device: HOT_REMOVE_DISK
- * device can be 'faulty' or 'detached' in which case all
- * matching devices are removed.
- * 'f' - set the device faulty SET_DISK_FAULTY
- * device can be 'detached' in which case any device that
- * is inaccessible will be marked faulty.
- * 'R' - mark this device as wanting replacement.
- * 'W' - this device is added if necessary and activated as
- * a replacement for a previous 'R' device.
- * -----
- * 'w' - 'W' will be changed to 'w' when it is paired with
- * a 'R' device. If a 'W' is found while walking the list
- * it must be unpaired, and is an error.
- * 'M' - this is created by a 'missing' target. It is a slight
- * variant on 'A'
- * 'F' - Another variant of 'A', where the device was faulty
- * so must be removed from the array first.
- * 'c' - confirm the device as found (for clustered environments)
- *
- * For 'f' and 'r', the device can also be a kernel-internal
- * name such as 'sdb'.
- */
mdu_array_info_t array;
unsigned long long array_size;
struct mddev_dev *dv;
/* Assume this is a kernel-internal name like 'sda1' */
int found = 0;
char dname[55];
- if (dv->disposition != 'r' && dv->disposition != 'f') {
- pr_err("%s only meaningful with -r or -f, not -%c\n",
+ if (dv->disposition != 'r' && dv->disposition != 'f' &&
+ dv->disposition != 'I') {
+ pr_err("%s only meaningful with -r, -f or -I, not -%c\n",
dv->devname, dv->disposition);
goto abort;
}
close(sysfd);
goto abort;
}
-
+ case 'I': /* incremental fail */
if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
(sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
rdev))) {
return rv;
}
-int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int verbose)
+int Update_subarray(char *dev, char *subarray, enum update_opt update,
+ struct mddev_ident *ident, int verbose)
{
struct supertype supertype, *st = &supertype;
int fd, rv = 2;
struct mdinfo *info = NULL;
+ char *update_verb = map_num(update_options, update);
memset(st, 0, sizeof(*st));
if (is_subarray_active(subarray, st->devnm)) {
if (verbose >= 0)
pr_err("Subarray %s in %s is active, cannot update %s\n",
- subarray, dev, update);
+ subarray, dev, update_verb);
goto free_super;
}
info = st->ss->container_content(st, subarray);
- if (strncmp(update, "ppl", 3) == 0 && !is_level456(info->array.level)) {
+ if (update == UOPT_PPL && !is_level456(info->array.level)) {
pr_err("RWH policy ppl is supported only for raid4, raid5 and raid6.\n");
goto free_super;
}
if (rv) {
if (verbose >= 0)
pr_err("Failed to update %s of subarray-%s in %s\n",
- update, subarray, dev);
+ update_verb, subarray, dev);
} else if (st->update_tail)
flush_metadata_updates(st);
else
st->ss->sync_metadata(st);
- if (rv == 0 && strcmp(update, "name") == 0 && verbose >= 0)
+ if (rv == 0 && update == UOPT_NAME && verbose >= 0)
pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
subarray, dev);
sprintf(devname, "%d:%d", major(devid), minor(devid));
devlist.disposition = 'r';
- if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
+ if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, UOPT_UNDEFINED, 0) == 0) {
devlist.disposition = 'a';
if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0,
- NULL, 0) == 0) {
+ UOPT_UNDEFINED, 0) == 0) {
/* make sure manager is aware of changes */
ping_manager(to_devname);
ping_manager(from_devname);
}
else
Manage_subdevs(from_devname, fd2, &devlist,
- -1, 0, NULL, 0);
+ -1, 0, UOPT_UNDEFINED, 0);
}
close(fd1);
close(fd2);