aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-15 22:33:13 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-15 22:33:13 +0000
commit018bee6afb0a7b9e09616a52f2f24f65fcf07322 (patch)
tree8c86e74a094c12686adac6bb4cec56ba52347bda
parent97faf531c81be075ecafb2ac83b17eae78cd2afb (diff)
downloadbusybox-w32-018bee6afb0a7b9e09616a52f2f24f65fcf07322.tar.gz
busybox-w32-018bee6afb0a7b9e09616a52f2f24f65fcf07322.tar.bz2
busybox-w32-018bee6afb0a7b9e09616a52f2f24f65fcf07322.zip
mdev: support for serializing hotplug
function old new delta mdev_main 503 647 +144
-rw-r--r--docs/mdev.txt23
-rw-r--r--util-linux/mdev.c31
2 files changed, 51 insertions, 3 deletions
diff --git a/docs/mdev.txt b/docs/mdev.txt
index 1a97be4ce..555c2bf61 100644
--- a/docs/mdev.txt
+++ b/docs/mdev.txt
@@ -95,3 +95,26 @@ properly initialize a device. Place all such firmware files into the
95filename of the firmware which mdev will load out of /lib/firmware/ and into 95filename of the firmware which mdev will load out of /lib/firmware/ and into
96the kernel via the sysfs interface. The exact filename is hardcoded in the 96the kernel via the sysfs interface. The exact filename is hardcoded in the
97kernel, so look there if you need to know how to name the file in userspace. 97kernel, so look there if you need to know how to name the file in userspace.
98
99------------
100 SEQUENCING
101------------
102
103Kernel does not serialize hotplug events. It increments SEQNUM environmental
104variable for each successive hotplug invocation. Normally, mdev doesn't care.
105This may reorder hotplug and hot-unplug events, with typical symptoms of
106device nodes sometimes not created as expected.
107
108However, if /dev/mdev.seq file is found, mdev will compare its
109contents with SEQNUM. It will retry up to two seconds, waiting for them
110to match. If they match exactly (not even trailing '\n' is allowed),
111or if two seconds pass, mdev runs as usual, then it rewrites /dev/mdev.seq
112with SEQNUM+1.
113
114IOW: this will serialize concurrent mdev invocations.
115
116If you want to activate this feature, execute "echo >/dev/mdev.seq" prior to
117setting mdev to be the hotplug handler. This writes single '\n' to the file.
118NB: mdev recognizes /dev/mdev.seq consisting of single '\n' characher
119as a special case. IOW: this will not make your first hotplug event
120to stall for two seconds.
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index c61521cbb..8968e45f8 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -374,8 +374,6 @@ static void load_firmware(const char *const firmware, const char *const sysfs_pa
374int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 374int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
375int mdev_main(int argc UNUSED_PARAM, char **argv) 375int mdev_main(int argc UNUSED_PARAM, char **argv)
376{ 376{
377 char *action;
378 char *env_path;
379 RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE); 377 RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE);
380 378
381 /* We can be called as hotplug helper */ 379 /* We can be called as hotplug helper */
@@ -417,8 +415,14 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
417 ACTION_RECURSE | ACTION_FOLLOWLINKS, 415 ACTION_RECURSE | ACTION_FOLLOWLINKS,
418 fileAction, dirAction, temp, 0); 416 fileAction, dirAction, temp, 0);
419 } else { 417 } else {
418 char *seq;
419 char *action;
420 char *env_path;
421 char seqbuf[sizeof(int)*3 + 2];
422 int seqlen = seqlen; /* for compiler */
423
420 /* Hotplug: 424 /* Hotplug:
421 * env ACTION=... DEVPATH=... mdev 425 * env ACTION=... DEVPATH=... [SEQNUM=...] mdev
422 * ACTION can be "add" or "remove" 426 * ACTION can be "add" or "remove"
423 * DEVPATH is like "/block/sda" or "/class/input/mice" 427 * DEVPATH is like "/block/sda" or "/class/input/mice"
424 */ 428 */
@@ -427,6 +431,23 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
427 if (!action || !env_path) 431 if (!action || !env_path)
428 bb_show_usage(); 432 bb_show_usage();
429 433
434 seq = getenv("SEQNUM");
435 if (seq) {
436 int timeout = 2000 / 32;
437 do {
438 seqlen = open_read_close("mdev.seq", seqbuf, sizeof(seqbuf-1));
439 if (seqlen < 0)
440 break;
441 seqbuf[seqlen] = '\0';
442 if (seqbuf[0] == '\n' /* seed file? */
443 || strcmp(seq, seqbuf) == 0 /* correct idx? */
444 ) {
445 break;
446 }
447 usleep(32*1000);
448 } while (--timeout);
449 }
450
430 snprintf(temp, PATH_MAX, "/sys%s", env_path); 451 snprintf(temp, PATH_MAX, "/sys%s", env_path);
431 if (!strcmp(action, "remove")) 452 if (!strcmp(action, "remove"))
432 make_device(temp, 1); 453 make_device(temp, 1);
@@ -439,6 +460,10 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
439 load_firmware(fw, temp); 460 load_firmware(fw, temp);
440 } 461 }
441 } 462 }
463
464 if (seq && seqlen >= 0) {
465 xopen_xwrite_close("mdev.seq", utoa(xatou(seq) + 1));
466 }
442 } 467 }
443 468
444 if (ENABLE_FEATURE_CLEAN_UP) 469 if (ENABLE_FEATURE_CLEAN_UP)