diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h index 5fef3b1ac9..7f6d5b8b50 100644 --- a/src/libsystemd/sd-event/event-source.h +++ b/src/libsystemd/sd-event/event-source.h @@ -42,7 +42,8 @@ typedef enum WakeupType { _WAKEUP_TYPE_INVALID = -EINVAL, } WakeupType; -struct inode_data; +typedef struct inode_data InodeData; +typedef struct inotify_data InotifyData; struct sd_event_source { WakeupType wakeup; @@ -87,8 +88,8 @@ struct sd_event_source { int fd; uint32_t events; uint32_t revents; - bool registered:1; - bool owned:1; + bool registered; + bool owned; } io; struct { sd_event_time_handler_t callback; @@ -106,11 +107,16 @@ struct sd_event_source { pid_t pid; int options; int pidfd; - bool registered:1; /* whether the pidfd is registered in the epoll */ + /* We have five bools, and we want to fit them into 4 bytes so the whole struct + * remains 32 bytes. Thus, use bitfields for two of them and single bytes for the + * other three. */ + bool registered; /* whether the pidfd is registered in the epoll */ bool pidfd_owned:1; /* close pidfd when event source is freed */ bool process_owned:1; /* kill+reap process when event source is freed */ - bool exited:1; /* true if process exited (i.e. if there's value in SIGKILLing it if we want to get rid of it) */ - bool waited:1; /* true if process was waited for (i.e. if there's value in waitid(P_PID)'ing it if we want to get rid of it) */ + bool exited; /* true if process exited (i.e. if there's value in SIGKILLing it if + * we want to get rid of it) */ + bool waited; /* true if process was waited for (i.e. if there's value in + * waitid(P_PID)'ing it if we want to get rid of it) */ } child; struct { sd_event_handler_t callback; @@ -125,19 +131,19 @@ struct sd_event_source { struct { sd_event_inotify_handler_t callback; uint32_t mask; - struct inode_data *inode_data; + InodeData *inode_data; LIST_FIELDS(sd_event_source, by_inode_data); } inotify; struct { int fd; + bool registered; + bool locked; + bool in_write_list; sd_event_handler_t callback; void *write_buffer; size_t write_buffer_size; uint32_t events, revents; LIST_FIELDS(sd_event_source, write_list); - bool registered:1; - bool locked:1; - bool in_write_list:1; } memory_pressure; }; }; @@ -157,7 +163,7 @@ struct clock_data { Prioq *latest; usec_t next; - bool needs_rearm:1; + bool needs_rearm; }; struct signal_data { @@ -182,7 +188,7 @@ struct inode_data { /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can * rearrange the priority still until then, as we need the original inode to change the priority as we need to * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the - * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of + * original inode. We keep a list of all InodeData objects with an open fd in the to_close list (see below) of * the sd-event object, so that it is efficient to close everything, before entering the next event loop * iteration. */ int fd; @@ -201,10 +207,10 @@ struct inode_data { LIST_HEAD(sd_event_source, event_sources); /* The inotify object we watch this inode with */ - struct inotify_data *inotify_data; + InotifyData *inotify_data; /* A linked list of all inode data objects with fds to close (see above) */ - LIST_FIELDS(struct inode_data, to_close); + LIST_FIELDS(InodeData, to_close); }; /* A structure encapsulating an inotify fd */ @@ -217,8 +223,8 @@ struct inotify_data { int fd; int64_t priority; - Hashmap *inodes; /* The inode_data structures keyed by dev+ino */ - Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */ + Hashmap *inodes; /* The InodeData structures keyed by dev+ino */ + Hashmap *wd; /* The InodeData structures keyed by the watch descriptor for each */ /* How many event sources are currently marked pending for this inotify. We won't read new events off the * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing @@ -230,12 +236,18 @@ struct inotify_data { * is gone. */ unsigned n_busy; - /* A linked list of all inotify objects with data already read, that still need processing. We keep this list - * to make it efficient to figure out what inotify objects to process data on next. */ - LIST_FIELDS(struct inotify_data, buffered); + /* A linked list of all InotifyData objects with data already read, that still need processing. We + * keep this list to make it efficient to figure out what inotify objects to process data on next. */ + LIST_FIELDS(InotifyData, buffered); /* The buffer we read inotify events into */ size_t buffer_filled; /* fill level of the buffer */ - union inotify_event_buffer buffer; /* struct inotify_event in union inotify_event_buffer has flex - * array. Hence, this must be at the end. */ + union inotify_event_buffer buffer; /* We use a union to allow type-punning. One of the variants in + * the union — struct inotify_event — has a flex array, so C99 + * only allows this union to be used at the end of the structure. + * The other variant in the union defines a fixed-size buffer that + * covers the maximum size that can be used for the flex variant, + * so in fact this field has a fixed size and could be safely + * placed in the middle of the struct. Unfortunately, there is no + * mechanism to let the compiler know that. */ }; diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 671fedf6fd..e108ba6546 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -139,10 +139,10 @@ struct sd_event { Hashmap *inotify_data; /* indexed by priority */ /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */ - LIST_HEAD(struct inode_data, inode_data_to_close_list); + LIST_HEAD(InodeData, inode_data_to_close_list); /* A list of inotify objects that already have events buffered which aren't processed yet */ - LIST_HEAD(struct inotify_data, buffered_inotify_data_list); + LIST_HEAD(InotifyData, buffered_inotify_data_list); /* A list of memory pressure event sources that still need their subscription string written */ LIST_HEAD(sd_event_source, memory_pressure_write_list); @@ -182,7 +182,7 @@ DEFINE_PRIVATE_ORIGIN_ID_HELPERS(sd_event, event); static thread_local sd_event *default_event = NULL; static void source_disconnect(sd_event_source *s); -static void event_gc_inode_data(sd_event *e, struct inode_data *d); +static void event_gc_inode_data(sd_event *e, InodeData *d); static sd_event* event_resolve(sd_event *e) { return e == SD_EVENT_DEFAULT ? default_event : e; @@ -1011,11 +1011,11 @@ static void source_disconnect(sd_event_source *s) { break; case SOURCE_INOTIFY: { - struct inode_data *inode_data; + InodeData *inode_data; inode_data = s->inotify.inode_data; if (inode_data) { - struct inotify_data *inotify_data; + InotifyData *inotify_data; assert_se(inotify_data = inode_data->inotify_data); /* Detach this event source from the inode object */ @@ -2103,7 +2103,7 @@ _public_ int sd_event_add_memory_pressure( return 0; } -static void event_free_inotify_data(sd_event *e, struct inotify_data *d) { +static void event_free_inotify_data(sd_event *e, InotifyData *d) { assert(e); if (!d) @@ -2130,13 +2130,9 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) { free(d); } -static int event_make_inotify_data( - sd_event *e, - int64_t priority, - struct inotify_data **ret) { - +static int event_make_inotify_data(sd_event *e, int64_t priority, InotifyData **ret) { _cleanup_close_ int fd = -EBADF; - struct inotify_data *d; + InotifyData *d; int r; assert(e); @@ -2154,11 +2150,11 @@ static int event_make_inotify_data( fd = fd_move_above_stdio(fd); - d = new(struct inotify_data, 1); + d = new(InotifyData, 1); if (!d) return -ENOMEM; - *d = (struct inotify_data) { + *d = (InotifyData) { .wakeup = WAKEUP_INOTIFY_DATA, .fd = TAKE_FD(fd), .priority = priority, @@ -2191,7 +2187,7 @@ static int event_make_inotify_data( return 1; } -static int inode_data_compare(const struct inode_data *x, const struct inode_data *y) { +static int inode_data_compare(const InodeData *x, const InodeData *y) { int r; assert(x); @@ -2204,19 +2200,16 @@ static int inode_data_compare(const struct inode_data *x, const struct inode_dat return CMP(x->ino, y->ino); } -static void inode_data_hash_func(const struct inode_data *d, struct siphash *state) { +static void inode_data_hash_func(const InodeData *d, struct siphash *state) { assert(d); siphash24_compress_typesafe(d->dev, state); siphash24_compress_typesafe(d->ino, state); } -DEFINE_PRIVATE_HASH_OPS(inode_data_hash_ops, struct inode_data, inode_data_hash_func, inode_data_compare); - -static void event_free_inode_data( - sd_event *e, - struct inode_data *d) { +DEFINE_PRIVATE_HASH_OPS(inode_data_hash_ops, InodeData, inode_data_hash_func, inode_data_compare); +static void event_free_inode_data(sd_event *e, InodeData *d) { assert(e); if (!d) @@ -2252,16 +2245,14 @@ static void event_free_inode_data( free(d); } -static void event_gc_inotify_data( - sd_event *e, - struct inotify_data *d) { - +static void event_gc_inotify_data(sd_event *e, InotifyData *d) { assert(e); - /* GCs the inotify data object if we don't need it anymore. That's the case if we don't want to watch - * any inode with it anymore, which in turn happens if no event source of this priority is interested - * in any inode any longer. That said, we maintain an extra busy counter: if non-zero we'll delay GC - * (under the expectation that the GC is called again once the counter is decremented). */ + /* Collects the InotifyData object if we don't need it anymore. That's the case if we don't want to + * watch any inode with it anymore, which in turn happens if no event source of this priority is + * interested in any inode any longer. That said, we maintain an extra busy counter: if non-zero + * we'll delay GC (under the expectation that the GC is called again once the counter is + * decremented). */ if (!d) return; @@ -2275,11 +2266,8 @@ static void event_gc_inotify_data( event_free_inotify_data(e, d); } -static void event_gc_inode_data( - sd_event *e, - struct inode_data *d) { - - struct inotify_data *inotify_data; +static void event_gc_inode_data(sd_event *e, InodeData *d) { + InotifyData *inotify_data; assert(e); @@ -2297,18 +2285,18 @@ static void event_gc_inode_data( static int event_make_inode_data( sd_event *e, - struct inotify_data *inotify_data, + InotifyData *inotify_data, dev_t dev, ino_t ino, - struct inode_data **ret) { + InodeData **ret) { - struct inode_data *d, key; + InodeData *d, key; int r; assert(e); assert(inotify_data); - key = (struct inode_data) { + key = (InodeData) { .ino = ino, .dev = dev, }; @@ -2325,11 +2313,11 @@ static int event_make_inode_data( if (r < 0) return r; - d = new(struct inode_data, 1); + d = new(InodeData, 1); if (!d) return -ENOMEM; - *d = (struct inode_data) { + *d = (InodeData) { .dev = dev, .ino = ino, .wd = -1, @@ -2349,7 +2337,7 @@ static int event_make_inode_data( return 1; } -static uint32_t inode_data_determine_mask(struct inode_data *d) { +static uint32_t inode_data_determine_mask(InodeData *d) { bool excl_unlink = true; uint32_t combined = 0; @@ -2374,7 +2362,7 @@ static uint32_t inode_data_determine_mask(struct inode_data *d) { return (combined & ~(IN_ONESHOT|IN_DONT_FOLLOW|IN_ONLYDIR|IN_EXCL_UNLINK)) | (excl_unlink ? IN_EXCL_UNLINK : 0); } -static int inode_data_realize_watch(sd_event *e, struct inode_data *d) { +static int inode_data_realize_watch(sd_event *e, InodeData *d) { uint32_t combined_mask; int wd, r; @@ -2431,8 +2419,8 @@ static int event_add_inotify_fd_internal( _cleanup_close_ int donated_fd = donate ? fd : -EBADF; _cleanup_(source_freep) sd_event_source *s = NULL; - struct inotify_data *inotify_data = NULL; - struct inode_data *inode_data = NULL; + InotifyData *inotify_data = NULL; + InodeData *inode_data = NULL; struct stat st; int r; @@ -2744,8 +2732,8 @@ _public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *ret) { _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) { bool rm_inotify = false, rm_inode = false; - struct inotify_data *new_inotify_data = NULL; - struct inode_data *new_inode_data = NULL; + InotifyData *new_inotify_data = NULL; + InodeData *new_inode_data = NULL; int r; assert_return(s, -EINVAL); @@ -2756,7 +2744,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) return 0; if (s->type == SOURCE_INOTIFY) { - struct inode_data *old_inode_data; + InodeData *old_inode_data; assert(s->inotify.inode_data); old_inode_data = s->inotify.inode_data; @@ -3840,7 +3828,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, i } } -static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents, int64_t threshold) { +static int event_inotify_data_read(sd_event *e, InotifyData *d, uint32_t revents, int64_t threshold) { ssize_t n; assert(e); @@ -3874,7 +3862,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t return 1; } -static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t sz) { +static void event_inotify_data_drop(sd_event *e, InotifyData *d, size_t sz) { assert(e); assert(d); assert(sz <= d->buffer_filled); @@ -3890,7 +3878,7 @@ static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t LIST_REMOVE(buffered, e->buffered_inotify_data_list, d); } -static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { +static int event_inotify_data_process(sd_event *e, InotifyData *d) { int r; assert(e); @@ -3912,7 +3900,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { return -EIO; if (d->buffer.ev.mask & IN_Q_OVERFLOW) { - struct inode_data *inode_data; + InodeData *inode_data; /* The queue overran, let's pass this event to all event sources connected to this inotify * object */ @@ -3928,7 +3916,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { return r; } } else { - struct inode_data *inode_data; + InodeData *inode_data; /* Find the inode object for this watch descriptor. If IN_IGNORED is set we also remove it from * our watch descriptor table. */ @@ -4212,7 +4200,7 @@ static int source_dispatch(sd_event_source *s) { case SOURCE_INOTIFY: { struct sd_event *e = s->event; - struct inotify_data *d; + InotifyData *d; size_t sz; assert(s->inotify.inode_data); @@ -4387,7 +4375,7 @@ static int process_watchdog(sd_event *e) { } static void event_close_inode_data_fds(sd_event *e) { - struct inode_data *d; + InodeData *d; assert(e);