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';
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
#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"
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
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;
+}