chiark / gitweb /
udevd: export current seqnum and add udevsettle
authorKay Sievers <kay.sievers@suse.de>
Tue, 4 Apr 2006 22:08:10 +0000 (00:08 +0200)
committerKay Sievers <kay.sievers@suse.de>
Tue, 4 Apr 2006 22:08:10 +0000 (00:08 +0200)
Makefile
udevd.c
udevd.h
udevsettle.8 [new file with mode: 0644]
udevsettle.c [new file with mode: 0644]
udevsettle.xml [new file with mode: 0644]

index 5e4322481cb15e7402047521ba1b4eb94cae20f5..1ce1abeab453d3532a0292bcc76eeb88185eca29 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,7 @@ PROGRAMS = \
        udev                            \
        udevd                           \
        udevtrigger                     \
+       udevsettle                      \
        udevsend                        \
        udevcontrol                     \
        udevmonitor                     \
@@ -86,6 +87,7 @@ MAN_PAGES = \
        udevmonitor.8                   \
        udevd.8                         \
        udevtrigger.8                   \
+       udevsettle.8                    \
        udevsend.8                      \
        udevtest.8                      \
        udevinfo.8                      \
@@ -261,6 +263,7 @@ install-man:
        $(INSTALL_DATA) -D udevtest.8 $(DESTDIR)$(mandir)/man8/udevtest.8
        $(INSTALL_DATA) -D udevd.8 $(DESTDIR)$(mandir)/man8/udevd.8
        $(INSTALL_DATA) -D udevtrigger.8 $(DESTDIR)$(mandir)/man8/udevtrigger.8
+       $(INSTALL_DATA) -D udevsettle.8 $(DESTDIR)$(mandir)/man8/udevsettle.8
        $(INSTALL_DATA) -D udevmonitor.8 $(DESTDIR)$(mandir)/man8/udevmonitor.8
        - ln -f -s udevd.8 $(DESTDIR)$(mandir)/man8/udevcontrol.8
        @extras="$(EXTRAS)"; for target in $$extras; do \
@@ -274,6 +277,7 @@ uninstall-man:
        - rm -f $(DESTDIR)$(mandir)/man8/udevtest.8
        - rm -f $(DESTDIR)$(mandir)/man8/udevd.8
        - rm -f $(DESTDIR)$(mandir)/man8/udevtrigger.8
+       - rm -f $(DESTDIR)$(mandir)/man8/udevsettle.8
        - rm -f $(DESTDIR)$(mandir)/man8/udevmonitor.8
        - rm -f $(DESTDIR)$(mandir)/man8/udevcontrol.8
        @ extras="$(EXTRAS)"; for target in $$extras; do \
@@ -285,6 +289,7 @@ install-bin:
        $(INSTALL) -d $(DESTDIR)$(udevdir)
        $(INSTALL_PROGRAM) -D udevd $(DESTDIR)$(sbindir)/udevd
        $(INSTALL_PROGRAM) -D udevtrigger $(DESTDIR)$(sbindir)/udevtrigger
+       $(INSTALL_PROGRAM) -D udevsettle $(DESTDIR)$(sbindir)/udevsettle
        $(INSTALL_PROGRAM) -D udevcontrol $(DESTDIR)$(sbindir)/udevcontrol
        $(INSTALL_PROGRAM) -D udevmonitor $(DESTDIR)$(usrsbindir)/udevmonitor
        $(INSTALL_PROGRAM) -D udevinfo $(DESTDIR)$(usrbindir)/udevinfo
@@ -302,6 +307,7 @@ endif
 uninstall-bin:
        - rm -f $(DESTDIR)$(sbindir)/udevd
        - rm -f $(DESTDIR)$(sbindir)/udevtrigger
+       - rm -f $(DESTDIR)$(sbindir)/udevsettle
        - rm -f $(DESTDIR)$(sbindir)/udevcontrol
        - rm -f $(DESTDIR)$(usrsbindir)/udevmonitor
        - rm -f $(DESTDIR)$(usrbindir)/udevinfo
diff --git a/udevd.c b/udevd.c
index 701165b9ad0df601ecb53dcf53480843634ae0f9..8741a0901b1752e6088c5887c97f0dbd6bf9ea28 100644 (file)
--- a/udevd.c
+++ b/udevd.c
@@ -279,8 +279,23 @@ static void udev_event_run(struct uevent_msg *msg)
 
 static void msg_queue_insert(struct uevent_msg *msg)
 {
+       char filename[PATH_SIZE];
+       int fd;
+
        msg->queue_time = time(NULL);
 
+       strlcpy(filename, udev_root, sizeof(filename));
+       strlcat(filename, "/" EVENT_SEQNUM, sizeof(filename));
+       fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
+       if (fd > 0) {
+               char str[32];
+               int len;
+
+               len = sprintf(str, "%llu\n", msg->seqnum);
+               write(fd, str, len);
+               close(fd);
+       }
+
        export_event_state(msg, EVENT_QUEUED);
 
        /* run all events with a timeout set immediately */
diff --git a/udevd.h b/udevd.h
index 9ab6a445b9420e558e113ad40bdf9bd01d0094be..e6ed58d622d1786b6bad858722240bc58f32e189 100644 (file)
--- a/udevd.h
+++ b/udevd.h
@@ -31,6 +31,7 @@
 
 #define EVENT_QUEUE_DIR                        ".udev/queue"
 #define EVENT_FAILED_DIR               ".udev/failed"
+#define EVENT_SEQNUM                   ".udev/uevent_seqnum"
 
 /* maximum limit of forked childs */
 #define UDEVD_MAX_CHILDS               64
diff --git a/udevsettle.8 b/udevsettle.8
new file mode 100644 (file)
index 0000000..6015539
--- /dev/null
@@ -0,0 +1,32 @@
+.\" ** You probably do not want to edit this file directly **
+.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
+.\" Instead of manually editing it, you probably should edit the DocBook XML
+.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
+.TH "UDEVSETTLE" "8" "March 2006" "udev" "udevsettle"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+udevsettle \- wait until queued kernel/udev events are handled
+.SH "SYNOPSIS"
+.HP 11
+\fBudevsettle\fR [\fB\-\-timeout=\fR\fB\fIseconds\fR\fR]
+.SH "DESCRIPTION"
+.PP
+Waits watching the udev event queue and exits if all current events are handled.
+.SH "OPTIONS"
+.TP
+\fB\-\-timeout=\fR\fB\fIseconds\fR\fR
+maximum seconds to wait for the queue to become empty.
+.SH "ENVIRONMENT"
+.TP
+\fBUDEV_LOG\fR
+Overrides the syslog priority specified in the config file.
+.SH "AUTHOR"
+.PP
+Written by Kay Sievers
+<kay.sievers@vrfy.org>.
+.SH "SEE ALSO"
+.PP
+\fBudev\fR(7)
diff --git a/udevsettle.c b/udevsettle.c
new file mode 100644 (file)
index 0000000..f0f85ff
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * udevsettle.c
+ *
+ * Copyright (C) 2006 Kay Sievers <kay@vrfy.org>
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the
+ *     Free Software Foundation version 2 of the License.
+ * 
+ *     This program is distributed in the hope that it will be useful, but
+ *     WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License along
+ *     with this program; if not, write to the Free Software Foundation, Inc.,
+ *     675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "udev.h"
+#include "udevd.h"
+
+#define LOOP_PER_SECOND                        20
+
+static const char *udev_log_str;
+
+#ifdef USE_LOG
+void log_message(int priority, const char *format, ...)
+{
+       va_list args;
+
+       if (priority > udev_log_priority)
+               return;
+
+       va_start(args, format);
+       vsyslog(priority, format, args);
+       va_end(args);
+}
+#endif
+
+int main(int argc, char *argv[], char *envp[])
+{
+       char queuename[PATH_SIZE];
+       char filename[PATH_SIZE];
+       unsigned long long seq_kernel;
+       unsigned long long seq_udev;
+       char seqnum[32];
+       int fd;
+       ssize_t len;
+       int timeout = 30;
+       int loop;
+       int i;
+       int rc = 1;
+
+       logging_init("udevsettle");
+       udev_config_init();
+       dbg("version %s", UDEV_VERSION);
+
+       udev_log_str = getenv("UDEV_LOG");
+
+       for (i = 1 ; i < argc; i++) {
+               char *arg = argv[i];
+
+               if (strncmp(arg, "--timeout=", 10) == 0) {
+                       char *str = &arg[10];
+
+                       timeout = atoi(str);
+                       dbg("timeout=%i", timeout);
+                       if (timeout <= 0) {
+                               fprintf(stderr, "Invalid timeout value.\n");
+                               goto exit;
+                       }
+               } else {
+                       fprintf(stderr, "Usage: udevsettle [--timeout=<seconds>]\n");
+                       goto exit;
+               }
+       }
+
+       sysfs_init();
+       strlcpy(queuename, udev_root, sizeof(queuename));
+       strlcat(queuename, "/" EVENT_QUEUE_DIR, sizeof(queuename));
+
+       loop = timeout * LOOP_PER_SECOND;
+       while (loop--) {
+               /* wait for events in queue to finish */
+               while (loop--) {
+                       struct stat statbuf;
+
+                       if (stat(queuename, &statbuf) < 0) {
+                               info("queue is empty");
+                               break;
+                       }
+                       usleep(1000 * 1000 / LOOP_PER_SECOND);
+               }
+               if (loop <= 0) {
+                       info("timeout waiting for queue");
+                       goto exit;
+               }
+
+               /* read current kernel seqnum */
+               strlcpy(filename, sysfs_path, sizeof(filename));
+               strlcat(filename, "/kernel/uevent_seqnum", sizeof(filename));
+               fd = open(filename, O_RDONLY);
+               if (fd < 0)
+                       goto exit;
+               len = read(fd, seqnum, sizeof(seqnum)-1);
+               close(fd);
+               if (len <= 0)
+                       goto exit;
+               seqnum[len] = '\0';
+               seq_kernel = strtoull(seqnum, NULL, 10);
+               info("kernel seqnum = %llu", seq_kernel);
+
+               /* read current udev seqnum */
+               strlcpy(filename, udev_root, sizeof(filename));
+               strlcat(filename, "/" EVENT_SEQNUM, sizeof(filename));
+               fd = open(filename, O_RDONLY);
+               if (fd < 0)
+                       goto exit;
+               len = read(fd, seqnum, sizeof(seqnum)-1);
+               close(fd);
+               if (len <= 0)
+                       goto exit;
+               seqnum[len] = '\0';
+               seq_udev = strtoull(seqnum, NULL, 10);
+               info("udev seqnum = %llu", seq_udev);
+
+               /* make sure all kernel events have arrived in the queue */
+               if (seq_udev >= seq_kernel) {
+                       info("queue is empty and no pending events left");
+                       rc = 0;
+                       goto exit;
+               }
+               usleep(1000 * 1000 / LOOP_PER_SECOND);
+               info("queue is empty, but events still pending");
+       }
+
+exit:
+       sysfs_cleanup();
+       logging_close();
+       return rc;
+}
diff --git a/udevsettle.xml b/udevsettle.xml
new file mode 100644 (file)
index 0000000..5f8f1ee
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version='1.0'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<article>
+  <articleinfo>
+    <title>xmlto</title>
+    <author>
+      <firstname>Kay</firstname>
+      <surname>Sievers</surname>
+      <email>kay.sievers@vrfy.org</email>
+    </author>
+    <copyright>
+      <year>2006</year>
+      <holder>Kay Sievers</holder>
+    </copyright>
+  </articleinfo>
+
+  <section>
+    <title>udevsettle</title>
+    <refentry>
+      <refentryinfo>
+        <title>udevsettle</title>
+        <date>March 2006</date>
+        <productname>udev</productname>
+      </refentryinfo>
+
+      <refmeta>
+        <refentrytitle>udevsettle</refentrytitle>
+        <manvolnum>8</manvolnum>
+      </refmeta>
+
+      <refnamediv>
+        <refname>udevsettle</refname><refpurpose>wait until queued kernel/udev events are handled</refpurpose>
+      </refnamediv>
+
+      <refsynopsisdiv>
+        <cmdsynopsis>
+          <command>udevsettle</command>
+          <arg><option>--timeout=<replaceable>seconds</replaceable></option></arg>
+        </cmdsynopsis>
+      </refsynopsisdiv>
+
+      <refsect1><title>DESCRIPTION</title>
+        <para>Waits watching the udev event queue and exits if all current events are handled.</para>
+      </refsect1>
+
+      <refsect1><title>OPTIONS</title>
+        <variablelist>
+          <varlistentry>
+            <term><option>--timeout=<replaceable>seconds</replaceable></option></term>
+            <listitem>
+              <para>maximum seconds to wait for the queue to become empty.</para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+      </refsect1>
+
+      <refsect1><title>ENVIRONMENT</title>
+        <variablelist>
+          <varlistentry>
+            <term><option>UDEV_LOG</option></term>
+            <listitem>
+              <para>Overrides the syslog priority specified in the config file.</para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+     </refsect1>
+
+      <refsect1><title>AUTHOR</title>
+        <para>Written by Kay Sievers <email>kay.sievers@vrfy.org</email>.</para>
+      </refsect1>
+
+      <refsect1>
+        <title>SEE ALSO</title>
+        <para><citerefentry>
+            <refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum>
+        </citerefentry></para>
+      </refsect1>
+    </refentry>
+  </section>
+</article>