[git commit] mdev: if a "future" mdev.seq is seen, do not overwrite it with ours

Denys Vlasenko vda.linux at googlemail.com
Sun Apr 19 16:55:12 UTC 2015


commit: http://git.busybox.net/busybox/commit/?id=ad795510d9fd6f4290be170c84c0d30eb1af7245
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 util-linux/mdev.c |   29 ++++++++++++++++++++++-------
 1 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 884e5de..ca4b915 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);
 		}
 	}


More information about the busybox-cvs mailing list