summaryrefslogtreecommitdiffstats
path: root/src/udev/udev-watch.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-03-07 07:35:33 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-04-30 12:41:41 +0200
commite7f781e473f5119bf9246208a6de9f6b76a39c5d (patch)
tree80ce166a1fea649dc0b61efcf32c54d4027619cf /src/udev/udev-watch.c
parentudev: make udev_watch_end() noop when device does not have devname (diff)
downloadsystemd-e7f781e473f5119bf9246208a6de9f6b76a39c5d.tar.xz
systemd-e7f781e473f5119bf9246208a6de9f6b76a39c5d.zip
udev,sd_device: also save map from device ID to watch handle in /run/udev/watch
Previously, watch handle is saved in the udev databse. But in most cases, the handle saved in the database is not updated. Especially, when udevd is restarted, the inotify watch is restarted, but the database is not updated. Moreover, it is not necessary to save watch handle in the database, as the handle is only take a effect during udevd is running, and the value is meaningless when udevd is restarted. So, this makes the opposite map from device ID to watch handle is saved in /run/udev/watch as a symbolic link, and the handle not saved in the database anymore. Fixes #18525.
Diffstat (limited to 'src/udev/udev-watch.c')
-rw-r--r--src/udev/udev-watch.c105
1 files changed, 35 insertions, 70 deletions
diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c
index f5085107be..7f15c87870 100644
--- a/src/udev/udev-watch.c
+++ b/src/udev/udev-watch.c
@@ -5,52 +5,55 @@
*/
#include <sys/inotify.h>
-#include <unistd.h>
#include "alloc-util.h"
#include "device-private.h"
#include "device-util.h"
#include "dirent-util.h"
#include "fs-util.h"
-#include "mkdir.h"
-#include "stdio-util.h"
+#include "parse-util.h"
#include "udev-watch.h"
-/* Move any old watches directory out of the way, and then restore the watches. */
int udev_watch_restore(int inotify_fd) {
struct dirent *ent;
DIR *dir;
int r;
+ /* Move any old watches directory out of the way, and then restore the watches. */
+
assert(inotify_fd >= 0);
if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) {
if (errno != ENOENT)
- return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m");
+ return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. "
+ "Old watches will not be restored: %m");
return 0;
}
dir = opendir("/run/udev/watch.old");
if (!dir)
- return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m");
+ return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. "
+ "Old watches will not be restored: %m");
FOREACH_DIRENT_ALL(ent, dir, break) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
- _cleanup_free_ char *id = NULL;
+ int wd;
if (ent->d_name[0] == '.')
continue;
- r = readlinkat_malloc(dirfd(dir), ent->d_name, &id);
- if (r < 0) {
- log_debug_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name);
+ /* For backward compatibility, read symlink from watch handle to device id, and ignore
+ * the opposite direction symlink. */
+
+ if (safe_atoi(ent->d_name, &wd) < 0)
goto unlink;
- }
- r = sd_device_new_from_device_id(&dev, id);
+ r = device_new_from_watch_handle_at(&dev, dirfd(dir), wd);
if (r < 0) {
- log_debug_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", id);
+ log_full_errno(r == -ENODEV ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to create sd_device object from saved watch handle '%s', ignoring: %m",
+ ent->d_name);
goto unlink;
}
@@ -67,8 +70,7 @@ unlink:
}
int udev_watch_begin(int inotify_fd, sd_device *dev) {
- char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
- const char *devnode, *id;
+ const char *devnode;
int wd, r;
assert(inotify_fd >= 0);
@@ -76,35 +78,27 @@ int udev_watch_begin(int inotify_fd, sd_device *dev) {
r = sd_device_get_devname(dev, &devnode);
if (r < 0)
- return log_device_error_errno(dev, r, "Failed to get device name: %m");
+ return log_device_debug_errno(dev, r, "Failed to get device name: %m");
log_device_debug(dev, "Adding watch on '%s'", devnode);
wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE);
- if (wd < 0)
- return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
- "Failed to add device '%s' to watch: %m", devnode);
-
- device_set_watch_handle(dev, wd);
+ if (wd < 0) {
+ r = log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ errno, "Failed to add device '%s' to watch: %m", devnode);
- xsprintf(filename, "/run/udev/watch/%d", wd);
- r = mkdir_parents(filename, 0755);
- if (r < 0)
- return log_device_error_errno(dev, r, "Failed to create parent directory of '%s': %m", filename);
- (void) unlink(filename);
+ (void) device_set_watch_handle(dev, -1);
+ return r;
+ }
- r = device_get_device_id(dev, &id);
+ r = device_set_watch_handle(dev, wd);
if (r < 0)
- return log_device_error_errno(dev, r, "Failed to get device id-filename: %m");
-
- if (symlink(id, filename) < 0)
- return log_device_error_errno(dev, errno, "Failed to create symlink %s: %m", filename);
+ return log_device_warning_errno(dev, r, "Failed to save watch handle in /run/udev/watch: %m");
return 0;
}
int udev_watch_end(int inotify_fd, sd_device *dev) {
- char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
- int wd, r;
+ int wd;
assert(dev);
@@ -115,43 +109,14 @@ int udev_watch_end(int inotify_fd, sd_device *dev) {
if (sd_device_get_devname(dev, NULL) < 0)
return 0;
- r = device_get_watch_handle(dev, &wd);
- if (r == -ENOENT)
- return 0;
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to get watch handle, ignoring: %m");
-
- log_device_debug(dev, "Removing watch");
- (void) inotify_rm_watch(inotify_fd, wd);
-
- xsprintf(filename, "/run/udev/watch/%d", wd);
- (void) unlink(filename);
-
- device_set_watch_handle(dev, -1);
+ wd = device_get_watch_handle(dev);
+ if (wd < 0)
+ log_device_debug_errno(dev, wd, "Failed to get watch handle, ignoring: %m");
+ else {
+ log_device_debug(dev, "Removing watch");
+ (void) inotify_rm_watch(inotify_fd, wd);
+ }
+ (void) device_set_watch_handle(dev, -1);
return 0;
}
-
-int udev_watch_lookup(int wd, sd_device **ret) {
- char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
- _cleanup_free_ char *id = NULL;
- int r;
-
- assert(wd >= 0);
- assert(ret);
-
- xsprintf(filename, "/run/udev/watch/%d", wd);
- r = readlink_malloc(filename, &id);
- if (r == -ENOENT)
- return 0;
- if (r < 0)
- return log_debug_errno(r, "Failed to read link '%s': %m", filename);
-
- r = sd_device_new_from_device_id(ret, id);
- if (r == -ENODEV)
- return 0;
- if (r < 0)
- return log_debug_errno(r, "Failed to create sd_device object for '%s': %m", id);
-
- return 1;
-}