summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--udevd.c15
-rw-r--r--udevd.h1
-rw-r--r--udevsettle.832
-rw-r--r--udevsettle.c155
-rw-r--r--udevsettle.xml82
6 files changed, 291 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 5e4322481c..1ce1abeab4 100644
--- 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 701165b9ad..8741a0901b 100644
--- 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 9ab6a445b9..e6ed58d622 100644
--- 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
index 0000000000..601553980d
--- /dev/null
+++ b/udevsettle.8
@@ -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
index 0000000000..f0f85ff059
--- /dev/null
+++ b/udevsettle.c
@@ -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
index 0000000000..5f8f1ee0a5
--- /dev/null
+++ b/udevsettle.xml
@@ -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>