summaryrefslogtreecommitdiff
path: root/udev/udevd.c
diff options
context:
space:
mode:
authorScott James Remnant <scott@ubuntu.com>2009-02-11 17:38:56 +0000
committerScott James Remnant <scott@ubuntu.com>2009-02-11 17:38:56 +0000
commitbd284db142c1d3fb6e2a709678c8828c12c52466 (patch)
tree955c71b48e38c2bcc99a8a422b0b7c8548ea9501 /udev/udevd.c
parent10b2d011e70ddf9361c61f6147dc88f670d28abd (diff)
udevd: optionally watch device nodes with inotify
This allows you to re-process the rules if the content of the device has been changed, most useful for block subsystem to cause vol_id to be run again.
Diffstat (limited to 'udev/udevd.c')
-rw-r--r--udev/udevd.c84
1 files changed, 58 insertions, 26 deletions
diff --git a/udev/udevd.c b/udev/udevd.c
index d08cf30f29..d93781f411 100644
--- a/udev/udevd.c
+++ b/udev/udevd.c
@@ -65,7 +65,6 @@ static int debug_trace;
static struct udev_rules *rules;
static struct udev_ctrl *udev_ctrl;
static struct udev_monitor *kernel_monitor;
-static int inotify_fd = -1;
static volatile int sigchilds_waiting;
static volatile int udev_exit;
static volatile int reload_config;
@@ -195,8 +194,6 @@ static void event_fork(struct udev_event *event)
/* child */
udev_monitor_unref(kernel_monitor);
udev_ctrl_unref(udev_ctrl);
- if (inotify_fd >= 0)
- close(inotify_fd);
logging_close();
logging_init("udevd-event");
setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
@@ -513,6 +510,58 @@ static void handle_ctrl_msg(struct udev_ctrl *uctrl)
udev_ctrl_msg_unref(ctrl_msg);
}
+/* read inotify messages */
+static int handle_inotify(struct udev *udev)
+{
+ int nbytes, pos;
+ char *buf;
+ struct inotify_event *ev;
+ int reload_config = 0;
+
+ if ((ioctl(inotify_fd, FIONREAD, &nbytes) < 0) || (nbytes <= 0))
+ return 0;
+
+ buf = malloc(nbytes);
+ if (buf == NULL) {
+ err(udev, "error getting buffer for inotify, disable watching\n");
+ close(inotify_fd);
+ inotify_fd = -1;
+ return 0;
+ }
+
+ read(inotify_fd, buf, nbytes);
+
+ for (pos = 0, ev = (struct inotify_event *)(buf + pos); pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) {
+ const char *syspath;
+
+ dbg(udev, "inotify event: %x for %d (%s)\n", ev->mask, ev->wd, ev->len ? ev->name : "*");
+
+ syspath = udev_watch_lookup(udev, ev->wd);
+ if (syspath != NULL) {
+ dbg(udev, "inotify event: %x for %s\n", ev->mask, syspath);
+ if (ev->mask & IN_CLOSE_WRITE) {
+ char filename[UTIL_PATH_SIZE];
+ int fd;
+
+ info(udev, "device %s closed, synthesising write\n", syspath);
+ util_strlcpy(filename, syspath, sizeof(filename));
+ util_strlcat(filename, "/uevent", sizeof(filename));
+ fd = open(filename, O_WRONLY);
+ if (fd < 0 || write(fd, "change", 6) < 0)
+ info(udev, "error writing uevent: %m\n");
+ close(fd);
+ }
+ if (ev->mask & IN_IGNORED)
+ udev_watch_end(udev, ev->wd);
+ } else {
+ reload_config = 1;
+ }
+ }
+
+ free (buf);
+ return reload_config;
+}
+
static void asmlinkage sig_handler(int signum)
{
switch (signum) {
@@ -838,7 +887,7 @@ int main(int argc, char *argv[])
sigaction(SIGHUP, &act, NULL);
/* watch rules directory */
- inotify_fd = inotify_init();
+ udev_watch_init(udev);
if (inotify_fd >= 0) {
if (udev_get_rules_path(udev) != NULL) {
inotify_add_watch(inotify_fd, udev_get_rules_path(udev),
@@ -857,10 +906,9 @@ int main(int argc, char *argv[])
inotify_add_watch(inotify_fd, filename,
IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
}
- } else if (errno == ENOSYS)
- info(udev, "unable to use inotify, udevd will not monitor rule files changes\n");
- else
- err(udev, "inotify_init failed: %m\n");
+
+ udev_watch_restore(udev);
+ }
/* in trace mode run one event after the other */
if (debug_trace) {
@@ -936,24 +984,8 @@ int main(int argc, char *argv[])
}
/* rules directory inotify watch */
- if (inotify_poll && (inotify_poll->revents & POLLIN)) {
- int nbytes;
-
- /* discard all possible events, we can just reload the config */
- if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes > 0) {
- char *buf;
-
- reload_config = 1;
- buf = malloc(nbytes);
- if (buf == NULL) {
- err(udev, "error getting buffer for inotify, disable watching\n");
- close(inotify_fd);
- inotify_fd = -1;
- }
- read(inotify_fd, buf, nbytes);
- free(buf);
- }
- }
+ if (inotify_poll && (inotify_poll->revents & POLLIN))
+ reload_config = handle_inotify(udev);
handle_signals:
signal_received = 0;