aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-04-19 18:55:12 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2015-04-19 18:55:12 +0200
commitad795510d9fd6f4290be170c84c0d30eb1af7245 (patch)
treed9fdc1a48404e9d26b016adbfe3e58e7a0e279e9
parentbd77e9d6093dc8632788a3c3efffd53ac8ba3233 (diff)
downloadbusybox-ad795510d9fd6f4290be170c84c0d30eb1af7245.tar.gz
mdev: if a "future" mdev.seq is seen, do not overwrite it with ours
This was seen to happen if two mdevs are run in parallel, mdev.seq is empty, and the "newer" one manages to write it first. function old new delta mdev_main 1366 1388 +22 atoll - 20 +20 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/mdev.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 884e5de33..ca4b91510 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -947,7 +947,7 @@ static void open_mdev_log(const char *seq, unsigned my_pid)
* Active mdev pokes us with SIGCHLD to check the new file.
*/
static int
-wait_for_seqfile(const char *seq)
+wait_for_seqfile(unsigned expected_seq)
{
/* We time out after 2 sec */
static const struct timespec ts = { 0, 32*1000*1000 };
@@ -962,12 +962,14 @@ wait_for_seqfile(const char *seq)
for (;;) {
int seqlen;
- char seqbuf[sizeof(int)*3 + 2];
+ char seqbuf[sizeof(long)*3 + 2];
+ unsigned seqbufnum;
if (seq_fd < 0) {
seq_fd = open("mdev.seq", O_RDWR);
if (seq_fd < 0)
break;
+ close_on_exec_on(seq_fd);
}
seqlen = pread(seq_fd, seqbuf, sizeof(seqbuf) - 1, 0);
if (seqlen < 0) {
@@ -978,17 +980,25 @@ wait_for_seqfile(const char *seq)
seqbuf[seqlen] = '\0';
if (seqbuf[0] == '\n' || seqbuf[0] == '\0') {
/* seed file: write out seq ASAP */
- xwrite_str(seq_fd, seq);
+ xwrite_str(seq_fd, utoa(expected_seq));
xlseek(seq_fd, 0, SEEK_SET);
dbg2("first seq written");
break;
}
- if (strcmp(seq, seqbuf) == 0) {
+ seqbufnum = atoll(seqbuf);
+ if (seqbufnum == expected_seq) {
/* correct idx */
break;
}
+ if (seqbufnum > expected_seq) {
+ /* a later mdev runs already (this was seen by users to happen) */
+ /* do not overwrite seqfile on exit */
+ close(seq_fd);
+ seq_fd = -1;
+ break;
+ }
if (do_once) {
- dbg2("%s mdev.seq='%s', need '%s'", curtime(), seqbuf, seq);
+ dbg2("%s mdev.seq='%s', need '%u'", curtime(), seqbuf, expected_seq);
do_once = 0;
}
if (sigtimedwait(&set_CHLD, NULL, &ts) >= 0) {
@@ -1079,6 +1089,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
char *env_devname;
char *env_devpath;
unsigned my_pid;
+ unsigned seqnum = seqnum; /* for compiler */
int seq_fd;
smalluint op;
@@ -1100,7 +1111,11 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
my_pid = getpid();
open_mdev_log(seq, my_pid);
- seq_fd = seq ? wait_for_seqfile(seq) : -1;
+ seq_fd = -1;
+ if (seq) {
+ seqnum = atoll(seq);
+ seq_fd = wait_for_seqfile(seqnum);
+ }
dbg1("%s "
"ACTION:%s SUBSYSTEM:%s DEVNAME:%s DEVPATH:%s"
@@ -1128,7 +1143,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
dbg1("%s exiting", curtime());
if (seq_fd >= 0) {
- xwrite_str(seq_fd, utoa(xatou(seq) + 1));
+ xwrite_str(seq_fd, utoa(seqnum + 1));
signal_mdevs(my_pid);
}
}