From: NeilBrown Date: Sun, 12 Aug 2012 22:00:21 +0000 (+1000) Subject: Manage: split out attempt_re_add. X-Git-Tag: mdadm-3.3-rc1~250 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=abe94694dadc1a889e208bfafdfce7d742e9cbd4;p=thirdparty%2Fmdadm.git 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 --- 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<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<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)