From 356d44a063a425704bd9c35c01c53ff57e512995 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 7 May 2025 00:59:56 +0900 Subject: [PATCH 1/2] udev-worker: allocate UdevEvent object just before use No functional change, just refactoring. --- src/udev/udev-worker.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c index f6b86e5e4f..56d9f63900 100644 --- a/src/udev/udev-worker.c +++ b/src/udev/udev-worker.c @@ -173,8 +173,6 @@ static int worker_mark_block_device_read_only(sd_device *dev) { } static int worker_process_device(UdevWorker *worker, sd_device *dev) { - _cleanup_(udev_event_unrefp) UdevEvent *udev_event = NULL; - _cleanup_close_ int fd_lock = -EBADF; int r; assert(worker); @@ -182,16 +180,12 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) { log_device_uevent(dev, "Processing device"); - udev_event = udev_event_new(dev, worker, EVENT_UDEV_WORKER); - if (!udev_event) - return -ENOMEM; - udev_event->trace = worker->config.trace; - /* If this is a block device and the device is locked currently via the BSD advisory locks, * someone else is using it exclusively. We don't run our udev rules now to not interfere. * Instead of processing the event, we requeue the event and will try again after a delay. * * The user-facing side of this: https://systemd.io/BLOCK_DEVICE_LOCKING */ + _cleanup_close_ int fd_lock = -EBADF; r = worker_lock_whole_disk(dev, &fd_lock); if (r == -EAGAIN) { log_device_debug(dev, "Block device is currently locked, requeuing the event."); @@ -215,6 +209,11 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) { if (r < 0) log_device_warning_errno(dev, r, "Failed to remove inotify watch, ignoring: %m"); + _cleanup_(udev_event_unrefp) UdevEvent *udev_event = udev_event_new(dev, worker, EVENT_UDEV_WORKER); + if (!udev_event) + return -ENOMEM; + udev_event->trace = worker->config.trace; + /* apply rules, create node, symlinks */ r = udev_event_execute_rules(udev_event, worker->rules); if (r < 0) From 22750aa91e3fbe2519413a4f238bc8909e96e891 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 7 May 2025 01:02:26 +0900 Subject: [PATCH 2/2] udev-worker: notify device node of whole disk to manager when the disk is locked It is currently unused, but will be used later. --- src/udev/udev-worker.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/udev/udev-worker.c b/src/udev/udev-worker.c index 56d9f63900..ba3c18c534 100644 --- a/src/udev/udev-worker.c +++ b/src/udev/udev-worker.c @@ -86,12 +86,13 @@ irrelevant: return 0; } -static int worker_lock_whole_disk(sd_device *dev, int *ret_fd) { +static int worker_lock_whole_disk(UdevWorker *worker, sd_device *dev, int *ret_fd) { _cleanup_close_ int fd = -EBADF; sd_device *dev_whole_disk; - const char *val; + const char *whole_disk; int r; + assert(worker); assert(dev); assert(ret_fd); @@ -106,7 +107,7 @@ static int worker_lock_whole_disk(sd_device *dev, int *ret_fd) { if (device_for_action(dev, SD_DEVICE_REMOVE)) goto nolock; - r = udev_get_whole_disk(dev, &dev_whole_disk, &val); + r = udev_get_whole_disk(dev, &dev_whole_disk, &whole_disk); if (r < 0) return r; if (r == 0) @@ -116,17 +117,29 @@ static int worker_lock_whole_disk(sd_device *dev, int *ret_fd) { if (fd < 0) { bool ignore = ERRNO_IS_DEVICE_ABSENT(fd); - log_device_debug_errno(dev, fd, "Failed to open '%s'%s: %m", val, ignore ? ", ignoring" : ""); + log_device_debug_errno(dev, fd, "Failed to open '%s'%s: %m", whole_disk, ignore ? ", ignoring" : ""); if (!ignore) return fd; goto nolock; } - if (flock(fd, LOCK_SH|LOCK_NB) < 0) - return log_device_debug_errno(dev, errno, "Failed to flock(%s): %m", val); + if (flock(fd, LOCK_SH|LOCK_NB) < 0) { + if (errno != EAGAIN) + return log_device_debug_errno(dev, errno, "Failed to flock(%s): %m", whole_disk); - log_device_debug(dev, "Successfully took flock(LOCK_SH) for %s, it will be released after the event has been processed.", val); + log_device_debug_errno(dev, errno, "Block device %s is currently locked, requeuing the event.", whole_disk); + + r = sd_notifyf(/* unset_environment = */ false, "TRY_AGAIN=1\nWHOLE_DISK=%s", whole_disk); + if (r < 0) { + log_device_warning_errno(dev, r, "Failed to send notification message to manager process: %m"); + (void) sd_event_exit(worker->event, r); + } + + return -EAGAIN; + } + + log_device_debug(dev, "Successfully took flock(LOCK_SH) for %s, it will be released after the event has been processed.", whole_disk); *ret_fd = TAKE_FD(fd); return 1; @@ -186,18 +199,9 @@ static int worker_process_device(UdevWorker *worker, sd_device *dev) { * * The user-facing side of this: https://systemd.io/BLOCK_DEVICE_LOCKING */ _cleanup_close_ int fd_lock = -EBADF; - r = worker_lock_whole_disk(dev, &fd_lock); - if (r == -EAGAIN) { - log_device_debug(dev, "Block device is currently locked, requeuing the event."); - - r = sd_notify(/* unset_environment = */ false, "TRY_AGAIN=1"); - if (r < 0) { - log_device_warning_errno(dev, r, "Failed to send notification message to manager process: %m"); - (void) sd_event_exit(worker->event, r); - } - + r = worker_lock_whole_disk(worker, dev, &fd_lock); + if (r == -EAGAIN) return 0; - } if (r < 0) return r;