diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | udevd.c | 15 | ||||
-rw-r--r-- | udevd.h | 1 | ||||
-rw-r--r-- | udevsettle.8 | 32 | ||||
-rw-r--r-- | udevsettle.c | 155 | ||||
-rw-r--r-- | udevsettle.xml | 82 |
6 files changed, 291 insertions, 0 deletions
@@ -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 @@ -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 */ @@ -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> |