From 403410eb97e9ae77f99fd7632f0093660748197f Mon Sep 17 00:00:00 2001 From: Przemyslaw Czarnowski Date: Mon, 22 Nov 2010 20:58:06 +1100 Subject: [PATCH] extension of IncrementalRemove to store location (path-id) of removed device If the disk is taken out from its port this port information is lost. Only udev rule can provide us with this information, and then we have to store it somehow. This patch adds writing 'cookie' file in /dev/.mdadm/failed-slots directory in form of file named with value of f containing the metadata type and uuid of the array (or container) that the device was a member of. The uuid is in exactly the same format as in the mapfile. FAILED_SLOTS_DIR constant has been added to hold the location of cookie files. Signed-off-by: Przemyslaw Czarnowski Signed-off-by: NeilBrown --- Incremental.c | 9 +++++++ Makefile | 3 +++ mdadm.h | 11 +++++++++ policy.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) diff --git a/Incremental.c b/Incremental.c index 0fef20f5..7b43963c 100644 --- a/Incremental.c +++ b/Incremental.c @@ -1385,6 +1385,15 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) free_mdstat(ent); return 1; } + + if (id_path) { + struct map_ent *map = NULL, *me; + me = map_by_devnum(&map, ent->devnum); + if (me) + policy_save_path(id_path, me); + map_free(map); + } + memset(&devlist, 0, sizeof(devlist)); devlist.devname = devname; devlist.disposition = 'f'; diff --git a/Makefile b/Makefile index 40f65af3..2b888188 100644 --- a/Makefile +++ b/Makefile @@ -71,8 +71,11 @@ CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE)\" -DCONFFILE2=\"$(CONFFILE2)\" MAP_DIR=/dev/.mdadm MAP_FILE = map MDMON_DIR = /dev/.mdadm +# place for autoreplace cookies +FAILED_SLOTS_DIR = /dev/.mdadm/failed-slots DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\" DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\" +DIRFLAGS += -DFAILED_SLOTS_DIR=\"$(FAILED_SLOTS_DIR)\" CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) # The glibc TLS ABI requires applications that call clone(2) to set up diff --git a/mdadm.h b/mdadm.h index c6fdebed..43934115 100644 --- a/mdadm.h +++ b/mdadm.h @@ -93,6 +93,14 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); #define MDMON_DIR "/dev/.mdadm/" #endif /* MDMON_DIR */ +/* FAILED_SLOTS is where to save files storing recent removal of array + * member in order to allow future reuse of disk inserted in the same + * slot for array recovery + */ +#ifndef FAILED_SLOTS_DIR +#define FAILED_SLOTS_DIR "/dev/.mdadm/failed-slots" +#endif /* FAILED_SLOTS */ + #include "md_u.h" #include "md_p.h" #include "bitmap.h" @@ -831,6 +839,9 @@ extern void domain_free(struct domainlist *dl); extern void domain_merge(struct domainlist **domp, struct dev_policy *pol, const char *metadata); +extern void policy_save_path(char *id_path, struct map_ent *array); +extern int policy_check_path(struct mdinfo *disk, struct map_ent *array); + #if __GNUC__ < 3 struct stat64; #endif diff --git a/policy.c b/policy.c index 0bc3c452..28751fb9 100644 --- a/policy.c +++ b/policy.c @@ -644,3 +644,70 @@ void domain_free(struct domainlist *dl) free(head); } } + +/* + * same-path policy. + * Some policy decisions are guided by knowledge of which + * array previously owned the device at a given physical location (path). + * When removing a device from an array we might record the array against + * the path, and when finding a new device, we might look for which + * array previously used that path. + * + * The 'array' is described by a map_ent, and the path by a the disk in an + * mdinfo, or a string. + */ + +void policy_save_path(char *id_path, struct map_ent *array) +{ + char path[PATH_MAX]; + FILE *f = NULL; + + if (mkdir(FAILED_SLOTS_DIR, S_IRWXU) < 0 && errno != EEXIST) { + fprintf(stderr, Name ": can't create file to save path " + "to old disk: %s\n", strerror(errno)); + return; + } + + snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); + f = fopen(path, "w"); + if (!f) { + fprintf(stderr, Name ": can't create file to" + " save path to old disk: %s\n", + strerror(errno)); + return; + } + + if (fprintf(f, "%s %08x:%08x:%08x:%08x\n", + array->metadata, + array->uuid[0], array->uuid[1], + array->uuid[2], array->uuid[3]) <= 0) + fprintf(stderr, Name ": Failed to write to " + " cookie\n"); + + fclose(f); +} + +int policy_check_path(struct mdinfo *disk, struct map_ent *array) +{ + char path[PATH_MAX]; + FILE *f = NULL; + char *id_path = disk_path(disk); + int rv; + + if (!id_path) + return 0; + + snprintf(path, PATH_MAX, FAILED_SLOTS_DIR "/%s", id_path); + f = fopen(path, "r"); + if (!f) + return 0; + + rv = fscanf(f, " %s %x:%x:%x:%x\n", + array->metadata, + array->uuid, + array->uuid+1, + array->uuid+2, + array->uuid+3); + fclose(f); + return rv == 5; +} -- 2.39.2