X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=mapfile.c;h=f27623221ce9e706cec05d29d0140447bcc7e3fa;hp=cf2ca2bf8a5837ba28456fb7a9cd32938e4294b0;hb=506ffd1e0bd08cc74f5177d4f4db7c66d7724f6a;hpb=1522c538b1b8a685d4f0280eefbb2b82b82c1b6a diff --git a/mapfile.c b/mapfile.c index cf2ca2bf..f2762322 100644 --- a/mapfile.c +++ b/mapfile.c @@ -53,11 +53,13 @@ int map_write(struct map_ent *mel) f = fopen("/var/run/mdadm/map.new", "w"); if (!f) { f = fopen("/var/run/mdadm.map.new", "w"); - subdir = 1; + subdir = 0; } if (!f) return 0; - while (mel) { + for (; mel; mel = mel->next) { + if (mel->bad) + continue; if (mel->devnum < 0) fprintf(f, "mdp%d ", -1-mel->devnum); else @@ -66,7 +68,6 @@ int map_write(struct map_ent *mel) fprintf(f, "%08x:%08x:%08x:%08x ", mel->uuid[0], mel->uuid[1], mel->uuid[2], mel->uuid[3]); fprintf(f, "%s\n", mel->path); - mel = mel->next; } fflush(f); err = ferror(f); @@ -86,6 +87,43 @@ int map_write(struct map_ent *mel) "/var/run/mdadm.map") == 0; } + +static int lfd = -1; +static int lsubdir = 0; +int map_lock(struct map_ent **melp) +{ + if (lfd < 0) { + lfd = open("/var/run/mdadm/map.lock", O_CREAT|O_RDWR, 0600); + if (lfd < 0) { + lfd = open("/var/run/mdadm.map.lock", O_CREAT|O_RDWR, 0600); + lsubdir = 0; + } else + lsubdir = 1; + if (lfd < 0) + return -1; + if (lockf(lfd, F_LOCK, 0) != 0) { + close(lfd); + lfd = -1; + return -1; + } + } + if (*melp) + map_free(*melp); + map_read(melp); + return 0; +} + +void map_unlock(struct map_ent **melp) +{ + if (lfd >= 0) + close(lfd); + if (lsubdir) + unlink("/var/run/mdadm/map.lock"); + else + unlink("/var/run/mdadm.map.lock"); + lfd = -1; +} + void map_add(struct map_ent **melp, int devnum, char *metadata, int uuid[4], char *path) { @@ -96,6 +134,7 @@ void map_add(struct map_ent **melp, memcpy(me->uuid, uuid, 16); me->path = strdup(path); me->next = *melp; + me->bad = 0; *melp = me; } @@ -111,16 +150,24 @@ void map_read(struct map_ent **melp) *melp = NULL; f = fopen("/var/run/mdadm/map", "r"); + if (!f) + f = fopen("/var/run/mdadm.map", "r"); + if (!f) { + RebuildMap(); + f = fopen("/var/run/mdadm/map", "r"); + } if (!f) f = fopen("/var/run/mdadm.map", "r"); if (!f) return; while (fgets(buf, sizeof(buf), f)) { - if (sscanf(buf, " md%1[p]%d %s %x:%x:%x:%x %200s", + if (sscanf(buf, " %3[mdp]%d %s %x:%x:%x:%x %200s", nam, &devnum, metadata, uuid, uuid+1, - uuid+2, uuid+3, path) == 9) { - if (nam[0] == 'p') + uuid+2, uuid+3, path) == 8) { + if (strncmp(nam, "md", 2) != 0) + continue; + if (nam[2] == 'p') devnum = -1 - devnum; map_add(melp, devnum, metadata, uuid, path); } @@ -159,7 +206,8 @@ int map_update(struct map_ent **mpp, int devnum, char *metadata, } if (!mp) map_add(&map, devnum, metadata, uuid, path); - *mpp = NULL; + if (mpp) + *mpp = NULL; rv = map_write(map); map_free(map); return rv; @@ -188,9 +236,109 @@ struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]) if (!*map) map_read(map); - for (mp = *map ; mp ; mp = mp->next) - if (memcmp(uuid, mp->uuid, 16) == 0) - return mp; + for (mp = *map ; mp ; mp = mp->next) { + if (memcmp(uuid, mp->uuid, 16) != 0) + continue; + if (!mddev_busy(mp->devnum)) { + mp->bad = 1; + continue; + } + 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) + continue; + if (!mddev_busy(mp->devnum)) { + mp->bad = 1; + continue; + } + return mp; + } + return NULL; +} + +struct map_ent *map_by_name(struct map_ent **map, char *name) +{ + struct map_ent *mp; + if (!*map) + map_read(map); + + for (mp = *map ; mp ; mp = mp->next) { + if (strncmp(mp->path, "/dev/md/", 8) != 0) + continue; + if (strcmp(mp->path+8, name) != 0) + continue; + if (!mddev_busy(mp->devnum)) { + mp->bad = 1; + continue; + } + return mp; + } return NULL; +} + +void RebuildMap(void) +{ + struct mdstat_ent *mdstat = mdstat_read(0, 0); + struct mdstat_ent *md; + struct map_ent *map = NULL; + int mdp = get_mdp_major(); + + for (md = mdstat ; md ; md = md->next) { + struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_DEVS|SKIP_GONE_DEVS); + struct mdinfo *sd; + + if (!sra) + continue; + for (sd = sra->devs ; sd ; sd = sd->next) { + char dn[30]; + int dfd; + int ok; + struct supertype *st; + char *path; + struct mdinfo info; + + sprintf(dn, "%d:%d", sd->disk.major, sd->disk.minor); + dfd = dev_open(dn, O_RDONLY); + if (dfd < 0) + continue; + st = guess_super(dfd); + if ( st == NULL) + ok = -1; + else + ok = st->ss->load_super(st, dfd, NULL); + close(dfd); + if (ok != 0) + continue; + st->ss->getinfo_super(st, &info); + if (md->devnum > 0) + path = map_dev(MD_MAJOR, md->devnum, 0); + else + path = map_dev(mdp, (-1-md->devnum)<< 6, 0); + map_add(&map, md->devnum, + info.text_version, + info.uuid, path ? : "/unknown"); + st->ss->free_super(st); + break; + } + sysfs_free(sra); + } + map_write(map); + map_free(map); + for (md = mdstat ; md ; md = md->next) { + struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_VERSION); + sysfs_uevent(sra, "change"); + sysfs_free(sra); + } + free_mdstat(mdstat); }