Skip to content
2 changes: 1 addition & 1 deletion Assemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -2221,8 +2221,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
set_array_assembly_status(c, result, INCR_NO, &array);
else {
set_array_assembly_status(c, result, INCR_YES, &array);
wait_for(chosen_name, mdfd);
sysfs_rules_apply(chosen_name, content, st);
wait_for(chosen_name, mdfd);
}

return err;
Expand Down
14 changes: 9 additions & 5 deletions Create.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
int container_fd = -1;
int need_mdmon = 0;
unsigned long long bitmapsize;
bool udev_blocked;
struct mdinfo info;
int did_default = 0;
int do_default_layout = 0;
Expand Down Expand Up @@ -1029,7 +1030,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,

/* We need to create the device */
map_lock(&map);
mdfd = create_mddev(ident->devname, ident->name, LOCAL, chosen_name, 1);
udev_blocked = udev_is_available();
mdfd = create_mddev(ident->devname, ident->name, LOCAL, chosen_name, udev_blocked);
if (mdfd < 0) {
map_unlock(&map);
return 1;
Expand All @@ -1043,7 +1045,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
pr_err("Array name %s is in use already.\n", chosen_name);
close(mdfd);
map_unlock(&map);
udev_unblock();
if (udev_blocked)
udev_unblock();
return 1;
}

Expand Down Expand Up @@ -1331,14 +1334,15 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
pr_err("not starting array - not enough devices.\n");
}
close(mdfd);
udev_unblock();
sysfs_uevent(&info, "change");
if (udev_blocked)
udev_ready(&info);
dev_policy_free(custom_pols);

return 0;

abort:
udev_unblock();
if (udev_blocked)
udev_unblock();
map_lock(&map);
abort_locked:
map_remove(&map, fd2devnm(mdfd));
Expand Down
45 changes: 26 additions & 19 deletions Incremental.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
int have_target;
char *devname = devlist->devname;
int journal_device_missing = 0;
bool array_started = false;
bool udev_blocked = false;

if (!stat_is_blkdev(devname, &rdev))
return rv;
Expand Down Expand Up @@ -286,8 +288,9 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
goto out_unlock;

/* Couldn't find an existing array, maybe make a new one */
udev_blocked = udev_is_available();
mdfd = create_mddev(match ? match->devname : NULL, name_to_use, trustworthy,
chosen_name, 1);
chosen_name, udev_blocked);

if (mdfd < 0)
goto out_unlock;
Expand Down Expand Up @@ -469,14 +472,12 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
chosen_name, info.array.working_disks,
info.array.working_disks == 1?"":"s");
sysfs_rules_apply(chosen_name, &info, st);
wait_for(chosen_name, mdfd);
if (st->ss->external)
strcpy(devnm, fd2devnm(mdfd));
if (st->ss->load_container)
rv = st->ss->load_container(st, mdfd, NULL);
close(mdfd);
udev_unblock();
sysfs_uevent(sra, "change");
if (udev_blocked)
udev_ready(sra);
sysfs_free(sra);
if (!rv)
rv = Incremental_container(st, chosen_name, c, NULL);
Expand All @@ -485,7 +486,8 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
* so that it can eg. try to rebuild degraded array */
if (st->ss->external)
ping_monitor(devnm);
udev_unblock();
wait_for(chosen_name, mdfd);
close(mdfd);
return rv;
}

Expand Down Expand Up @@ -604,8 +606,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
} else if (c->verbose >= 0)
pr_err("%s attached to %s, which has been started.\n",
devname, chosen_name);
rv = 0;
wait_for(chosen_name, mdfd);
array_started = true;
/* We just started the array, so some devices
* might have been evicted from the array
* because their event counts were too old.
Expand Down Expand Up @@ -638,15 +639,19 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
free(avail);
if (dfd >= 0)
close(dfd);
if (mdfd >= 0)
close(mdfd);
if (policy)
dev_policy_free(policy);
udev_unblock();
if (sra) {
sysfs_uevent(sra, "change");
sysfs_free(sra);
if (udev_blocked) {
if (sra)
udev_ready(sra);
else
udev_unblock();
}
sysfs_free(sra);
if (array_started)
wait_for(chosen_name, mdfd);
if (mdfd >= 0)
close(mdfd);
return rv;
out_unlock:
map_unlock(&map);
Expand Down Expand Up @@ -1531,6 +1536,7 @@ static int Incremental_container(struct supertype *st, char *devname,
char *sysname;
struct map_ent *mp;
struct mddev_ident *match = NULL;
bool udev_blocked = false;

/* do not activate arrays blocked by metadata handler */
if (ra->array.state & (1 << MD_SB_BLOCK_VOLUME)) {
Expand Down Expand Up @@ -1601,8 +1607,9 @@ static int Incremental_container(struct supertype *st, char *devname,
if (match)
trustworthy = LOCAL;

udev_blocked = udev_is_available();
mdfd = create_mddev(match ? match->devname : NULL, ra->name, trustworthy,
chosen_name, 1);
chosen_name, udev_blocked);

if (!is_fd_valid(mdfd)) {
pr_err("create_mddev failed with chosen name %s: %s.\n",
Expand All @@ -1613,6 +1620,8 @@ static int Incremental_container(struct supertype *st, char *devname,
}

if (only && (!mp || strcmp(mp->devnm, only) != 0)) {
if (udev_blocked)
udev_unblock();
close_fd(&mdfd);
continue;
}
Expand All @@ -1624,8 +1633,8 @@ static int Incremental_container(struct supertype *st, char *devname,
sysname = fd2devnm(mdfd);
strncpy(info.sys_name, sysname, sizeof(sysname) - 1);
close_fd(&mdfd);
udev_unblock();
sysfs_uevent(&info, "change");
if (udev_blocked)
udev_ready(&info);
}
if (c->export && result) {
char sep = '=';
Expand All @@ -1652,8 +1661,6 @@ static int Incremental_container(struct supertype *st, char *devname,
release:
map_free(map);
sysfs_free(list);
udev_unblock();
sysfs_uevent(&info, "change");
return rv;
}

Expand Down
24 changes: 15 additions & 9 deletions mdopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ int create_mddev(char *dev, char *name, int trustworthy,
return -1;
}

if (!udev_is_available())
block_udev = 0;

if (chosen == NULL)
chosen = cbuf;

Expand Down Expand Up @@ -273,7 +270,8 @@ int create_mddev(char *dev, char *name, int trustworthy,
return -1;
if (!create_named_array(devnm)) {
devnm[0] = 0;
udev_unblock();
if (block_udev)
udev_unblock();
}
}
if (num >= 0) {
Expand All @@ -282,7 +280,8 @@ int create_mddev(char *dev, char *name, int trustworthy,
return -1;
if (!create_named_array(devnm)) {
devnm[0] = 0;
udev_unblock();
if (block_udev)
udev_unblock();
}
}
if (devnm[0] == 0) {
Expand Down Expand Up @@ -327,14 +326,14 @@ int create_mddev(char *dev, char *name, int trustworthy,
stb.st_rdev != devnm2devid(devnm)) {
pr_err("%s exists but looks wrong, please fix\n",
devname);
return -1;
goto error;
}
} else {
if (mknod(devname, S_IFBLK|0600,
devnm2devid(devnm)) != 0) {
pr_err("failed to create %s\n",
devname);
return -1;
goto error;
}
if (chown(devname, ci->uid, ci->gid))
perror("chown");
Expand All @@ -343,7 +342,7 @@ int create_mddev(char *dev, char *name, int trustworthy,
if (stat(devname, &stb) < 0) {
pr_err("failed to stat %s\n",
devname);
return -1;
goto error;
}
add_dev(devname, &stb, 0, NULL);
}
Expand Down Expand Up @@ -379,10 +378,17 @@ int create_mddev(char *dev, char *name, int trustworthy,
}
}
mdfd = open_dev_excl(devnm);
if (mdfd < 0)
if (mdfd < 0) {
pr_err("unexpected failure opening %s\n",
devname);
goto error;
}
return mdfd;

error:
if (block_udev)
udev_unblock();
return -1;
}

/* Open this and check that it is an md device.
Expand Down
20 changes: 18 additions & 2 deletions udev.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,24 @@ enum udev_status udev_block(char *devnm)
*/
void udev_unblock(void)
{
if (unblock_path)
unlink(unblock_path);
if (!unblock_path) {
pr_err("Called without prior udev block.\n");
return;
}

unlink(unblock_path);
free(unblock_path);
unblock_path = NULL;
}

/*
* udev_ready() - Unblock udev and signal that the device is ready.
*
* Removes the blocking file and sends a synthetic change uevent
* so udev re-evaluates the device in its final state.
*/
void udev_ready(struct mdinfo *sra)
{
udev_unblock();
sysfs_uevent(sra, "change");
}
1 change: 1 addition & 0 deletions udev.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ enum udev_status udev_wait_for_events(int seconds);

enum udev_status udev_block(char *devnm);
void udev_unblock(void);
void udev_ready(struct mdinfo *sra);

#endif