summaryrefslogtreecommitdiff
path: root/Manage.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-08-13 08:00:21 +1000
committerNeilBrown <neilb@suse.de>2012-08-13 08:00:21 +1000
commitabe94694dadc1a889e208bfafdfce7d742e9cbd4 (patch)
treec24d8ae9e7040ae7cf91367b0b915e3d397ba036 /Manage.c
parent46d475beb4b50272af31992c2acf08b24e6e7c58 (diff)
Manage: split out attempt_re_add.
The indent level is way too deep here, and this is a well defined task, so split it out to a separate function. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'Manage.c')
-rw-r--r--Manage.c203
1 files changed, 112 insertions, 91 deletions
diff --git a/Manage.c b/Manage.c
index b5a9a5dc..c80738c5 100644
--- a/Manage.c
+++ b/Manage.c
@@ -433,6 +433,102 @@ static void add_detached(struct mddev_dev *dv, int fd, char disp)
}
}
+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)
+{
+ struct mdinfo mdi;
+ int duuid[4];
+ int ouuid[4];
+
+ dev_st->ss->getinfo_super(dev_st, &mdi, NULL);
+ dev_st->ss->uuid_from_super(dev_st, ouuid);
+ if (tst->sb)
+ tst->ss->uuid_from_super(tst, duuid);
+ else
+ /* Assume uuid matches: kernel will check */
+ memcpy(duuid, ouuid, sizeof(ouuid));
+ if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
+ !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
+ memcmp(duuid, ouuid, sizeof(ouuid))==0) {
+ /* Looks like it is worth a
+ * try. Need to make sure
+ * kernel will accept it
+ * 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 (ioctl(fd, GET_DISK_INFO, &disc) != 0
+ || disc.major != 0 || disc.minor != 0
+ )
+ goto skip_re_add;
+ disc.major = major(rdev);
+ disc.minor = minor(rdev);
+ disc.number = mdi.disk.number;
+ disc.raid_disk = mdi.disk.raid_disk;
+ disc.state = mdi.disk.state;
+ if (dv->writemostly == 1)
+ disc.state |= 1 << MD_DISK_WRITEMOSTLY;
+ if (dv->writemostly == 2)
+ disc.state &= ~(1 << MD_DISK_WRITEMOSTLY);
+ remove_partitions(tfd);
+ if (update || dv->writemostly > 0) {
+ int rv = -1;
+ tfd = dev_open(dv->devname, O_RDWR);
+ if (tfd < 0) {
+ pr_err("failed to open %s for"
+ " superblock update during re-add\n", dv->devname);
+ return -1;
+ }
+
+ if (dv->writemostly == 1)
+ rv = dev_st->ss->update_super(
+ dev_st, NULL, "writemostly",
+ devname, verbose, 0, NULL);
+ if (dv->writemostly == 2)
+ rv = dev_st->ss->update_super(
+ dev_st, NULL, "readwrite",
+ devname, verbose, 0, NULL);
+ if (update)
+ rv = dev_st->ss->update_super(
+ dev_st, NULL, update,
+ devname, verbose, 0, NULL);
+ if (rv == 0)
+ rv = dev_st->ss->store_super(dev_st, tfd);
+ close(tfd);
+ if (rv != 0) {
+ pr_err("failed to update"
+ " superblock during re-add\n");
+ return -1;
+ }
+ }
+ /* don't even try if disk is marked as faulty */
+ errno = 0;
+ if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
+ if (verbose >= 0)
+ pr_err("re-added %s\n", dv->devname);
+ return 1;
+ }
+ if (errno == ENOMEM || errno == EROFS) {
+ pr_err("add new device failed for %s: %s\n",
+ dv->devname, strerror(errno));
+ if (dv->disposition == 'M')
+ return 0;
+ return -1;
+ }
+ }
+skip_re_add:
+ return 0;
+}
+
int Manage_subdevs(char *devname, int fd,
struct mddev_dev *devlist, int verbose, int test,
char *update, int force)
@@ -461,8 +557,6 @@ int Manage_subdevs(char *devname, int fd,
int tfd = -1;
struct supertype *dev_st, *tst;
char *subarray = NULL;
- int duuid[4];
- int ouuid[4];
int lfd = -1;
int sysfd = -1;
int count = 0; /* number of actions taken */
@@ -756,98 +850,25 @@ int Manage_subdevs(char *devname, int fd,
dev_st->ss->load_super(dev_st, tfd, NULL);
}
if (dev_st && dev_st->sb) {
- struct mdinfo mdi;
- dev_st->ss->getinfo_super(dev_st, &mdi, NULL);
- dev_st->ss->uuid_from_super(dev_st, ouuid);
- if (tst->sb)
- tst->ss->uuid_from_super(tst, duuid);
- else
- /* Assume uuid matches: kernel will check */
- memcpy(duuid, ouuid, sizeof(ouuid));
- if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
- !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
- memcmp(duuid, ouuid, sizeof(ouuid))==0) {
- /* Looks 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
- )
- goto skip_re_add;
- disc.major = major(stb.st_rdev);
- disc.minor = minor(stb.st_rdev);
- disc.number = mdi.disk.number;
- disc.raid_disk = mdi.disk.raid_disk;
- disc.state = mdi.disk.state;
- if (dv->writemostly == 1)
- disc.state |= 1 << MD_DISK_WRITEMOSTLY;
- if (dv->writemostly == 2)
- disc.state &= ~(1 << MD_DISK_WRITEMOSTLY);
- remove_partitions(tfd);
+ int rv = attempt_re_add(fd, tfd, dv,
+ dev_st, tst,
+ stb.st_rdev,
+ update, devname,
+ verbose,
+ &array);
+ dev_st->ss->free_super(dev_st);
+ if (rv < 0) {
+ /* Bad failure */
+ close(tfd);
+ goto abort;
+ }
+ if (rv > 0) {
+ /* success! */
close(tfd);
tfd = -1;
- if (update || dv->writemostly > 0) {
- int rv = -1;
- tfd = dev_open(dv->devname, O_RDWR);
- if (tfd < 0) {
- pr_err("failed to open %s for"
- " superblock update during re-add\n", dv->devname);
- dev_st->ss->free_super(dev_st);
- goto abort;
- }
-
- if (dv->writemostly == 1)
- rv = dev_st->ss->update_super(
- dev_st, NULL, "writemostly",
- devname, verbose, 0, NULL);
- if (dv->writemostly == 2)
- rv = dev_st->ss->update_super(
- dev_st, NULL, "readwrite",
- devname, verbose, 0, NULL);
- if (update)
- rv = dev_st->ss->update_super(
- dev_st, NULL, update,
- devname, verbose, 0, NULL);
- if (rv == 0)
- rv = dev_st->ss->store_super(dev_st, tfd);
- close(tfd);
- tfd = -1;
- if (rv != 0) {
- pr_err("failed to update"
- " superblock during re-add\n");
- dev_st->ss->free_super(dev_st);
- goto abort;
- }
- }
- /* don't even try if disk is marked as faulty */
- errno = 0;
- if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
- if (verbose >= 0)
- pr_err("re-added %s\n", dv->devname);
- count++;
- dev_st->ss->free_super(dev_st);
- continue;
- }
- if (errno == ENOMEM || errno == EROFS) {
- pr_err("add new device failed for %s: %s\n",
- dv->devname, strerror(errno));
- dev_st->ss->free_super(dev_st);
- if (dv->disposition == 'M')
- continue;
- goto abort;
- }
+ count++;
+ continue;
}
- skip_re_add:
- dev_st->ss->free_super(dev_st);
}
if (dv->disposition == 'M') {
if (verbose > 0)