summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2020-09-24 21:37:35 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2020-09-24 21:37:35 +0000
commit46be82dc605e24419482d2de2f22e336865707f1 (patch)
tree378c97c411b3cf04ba2f3bdfe2dde6d86ab2389f
parent627ccd3d1ee8b14ffd76998da08d655c23485aa5 (diff)
downloadmdevd-46be82dc605e24419482d2de2f22e336865707f1.tar.xz
Add -o outputfd, first draft
-rw-r--r--NEWS6
-rw-r--r--doc/index.html2
-rw-r--r--doc/mdevd.html14
-rw-r--r--doc/upgrade.html7
-rw-r--r--package/info2
-rw-r--r--src/mdevd/mdevd.c49
6 files changed, 67 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 5b9a6f7..92add91 100644
--- a/NEWS
+++ b/NEWS
@@ -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>&nbsp;<em>outputfd</em>&nbsp;: 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>&nbsp;<em>kbufsz</em>&nbsp;: 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, &notif)) 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) ;