diff options
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/mdevd.html | 14 | ||||
-rw-r--r-- | doc/upgrade.html | 7 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/mdevd/mdevd.c | 49 |
6 files changed, 67 insertions, 13 deletions
@@ -1,5 +1,11 @@ Changelog for mdevd. +In 0.1.2.0 +---------- + + - -o fd option to see the uevents after mdevd has processed them. + + In 0.1.1.2 ---------- diff --git a/doc/index.html b/doc/index.html index 0d2c62b..9b6f46b 100644 --- a/doc/index.html +++ b/doc/index.html @@ -114,7 +114,7 @@ library. </li> <ul> <li> The current released version of mdevd is -<a href="mdevd-0.1.1.2.tar.gz">0.1.1.2</a>. </li> +<a href="mdevd-0.1.2.0.tar.gz">0.1.2.0</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/mdevd/">mdevd git repository</a>: diff --git a/doc/mdevd.html b/doc/mdevd.html index e7231e2..2ef2dfb 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> ] [ -b <em>kbufsz</em> ] [ -f <em>conffile</em> ] [ -n ] [ -s <em>slashsys</em> ] [ -d <em>slashdev</em> ] [ -F <em>fwbase</em> ] + mdevd [ -v <em>verbosity</em> ] [ -D <em>notif</em> ] [ -o <em>outputfd</em> ] [ -b <em>kbufsz</em> ] [ -f <em>conffile</em> ] [ -n ] [ -s <em>slashsys</em> ] [ -d <em>slashdev</em> ] [ -F <em>fwbase</em> ] </pre> <ul> @@ -92,6 +92,18 @@ This allows mdevd to use the <a href="//skarnet.org/software/s6/notifywhenup.html">s6 mechanism to notify readiness</a>. <em>notif</em> cannot be lesser than 3. If this option is not given, no readiness notification is sent. </li> + <li> <tt>-o</tt> <em>outputfd</em> : send a copy of the complete +uevent, with possible new fields, to file descriptor <em>outputfd</em>, +<strong>after</strong> mdevd has handled them. (This can serve as a +synchronization mechanism with an external program that needs a device to +have been properly configured by the device manager before acting on the +device.) +The uevent is sent with the kernel format: fields are separated by a null +character. The uevent is terminated by an additional null character. +<em>outputfd</em> cannot be lesser than 3 and cannot be the same as <em>notif</em>. +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>-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 500 kB, which should be diff --git a/doc/upgrade.html b/doc/upgrade.html index 138f277..d9a7d38 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,6 +18,13 @@ <h1> What has changed in mdevd </h1> +<h2> in 0.1.2.0 </h2> + +<ul> + <li> A <tt>-o <em>outputfd</em></tt> option has been added to +<a href="mdevd.html">mdevd</a>. </li> +</ul> + <h2> in 0.1.1.2 </h2> <ul> diff --git a/package/info b/package/info index d39cf55..a7500f8 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=mdevd -version=0.1.1.2 +version=0.1.2.0 category=admin package_macro_name=MDEVD diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c index 6ae5ff0..98d454d 100644 --- a/src/mdevd/mdevd.c +++ b/src/mdevd/mdevd.c @@ -7,6 +7,7 @@ #include <sys/types.h> #include <sys/sysmacros.h> /* makedev, major, minor */ #include <sys/stat.h> +#include <sys/uio.h> #include <fcntl.h> #include <stdint.h> #include <unistd.h> @@ -40,7 +41,7 @@ #include <skalibs/surf.h> #include <skalibs/random.h> -#define USAGE "mdevd [ -v verbosity ] [ -D notif ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ]" +#define USAGE "mdevd [ -v verbosity ] [ -D notif ] [ -o outputfd ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ]" #define dieusage() strerr_dieusage(100, USAGE) #define CONFBUFSIZE 8192 @@ -54,6 +55,7 @@ static int dryrun = 0 ; static int cont = 1 ; static pid_t pid = 0 ; +static unsigned int outputfd = 0 ; static unsigned int verbosity = 1 ; static char const *slashsys = "/sys" ; static char const *fwbase = "/lib/firmware" ; @@ -950,8 +952,9 @@ static inline void on_event (struct uevent_s *event, scriptelem const *script, u /* Tying it all together */ -static inline void handle_signals (void) +static inline int handle_signals (void) { + int e = 0 ; for (;;) { int c = selfpipe_read() ; @@ -960,7 +963,7 @@ static inline void handle_signals (void) case -1 : strerr_diefu1sys(111, "selfpipe_read") ; case SIGTERM : case SIGHUP : cont = c == SIGHUP ; - case 0 : return ; + case 0 : return e ; case SIGCHLD : if (!pid) wait_reap() ; else @@ -972,6 +975,7 @@ static inline void handle_signals (void) else break ; else if (!r) break ; pid = 0 ; + e = 1 ; } break ; default : @@ -980,11 +984,25 @@ static inline void handle_signals (void) } } -static inline void handle_event (int fd, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch) +static inline int handle_event (int fd, struct uevent_s *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch) { - struct uevent_s event = UEVENT_ZERO ; - if (uevent_read(fd, &event) && event.varn > 1) - on_event(&event, script, scriptlen, storage, envmatch) ; + if (!uevent_read(fd, event) || event->varn <= 1) return 0 ; + on_event(event, script, scriptlen, storage, envmatch) ; + return 1 ; +} + +static void output_event (struct uevent_s *event) +{ + static char const c = 0 ; + struct iovec v[2] = { { .iov_base = event->buf, .iov_len = event->len }, { .iov_base = (char *)&c, .iov_len = 1 } } ; + if (fd_writev(outputfd, v, 2) < event->len + 1) + { + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, outputfd)] = 0 ; + fd_close(outputfd) ; + outputfd = 0 ; + strerr_warnwu3sys("write to descriptor ", fmt, " (closing it)") ; + } } int main (int argc, char const *const *argv) @@ -999,7 +1017,7 @@ int main (int argc, char const *const *argv) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "nv:D:b:f:s:d:F:", &l) ; + int opt = subgetopt_r(argc, argv, "nv:D:o:b:f:s:d:F:", &l) ; if (opt == -1) break ; switch (opt) { @@ -1009,6 +1027,14 @@ int main (int argc, char const *const *argv) if (!uint0_scan(l.arg, ¬if)) dieusage() ; 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") ; + if (outputfd == notif) strerr_dief1x(100, "output fd and notification fd must not be the same") ; + break ; + case 'o' : + if (!uint0_scan(l.arg, &outputfd)) dieusage() ; + if (outputfd < 3) strerr_dief1x(100, "output fd must be 3 or more") ; + if (fcntl(outputfd, F_GETFD) < 0) strerr_dief1sys(100, "invalid output fd") ; + if (outputfd == notif) strerr_dief1x(100, "output fd and notification fd must not be the same") ; + if (ndelay_on(outputfd) < 0) strerr_diefu1sys(111, "set output fd non-blocking") ; break ; case 'b' : if (!uint0_scan(l.arg, &kbufsz)) dieusage() ; break ; case 'f' : configfile = l.arg ; break ; @@ -1071,6 +1097,7 @@ int main (int argc, char const *const *argv) script_firstpass(storage, &scriptlen, &envmatchlen) ; { + struct uevent_s event = UEVENT_ZERO ; struct envmatch_s envmatch[envmatchlen ? envmatchlen : 1] ; scriptelem script[scriptlen + 1] ; memset(script, 0, scriptlen * sizeof(scriptelem)) ; @@ -1088,9 +1115,11 @@ int main (int argc, char const *const *argv) { if (iopause_stamp(x, 1 + (!pid && cont == 2), 0, 0) < 0) strerr_diefu1sys(111, "iopause") ; if (x[0].revents & IOPAUSE_READ) - handle_signals() ; + if (handle_signals() && outputfd) + output_event(&event) ; if (!pid && cont == 2 && x[1].revents & IOPAUSE_READ) - handle_event(x[1].fd, script, scriptlen, storage, envmatch) ; + if (handle_event(x[1].fd, &event, script, scriptlen, storage, envmatch) && !pid && outputfd) + output_event(&event) ; } script_free(script, scriptlen, envmatch, envmatchlen) ; |