]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
extension of IncrementalRemove to store location (path-id) of removed device
authorPrzemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
Mon, 22 Nov 2010 09:58:06 +0000 (20:58 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 09:58:06 +0000 (20:58 +1100)
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<path-id> 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 <przemyslaw.hawrylewicz.czarnowski@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Incremental.c
Makefile
mdadm.h
policy.c

index 0fef20f5206e3f7472d661befed3b9dd72a7938f..7b43963c1da2fbab7d35f58a2ae0c92a732b600a 100644 (file)
@@ -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';
index 40f65af30eae32f00bba5a27140b92fee70d3a56..2b888188cbb8497303ce4c1382580050fe18f22c 100644 (file)
--- 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 c6fdebedf4d7dc512328db4625faae95064fbe98..43934115df40d8bba47e36cf94c63a04b7b37ae7 100644 (file)
--- 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
index 0bc3c4525cd8b98e2292f0ed39893ae70905a63a..28751fb98993c8e96f6994bbad34ed01e1447258 100644 (file)
--- 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 "
+                       "<id_path> 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;
+}