From: Yu Watanabe Date: Sat, 20 Apr 2024 04:20:46 +0000 (+0900) Subject: sd-event: fix sd_event_source_get_inotify_path() X-Git-Tag: v256-rc1~98 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a7cd0caad8d9f1f3ed7c4cfc6a66b4e94c28b4e;p=thirdparty%2Fsystemd.git sd-event: fix sd_event_source_get_inotify_path() Follow-ups for 74c4231ce5f6cddabc2500391a8d5fd69e89b79e. Previously, the path is obtained from the fd, but it is closed in sd_event_loop() to unpin the filesystem. So, let's save the path when the event source is created, and make sd_event_source_get_inotify_path() simply read it. --- diff --git a/man/sd_event_add_inotify.xml b/man/sd_event_add_inotify.xml index 636f37b0012..ed26c8ac96e 100644 --- a/man/sd_event_add_inotify.xml +++ b/man/sd_event_add_inotify.xml @@ -67,7 +67,7 @@ int sd_event_source_get_inotify_path sd_event_source *source - char **ret + const char **ret @@ -144,7 +144,8 @@ sd_event_source_get_inotify_path() retrieves the target path of the configured inotify watch of an event source created previously with sd_event_add_inotify(). It takes the event source object as the source parameter and a pointer to a - char ** variable to return the path in. The caller needs to free the returned path. + const char ** variable to return the path in. The caller must not free the returned path. + @@ -207,8 +208,11 @@ -ENOSYS - sd_event_add_inotify_fd() was called without - /proc/ mounted. + + sd_event_add_inotify_fd() or + sd_event_source_get_inotify_path() was called without + /proc/ mounted. + diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h index f4e38d78d08..d05bcf0538d 100644 --- a/src/libsystemd/sd-event/event-source.h +++ b/src/libsystemd/sd-event/event-source.h @@ -189,6 +189,9 @@ struct inode_data { * iteration. */ int fd; + /* The path that the fd points to. The field is optional. */ + char *path; + /* The inotify "watch descriptor" */ int wd; diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 23d9dc10c0f..39c60297f06 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -2272,6 +2272,7 @@ static void event_free_inode_data( assert_se(hashmap_remove(d->inotify_data->inodes, d) == d); } + free(d->path); free(d); } @@ -2512,6 +2513,15 @@ static int event_add_inotify_fd_internal( } LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data); + + _cleanup_free_ char *path = NULL; + r = fd_get_path(inode_data->fd, &path); + if (r < 0 && r != -ENOSYS) { /* The path is optional, hence ignore -ENOSYS. */ + event_gc_inode_data(e, inode_data); + return r; + } + + free_and_replace(inode_data->path, path); } /* Link our event source to the inode data object */ @@ -2798,6 +2808,13 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) } LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data); + + _cleanup_free_ char *path = NULL; + r = fd_get_path(new_inode_data->fd, &path); + if (r < 0 && r != -ENOSYS) + goto fail; + + free_and_replace(new_inode_data->path, path); } /* Move the event source to the new inode data structure */ @@ -3292,16 +3309,20 @@ _public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret) return 0; } -_public_ int sd_event_source_get_inotify_path(sd_event_source *s, char **ret) { +_public_ int sd_event_source_get_inotify_path(sd_event_source *s, const char **ret) { assert_return(s, -EINVAL); assert_return(ret, -EINVAL); assert_return(s->type == SOURCE_INOTIFY, -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - if (!s->inotify.inode_data || s->inotify.inode_data->fd < 0) - return -ESTALE; + if (!s->inotify.inode_data) + return -ESTALE; /* already disconnected. */ - return fd_get_path(s->inotify.inode_data->fd, ret); + if (!s->inotify.inode_data->path) + return -ENOSYS; /* /proc was not mounted? */ + + *ret = s->inotify.inode_data->path; + return 0; } _public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) { diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index 87f704ecb19..991aa925a42 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -396,6 +396,7 @@ struct inotify_context { unsigned create_called[CREATE_EVENTS_MAX]; unsigned create_overflow; unsigned n_create_events; + const char *path; }; static void maybe_exit(sd_event_source *s, struct inotify_context *c) { @@ -422,10 +423,12 @@ static void maybe_exit(sd_event_source *s, struct inotify_context *c) { } static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { - struct inotify_context *c = userdata; - const char *description; + struct inotify_context *c = ASSERT_PTR(userdata); + const char *path, *description; unsigned bit, n; + assert_se(sd_event_source_get_inotify_path(s, &path) >= 0); + assert_se(sd_event_source_get_description(s, &description) >= 0); assert_se(safe_atou(description, &n) >= 0); @@ -433,11 +436,12 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v bit = 1U << n; if (ev->mask & IN_Q_OVERFLOW) { - log_info("inotify-handler <%s>: overflow", description); + log_info("inotify-handler for %s <%s>: overflow", path, description); c->create_overflow |= bit; } else if (ev->mask & IN_CREATE) { + assert_se(path_equal_or_inode_same(path, c->path, 0)); if (streq(ev->name, "sub")) - log_debug("inotify-handler <%s>: create on %s", description, ev->name); + log_debug("inotify-handler for %s <%s>: create on %s", path, description, ev->name); else { unsigned i; @@ -446,7 +450,7 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v c->create_called[i] |= bit; } } else if (ev->mask & IN_DELETE) { - log_info("inotify-handler <%s>: delete of %s", description, ev->name); + log_info("inotify-handler for %s <%s>: delete of %s", path, description, ev->name); assert_se(streq(ev->name, "sub")); } else assert_not_reached(); @@ -456,16 +460,19 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v } static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { - struct inotify_context *c = userdata; + struct inotify_context *c = ASSERT_PTR(userdata); + const char *path; + + assert_se(sd_event_source_get_inotify_path(s, &path) >= 0); if (ev->mask & IN_Q_OVERFLOW) { - log_info("delete-self-handler: overflow"); + log_info("delete-self-handler for %s: overflow", path); c->delete_self_handler_called = true; } else if (ev->mask & IN_DELETE_SELF) { - log_info("delete-self-handler: delete-self"); + log_info("delete-self-handler for %s: delete-self", path); c->delete_self_handler_called = true; } else if (ev->mask & IN_IGNORED) { - log_info("delete-self-handler: ignore"); + log_info("delete-self-handler for %s: ignore", path); } else assert_not_reached(); @@ -475,13 +482,12 @@ static int delete_self_handler(sd_event_source *s, const struct inotify_event *e static void test_inotify_one(unsigned n_create_events) { _cleanup_(rm_rf_physical_and_freep) char *p = NULL; - _cleanup_free_ char *pp = NULL; sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL; struct inotify_context context = { .n_create_events = n_create_events, }; sd_event *e = NULL; - const char *q; + const char *q, *pp; unsigned i; log_info("/* %s(%u) */", __func__, n_create_events); @@ -489,6 +495,7 @@ static void test_inotify_one(unsigned n_create_events) { assert_se(sd_event_default(&e) >= 0); assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0); + context.path = p; assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0); assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0); @@ -503,13 +510,10 @@ static void test_inotify_one(unsigned n_create_events) { assert_se(sd_event_source_get_inotify_path(a, &pp) >= 0); assert_se(path_equal_or_inode_same(pp, p, 0)); - pp = mfree(pp); assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0); assert_se(path_equal_or_inode_same(pp, p, 0)); - pp = mfree(pp); assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0); assert_se(path_equal_or_inode_same(pp, p, 0)); - pp = mfree(pp); q = strjoina(p, "/sub"); assert_se(touch(q) >= 0); diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h index e306c891cb1..a876add00c1 100644 --- a/src/systemd/sd-event.h +++ b/src/systemd/sd-event.h @@ -161,7 +161,7 @@ int sd_event_source_send_child_signal(sd_event_source *s, int sig, const siginfo int sd_event_source_send_child_signal(sd_event_source *s, int sig, const void *si, unsigned flags); #endif int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret); -int sd_event_source_get_inotify_path(sd_event_source *s, char **ret); +int sd_event_source_get_inotify_path(sd_event_source *s, const char **ret); int sd_event_source_set_memory_pressure_type(sd_event_source *e, const char *ty); int sd_event_source_set_memory_pressure_period(sd_event_source *s, uint64_t threshold_usec, uint64_t window_usec); int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback);