From 7baada47bea60dd192067fd36778a77481a3ed3a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 5 Apr 2006 00:08:10 +0200 Subject: [PATCH] udevd: export current seqnum and add udevsettle --- Makefile | 6 ++ udevd.c | 15 +++++ udevd.h | 1 + udevsettle.8 | 32 ++++++++++ udevsettle.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ udevsettle.xml | 82 ++++++++++++++++++++++++++ 6 files changed, 291 insertions(+) create mode 100644 udevsettle.8 create mode 100644 udevsettle.c create mode 100644 udevsettle.xml diff --git a/Makefile b/Makefile index 5e4322481..1ce1abeab 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 701165b9a..8741a0901 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 9ab6a445b..e6ed58d62 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 000000000..601553980 --- /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 +. +.SH "SEE ALSO" +.PP +\fBudev\fR(7) diff --git a/udevsettle.c b/udevsettle.c new file mode 100644 index 000000000..f0f85ff05 --- /dev/null +++ b/udevsettle.c @@ -0,0 +1,155 @@ +/* + * udevsettle.c + * + * Copyright (C) 2006 Kay Sievers + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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=]\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 000000000..5f8f1ee0a --- /dev/null +++ b/udevsettle.xml @@ -0,0 +1,82 @@ + + + +
+ + xmlto + + Kay + Sievers + kay.sievers@vrfy.org + + + 2006 + Kay Sievers + + + +
+ udevsettle + + + udevsettle + March 2006 + udev + + + + udevsettle + 8 + + + + udevsettlewait until queued kernel/udev events are handled + + + + + udevsettle + + + + + DESCRIPTION + Waits watching the udev event queue and exits if all current events are handled. + + + OPTIONS + + + + + maximum seconds to wait for the queue to become empty. + + + + + + ENVIRONMENT + + + + + Overrides the syslog priority specified in the config file. + + + + + + AUTHOR + Written by Kay Sievers kay.sievers@vrfy.org. + + + + SEE ALSO + + udev7 + + + +
+
-- 2.30.2