You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
9.0 KiB
233 lines
9.0 KiB
From a78186fbbc05637ef9678b20c630597f2e5d6270 Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Tue, 9 Nov 2021 00:10:58 +0100
|
|
Subject: [PATCH] sd-event: add sd_event_add_inotify_fd() call
|
|
|
|
sd_event_add_inotify_fd() is like sd_event_add_inotify(), but takes an
|
|
fd to an inode instead of a path, and is hence a ton nicer.
|
|
|
|
(cherry picked from commit e67d738a8771c220a2e1ee81d5499a90589dd15d)
|
|
|
|
Related: #2211358
|
|
---
|
|
man/rules/meson.build | 4 +-
|
|
man/sd_event_add_inotify.xml | 16 +++++++
|
|
src/libsystemd/libsystemd.sym | 1 +
|
|
src/libsystemd/sd-event/sd-event.c | 76 +++++++++++++++++++++++-------
|
|
src/systemd/sd-event.h | 1 +
|
|
5 files changed, 81 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/man/rules/meson.build b/man/rules/meson.build
|
|
index 05eb0a1604..431a1cf269 100644
|
|
--- a/man/rules/meson.build
|
|
+++ b/man/rules/meson.build
|
|
@@ -272,7 +272,9 @@ manpages = [
|
|
''],
|
|
['sd_event_add_inotify',
|
|
'3',
|
|
- ['sd_event_inotify_handler_t', 'sd_event_source_get_inotify_mask'],
|
|
+ ['sd_event_add_inotify_fd',
|
|
+ 'sd_event_inotify_handler_t',
|
|
+ 'sd_event_source_get_inotify_mask'],
|
|
''],
|
|
['sd_event_add_io',
|
|
'3',
|
|
diff --git a/man/sd_event_add_inotify.xml b/man/sd_event_add_inotify.xml
|
|
index 605863c356..17415bbc17 100644
|
|
--- a/man/sd_event_add_inotify.xml
|
|
+++ b/man/sd_event_add_inotify.xml
|
|
@@ -18,6 +18,7 @@
|
|
|
|
<refnamediv>
|
|
<refname>sd_event_add_inotify</refname>
|
|
+ <refname>sd_event_add_inotify_fd</refname>
|
|
<refname>sd_event_source_get_inotify_mask</refname>
|
|
<refname>sd_event_inotify_handler_t</refname>
|
|
|
|
@@ -47,6 +48,16 @@
|
|
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
|
</funcprototype>
|
|
|
|
+ <funcprototype>
|
|
+ <funcdef>int <function>sd_event_add_inotify_fd</function></funcdef>
|
|
+ <paramdef>sd_event *<parameter>event</parameter></paramdef>
|
|
+ <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
|
|
+ <paramdef>int <parameter>fd</parameter></paramdef>
|
|
+ <paramdef>uint32_t <parameter>mask</parameter></paramdef>
|
|
+ <paramdef>sd_event_inotify_handler_t <parameter>handler</parameter></paramdef>
|
|
+ <paramdef>void *<parameter>userdata</parameter></paramdef>
|
|
+ </funcprototype>
|
|
+
|
|
<funcprototype>
|
|
<funcdef>int <function>sd_event_source_get_inotify_mask</function></funcdef>
|
|
<paramdef>sd_event_source *<parameter>source</parameter></paramdef>
|
|
@@ -72,6 +83,11 @@
|
|
<citerefentry project='man-pages'><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
|
further information.</para>
|
|
|
|
+ <para><function>sd_event_add_inotify_fd()</function> is identical to
|
|
+ <function>sd_event_add_inotify()</function>, except that it takes a file descriptor to an inode (possibly
|
|
+ an <constant>O_PATH</constant> one, but any other will do too) instead of a path in the file
|
|
+ system.</para>
|
|
+
|
|
<para>If multiple event sources are installed for the same inode the backing inotify watch descriptor is
|
|
automatically shared. The mask parameter may contain any flag defined by the inotify API, with the exception of
|
|
<constant>IN_MASK_ADD</constant>.</para>
|
|
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
|
|
index 449918093c..dc37472b18 100644
|
|
--- a/src/libsystemd/libsystemd.sym
|
|
+++ b/src/libsystemd/libsystemd.sym
|
|
@@ -593,5 +593,6 @@ global:
|
|
|
|
LIBSYSTEMD_250 {
|
|
global:
|
|
+ sd_event_add_inotify_fd;
|
|
sd_event_source_set_ratelimit_expire_callback;
|
|
} LIBSYSTEMD_248;
|
|
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
|
|
index 01a97a4801..9247087c41 100644
|
|
--- a/src/libsystemd/sd-event/sd-event.c
|
|
+++ b/src/libsystemd/sd-event/sd-event.c
|
|
@@ -2013,25 +2013,25 @@ static int inode_data_realize_watch(sd_event *e, struct inode_data *d) {
|
|
return 1;
|
|
}
|
|
|
|
-_public_ int sd_event_add_inotify(
|
|
+static int event_add_inotify_fd_internal(
|
|
sd_event *e,
|
|
sd_event_source **ret,
|
|
- const char *path,
|
|
+ int fd,
|
|
+ bool donate,
|
|
uint32_t mask,
|
|
sd_event_inotify_handler_t callback,
|
|
void *userdata) {
|
|
|
|
+ _cleanup_close_ int donated_fd = donate ? fd : -1;
|
|
+ _cleanup_(source_freep) sd_event_source *s = NULL;
|
|
struct inotify_data *inotify_data = NULL;
|
|
struct inode_data *inode_data = NULL;
|
|
- _cleanup_close_ int fd = -1;
|
|
- _cleanup_(source_freep) sd_event_source *s = NULL;
|
|
struct stat st;
|
|
int r;
|
|
|
|
assert_return(e, -EINVAL);
|
|
assert_return(e = event_resolve(e), -ENOPKG);
|
|
- assert_return(path, -EINVAL);
|
|
- assert_return(callback, -EINVAL);
|
|
+ assert_return(fd >= 0, -EBADF);
|
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
|
assert_return(!event_pid_changed(e), -ECHILD);
|
|
|
|
@@ -2041,12 +2041,6 @@ _public_ int sd_event_add_inotify(
|
|
if (mask & IN_MASK_ADD)
|
|
return -EINVAL;
|
|
|
|
- fd = open(path, O_PATH|O_CLOEXEC|
|
|
- (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
|
|
- (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
|
|
- if (fd < 0)
|
|
- return -errno;
|
|
-
|
|
if (fstat(fd, &st) < 0)
|
|
return -errno;
|
|
|
|
@@ -2066,14 +2060,24 @@ _public_ int sd_event_add_inotify(
|
|
|
|
r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data);
|
|
if (r < 0) {
|
|
- event_free_inotify_data(e, inotify_data);
|
|
+ event_gc_inotify_data(e, inotify_data);
|
|
return r;
|
|
}
|
|
|
|
/* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of
|
|
* the event source, until then, for which we need the original inode. */
|
|
if (inode_data->fd < 0) {
|
|
- inode_data->fd = TAKE_FD(fd);
|
|
+ if (donated_fd >= 0)
|
|
+ inode_data->fd = TAKE_FD(donated_fd);
|
|
+ else {
|
|
+ inode_data->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
|
+ if (inode_data->fd < 0) {
|
|
+ r = -errno;
|
|
+ event_gc_inode_data(e, inode_data);
|
|
+ return r;
|
|
+ }
|
|
+ }
|
|
+
|
|
LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
|
|
}
|
|
|
|
@@ -2086,8 +2090,6 @@ _public_ int sd_event_add_inotify(
|
|
if (r < 0)
|
|
return r;
|
|
|
|
- (void) sd_event_source_set_description(s, path);
|
|
-
|
|
if (ret)
|
|
*ret = s;
|
|
TAKE_PTR(s);
|
|
@@ -2095,6 +2097,48 @@ _public_ int sd_event_add_inotify(
|
|
return 0;
|
|
}
|
|
|
|
+_public_ int sd_event_add_inotify_fd(
|
|
+ sd_event *e,
|
|
+ sd_event_source **ret,
|
|
+ int fd,
|
|
+ uint32_t mask,
|
|
+ sd_event_inotify_handler_t callback,
|
|
+ void *userdata) {
|
|
+
|
|
+ return event_add_inotify_fd_internal(e, ret, fd, /* donate= */ false, mask, callback, userdata);
|
|
+}
|
|
+
|
|
+_public_ int sd_event_add_inotify(
|
|
+ sd_event *e,
|
|
+ sd_event_source **ret,
|
|
+ const char *path,
|
|
+ uint32_t mask,
|
|
+ sd_event_inotify_handler_t callback,
|
|
+ void *userdata) {
|
|
+
|
|
+ sd_event_source *s;
|
|
+ int fd, r;
|
|
+
|
|
+ assert_return(path, -EINVAL);
|
|
+
|
|
+ fd = open(path, O_PATH|O_CLOEXEC|
|
|
+ (mask & IN_ONLYDIR ? O_DIRECTORY : 0)|
|
|
+ (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0));
|
|
+ if (fd < 0)
|
|
+ return -errno;
|
|
+
|
|
+ r = event_add_inotify_fd_internal(e, &s, fd, /* donate= */ true, mask, callback, userdata);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+
|
|
+ (void) sd_event_source_set_description(s, path);
|
|
+
|
|
+ if (ret)
|
|
+ *ret = s;
|
|
+
|
|
+ return r;
|
|
+}
|
|
+
|
|
_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
|
|
|
|
if (!s)
|
|
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
|
|
index 960bea1ac4..48b053c127 100644
|
|
--- a/src/systemd/sd-event.h
|
|
+++ b/src/systemd/sd-event.h
|
|
@@ -91,6 +91,7 @@ int sd_event_add_time_relative(sd_event *e, sd_event_source **s, clockid_t clock
|
|
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
|
|
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
|
|
int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
|
|
+int sd_event_add_inotify_fd(sd_event *e, sd_event_source **s, int fd, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata);
|
|
int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
|
|
int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
|
|
int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata);
|