* UUID - uuid of the array
* path - path where device created: /dev/md/home
*
- * The best place for the mapfile wold be /var/run/mdadm/map. However
- * it is needed during initramfs early-boot, and /var/run doesn't exist there
- * and certainly doesn't persist through to normal boot.
- * So we store it in /dev/.mdadm/map but allow this to be changed at
- * compile time. via MAP_DIR and MAP_FILE
- *
+ * The best place for the mapfile is /run/mdadm/map. Distros and users
+ * which have not switched to /run yet can choose a different location
+ * at compile time via MAP_DIR and MAP_FILE.
*/
#include "mdadm.h"
#include <sys/file.h>
#include <ctype.h>
-#ifndef MAP_DIR
-#define MAP_DIR "/dev/.mdadm"
-#define MAP_FILE "map"
-#endif
#define MAP_READ 0
#define MAP_NEW 1
#define MAP_LOCK 2
#define MAP_DIRNAME 3
-#define mapnames(dir, base) { \
char *mapname[4] = {
MAP_DIR "/" MAP_FILE,
lf = NULL;
}
+void map_fork(void)
+{
+ /* We are forking, so must close the lock file.
+ * Don't risk flushing anything though.
+ */
+ if (lf) {
+ close(fileno(lf));
+ fclose(lf);
+ lf = NULL;
+ }
+}
+
void map_add(struct map_ent **melp,
int devnum, char *metadata, int uuid[4], char *path)
{
- struct map_ent *me = malloc(sizeof(*me));
+ struct map_ent *me = xmalloc(sizeof(*me));
me->devnum = devnum;
strcpy(me->metadata, metadata);
memcpy(me->uuid, uuid, 16);
- me->path = path ? strdup(path) : NULL;
+ me->path = path ? xstrdup(path) : NULL;
me->next = *melp;
me->bad = 0;
*melp = me;
strcpy(mp->metadata, metadata);
memcpy(mp->uuid, uuid, 16);
free(mp->path);
- mp->path = path ? strdup(path) : NULL;
+ mp->path = path ? xstrdup(path) : NULL;
+ mp->bad = 0;
break;
}
if (!mp)
* version super_by_fd does this automatically, this routine is meant as
* a supplement for guess_super()
*/
-static void set_member_info(struct supertype *st, struct mdstat_ent *ent)
+static char *get_member_info(struct mdstat_ent *ent)
{
- st->subarray[0] = '\0';
-
if (ent->metadata_version == NULL ||
strncmp(ent->metadata_version, "external:", 9) != 0)
- return;
+ return NULL;
if (is_subarray(&ent->metadata_version[9])) {
- char version[strlen(ent->metadata_version)+1];
char *subarray;
- char *name = &version[10];
-
- strcpy(version, ent->metadata_version);
- subarray = strrchr(version, '/');
- name = &version[10];
-
- if (!subarray)
- return;
- *subarray++ = '\0';
- st->container_dev = devname2devnum(name);
- strncpy(st->subarray, subarray, sizeof(st->subarray));
+ subarray = strrchr(ent->metadata_version, '/');
+ return subarray + 1;
}
+ return NULL;
}
void RebuildMap(void)
int dfd;
int ok;
struct supertype *st;
+ char *subarray = NULL;
char *path;
- struct mdinfo info;
+ struct mdinfo *info;
sprintf(dn, "%d:%d", sd->disk.major, sd->disk.minor);
dfd = dev_open(dn, O_RDONLY);
if ( st == NULL)
ok = -1;
else {
- set_member_info(st, md);
+ subarray = get_member_info(md);
ok = st->ss->load_super(st, dfd, NULL);
}
close(dfd);
if (ok != 0)
continue;
- st->ss->getinfo_super(st, &info);
+ info = st->ss->container_content(st, subarray);
+ if (!info)
+ continue;
+
if (md->devnum >= 0)
path = map_dev(MD_MAJOR, md->devnum, 0);
else
* find a unique name based on metadata name.
*
*/
- struct mddev_ident_s *match = conf_match(&info, st);
+ struct mddev_ident *match = conf_match(st, info,
+ NULL, 0,
+ NULL);
struct stat stb;
if (match && match->devname && match->devname[0] == '/') {
path = match->devname;
st->ss->match_home(st, homehost) != 1) &&
st->ss->match_home(st, "any") != 1 &&
(require_homehost
- || ! conf_name_is_free(info.name)))
+ || ! conf_name_is_free(info->name)))
/* require a numeric suffix */
unum = 0;
else
/* allow name to be used as-is if no conflict */
unum = -1;
- name = info.name;
+ name = info->name;
if (!*name) {
name = st->ss->name;
if (!isdigit(name[strlen(name)-1]) &&
}
}
map_add(&map, md->devnum,
- info.text_version,
- info.uuid, path);
+ info->text_version,
+ info->uuid, path);
st->ss->free_super(st);
+ free(info);
break;
}
sysfs_free(sra);