Incremental: lock against multiple concurrent additions to an array.
In two devices are added via -I to one array at the same time, mdadm can get badly confused. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
7e6c6cb267
commit
ad5bc697ad
9
Build.c
9
Build.c
|
@ -62,6 +62,7 @@ int Build(char *mddev, int chunk, int level, int layout,
|
||||||
int mdfd;
|
int mdfd;
|
||||||
char chosen_name[1024];
|
char chosen_name[1024];
|
||||||
int uuid[4] = {0,0,0,0};
|
int uuid[4] = {0,0,0,0};
|
||||||
|
struct map_ent *map = NULL;
|
||||||
|
|
||||||
/* scan all devices, make sure they really are block devices */
|
/* scan all devices, make sure they really are block devices */
|
||||||
for (dv = devlist; dv; dv=dv->next) {
|
for (dv = devlist; dv; dv=dv->next) {
|
||||||
|
@ -116,12 +117,16 @@ int Build(char *mddev, int chunk, int level, int layout,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to create the device. It can have no name. */
|
/* We need to create the device. It can have no name. */
|
||||||
|
map_lock(&map);
|
||||||
mdfd = create_mddev(mddev, NULL, autof, LOCAL,
|
mdfd = create_mddev(mddev, NULL, autof, LOCAL,
|
||||||
chosen_name);
|
chosen_name);
|
||||||
if (mdfd < 0)
|
if (mdfd < 0) {
|
||||||
|
map_unlock(&map);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
map_update(NULL, fd2devnum(mdfd), "none", uuid, chosen_name);
|
map_update(&map, fd2devnum(mdfd), "none", uuid, chosen_name);
|
||||||
|
map_unlock(&map);
|
||||||
|
|
||||||
vers = md_get_version(mdfd);
|
vers = md_get_version(mdfd);
|
||||||
|
|
||||||
|
|
5
Create.c
5
Create.c
|
@ -80,6 +80,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
int did_default = 0;
|
int did_default = 0;
|
||||||
unsigned long safe_mode_delay = 0;
|
unsigned long safe_mode_delay = 0;
|
||||||
char chosen_name[1024];
|
char chosen_name[1024];
|
||||||
|
struct map_ent *map = NULL;
|
||||||
|
|
||||||
int major_num = BITMAP_MAJOR_HI;
|
int major_num = BITMAP_MAJOR_HI;
|
||||||
|
|
||||||
|
@ -422,6 +423,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to create the device */
|
/* We need to create the device */
|
||||||
|
map_lock(&map);
|
||||||
mdfd = create_mddev(mddev, name, autof, LOCAL, chosen_name);
|
mdfd = create_mddev(mddev, name, autof, LOCAL, chosen_name);
|
||||||
if (mdfd < 0)
|
if (mdfd < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -561,8 +563,9 @@ int Create(struct supertype *st, char *mddev,
|
||||||
" %s metadata\n", info.text_version);
|
" %s metadata\n", info.text_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
map_update(NULL, fd2devnum(mdfd), info.text_version,
|
map_update(&map, fd2devnum(mdfd), info.text_version,
|
||||||
info.uuid, chosen_name);
|
info.uuid, chosen_name);
|
||||||
|
map_unlock(&map);
|
||||||
|
|
||||||
if (bitmap_file && vers < 9003) {
|
if (bitmap_file && vers < 9003) {
|
||||||
major_num = BITMAP_MAJOR_HOSTENDIAN;
|
major_num = BITMAP_MAJOR_HOSTENDIAN;
|
||||||
|
|
|
@ -88,6 +88,7 @@ int Incremental(char *devname, int verbose, int runstop,
|
||||||
int active_disks;
|
int active_disks;
|
||||||
int trustworthy = FOREIGN;
|
int trustworthy = FOREIGN;
|
||||||
char *name_to_use;
|
char *name_to_use;
|
||||||
|
mdu_array_info_t ainf;
|
||||||
|
|
||||||
struct createinfo *ci = conf_get_create_info();
|
struct createinfo *ci = conf_get_create_info();
|
||||||
|
|
||||||
|
@ -243,8 +244,9 @@ int Incremental(char *devname, int verbose, int runstop,
|
||||||
return Incremental_container(st, devname, verbose, runstop,
|
return Incremental_container(st, devname, verbose, runstop,
|
||||||
autof, trustworthy);
|
autof, trustworthy);
|
||||||
}
|
}
|
||||||
/* 4/ Check is array exists.
|
/* 4/ Check if array exists.
|
||||||
*/
|
*/
|
||||||
|
map_lock(&map);
|
||||||
mp = map_by_uuid(&map, info.uuid);
|
mp = map_by_uuid(&map, info.uuid);
|
||||||
if (mp)
|
if (mp)
|
||||||
mdfd = open_mddev(mp->path, 0);
|
mdfd = open_mddev(mp->path, 0);
|
||||||
|
@ -298,6 +300,10 @@ int Incremental(char *devname, int verbose, int runstop,
|
||||||
}
|
}
|
||||||
info.array.working_disks = 1;
|
info.array.working_disks = 1;
|
||||||
sysfs_free(sra);
|
sysfs_free(sra);
|
||||||
|
/* 6/ Make sure /var/run/mdadm.map contains this array. */
|
||||||
|
map_update(&map, fd2devnum(mdfd),
|
||||||
|
info.text_version,
|
||||||
|
info.uuid, chosen_name);
|
||||||
} else {
|
} else {
|
||||||
/* 5b/ if it does */
|
/* 5b/ if it does */
|
||||||
/* - check one drive in array to make sure metadata is a reasonably */
|
/* - check one drive in array to make sure metadata is a reasonably */
|
||||||
|
@ -366,16 +372,13 @@ int Incremental(char *devname, int verbose, int runstop,
|
||||||
info.array.working_disks ++;
|
info.array.working_disks ++;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* 6/ Make sure /var/run/mdadm.map contains this array. */
|
|
||||||
map_update(&map, fd2devnum(mdfd),
|
|
||||||
info.text_version,
|
|
||||||
info.uuid, chosen_name);
|
|
||||||
|
|
||||||
/* 7/ Is there enough devices to possibly start the array? */
|
/* 7/ Is there enough devices to possibly start the array? */
|
||||||
/* 7a/ if not, finish with success. */
|
/* 7a/ if not, finish with success. */
|
||||||
if (info.array.level == LEVEL_CONTAINER) {
|
if (info.array.level == LEVEL_CONTAINER) {
|
||||||
/* Try to assemble within the container */
|
/* Try to assemble within the container */
|
||||||
close(mdfd);
|
close(mdfd);
|
||||||
|
map_unlock(&map);
|
||||||
sysfs_uevent(&info, "change");
|
sysfs_uevent(&info, "change");
|
||||||
if (verbose >= 0)
|
if (verbose >= 0)
|
||||||
fprintf(stderr, Name
|
fprintf(stderr, Name
|
||||||
|
@ -394,6 +397,7 @@ int Incremental(char *devname, int verbose, int runstop,
|
||||||
fprintf(stderr, Name
|
fprintf(stderr, Name
|
||||||
": %s attached to %s, not enough to start (%d).\n",
|
": %s attached to %s, not enough to start (%d).\n",
|
||||||
devname, chosen_name, active_disks);
|
devname, chosen_name, active_disks);
|
||||||
|
map_unlock(&map);
|
||||||
close(mdfd);
|
close(mdfd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -404,18 +408,18 @@ int Incremental(char *devname, int verbose, int runstop,
|
||||||
/* are enough, */
|
/* are enough, */
|
||||||
/* + add any bitmap file */
|
/* + add any bitmap file */
|
||||||
/* + start the array (auto-readonly). */
|
/* + start the array (auto-readonly). */
|
||||||
{
|
|
||||||
mdu_array_info_t ainf;
|
|
||||||
|
|
||||||
if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) {
|
if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) {
|
||||||
if (verbose >= 0)
|
if (verbose >= 0)
|
||||||
fprintf(stderr, Name
|
fprintf(stderr, Name
|
||||||
": %s attached to %s which is already active.\n",
|
": %s attached to %s which is already active.\n",
|
||||||
devname, chosen_name);
|
devname, chosen_name);
|
||||||
close (mdfd);
|
close(mdfd);
|
||||||
|
map_unlock(&map);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
map_unlock(&map);
|
||||||
if (runstop > 0 || active_disks >= info.array.working_disks) {
|
if (runstop > 0 || active_disks >= info.array.working_disks) {
|
||||||
struct mdinfo *sra;
|
struct mdinfo *sra;
|
||||||
/* Let's try to start it */
|
/* Let's try to start it */
|
||||||
|
@ -749,13 +753,16 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
|
||||||
|
|
||||||
struct mdinfo *list = st->ss->container_content(st);
|
struct mdinfo *list = st->ss->container_content(st);
|
||||||
struct mdinfo *ra;
|
struct mdinfo *ra;
|
||||||
|
struct map_ent *map = NULL;
|
||||||
|
|
||||||
|
map_lock(&map);
|
||||||
|
|
||||||
for (ra = list ; ra ; ra = ra->next) {
|
for (ra = list ; ra ; ra = ra->next) {
|
||||||
struct mdinfo *dev, *sra;
|
struct mdinfo *dev, *sra;
|
||||||
int mdfd;
|
int mdfd;
|
||||||
char chosen_name[1024];
|
char chosen_name[1024];
|
||||||
int working = 0, preexist = 0;
|
int working = 0, preexist = 0;
|
||||||
struct map_ent *mp, *map = NULL;
|
struct map_ent *mp;
|
||||||
struct mddev_ident_s *match = NULL;
|
struct mddev_ident_s *match = NULL;
|
||||||
|
|
||||||
mp = map_by_uuid(&map, ra->uuid);
|
mp = map_by_uuid(&map, ra->uuid);
|
||||||
|
@ -869,5 +876,6 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
|
||||||
ra->uuid, chosen_name);
|
ra->uuid, chosen_name);
|
||||||
close(mdfd);
|
close(mdfd);
|
||||||
}
|
}
|
||||||
|
map_unlock(&map);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
37
mapfile.c
37
mapfile.c
|
@ -86,6 +86,43 @@ int map_write(struct map_ent *mel)
|
||||||
"/var/run/mdadm.map") == 0;
|
"/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,
|
void map_add(struct map_ent **melp,
|
||||||
int devnum, char *metadata, int uuid[4], char *path)
|
int devnum, char *metadata, int uuid[4], char *path)
|
||||||
{
|
{
|
||||||
|
|
2
mdadm.h
2
mdadm.h
|
@ -325,6 +325,8 @@ extern void map_delete(struct map_ent **mapp, int devnum);
|
||||||
extern void map_free(struct map_ent *map);
|
extern void map_free(struct map_ent *map);
|
||||||
extern void map_add(struct map_ent **melp,
|
extern void map_add(struct map_ent **melp,
|
||||||
int devnum, char *metadata, int uuid[4], char *path);
|
int devnum, char *metadata, int uuid[4], char *path);
|
||||||
|
extern int map_lock(struct map_ent **melp);
|
||||||
|
extern void map_unlock(struct map_ent **melp);
|
||||||
|
|
||||||
/* various details can be requested */
|
/* various details can be requested */
|
||||||
#define GET_LEVEL 1
|
#define GET_LEVEL 1
|
||||||
|
|
Loading…
Reference in New Issue