From: Kay Sievers Date: Mon, 1 Aug 2005 18:22:46 +0000 (+0200) Subject: add udevmonitor, to debug netlink+udev events at the same time X-Git-Tag: 174~2663 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=1bc33626787f089523192c270790f9f878a4edd7 add udevmonitor, to debug netlink+udev events at the same time This rule: RUN+="socket:/org/kernel/udev/monitor" send the event to the running monitor. Running udevstart give a nice monitor output. Also the delay between the kernel uevent and the udev udev event can be investigated: pim:/home/kay/src/udev-kay # ./udevmonitor UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1 UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0 UEVENT[1122920113] add@/class/scsi_host/host12 UEVENT[1122920113] add@/class/usb_device/usbdev2.99 UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host12/target12:0:0/12:0:0:0 UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1 UEVENT[1122920113] add@/block/sda UEVENT[1122920113] add@/class/scsi_generic/sg0 UEVENT[1122920113] add@/class/scsi_device/12:0:0:0 UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0 UDEV [1122920113] add@/class/scsi_host/host12 UDEV [1122920113] add@/class/usb_device/usbdev2.99 UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host12/target12:0:0/12:0:0:0 UDEV [1122920113] add@/block/sda UDEV [1122920113] add@/class/scsi_generic/sg0 UDEV [1122920113] add@/class/scsi_device/12:0:0:0 UEVENT[1122920115] add@/block/sda/sda1 UDEV [1122920115] add@/block/sda/sda1 pim:/home/kay/src/udev-kay # ./udevmonitor --env UDEV [1122920185] add@/block/sda/sda1 ACTION=add DEVPATH=/block/sda/sda1 SUBSYSTEM=block SEQNUM=2159 MINOR=1 MAJOR=8 PHYSDEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host13/target13:0:0/13:0:0:0 PHYSDEVBUS=scsi PHYSDEVDRIVER=sd UDEVD_EVENT=1 UDEV_LOG=3 ID_VENDOR=IBM ID_MODEL=Memory_Key ID_REVISION=3.04 ID_SERIAL=IBM_Memory_Key_0218B301030027E8 ID_TYPE=disk ID_BUS=usb ID_PATH=usb-0218B301030027E8:0:0:0 ID_FS_USAGE=filesystem ID_FS_TYPE=vfat ID_FS_VERSION=FAT16 ID_FS_UUID=42D8-9E02 ID_FS_LABEL_SAFE=s_p_c DEVNAME=/dev/sda1 Signed-off-by: Kay Sievers --- diff --git a/Makefile b/Makefile index c9807de4b..5eb93bd50 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,7 @@ COMPILE = udevrulescompile INITSENDER = udevinitsend RECORDER = udeveventrecorder CONTROL = udevcontrol +MONITOR = udevmonitor INFO = udevinfo TESTER = udevtest STARTER = udevstart @@ -204,7 +205,7 @@ endif # config files automatically generated GEN_CONFIGS = $(LOCAL_CFG_DIR)/udev.conf -all: $(ROOT) $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) \ +all: $(ROOT) $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(MONITOR)\ $(DAEMON) $(COMPILE) $(INFO) $(TESTER) $(STARTER) $(GEN_CONFIGS) $(KLCC) @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \ @@ -275,6 +276,7 @@ $(COMPILE).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(INITSENDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(RECORDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(CONTROL).o: $(HEADERS) $( $(HEADERS)GEN_HEADERS) $(HOST_PROGS) $(KLCC) +$(MONITOR).o: $(HEADERS) $( $(HEADERS)GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(STARTER).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(ROOT): $(KLCC) $(ROOT).o $(OBJS) $(HEADERS) $(GEN_MANPAGES) @@ -313,6 +315,10 @@ $(CONTROL): $(KLCC) $(CONTROL).o $(OBJS) udevd.h $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CONTROL).o $(OBJS) $(LIB_OBJS) $(QUIET) $(STRIPCMD) $@ +$(MONITOR): $(KLCC) $(MONITOR).o $(OBJS) udevd.h + $(QUIET) $(LD) $(LDFLAGS) -o $@ $(MONITOR).o $(OBJS) $(LIB_OBJS) + $(QUIET) $(STRIPCMD) $@ + $(STARTER): $(KLCC) $(STARTER).o $(OBJS) $(QUIET) $(LD) $(LDFLAGS) -o $@ $(STARTER).o $(OBJS) $(LIB_OBJS) $(QUIET) $(STRIPCMD) $@ @@ -324,7 +330,7 @@ clean: -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ | xargs rm -f -rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(GEN_MANPAGES) $(INFO) $(DAEMON) \ - $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(TESTER) $(STARTER) + $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(MONITOR) $(TESTER) $(STARTER) -rm -f ccdv $(MAKE) -C klibc SUBDIRS=klibc clean @extras="$(EXTRAS)" ; for target in $$extras ; do \ @@ -374,6 +380,7 @@ install: install-config install-man all $(INSTALL_PROGRAM) -D $(DAEMON) $(DESTDIR)$(sbindir)/$(DAEMON) $(INSTALL_PROGRAM) -D $(SENDER) $(DESTDIR)$(sbindir)/$(SENDER) $(INSTALL_PROGRAM) -D $(CONTROL) $(DESTDIR)$(sbindir)/$(CONTROL) + $(INSTALL_PROGRAM) -D $(MONITOR) $(DESTDIR)$(sbindir)/$(MONITOR) $(INSTALL_PROGRAM) -D $(INFO) $(DESTDIR)$(usrbindir)/$(INFO) $(INSTALL_PROGRAM) -D $(TESTER) $(DESTDIR)$(usrbindir)/$(TESTER) $(INSTALL_PROGRAM) -D $(STARTER) $(DESTDIR)$(sbindir)/$(STARTER) @@ -399,6 +406,7 @@ uninstall: uninstall-man - rm $(sbindir)/$(INITSENDER) - rm $(sbindir)/$(RECORDER) - rm $(sbindir)/$(CONTROL) + - rm $(sbindir)/$(MONITOR) - rm $(sbindir)/$(STARTER) - rm $(usrbindir)/$(INFO) - rm $(usrbindir)/$(TESTER) diff --git a/udevd.h b/udevd.h index aadae31e5..da5f6b94f 100644 --- a/udevd.h +++ b/udevd.h @@ -22,7 +22,7 @@ #include "list.h" #define UDEV_MAGIC "udevd_" UDEV_VERSION -#define UDEVD_SOCK_PATH "udevd" +#define UDEVD_SOCK_PATH "/org/kernel/udev/udevd" #define UDEVSEND_WAIT_MAX_SECONDS 3 #define UDEVSEND_WAIT_LOOP_PER_SECOND 10 diff --git a/udevmonitor.c b/udevmonitor.c new file mode 100644 index 000000000..f4f28b165 --- /dev/null +++ b/udevmonitor.c @@ -0,0 +1,185 @@ +/* + * udevmonitor.c + * + * Copyright (C) 2004-2005 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 + +#include "udev.h" +#include "udevd.h" + +static int uevent_netlink_sock; +static int udev_monitor_sock; + +static int init_udev_monitor_socket(void) +{ + struct sockaddr_un saddr; + socklen_t addrlen; + const int feature_on = 1; + int retval; + + memset(&saddr, 0x00, sizeof(saddr)); + saddr.sun_family = AF_LOCAL; + /* use abstract namespace for socket path */ + strcpy(&saddr.sun_path[1], "/org/kernel/udev/monitor"); + addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1; + + udev_monitor_sock = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (udev_monitor_sock == -1) { + fprintf(stderr, "error getting socket, %s\n", strerror(errno)); + return -1; + } + + /* the bind takes care of ensuring only one copy running */ + retval = bind(udev_monitor_sock, (struct sockaddr *) &saddr, addrlen); + if (retval < 0) { + fprintf(stderr, "bind failed, %s\n", strerror(errno)); + close(udev_monitor_sock); + return -1; + } + + /* enable receiving of the sender credentials */ + setsockopt(udev_monitor_sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on)); + + return 0; +} + +static int init_uevent_netlink_sock(void) +{ + struct sockaddr_nl snl; + int retval; + + memset(&snl, 0x00, sizeof(struct sockaddr_nl)); + snl.nl_family = AF_NETLINK; + snl.nl_pid = getpid(); + snl.nl_groups = 0xffffffff; + + uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (uevent_netlink_sock == -1) { + fprintf(stderr, "error getting socket, %s\n", strerror(errno)); + return -1; + } + + retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, + sizeof(struct sockaddr_nl)); + if (retval < 0) { + fprintf(stderr, "bind failed, %s\n", strerror(errno)); + close(uevent_netlink_sock); + uevent_netlink_sock = -1; + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int env = 0; + int maxsockplus; + fd_set readfds; + int retval; + + if (getuid() != 0) { + printf("need to be root, exit\n"); + exit(1); + } + + if (argc == 2 && strstr(argv[1], "--env")) + env = 1; + + init_uevent_netlink_sock(); + init_udev_monitor_socket(); + + FD_ZERO(&readfds); + FD_SET(uevent_netlink_sock, &readfds); + FD_SET(udev_monitor_sock, &readfds); + maxsockplus = udev_monitor_sock+1; + + while (1) { + static char buf[UEVENT_BUFFER_SIZE*2]; + ssize_t buflen; + fd_set workreadfds; + + buflen = 0; + workreadfds = readfds; + + retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL); + if (retval < 0) { + if (errno != EINTR) + fprintf(stderr, "error receiving uevent message\n"); + continue; + } + + if (FD_ISSET(uevent_netlink_sock, &workreadfds)) { + buflen = recv(uevent_netlink_sock, &buf, sizeof(buf), 0); + if (buflen <= 0) { + fprintf(stderr, "error receiving uevent message\n"); + continue; + } + printf("UEVENT[%i] %s\n", time(NULL), buf); + } + + if (FD_ISSET(udev_monitor_sock, &workreadfds)) { + buflen = recv(udev_monitor_sock, &buf, sizeof(buf), 0); + if (buflen <= 0) { + fprintf(stderr, "error receiving udev message\n"); + continue; + } + printf("UDEV [%i] %s\n", time(NULL), buf); + } + + if (buflen == 0) + continue; + + /* print environment */ + if (env) { + size_t bufpos; + + /* start of payload */ + bufpos = strlen(buf) + 1; + + while (bufpos < (size_t)buflen) { + int keylen; + char *key; + + key = &buf[bufpos]; + keylen = strlen(key); + if (keylen == 0) + break; + printf("%s\n", key); + bufpos += keylen + 1; + } + printf("\n"); + } + } + + close(uevent_netlink_sock); + close(udev_monitor_sock); + exit(1); +}