summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-11-04 20:50:39 +1100
committerNeilBrown <neilb@suse.de>2008-11-04 20:50:39 +1100
commit4ccad7b163fd5f210883d10b2fd36dcc90436b71 (patch)
treef11be238a1924e3cbb4813004c58601fc2030c34
parentac2ecf554303102ca23554a925fae91ac4fa57ca (diff)
downloadmdadm-4ccad7b163fd5f210883d10b2fd36dcc90436b71.tar.gz
mdadm-4ccad7b163fd5f210883d10b2fd36dcc90436b71.tar.xz
mdadm-4ccad7b163fd5f210883d10b2fd36dcc90436b71.zip
Manage: when stopping an array, delete all names from /dev.
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>
-rw-r--r--Manage.c65
-rw-r--r--mapfile.c11
-rw-r--r--mdadm.h1
3 files changed, 71 insertions, 6 deletions
diff --git a/Manage.c b/Manage.c
index fea563a..7855e21 100644
--- 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);
diff --git a/mapfile.c b/mapfile.c
index 53d9aea..a59ea4d 100644
--- 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 c34efe9..dd33116 100644
--- 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);