X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fudev%2Fudevd.c;h=59b5568fb61753274d1d04c0b53adffb145535e0;hb=edd32000c806e4527c5f376d138f7bff07724c26;hp=1c9488e457e3f7d4ba551b7086b8b11737571d13;hpb=bf9bead187802a52a1f376a03caee762d663e945;p=elogind.git diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 1c9488e45..59b5568fb 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -290,7 +290,19 @@ static void worker_new(struct event *event) * acquired the lock, the external process will block until * udev has finished its event handling. */ - if (streq_ptr("block", udev_device_get_subsystem(dev))) { + + /* + * since we make check - device seems unused - we try + * ioctl to deactivate - and device is found to be opened + * sure, you try to take a write lock + * if you get it udev is out + * if you can't get it, udev is busy + * we cannot deactivate openned device (as it is in-use) + * maybe we should just exclude dm from that thing entirely + * IMHO this sounds like a good plan for this moment + */ + if (streq_ptr("block", udev_device_get_subsystem(dev)) && + !startswith("dm-", udev_device_get_sysname(dev))) { struct udev_device *d = dev; if (streq_ptr("partition", udev_device_get_devtype(d))) @@ -301,6 +313,7 @@ static void worker_new(struct event *event) if (fd_lock >= 0 && flock(fd_lock, LOCK_SH|LOCK_NB) < 0) { log_debug("Unable to flock(%s), skipping event handling: %m", udev_device_get_devnode(d)); err = -EWOULDBLOCK; + fd_lock = safe_close(fd_lock); goto skip; } } @@ -317,8 +330,7 @@ static void worker_new(struct event *event) udev_device_update_db(dev); } - if (fd_lock >= 0) - close(fd_lock); + safe_close(fd_lock); /* send processed event back to libudev listeners */ udev_monitor_send_device(worker_monitor, NULL, dev); @@ -377,10 +389,8 @@ skip: } out: udev_device_unref(dev); - if (fd_signal >= 0) - close(fd_signal); - if (fd_ep >= 0) - close(fd_ep); + safe_close(fd_signal); + safe_close(fd_ep); close(fd_inotify); close(worker_watch[WRITE_END]); udev_rules_unref(rules); @@ -723,20 +733,30 @@ out: return udev_ctrl_connection_unref(ctrl_conn); } +static void synthesize_change(struct udev_device *dev) { + char filename[UTIL_PATH_SIZE]; + + log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); + strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); + write_string_file(filename, "change"); +} + /* read inotify messages */ static int handle_inotify(struct udev *udev) { int nbytes, pos; char *buf; struct inotify_event *ev; + int r; - if ((ioctl(fd_inotify, FIONREAD, &nbytes) < 0) || (nbytes <= 0)) - return 0; + r = ioctl(fd_inotify, FIONREAD, &nbytes); + if (r < 0 || nbytes <= 0) + return -errno; buf = malloc(nbytes); - if (buf == NULL) { + if (!buf) { log_error("error getting buffer for inotify"); - return -1; + return -ENOMEM; } nbytes = read(fd_inotify, buf, nbytes); @@ -746,27 +766,16 @@ static int handle_inotify(struct udev *udev) ev = (struct inotify_event *)(buf + pos); dev = udev_watch_lookup(udev, ev->wd); - if (dev != NULL) { - log_debug("inotify event: %x for %s", ev->mask, udev_device_get_devnode(dev)); - if (ev->mask & IN_CLOSE_WRITE) { - char filename[UTIL_PATH_SIZE]; - int fd; - - log_debug("device %s closed, synthesising 'change'", udev_device_get_devnode(dev)); - strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); - fd = open(filename, O_WRONLY|O_CLOEXEC); - if (fd >= 0) { - if (write(fd, "change", 6) < 0) - log_debug("error writing uevent: %m"); - close(fd); - } - } - if (ev->mask & IN_IGNORED) - udev_watch_end(udev, dev); + if (!dev) + continue; - udev_device_unref(dev); - } + log_debug("inotify event: %x for %s", ev->mask, udev_device_get_devnode(dev)); + if (ev->mask & IN_CLOSE_WRITE) + synthesize_change(dev); + else if (ev->mask & IN_IGNORED) + udev_watch_end(udev, dev); + udev_device_unref(dev); } free(buf);