]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Support failing and removed of detached and faulty devices.
authorNeil Brown <neilb@suse.de>
Fri, 11 May 2007 06:13:03 +0000 (16:13 +1000)
committerNeil Brown <neilb@suse.de>
Fri, 11 May 2007 06:13:03 +0000 (16:13 +1000)
This if you unplug a device and udev removes the entry from /dev,
you can still remove the device.

ChangeLog
Manage.c
mdadm.8

index 28b551278cd57cdd27abfb3ab0d8de91431ac2c8..caa25391ec1dfb7c329866427a545a497b88ab2d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Changes Prior to this release
+    -   --fail detached and --remove faulty can be used to fail and
+       remove devices that are no longer physically present.
+    -   --export option for --detail or present information in a format
+       that can be processed by udev.
+    -   fix internal bitmap allocation problems with v1.1, v1.2 metadata.
+    -   --help now goes to stdout so you can direct it to a pager.
+    -   Various manpage updates.
+
 Changes Prior to 2.6.1 release
     -   --monitor was producing some meaningless warnings due to a bug.
     -   Fix some compiler warnings.
index 91934822cf83c923dabeafa5d9559911d184f3ef..3deb8ead690d8a2af899e1fc366626192f1a529a 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -180,13 +180,17 @@ int Manage_subdevs(char *devname, int fd,
         *         try HOT_ADD_DISK
         *         If that fails EINVAL, try ADD_NEW_DISK
         *  '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.
         */
        mdu_array_info_t array;
        mdu_disk_info_t disc;
-       mddev_dev_t dv;
+       mddev_dev_t dv, next = NULL;
        struct stat stb;
-       int j;
+       int j, jnext = 0;
        int tfd;
        struct supertype *st;
        void *dsuper = NULL;
@@ -199,18 +203,86 @@ int Manage_subdevs(char *devname, int fd,
                        devname);
                return 1;
        }
-       for (dv = devlist ; dv; dv=dv->next) {
+       for (dv = devlist, j=0 ; dv; dv = next, j = jnext) {
                unsigned long long ldsize;
+               char dvname[20];
+               char *dnprintable = dv->devname;
 
-               if (stat(dv->devname, &stb)) {
-                       fprintf(stderr, Name ": cannot find %s: %s\n",
-                               dv->devname, strerror(errno));
-                       return 1;
-               }
-               if ((stb.st_mode & S_IFMT) != S_IFBLK) {
-                       fprintf(stderr, Name ": %s is not a block device.\n",
-                               dv->devname);
-                       return 1;
+               next = dv->next;
+               jnext = 0;
+
+               if (strcmp(dv->devname, "failed")==0 ||
+                   strcmp(dv->devname, "faulty")==0) {
+                       if (dv->disposition != 'r') {
+                               fprintf(stderr, Name ": %s only meaningful "
+                                       "with -r, not -%c\n",
+                                       dv->devname, dv->disposition);
+                               return 1;
+                       }
+                       for (; j < array.raid_disks + array.nr_disks ; j++) {
+                               disc.number = j;
+                               if (ioctl(fd, GET_DISK_INFO, &disc))
+                                       continue;
+                               if (disc.major == 0 && disc.minor == 0)
+                                       continue;
+                               if ((disc.state & 1) == 0) /* faulty */
+                                       continue;
+                               stb.st_rdev = makedev(disc.major, disc.minor);
+                               next = dv;
+                               jnext = j+1;
+                               sprintf(dvname,"%d:%d", disc.major, disc.minor);
+                               dnprintable = dvname;
+                               break;
+                       }
+                       if (jnext == 0)
+                               continue;
+               } else if (strcmp(dv->devname, "detached") == 0) {
+                       if (dv->disposition != 'r' && dv->disposition != 'f') {
+                               fprintf(stderr, Name ": %s only meaningful "
+                                       "with -r of -f, not -%c\n",
+                                       dv->devname, dv->disposition);
+                               return 1;
+                       }
+                       for (; j < array.raid_disks + array.nr_disks; j++) {
+                               int sfd;
+                               disc.number = j;
+                               if (ioctl(fd, GET_DISK_INFO, &disc))
+                                       continue;
+                               if (disc.major == 0 && disc.minor == 0)
+                                       continue;
+                               sprintf(dvname,"%d:%d", disc.major, disc.minor);
+                               sfd = dev_open(dvname, O_RDONLY);
+                               if (sfd >= 0) {
+                                       close(sfd);
+                                       continue;
+                               }
+                               if (dv->disposition == 'f' &&
+                                   (disc.state & 1) == 1) /* already faulty */
+                                       continue;
+                               if (errno != ENXIO)
+                                       continue;
+                               stb.st_rdev = makedev(disc.major, disc.minor);
+                               next = dv;
+                               jnext = j+1;
+                               dnprintable = dvname;
+                               break;
+                       }
+                       if (jnext == 0)
+                               continue;
+               } else {
+                       j = 0;
+
+                       if (stat(dv->devname, &stb)) {
+                               fprintf(stderr, Name ": cannot find %s: %s\n",
+                                       dv->devname, strerror(errno));
+                               return 1;
+                       }
+                       if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+                               fprintf(stderr, Name ": %s is not a "
+                                       "block device.\n",
+                                       dv->devname);
+                               return 1;
+                       }
                }
                switch(dv->disposition){
                default:
@@ -409,24 +481,26 @@ int Manage_subdevs(char *devname, int fd,
                        /* hot remove */
                        /* FIXME check that it is a current member */
                        if (ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev)) {
-                               fprintf(stderr, Name ": hot remove failed for %s: %s\n",
-                                       dv->devname, strerror(errno));
+                               fprintf(stderr, Name ": hot remove failed "
+                                       "for %s: %s\n", dnprintable,
+                                       strerror(errno));
                                return 1;
                        }
                        if (verbose >= 0)
-                               fprintf(stderr, Name ": hot removed %s\n", dv->devname);
+                               fprintf(stderr, Name ": hot removed %s\n",
+                                       dnprintable);
                        break;
 
                case 'f': /* set faulty */
                        /* FIXME check current member */
                        if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) {
                                fprintf(stderr, Name ": set device faulty failed for %s:  %s\n",
-                                       dv->devname, strerror(errno));
+                                       dnprintable, strerror(errno));
                                return 1;
                        }
                        if (verbose >= 0)
                                fprintf(stderr, Name ": set %s faulty in %s\n",
-                                       dv->devname, devname);
+                                       dnprintable, devname);
                        break;
                }
        }
diff --git a/mdadm.8 b/mdadm.8
index 321c1f4dbe0d156cbfaa939aa0992ddd5574aad7..16f71f20b8cd9177dde4bc2c49d6ff891b457c83 100644 (file)
--- a/mdadm.8
+++ b/mdadm.8
@@ -859,11 +859,29 @@ re-add a device that was recently removed from an array.
 .TP
 .BR \-r ", " \-\-remove
 remove listed devices.  They must not be active.  i.e. they should
-be failed or spare devices.
+be failed or spare devices.  As well as the name of a device file
+(e.g.
+.BR /dev/sda1 )
+the words
+.B failed
+and
+.B detached
+can be given to
+.BR \-\-remove .
+The first causes all failed device to be removed.  The second causes
+any device which is no longer connected to the system (i.e and open
+returns
+.BR ENXIO )
+to be removed.  This will only succeed for devices that are spares or
+have already been marked as failed.
 
 .TP
 .BR \-f ", " \-\-fail
 mark listed devices as faulty.
+As well as the name of a device file, the word
+.B detached
+can be given.  This will cause any device that has been detached from
+the system to be marked as failed.  It can then be removed.
 
 .TP
 .BR \-\-set\-faulty
@@ -1977,6 +1995,11 @@ appropriate.
 Rebuild the array map from any current arrays, and then start any that
 can be started.
 
+.B "  mdadm /dev/md4 --fail detached --remove detached"
+.br
+Any devices which are components of /dev/md4 will be marked as faulty
+and then remove from the array.
+
 .B "  mdadm \-\-create \-\-help"
 .br
 Provide help about the Create mode.