diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-15 22:33:13 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-15 22:33:13 +0000 |
commit | 018bee6afb0a7b9e09616a52f2f24f65fcf07322 (patch) | |
tree | 8c86e74a094c12686adac6bb4cec56ba52347bda | |
parent | 97faf531c81be075ecafb2ac83b17eae78cd2afb (diff) | |
download | busybox-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.txt | 23 | ||||
-rw-r--r-- | util-linux/mdev.c | 31 |
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 | |||
95 | filename of the firmware which mdev will load out of /lib/firmware/ and into | 95 | filename of the firmware which mdev will load out of /lib/firmware/ and into |
96 | the kernel via the sysfs interface. The exact filename is hardcoded in the | 96 | the kernel via the sysfs interface. The exact filename is hardcoded in the |
97 | kernel, so look there if you need to know how to name the file in userspace. | 97 | kernel, so look there if you need to know how to name the file in userspace. |
98 | |||
99 | ------------ | ||
100 | SEQUENCING | ||
101 | ------------ | ||
102 | |||
103 | Kernel does not serialize hotplug events. It increments SEQNUM environmental | ||
104 | variable for each successive hotplug invocation. Normally, mdev doesn't care. | ||
105 | This may reorder hotplug and hot-unplug events, with typical symptoms of | ||
106 | device nodes sometimes not created as expected. | ||
107 | |||
108 | However, if /dev/mdev.seq file is found, mdev will compare its | ||
109 | contents with SEQNUM. It will retry up to two seconds, waiting for them | ||
110 | to match. If they match exactly (not even trailing '\n' is allowed), | ||
111 | or if two seconds pass, mdev runs as usual, then it rewrites /dev/mdev.seq | ||
112 | with SEQNUM+1. | ||
113 | |||
114 | IOW: this will serialize concurrent mdev invocations. | ||
115 | |||
116 | If you want to activate this feature, execute "echo >/dev/mdev.seq" prior to | ||
117 | setting mdev to be the hotplug handler. This writes single '\n' to the file. | ||
118 | NB: mdev recognizes /dev/mdev.seq consisting of single '\n' characher | ||
119 | as a special case. IOW: this will not make your first hotplug event | ||
120 | to 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 | |||
374 | int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 374 | int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
375 | int mdev_main(int argc UNUSED_PARAM, char **argv) | 375 | int 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) |