mirror of
https://github.com/troglobit/finit.git
synced 2026-11-06 15:51:03 +00:00
keventd: add -S settle mode polling /sys/kernel/uevent_seqnum
Stop-gap "settle" equivalent of udevadm settle for migration scenarios. Polls /sys/kernel/uevent_seqnum every 50ms and exits zero when the sequence number has been stable for 200ms (or non-zero after -t SECONDS timeout, default 30s). This is racy by design -- a slow probe firing after we return still races -- so the doc steers users toward dev/, class/, and bind/ conditions for any service they control. Settle is for legacy boot scripts and init transitions where condition wiring isn't feasible. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
2 files changed
+86
-3
No files matched your search
+23
-1
@@ -301,7 +301,7 @@ battery:
|
|||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
keventd [-cdGhnpv] [-g GROUP] [-r DIR]
|
keventd [-cdGhnpSv] [-g GROUP] [-r DIR] [-t SECONDS]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-c Run coldplug at startup
|
-c Run coldplug at startup
|
||||||
@@ -310,12 +310,34 @@ Usage
|
|||||||
-G Disable netlink rebroadcast entirely
|
-G Disable netlink rebroadcast entirely
|
||||||
-h Show help text
|
-h Show help text
|
||||||
-n Run in foreground (no daemon)
|
-n Run in foreground (no daemon)
|
||||||
|
-p Passive mode: power supply events only
|
||||||
|
-r DIR Extra rules directory
|
||||||
|
-S Settle mode: wait for kernel uevent queue to quiet, then exit
|
||||||
|
-t SEC Settle timeout (default 30s, used with -S)
|
||||||
-v Show version
|
-v Show version
|
||||||
|
|
||||||
In normal operation, Finit starts keventd automatically via its system
|
In normal operation, Finit starts keventd automatically via its system
|
||||||
configuration. The `-d` flag is useful for debugging device issues --
|
configuration. The `-d` flag is useful for debugging device issues --
|
||||||
it runs keventd in the foreground and logs all received uevents.
|
it runs keventd in the foreground and logs all received uevents.
|
||||||
|
|
||||||
|
`keventd -S` is a one-shot command, not a flag to the running daemon.
|
||||||
|
It is the `udevadm settle` equivalent for migration scenarios:
|
||||||
|
|
||||||
|
keventd -S -t 10 && start-graphical-session
|
||||||
|
|
||||||
|
It does not talk to the running keventd (or any device manager) -- it
|
||||||
|
simply opens `/sys/kernel/uevent_seqnum` and polls until the kernel's
|
||||||
|
sequence counter has been stable for 200ms, then exits zero. After
|
||||||
|
the `-t SECONDS` timeout (default 30) it exits non-zero instead.
|
||||||
|
Because `uevent_seqnum` is maintained by the kernel itself, `-S` works
|
||||||
|
regardless of which device manager is active, or even if none is.
|
||||||
|
|
||||||
|
Prefer the condition-based model (`<dev/X>`, `<class/...>`,
|
||||||
|
`<driver/...>`) over settle when you control the service definition --
|
||||||
|
settle is racy with slow probes that fire after the queue appears
|
||||||
|
quiet. It is provided for legacy boot scripts and init transitions
|
||||||
|
where condition wiring isn't feasible.
|
||||||
|
|
||||||
Debug logging can also be toggled at runtime by sending `SIGUSR1`:
|
Debug logging can also be toggled at runtime by sending `SIGUSR1`:
|
||||||
|
|
||||||
kill -USR1 $(pidof keventd)
|
kill -USR1 $(pidof keventd)
|
||||||
|
|||||||
+63
-2
@@ -44,6 +44,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -536,10 +537,57 @@ static void uevent_cb(uev_t *w, void *arg, int events)
|
|||||||
rebc_event(rebc_buf, len);
|
rebc_event(rebc_buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop-gap "settle" mode: poll /sys/kernel/uevent_seqnum until it has
|
||||||
|
* been stable for `stable_ms` (default 200ms), or until `timeout_s`
|
||||||
|
* elapses. Imperfect -- a slow probe firing after we return still
|
||||||
|
* races -- but matches what typical `udevadm settle` users want.
|
||||||
|
*
|
||||||
|
* The proper fix lives in the IPC/queue work (see audit doc).
|
||||||
|
*/
|
||||||
|
static int cmd_settle(int timeout_s, int stable_ms)
|
||||||
|
{
|
||||||
|
struct timespec start, last_change, now;
|
||||||
|
unsigned long long last_seq = 0, cur_seq = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
|
last_change = start;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
fp = fopen("/sys/kernel/uevent_seqnum", "r");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "keventd: cannot read uevent_seqnum: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (fscanf(fp, "%llu", &cur_seq) != 1)
|
||||||
|
cur_seq = last_seq;
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
if (cur_seq != last_seq) {
|
||||||
|
last_seq = cur_seq;
|
||||||
|
last_change = now;
|
||||||
|
} else {
|
||||||
|
long dt_ms = (now.tv_sec - last_change.tv_sec) * 1000 +
|
||||||
|
(now.tv_nsec - last_change.tv_nsec) / 1000000;
|
||||||
|
if (dt_ms >= stable_ms)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now.tv_sec - start.tv_sec >= timeout_s)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
usleep(50000); /* 50ms */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int usage(int rc)
|
static int usage(int rc)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: keventd [-dGhnpv] [-c] [-g GROUP] [-r DIR]\n"
|
"Usage: keventd [-dGhnpSv] [-c] [-g GROUP] [-r DIR] [-t SECONDS]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -c Run coldplug at startup\n"
|
" -c Run coldplug at startup\n"
|
||||||
@@ -550,6 +598,8 @@ static int usage(int rc)
|
|||||||
" -n Run in foreground (no daemon)\n"
|
" -n Run in foreground (no daemon)\n"
|
||||||
" -p Passive mode: power supply events only (no device management)\n"
|
" -p Passive mode: power supply events only (no device management)\n"
|
||||||
" -r DIR Extra rules directory (in addition to standard udev paths)\n"
|
" -r DIR Extra rules directory (in addition to standard udev paths)\n"
|
||||||
|
" -S Settle: wait until kernel uevent queue is quiet, then exit\n"
|
||||||
|
" -t SEC Settle timeout in seconds (default: 30, with -S)\n"
|
||||||
" -v Show version\n"
|
" -v Show version\n"
|
||||||
"\n", REBC_DEFAULT_NLGROUP);
|
"\n", REBC_DEFAULT_NLGROUP);
|
||||||
|
|
||||||
@@ -577,6 +627,8 @@ int main(int argc, char *argv[])
|
|||||||
uev_t netlink_watcher;
|
uev_t netlink_watcher;
|
||||||
uev_ctx_t ctx;
|
uev_ctx_t ctx;
|
||||||
int do_coldplug = 0;
|
int do_coldplug = 0;
|
||||||
|
int do_settle = 0;
|
||||||
|
int settle_timeout = 30;
|
||||||
int foreground = 0;
|
int foreground = 0;
|
||||||
int nlfd;
|
int nlfd;
|
||||||
int c;
|
int c;
|
||||||
@@ -586,7 +638,7 @@ int main(int argc, char *argv[])
|
|||||||
* requested bits verbatim instead of masking them. */
|
* requested bits verbatim instead of masking them. */
|
||||||
umask(0);
|
umask(0);
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "cdg:Ghnpr:v")) != -1) {
|
while ((c = getopt(argc, argv, "cdg:Ghnpr:St:v")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
do_coldplug = 1;
|
do_coldplug = 1;
|
||||||
@@ -612,6 +664,12 @@ int main(int argc, char *argv[])
|
|||||||
case 'r':
|
case 'r':
|
||||||
rules_dir = optarg;
|
rules_dir = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
do_settle = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
settle_timeout = atoi(optarg);
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
printf("keventd v%s\n", KEVENTD_VERSION);
|
printf("keventd v%s\n", KEVENTD_VERSION);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -620,6 +678,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_settle)
|
||||||
|
return cmd_settle(settle_timeout, 200);
|
||||||
|
|
||||||
if (!foreground) {
|
if (!foreground) {
|
||||||
openlog("keventd", LOG_PID, LOG_DAEMON);
|
openlog("keventd", LOG_PID, LOG_DAEMON);
|
||||||
set_logging(LOG_NOTICE);
|
set_logging(LOG_NOTICE);
|
||||||
|
|||||||
Reference in new issue
Block a user