]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Manage: when stopping an array, delete all names from /dev.
authorNeilBrown <neilb@suse.de>
Tue, 4 Nov 2008 09:50:39 +0000 (20:50 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 4 Nov 2008 09:50:39 +0000 (20:50 +1100)
This only applies if udev isn't installed or is disabled
by MDADM_NO_UDEV
We try to remove partitions too.
We find names to remove by looking in /var/run/mdadm/map

Signed-off-by: NeilBrown <neilb@suse.de>
Manage.c
mapfile.c
mdadm.h

index fea563a6403ee3ab66d085f26f8d840d5b76b1da..7855e21aa561b5320a08aa0ec5f23f8360aa236a 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -30,6 +30,7 @@
 #include "mdadm.h"
 #include "md_u.h"
 #include "md_p.h"
+#include <ctype.h>
 
 #define REGISTER_DEV           _IO (MD_MAJOR, 1)
 #define START_MD               _IO (MD_MAJOR, 2)
@@ -120,6 +121,52 @@ int Manage_ro(char *devname, int fd, int readonly)
 
 #ifndef MDASSEMBLE
 
+static void remove_devices(int devnum, char *path)
+{
+       /* Remove all 'standard' devices for 'devnum', including
+        * partitions.  Also remove names at 'path' - possibly with
+        * partition suffixes - which link to those names.
+        */
+       char base[40];
+       char *path2;
+       char link[1024];
+       int n;
+       int part;
+       char *be;
+       char *pe;
+
+       if (devnum >= 0)
+               sprintf(base, "/dev/md%d", devnum);
+       else
+               sprintf(base, "/dev/md_d%d", -1-devnum);
+       be = base + strlen(base);
+       if (path) {
+               path2 = malloc(strlen(path)+20);
+               strcpy(path2, path);
+               pe = path2 + strlen(path2);
+       } else
+               path = NULL;
+       
+       for (part = 0; part < 16; part++) {
+               if (part) {
+                       sprintf(be, "p%d", part);
+                       if (isdigit(pe[-1]))
+                               sprintf(pe, "p%d", part);
+                       else
+                               sprintf(pe, "%d", part);
+               }
+               /* FIXME test if really is md device ?? */
+               unlink(base);
+               if (path) {
+                       n = readlink(path2, link, sizeof(link));
+                       if (n && strlen(base) == n &&
+                           strncmp(link, base, n) == 0)
+                               unlink(path2);
+               }
+       }
+}
+       
+
 int Manage_runstop(char *devname, int fd, int runstop, int quiet)
 {
        /* Run or stop the array. array must already be configured
@@ -163,9 +210,11 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
                struct map_ent *map = NULL;
                struct stat stb;
                struct mdinfo *mdi;
+               int devnum;
                /* If this is an mdmon managed array, just write 'inactive'
                 * to the array state and let mdmon clear up.
                 */
+               devnum = fd2devnum(fd);
                mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION);
                if (mdi &&
                    mdi->array.level > 0 &&
@@ -216,14 +265,18 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
                if (mdi)
                        sysfs_uevent(mdi, "change");
 
+               
+               if (devnum != NoMdDev &&
+                   (stat("/dev/.udev", &stb) != 0 ||
+                    check_env("MDADM_NO_UDEV"))) {
+                       struct map_ent *mp = map_by_devnum(&map, devnum);
+                       remove_devices(devnum, mp ? mp->path : NULL);
+               }
+
+
                if (quiet <= 0)
                        fprintf(stderr, Name ": stopped %s\n", devname);
-               if (fd >= 0 && fstat(fd, &stb) == 0) {
-                       int devnum;
-                       if (major(stb.st_rdev) == MD_MAJOR)
-                               devnum = minor(stb.st_rdev);
-                       else
-                               devnum = -1-(minor(stb.st_rdev)>>6);
+               if (devnum != NoMdDev) {
                        map_delete(&map, devnum);
                        map_write(map);
                        map_free(map);
index 53d9aea42c7d17f16e742da331c56febc5cabd75..a59ea4dd9dfbc5eb929ddabfb9b2d6471ca4949c 100644 (file)
--- a/mapfile.c
+++ b/mapfile.c
@@ -195,5 +195,16 @@ struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4])
                if (memcmp(uuid, mp->uuid, 16) == 0)
                        return mp;
        return NULL;
+}
 
+struct map_ent *map_by_devnum(struct map_ent **map, int devnum)
+{
+       struct map_ent *mp;
+       if (!*map)
+               map_read(map);
+
+       for (mp = *map ; mp ; mp = mp->next)
+               if (mp->devnum == devnum)
+                       return mp;
+       return NULL;
 }
diff --git a/mdadm.h b/mdadm.h
index c34efe9b8713bee2cd651bb5b7129e2749e5b420..dd33116cafcfdc46d803ff5b1786018f96e10207 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -318,6 +318,7 @@ struct map_ent {
 extern int map_update(struct map_ent **mpp, int devnum, char *metadata,
                      int uuid[4], char *path);
 extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
+struct map_ent *map_by_devnum(struct map_ent **map, int devnum);
 extern void map_read(struct map_ent **melp);
 extern int map_write(struct map_ent *mel);
 extern void map_delete(struct map_ent **mapp, int devnum);