Fix race between --create and --incremental
This modifies locking in Create to eliminate a situation where --incremental can assemble a device between write_init_super() and add_disk(), which causes Create to fail. It sporadically occurs e.g. when metadata is written on a device, causing an udev change event which triggers mdadm --incremental. Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
8d1d32bb33
commit
19ad4b2cb2
29
Create.c
29
Create.c
|
@ -740,7 +740,9 @@ int Create(struct supertype *st, char *mddev,
|
||||||
|
|
||||||
map_update(&map, fd2devnm(mdfd), info.text_version,
|
map_update(&map, fd2devnm(mdfd), info.text_version,
|
||||||
info.uuid, chosen_name);
|
info.uuid, chosen_name);
|
||||||
map_unlock(&map);
|
/* Keep map locked until devices have been added to array
|
||||||
|
* to stop another mdadm from finding and using those devices.
|
||||||
|
*/
|
||||||
|
|
||||||
if (s->bitmap_file && vers < 9003) {
|
if (s->bitmap_file && vers < 9003) {
|
||||||
major_num = BITMAP_MAJOR_HOSTENDIAN;
|
major_num = BITMAP_MAJOR_HOSTENDIAN;
|
||||||
|
@ -753,18 +755,18 @@ int Create(struct supertype *st, char *mddev,
|
||||||
if (s->bitmap_file && strcmp(s->bitmap_file, "internal")==0) {
|
if (s->bitmap_file && strcmp(s->bitmap_file, "internal")==0) {
|
||||||
if ((vers%100) < 2) {
|
if ((vers%100) < 2) {
|
||||||
pr_err("internal bitmaps not supported by this kernel.\n");
|
pr_err("internal bitmaps not supported by this kernel.\n");
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
if (!st->ss->add_internal_bitmap) {
|
if (!st->ss->add_internal_bitmap) {
|
||||||
pr_err("internal bitmaps not supported with %s metadata\n",
|
pr_err("internal bitmaps not supported with %s metadata\n",
|
||||||
st->ss->name);
|
st->ss->name);
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
if (!st->ss->add_internal_bitmap(st, &s->bitmap_chunk,
|
if (!st->ss->add_internal_bitmap(st, &s->bitmap_chunk,
|
||||||
c->delay, s->write_behind,
|
c->delay, s->write_behind,
|
||||||
bitmapsize, 1, major_num)) {
|
bitmapsize, 1, major_num)) {
|
||||||
pr_err("Given bitmap chunk size not supported.\n");
|
pr_err("Given bitmap chunk size not supported.\n");
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
s->bitmap_file = NULL;
|
s->bitmap_file = NULL;
|
||||||
}
|
}
|
||||||
|
@ -790,7 +792,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
if (container_fd < 0) {
|
if (container_fd < 0) {
|
||||||
pr_err("Cannot get exclusive "
|
pr_err("Cannot get exclusive "
|
||||||
"open on container - weird.\n");
|
"open on container - weird.\n");
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
if (mdmon_running(st->container_devnm)) {
|
if (mdmon_running(st->container_devnm)) {
|
||||||
if (c->verbose)
|
if (c->verbose)
|
||||||
|
@ -805,7 +807,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
if (rv) {
|
if (rv) {
|
||||||
pr_err("failed to set array info for %s: %s\n",
|
pr_err("failed to set array info for %s: %s\n",
|
||||||
mddev, strerror(errno));
|
mddev, strerror(errno));
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->bitmap_file) {
|
if (s->bitmap_file) {
|
||||||
|
@ -816,18 +818,18 @@ int Create(struct supertype *st, char *mddev,
|
||||||
c->delay, s->write_behind,
|
c->delay, s->write_behind,
|
||||||
bitmapsize,
|
bitmapsize,
|
||||||
major_num)) {
|
major_num)) {
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
bitmap_fd = open(s->bitmap_file, O_RDWR);
|
bitmap_fd = open(s->bitmap_file, O_RDWR);
|
||||||
if (bitmap_fd < 0) {
|
if (bitmap_fd < 0) {
|
||||||
pr_err("weird: %s cannot be openned\n",
|
pr_err("weird: %s cannot be openned\n",
|
||||||
s->bitmap_file);
|
s->bitmap_file);
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
|
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
|
||||||
pr_err("Cannot set bitmap file for %s: %s\n",
|
pr_err("Cannot set bitmap file for %s: %s\n",
|
||||||
mddev, strerror(errno));
|
mddev, strerror(errno));
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,7 +886,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
pr_err("failed to open %s "
|
pr_err("failed to open %s "
|
||||||
"after earlier success - aborting\n",
|
"after earlier success - aborting\n",
|
||||||
dv->devname);
|
dv->devname);
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
fstat(fd, &stb);
|
fstat(fd, &stb);
|
||||||
inf->disk.major = major(stb.st_rdev);
|
inf->disk.major = major(stb.st_rdev);
|
||||||
|
@ -896,7 +898,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
fd, dv->devname,
|
fd, dv->devname,
|
||||||
dv->data_offset)) {
|
dv->data_offset)) {
|
||||||
ioctl(mdfd, STOP_ARRAY, NULL);
|
ioctl(mdfd, STOP_ARRAY, NULL);
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
st->ss->getinfo_super(st, inf, NULL);
|
st->ss->getinfo_super(st, inf, NULL);
|
||||||
safe_mode_delay = inf->safe_mode_delay;
|
safe_mode_delay = inf->safe_mode_delay;
|
||||||
|
@ -922,7 +924,7 @@ int Create(struct supertype *st, char *mddev,
|
||||||
pr_err("ADD_NEW_DISK for %s "
|
pr_err("ADD_NEW_DISK for %s "
|
||||||
"failed: %s\n",
|
"failed: %s\n",
|
||||||
dv->devname, strerror(errno));
|
dv->devname, strerror(errno));
|
||||||
goto abort;
|
goto abort_locked;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -939,7 +941,6 @@ int Create(struct supertype *st, char *mddev,
|
||||||
* the subarray cursor such that ->getinfo_super once
|
* the subarray cursor such that ->getinfo_super once
|
||||||
* again returns container info.
|
* again returns container info.
|
||||||
*/
|
*/
|
||||||
map_lock(&map);
|
|
||||||
st->ss->getinfo_super(st, &info_new, NULL);
|
st->ss->getinfo_super(st, &info_new, NULL);
|
||||||
if (st->ss->external && s->level != LEVEL_CONTAINER &&
|
if (st->ss->external && s->level != LEVEL_CONTAINER &&
|
||||||
!same_uuid(info_new.uuid, info.uuid, 0)) {
|
!same_uuid(info_new.uuid, info.uuid, 0)) {
|
||||||
|
@ -964,12 +965,12 @@ int Create(struct supertype *st, char *mddev,
|
||||||
info_new.uuid, path);
|
info_new.uuid, path);
|
||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
map_unlock(&map);
|
|
||||||
|
|
||||||
flush_metadata_updates(st);
|
flush_metadata_updates(st);
|
||||||
st->ss->free_super(st);
|
st->ss->free_super(st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
map_unlock(&map);
|
||||||
free(infos);
|
free(infos);
|
||||||
|
|
||||||
if (s->level == LEVEL_CONTAINER) {
|
if (s->level == LEVEL_CONTAINER) {
|
||||||
|
|
Loading…
Reference in New Issue