diff --git a/doc/keventd.md b/doc/keventd.md index b6a934ff..1497ef3c 100644 --- a/doc/keventd.md +++ b/doc/keventd.md @@ -221,7 +221,7 @@ battery: Usage ----- - keventd [-cdGhnv] [-g GROUP] + keventd [-cdGhnpv] [-g GROUP] Options: -c Run coldplug at startup @@ -230,6 +230,7 @@ Usage -G Disable netlink rebroadcast entirely -h Show help text -n Run in foreground (no daemon) + -p Passive mode: power supply events only -v Show version In normal operation, Finit starts keventd automatically via its system @@ -259,11 +260,12 @@ This means keventd can also be tested independently: # Run without rebroadcast (e.g., headless embedded system) keventd -c -G -When keventd is enabled, it conflicts with external device managers. -Only one device manager should be active at a time. The system -configuration uses the `conflict:` directive to enforce this: - - service conflict:udevd,mdevd,mdev [...] keventd -c -- Finit device manager +Only one device manager should be active at a time. This is settled +at build time: with the hotplug plugin enabled, Finit starts keventd +in passive mode (`-p`), leaving device management to the udevd, mdevd, +or mdev service from `system/10-hotplug.conf` and monitoring only +power supply events. Without the hotplug plugin, keventd runs as the +system device manager (`keventd -c`). [libudev-zero]: https://github.com/illiliti/libudev-zero [mdevd]: https://skarnet.org/software/mdevd/ diff --git a/src/conf.c b/src/conf.c index 6ffd6afc..f4329e46 100644 --- a/src/conf.c +++ b/src/conf.c @@ -2683,15 +2683,23 @@ int conf_init(uev_ctx_t *ctx) } #endif /* - * Start kernel event daemon as soon as possible, if enabled + * Start kernel event daemon as soon as possible, if enabled. + * In passive mode (-p) alongside the hotplug plugin, keventd + * only monitors power supply events (sys/pwr/ac condition). */ if (whichp(FINIT_EXECPATH_ "/keventd")) conf_save_service(SVC_TYPE_SERVICE, "keventd", "keventd.conf", - "\tdescription = \"Finit kernel event daemon\"\n" - "\trunlevel = \"S12345789\"\n" + "\tdescription = \"kernel event daemon\"\n" + "\trunlevel = \"S0123456789\"\n" "\tnotify = \"none\"\n" "\tcgroup init {}\n" - "\tcommand = \"" FINIT_EXECPATH_ "/keventd\"\n"); + "\tcommand = \"" FINIT_EXECPATH_ "/keventd" +#ifdef HAVE_HOTPLUG_PLUGIN + " -p" +#else + " -c" +#endif + "\"\n"); dbg("Allow plugins to register early runlevel 1 run/task/services ..."); plugin_run_hooks(HOOK_SVC_PLUGIN); diff --git a/src/keventd.c b/src/keventd.c index 058077dd..6552bb68 100644 --- a/src/keventd.c +++ b/src/keventd.c @@ -76,6 +76,7 @@ static int num_ac; static int running = 1; static int level; static int logon; +static int passive; /* power-supply only, no device management */ int debug; /* debug in other modules as well */ @@ -283,29 +284,33 @@ static void handle_uevent(char *buf, size_t len) switch (ev.action) { case ACT_ADD: - /* Firmware loading takes priority */ - if (ev.firmware) - firmware_load(&ev); + if (!passive) { + /* Firmware loading takes priority */ + if (ev.firmware) + firmware_load(&ev); - /* Module loading */ - if (ev.modalias) - modprobe_load(ev.modalias); + /* Module loading */ + if (ev.modalias) + modprobe_load(ev.modalias); - /* Create device node if we have the info */ - if (ev.major >= 0 && ev.minor >= 0 && ev.devname) - devnode_add(&ev); + /* Create device node if we have the info */ + if (ev.major >= 0 && ev.minor >= 0 && ev.devname) + devnode_add(&ev); - /* Create symlinks */ - symlink_add(&ev); + /* Create symlinks */ + symlink_add(&ev); + } break; case ACT_REMOVE: - /* Remove symlinks first */ - symlink_del(&ev); + if (!passive) { + /* Remove symlinks first */ + symlink_del(&ev); - /* Remove device node */ - if (ev.devname) - devnode_del(&ev); + /* Remove device node */ + if (ev.devname) + devnode_del(&ev); + } break; case ACT_CHANGE: @@ -412,7 +417,7 @@ static void shut_down(int signo) static int usage(int rc) { fprintf(stderr, - "Usage: keventd [-dGhnv] [-c] [-g GROUP]\n" + "Usage: keventd [-dGhnpv] [-c] [-g GROUP]\n" "\n" "Options:\n" " -c Run coldplug at startup\n" @@ -421,6 +426,7 @@ static int usage(int rc) " -G Disable netlink rebroadcast entirely\n" " -h Show this help text\n" " -n Run in foreground (no daemon)\n" + " -p Passive mode: power supply events only (no device management)\n" " -v Show version\n" "\n", REBC_DEFAULT_NLGROUP); @@ -454,7 +460,7 @@ int main(int argc, char *argv[]) * requested bits verbatim instead of masking them. */ umask(0); - while ((c = getopt(argc, argv, "cdg:Ghnv")) != -1) { + while ((c = getopt(argc, argv, "cdg:Ghnpv")) != -1) { switch (c) { case 'c': do_coldplug = 1; @@ -474,6 +480,9 @@ int main(int argc, char *argv[]) case 'n': foreground = 1; break; + case 'p': + passive = 1; + break; case 'v': printf("keventd v%s\n", KEVENTD_VERSION); return 0; @@ -498,8 +507,10 @@ int main(int argc, char *argv[]) init_power_supply(); init_dev_condition_dir(); - /* Disable legacy kernel uevent helper; we own events via netlink */ - disable_uevent_helper(); + /* Disable legacy kernel uevent helper; we own events via netlink. + * Skip in passive mode -- the hotplug daemon handles this. */ + if (!passive) + disable_uevent_helper(); /* Set up netlink socket for kernel uevents */ pfd.events = POLLIN; @@ -519,8 +530,9 @@ int main(int argc, char *argv[]) setsockopt(pfd.fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); } - /* Initialize rebroadcast socket (default on, -G to disable) */ - if (nlgroups) + /* Initialize rebroadcast socket (default on, -G to disable). + * Skip in passive mode -- the hotplug daemon rebroadcasts. */ + if (nlgroups && !passive) rebc_init(nlgroups); /* Run coldplug if requested */