diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2025-04-08 06:39:59 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska@appnovation.com> | 2025-04-08 06:39:59 +0000 |
| commit | ea26c3662b37b92f6acd2330a81dfd2b72082e8a (patch) | |
| tree | 98f8e729867503e93bff1a961b05d117f53768ee | |
| parent | 94f626f54548bc6134267c2063a6f6df43b4858f (diff) | |
| download | mdevd-ea26c3662b37b92f6acd2330a81dfd2b72082e8a.tar.gz | |
Add intake option
Signed-off-by: Laurent Bercot <ska@appnovation.com>
| -rw-r--r-- | doc/mdevd.html | 16 | ||||
| -rw-r--r-- | src/mdevd/mdevd.c | 24 |
2 files changed, 30 insertions, 10 deletions
diff --git a/doc/mdevd.html b/doc/mdevd.html index 983dbb5..ca39b02 100644 --- a/doc/mdevd.html +++ b/doc/mdevd.html @@ -49,7 +49,7 @@ to running mdevd over mdev. </li> <h2> Interface </h2> <pre> - mdevd [ -v <em>verbosity</em> ] [ -D <em>notif</em> ] [ -o <em>outputfd</em> ] [ -O <em>nlgroups</em> ] [ -b <em>kbufsz</em> ] [ -f <em>conffile</em> ] [ -n ] [ -s <em>slashsys</em> ] [ -d <em>slashdev</em> ] [ -F <em>fwbase</em> ] [ -C ] + mdevd [ -v <em>verbosity</em> ] [ -D <em>notif</em> ] [ -I <em>intake</em> ] [ -o <em>outputfd</em> ] [ -I <em>intake</em> ] [ -O <em>nlgroups</em> ] [ -b <em>kbufsz</em> ] [ -f <em>conffile</em> ] [ -n ] [ -s <em>slashsys</em> ] [ -d <em>slashdev</em> ] [ -F <em>fwbase</em> ] [ -C ] </pre> <ul> @@ -104,11 +104,19 @@ character. The uevent is terminated by an additional null character. If for any reason, at any point, mdevd fails to write to <em>outputfd</em>, it stops writing, until it is restarted. (This is to preserve mdevd's memory stability guarantee.) By default, the uevents are not written anywhere. </li> + <li> <tt>-I</tt> <em>intake</em> : read the uevents from the netlink +groups identified by the mask <em>intake</em>. The default is <strong>1</strong>, +meaning the netlink group where the kernel sends its events, and it should not +be changed unless you have a very particular and rare setting (namely, a chain +of device managers reading events and rebroadcasting them to other netlink +groups). </li> <li> <tt>-O</tt> <em>nlgroups</em> : after mdevd has handled the uevents, rebroadcast them to the netlink groups identified by the mask -<em>nlgroups</em>. Bit 0 of <em>nlgroups</em> is always ignored (because -netlink group 1 is the one used by the kernel to send the original uevents and -that mdevd listens to, and we don't want to loopback on it). </li> +<em>nlgroups</em>. If the bit 0 or the bits specified in <em>intake</em> +(see above) are set in <em>nlgroups</em>, a warning is printed and these +bits are ignored, in order to avoid causing a loop. (Yes, you can still +cause a loop by chaining two separate instances of mdevd. mdevd will protect +you against accidents, not against intentional stupidity.) </li> <li> <tt>-b</tt> <em>kbufsz</em> : try and reserve a kernel buffer of <em>kbufsz</em> bytes for the netlink queue. Too large a buffer wastes kernel memory; too small a buffer risks losing events. The default is <strong>512288</strong>, diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c index bbef872..6b82874 100644 --- a/src/mdevd/mdevd.c +++ b/src/mdevd/mdevd.c @@ -43,7 +43,7 @@ #include <mdevd/config.h> #include "mdevd-internal.h" -#define USAGE "mdevd [ -v verbosity ] [ -D notif ] [ -o outputfd ] [ -O nlgroups ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ] [ -F fwbase ] [ -C ]" +#define USAGE "mdevd [ -v verbosity ] [ -D notif ] [ -I intake ] [ -o outputfd ] [ -O nlgroups ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ] [ -F fwbase ] [ -C ]" #define dieusage() strerr_dieusage(100, USAGE) #define CONFBUFSIZE 8192 @@ -186,7 +186,7 @@ static int makesubdirs (char const *path) static inline int rebc_init (unsigned int groups, unsigned int kbufsz) { - struct sockaddr_nl nl = { .nl_family = AF_NETLINK, .nl_pad = 0, .nl_groups = groups & ~1U, .nl_pid = 0 } ; + struct sockaddr_nl nl = { .nl_family = AF_NETLINK, .nl_pad = 0, .nl_groups = groups, .nl_pid = 0 } ; int fd = socket_internal(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT, O_CLOEXEC) ; if (fd == -1) return -1 ; if (connect(fd, (struct sockaddr *)&nl, sizeof nl) == -1) goto err ; @@ -907,6 +907,7 @@ int main (int argc, char const *const *argv) unsigned int kbufsz = 512288 ; char const *slashdev = "/dev" ; int docoldplug = 0 ; + unsigned int intake = 1 ; unsigned int outputfd = 0 ; unsigned int rebc = 0 ; PROG = "mdevd" ; @@ -914,13 +915,14 @@ int main (int argc, char const *const *argv) subgetopt l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "nv:D:o:O:b:f:s:d:F:C", &l) ; + int opt = subgetopt_r(argc, argv, "nv:D:I:o:O:b:f:s:d:F:C", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : dryrun = 1 ; break ; case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; case 'D' : if (!uint0_scan(l.arg, ¬if)) dieusage() ; break ; + case 'I' : if (!uint0_scan(l.arg, &intake)) dieusage() ; break ; case 'o' : if (!uint0_scan(l.arg, &outputfd)) dieusage() ; break ; case 'O' : if (!uint0_scan(l.arg, &rebc)) dieusage() ; break ; case 'b' : if (!uint0_scan(l.arg, &kbufsz)) dieusage() ; break ; @@ -947,6 +949,16 @@ int main (int argc, char const *const *argv) if (notif < 3) strerr_dief1x(100, "notification fd must be 3 or more") ; if (fcntl(notif, F_GETFD) < 0) strerr_dief1sys(100, "invalid notification fd") ; } + { + unsigned int loop = rebc & (intake | 1) ; + if (loop) + { + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, loop)] = 0 ; + strerr_warnw3x("ignoring rebroadcast request on nlgroups ", fmt, " to avoid loops") ; + rebc &= ~loop ; + } + } if (outputfd) { if (outputfd < 3) strerr_dief1x(100, "output fd must be 3 or more") ; @@ -961,8 +973,7 @@ int main (int argc, char const *const *argv) root_maj = major(st.st_dev) ; root_min = minor(st.st_dev) ; } - - x[1].fd = mdevd_netlink_init(1, kbufsz) ; + x[1].fd = mdevd_netlink_init(intake, kbufsz) ; if (x[1].fd < 0) strerr_diefu1sys(111, "init netlink") ; if (rebc) { @@ -973,7 +984,8 @@ int main (int argc, char const *const *argv) x[0].fd = selfpipe_init() ; if (x[0].fd < 0) strerr_diefu1sys(111, "init selfpipe") ; - if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ; + if (!sig_altignore(SIGPIPE)) + strerr_diefu1sys(111, "ignore SIGPIPE") ; { sigset_t set ; sigemptyset(&set) ; |
