mapfile: just have one place to store the mapfile

Having multiple possible locations and guessing where best to put the
file is too messy, confusing and makes locking problematic.

So just keep it in /dev/.mdadm/map.  It is a horrible place but it is
really all we have.  System integrators can change this easily at
build time.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2010-08-06 14:54:10 +10:00
parent 925211e323
commit 9e751dc7a0
1 changed files with 37 additions and 45 deletions

View File

@ -1,8 +1,8 @@
/* /*
* mapfile - manage /var/run/mdadm/map. Part of: * mapfile - keep track of uuid <-> array mapping. Part of:
* mdadm - manage Linux "md" devices aka RAID arrays. * mdadm - manage Linux "md" devices aka RAID arrays.
* *
* Copyright (C) 2006-2009 Neil Brown <neilb@suse.de> * Copyright (C) 2006-2010 Neil Brown <neilb@suse.de>
* *
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -28,7 +28,7 @@
* Australia * Australia
*/ */
/* /var/run/mdadm/map is used to track arrays being created in --incremental /* The mapfile is used to track arrays being created in --incremental
* mode. It particularly allows lookup from UUID to array device, but * mode. It particularly allows lookup from UUID to array device, but
* also allows the array device name to be easily found. * also allows the array device name to be easily found.
* *
@ -38,54 +38,49 @@
* UUID - uuid of the array * UUID - uuid of the array
* path - path where device created: /dev/md/home * path - path where device created: /dev/md/home
* *
* The preferred location for the map file is /var/run/mdadm/map. * The best place for the mapfile wold be /var/run/mdadm/map. However
* However /var/run may not exist or be writable in early boot. And if * it is needed during initramfs early-boot, and /var/run doesn't exist there
* no-one has created /var/run/mdadm, we still want to survive. * and certainly doesn't persist through to normal boot.
* So possible locations are: * So we store it in /dev/.mdadm/map but allow this to be changed at
* /var/run/mdadm/map /dev/.mdadm/map(changable at compile time). * compile time. via MAP_DIR and MAP_FILE
* We read from the first one that exists and write to the first *
* one that we can.
*/ */
#include "mdadm.h" #include "mdadm.h"
#include <sys/file.h> #include <sys/file.h>
#include <ctype.h> #include <ctype.h>
#ifndef MAP_DIR
#define MAP_DIR "/dev/.mdadm"
#define MAP_FILE "map"
#endif
#define MAP_READ 0 #define MAP_READ 0
#define MAP_NEW 1 #define MAP_NEW 1
#define MAP_LOCK 2 #define MAP_LOCK 2
#define MAP_DIRNAME 3 #define MAP_DIRNAME 3
#define mapnames(dir, base) { \ #define mapnames(dir, base) { \
dir "/" base, \
dir "/" base ".new", \
dir "/" base ".lock", \
dir }
#define MAP_DIRS 2 char *mapname[4] = {
char *mapname[MAP_DIRS][4] = { MAP_DIR "/" MAP_FILE,
mapnames("/var/run/mdadm", "map"), MAP_DIR "/" MAP_FILE ".new",
mapnames(MAP_DIR, MAP_FILE), MAP_DIR "/" MAP_FILE ".lock",
MAP_DIR
}; };
int mapmode[3] = { O_RDONLY, O_RDWR|O_CREAT, O_RDWR|O_CREAT|O_TRUNC }; int mapmode[3] = { O_RDONLY, O_RDWR|O_CREAT, O_RDWR|O_CREAT|O_TRUNC };
char *mapsmode[3] = { "r", "w", "w"}; char *mapsmode[3] = { "r", "w", "w"};
FILE *open_map(int modenum, int *choice) FILE *open_map(int modenum)
{ {
int i; int fd;
if ((mapmode[modenum] & O_CREAT))
for (i = 0 ; i <= MAP_DIRS ; i++) { /* Attempt to create directory, don't worry about
int fd; * failure.
if ((mapmode[modenum] & O_CREAT)) */
/* Attempt to create directory, don't worry about (void)mkdir(mapname[MAP_DIRNAME], 0755);
* failure. fd = open(mapname[modenum], mapmode[modenum], 0600);
*/ if (fd >= 0)
(void)mkdir(mapname[i][MAP_DIRNAME], 0755); return fdopen(fd, mapsmode[modenum]);
fd = open(mapname[i][modenum], mapmode[modenum], 0600);
if (fd >= 0) {
*choice = i;
return fdopen(fd, mapsmode[modenum]);
}
}
return NULL; return NULL;
} }
@ -93,9 +88,8 @@ int map_write(struct map_ent *mel)
{ {
FILE *f; FILE *f;
int err; int err;
int which;
f = open_map(MAP_NEW, &which); f = open_map(MAP_NEW);
if (!f) if (!f)
return 0; return 0;
@ -115,21 +109,20 @@ int map_write(struct map_ent *mel)
err = ferror(f); err = ferror(f);
fclose(f); fclose(f);
if (err) { if (err) {
unlink(mapname[which][1]); unlink(mapname[1]);
return 0; return 0;
} }
return rename(mapname[which][1], return rename(mapname[1],
mapname[which][0]) == 0; mapname[0]) == 0;
} }
static FILE *lf = NULL; static FILE *lf = NULL;
static int lwhich = 0;
int map_lock(struct map_ent **melp) int map_lock(struct map_ent **melp)
{ {
while (lf == NULL) { while (lf == NULL) {
struct stat buf; struct stat buf;
lf = open_map(MAP_LOCK, &lwhich); lf = open_map(MAP_LOCK);
if (lf == NULL) if (lf == NULL)
return -1; return -1;
if (flock(fileno(lf), LOCK_EX) != 0) { if (flock(fileno(lf), LOCK_EX) != 0) {
@ -160,7 +153,7 @@ void map_unlock(struct map_ent **melp)
* as only the owner of the lock may * as only the owner of the lock may
* unlink the file * unlink the file
*/ */
unlink(mapname[lwhich][2]); unlink(mapname[2]);
fclose(lf); fclose(lf);
} }
lf = NULL; lf = NULL;
@ -188,14 +181,13 @@ void map_read(struct map_ent **melp)
int devnum, uuid[4]; int devnum, uuid[4];
char metadata[30]; char metadata[30];
char nam[4]; char nam[4];
int which;
*melp = NULL; *melp = NULL;
f = open_map(MAP_READ, &which); f = open_map(MAP_READ);
if (!f) { if (!f) {
RebuildMap(); RebuildMap();
f = open_map(MAP_READ, &which); f = open_map(MAP_READ);
} }
if (!f) if (!f)
return; return;