X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Manage.c;h=4958cf8b838238953b5e5749382014f1cd406943;hb=9581efb1ae9348ef33d10d781cedde375c0d62c4;hp=63675d6d5bffce5ec24789fd11b4663d095cbf6e;hpb=3afaff930c4840911ebf114f43fdd5d93c07af1f;p=thirdparty%2Fmdadm.git diff --git a/Manage.c b/Manage.c index 63675d6d..4958cf8b 100644 --- a/Manage.c +++ b/Manage.c @@ -1,7 +1,7 @@ /* * mdadm - manage Linux "md" devices aka RAID arrays. * - * Copyright (C) 2001-2012 Neil Brown + * Copyright (C) 2001-2013 Neil Brown * * * This program is free software; you can redistribute it and/or modify @@ -170,28 +170,24 @@ static void remove_devices(char *devnm, char *path) free(path2); } -int Manage_run(char *devname, int fd, int verbose) +int Manage_run(char *devname, int fd, struct context *c) { /* Run the array. Array must already be configured * Requires >= 0.90.0 */ - mdu_param_t param; /* unused */ - int rv = 0; + char nm[32], *nmp; if (md_get_version(fd) < 9000) { pr_err("need md driver version 0.90.0 or later\n"); return 1; } - - if (ioctl(fd, RUN_ARRAY, ¶m)) { - if (verbose >= 0) - pr_err("failed to run array %s: %s\n", - devname, strerror(errno)); + nmp = fd2devnm(fd); + if (!nmp) { + pr_err("Cannot find %s in sysfs!!\n", devname); return 1; } - if (verbose >= 0) - pr_err("started %s\n", devname); - return rv; + strcpy(nm, nmp); + return IncrementalScan(c, nm); } int Manage_stop(char *devname, int fd, int verbose, int will_retry) @@ -215,8 +211,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) if (md_get_version(fd) < 9000) { if (ioctl(fd, STOP_MD, 0) == 0) return 0; - pr_err("stopping device %s " - "failed: %s\n", + pr_err("stopping device %s failed: %s\n", devname, strerror(errno)); return 1; } @@ -256,10 +251,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) if (fd >= 0) close(fd); if (verbose >= 0) - pr_err("Cannot get exclusive access to %s:" - "Perhaps a running " - "process, mounted filesystem " - "or active volume group?\n", + pr_err("Cannot get exclusive access to %s:Perhaps a running process, mounted filesystem or active volume group?\n", devname); return 1; } @@ -297,8 +289,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) fd = open_dev_excl(devnm); if (fd < 0) { if (verbose >= 0) - pr_err("failed to completely stop %s" - ": Device is busy\n", + pr_err("failed to completely stop %s: Device is busy\n", devname); rv = 1; goto out; @@ -324,9 +315,8 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) metadata_container_matches(m->metadata_version+9, devnm)) { if (verbose >= 0) - pr_err("Cannot stop container %s: " - "member %s still active\n", - devname, m->dev); + pr_err("Cannot stop container %s: member %s still active\n", + devname, m->devnm); free_mdstat(mds); rv = 1; goto out; @@ -464,9 +454,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) pr_err("failed to stop array %s: %s\n", devname, strerror(errno)); if (errno == EBUSY) - cont_err("Perhaps a running " - "process, mounted filesystem " - "or active volume group?\n"); + cont_err("Perhaps a running process, mounted filesystem or active volume group?\n"); } rv = 1; goto out; @@ -656,8 +644,7 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, 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); + pr_err("failed to open %s for superblock update during re-add\n", dv->devname); return -1; } @@ -677,8 +664,7 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, rv = dev_st->ss->store_super(dev_st, tfd); close(tfd); if (rv != 0) { - pr_err("failed to update" - " superblock during re-add\n"); + pr_err("failed to update superblock during re-add\n"); return -1; } } @@ -718,22 +704,16 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, return -1; } - if (tst->ss->validate_geometry( - tst, array->level, array->layout, - array->raid_disks, NULL, - ldsize >> 9, INVALID_SECTORS, NULL, NULL, 0) == 0) { + if (tst->ss == &super0 && ldsize > 4ULL*1024*1024*1024*1024) { + /* More than 4TB is wasted on v0.90 */ if (!force) { - pr_err("%s is larger than %s can " - "effectively use.\n" - " Add --force is you " - "really want to add this device.\n", + pr_err("%s is larger than %s can effectively use.\n" + " Add --force is you really want to add this device.\n", dv->devname, devname); return -1; } - pr_err("%s is larger than %s can " - "effectively use.\n" - " Adding anyway as --force " - "was given.\n", + pr_err("%s is larger than %s can effectively use.\n" + " Adding anyway as --force was given.\n", dv->devname, devname); } if (!tst->ss->external && @@ -789,7 +769,8 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, break; } /* FIXME this is a bad test to be using */ - if (!tst->sb && dv->disposition != 'a') { + if (!tst->sb && (dv->disposition != 'a' + && dv->disposition != 'S')) { /* we are re-adding a device to a * completely dead array - have to depend * on kernel to check @@ -800,7 +781,8 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, } /* Make sure device is large enough */ - if (tst->ss->avail_size(tst, ldsize/512, INVALID_SECTORS) < + if (tst->sb && + tst->ss->avail_size(tst, ldsize/512, INVALID_SECTORS) < array_size) { if (dv->disposition == 'M') return 0; @@ -819,7 +801,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, dev_st = dup_super(tst); dev_st->ss->load_super(dev_st, tfd, NULL); } - if (dev_st && dev_st->sb) { + if (dev_st && dev_st->sb && dv->disposition != 'S') { int rv = attempt_re_add(fd, tfd, dv, dev_st, tst, rdev, @@ -846,19 +828,20 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, int d; int found = 0; - for (d = 0; d < MAX_DISKS && found < array->active_disks; d++) { + for (d = 0; d < MAX_DISKS && found < array->nr_disks; d++) { disc.number = d; if (ioctl(fd, GET_DISK_INFO, &disc)) continue; if (disc.major == 0 && disc.minor == 0) continue; + found++; if (!(disc.state & (1<level, array->raid_disks, array->layout, 1, avail); + free(avail); } else array_failed = 0; if (array_failed) { @@ -953,8 +936,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, container_fd = open_dev_excl(devnm); if (container_fd < 0) { - pr_err("add failed for %s:" - " could not get exclusive access to container\n", + pr_err("add failed for %s: could not get exclusive access to container\n", dv->devname); tst->ss->free_super(tst); return -1; @@ -993,8 +975,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, * would block add_disk */ tst->ss->free_super(tst); if (sysfs_add_disk(sra, &new_mdi, 0) != 0) { - pr_err("add new device to external metadata" - " failed for %s\n", dv->devname); + pr_err("add new device to external metadata failed for %s\n", dv->devname); close(container_fd); sysfs_free(sra); return -1; @@ -1036,8 +1017,7 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, strcpy(devnm, fd2devnm(fd)); lfd = open_dev_excl(devnm); if (lfd < 0) { - pr_err("Cannot get exclusive access " - " to container - odd\n"); + pr_err("Cannot get exclusive access to container - odd\n"); return -1; } /* We may not be able to check on holders in @@ -1097,8 +1077,7 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, } } if (err) { - pr_err("hot remove failed " - "for %s: %s\n", dv->devname, + pr_err("hot remove failed for %s: %s\n", dv->devname, strerror(errno)); if (lfd >= 0) close(lfd); @@ -1218,7 +1197,7 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv, "slot", dv->used); if (rv) { sysfs_free(mdi); - pr_err("Failed to %s as preferred replacement.\n", + pr_err("Failed to set %s as preferred replacement.\n", dv->devname); return -1; } @@ -1242,6 +1221,7 @@ int Manage_subdevs(char *devname, int fd, * 'a' - add the device * try HOT_ADD_DISK * If that fails EINVAL, try ADD_NEW_DISK + * 'S' - add the device as a spare - don't try re-add * 'A' - re-add the device * 'r' - remove the device: HOT_REMOVE_DISK * device can be 'faulty' or 'detached' in which case all @@ -1267,7 +1247,6 @@ int Manage_subdevs(char *devname, int fd, mdu_array_info_t array; unsigned long long array_size; struct mddev_dev *dv; - struct stat stb; int tfd = -1; struct supertype *tst; char *subarray = NULL; @@ -1299,16 +1278,16 @@ int Manage_subdevs(char *devname, int fd, goto abort; } - stb.st_rdev = 0; for (dv = devlist; dv; dv = dv->next) { + unsigned long rdev = 0; /* device to add/remove etc */ int rv; + int mj,mn; 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", + pr_err("%s only meaningful with -r or --re-add, not -%c\n", dv->devname, dv->disposition); goto abort; } @@ -1318,8 +1297,7 @@ int Manage_subdevs(char *devname, int fd, } if (strcmp(dv->devname, "detached") == 0) { if (dv->disposition != 'r' && dv->disposition != 'f') { - pr_err("%s only meaningful " - "with -r of -f, not -%c\n", + pr_err("%s only meaningful with -r of -f, not -%c\n", dv->devname, dv->disposition); goto abort; } @@ -1331,8 +1309,7 @@ int Manage_subdevs(char *devname, int fd, struct mddev_dev *add_devlist = NULL; struct mddev_dev **dp; if (dv->disposition != 'A') { - pr_err("'missing' only meaningful " - "with --re-add\n"); + pr_err("'missing' only meaningful with --re-add\n"); goto abort; } add_devlist = conf_get_devs(); @@ -1384,8 +1361,7 @@ int Manage_subdevs(char *devname, int fd, 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", + pr_err("%s only meaningful with -r or -f, not -%c\n", dv->devname, dv->disposition); goto abort; } @@ -1394,10 +1370,9 @@ int Manage_subdevs(char *devname, int fd, sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev"); if (sysfd >= 0) { char dn[20]; - int mj,mn; if (sysfs_fd_get_str(sysfd, dn, 20) > 0 && sscanf(dn, "%d:%d", &mj,&mn) == 2) { - stb.st_rdev = makedev(mj,mn); + rdev = makedev(mj,mn); found = 1; } close(sysfd); @@ -1406,13 +1381,19 @@ int Manage_subdevs(char *devname, int fd, 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", + 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. + */ + rdev = makedev(mj, mn); } else { + struct stat stb; tfd = dev_open(dv->devname, O_RDONLY); if (tfd >= 0) fstat(tfd, &stb); @@ -1445,6 +1426,7 @@ int Manage_subdevs(char *devname, int fd, goto abort; } } + rdev = stb.st_rdev; } switch(dv->disposition){ default: @@ -1452,20 +1434,18 @@ int Manage_subdevs(char *devname, int fd, dv->devname, dv->disposition); goto abort; case 'a': + case 'S': /* --add-spare */ case 'A': case 'M': /* --re-add missing */ case 'F': /* --re-add faulty */ /* add the device */ if (subarray) { - pr_err("Cannot add disks to a" - " \'member\' array, perform this" - " operation on the parent container\n"); + pr_err("Cannot add disks to a \'member\' array, perform this operation on the parent container\n"); goto abort; } if (dv->disposition == 'F') /* Need to remove first */ - ioctl(fd, HOT_REMOVE_DISK, - (unsigned long)stb.st_rdev); + ioctl(fd, HOT_REMOVE_DISK, rdev); /* Make sure it isn't in use (in 2.6 or later) */ tfd = dev_open(dv->devname, O_RDONLY|O_EXCL); if (tfd >= 0) { @@ -1491,7 +1471,7 @@ int Manage_subdevs(char *devname, int fd, } rv = Manage_add(fd, tfd, dv, tst, &array, force, verbose, devname, update, - stb.st_rdev, array_size); + rdev, array_size); close(tfd); tfd = -1; if (rv < 0) @@ -1503,13 +1483,11 @@ int Manage_subdevs(char *devname, int fd, case 'r': /* hot remove */ if (subarray) { - pr_err("Cannot remove disks from a" - " \'member\' array, perform this" - " operation on the parent container\n"); + 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, - stb.st_rdev, verbose, + rdev, verbose, devname); if (sysfd >= 0) close(sysfd); @@ -1524,7 +1502,7 @@ int Manage_subdevs(char *devname, int fd, /* FIXME check current member */ if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) || (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY, - (unsigned long) stb.st_rdev))) { + rdev))) { if (errno == EBUSY) busy = 1; pr_err("set device faulty failed for %s: %s\n", @@ -1543,9 +1521,7 @@ int Manage_subdevs(char *devname, int fd, break; case 'R': /* Mark as replaceable */ if (subarray) { - pr_err("Cannot replace disks in a" - " \'member\' array, perform this" - " operation on the parent container\n"); + pr_err("Cannot replace disks in a \'member\' array, perform this operation on the parent container\n"); rv = -1; } else { if (!frozen) { @@ -1555,7 +1531,7 @@ int Manage_subdevs(char *devname, int fd, frozen = -1; } rv = Manage_replace(tst, fd, dv, - stb.st_rdev, verbose, + rdev, verbose, devname); } if (rv < 0) @@ -1569,7 +1545,7 @@ int Manage_subdevs(char *devname, int fd, goto abort; case 'w': /* --with device which was matched */ rv = Manage_with(tst, fd, dv, - stb.st_rdev, verbose, devname); + rdev, verbose, devname); if (rv < 0) goto abort; break;