From: Masatake YAMATO Date: Mon, 10 Jul 2023 14:49:41 +0000 (+0900) Subject: lsfd: add 'm' flag representing "multiplexed by epoll_wait(2)" to XMODE column X-Git-Tag: v2.40-rc1~338^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da9013142193231fadf430a118969453bedc0658;p=thirdparty%2Futil-linux.git lsfd: add 'm' flag representing "multiplexed by epoll_wait(2)" to XMODE column An example output: $ ./lsfd -p 3101482 -Q '(FD > 2)' COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME test_mkfds 3101482 yamato 3 rw---- eventpoll anon_inodefs 15 106 tfds=4,5 test_mkfds 3101482 yamato 4 r----m CHR mem:8 23 8 /dev/random test_mkfds 3101482 yamato 5 -w---m CHR mem:8 23 8 /dev/random The fd 4 and 5 is multiplexed by 3, an evetpoll fd. Therefore 'm' flags in XMODE column for fd 4 and 5 are set. Just one character but 'm' may help users to understand the "IO structure" of a process. Signed-off-by: Masatake YAMATO --- diff --git a/misc-utils/lsfd-file.c b/misc-utils/lsfd-file.c index c4546126ff..004dd665e2 100644 --- a/misc-utils/lsfd-file.c +++ b/misc-utils/lsfd-file.c @@ -302,6 +302,7 @@ static bool file_fill_column(struct proc *proc, char L = file->locked.write? 'L' :file->locked.read? 'l' : '-'; + char m = file->multiplexed? 'm': '-'; if (does_file_has_fdinfo_alike(file)) { r = file->mode & S_IRUSR? 'r': '-'; @@ -310,7 +311,7 @@ static bool file_fill_column(struct proc *proc, && file->mode & S_IXUSR)? 'x': '-'; } else r = w = x = '-'; - xasprintf(&str, "%c%c%c%c%c", r, w, x, D, L); + xasprintf(&str, "%c%c%c%c%c%c", r, w, x, D, L, m); break; } case COL_POS: diff --git a/misc-utils/lsfd-unkn.c b/misc-utils/lsfd-unkn.c index 76292f3b81..83367d3ce3 100644 --- a/misc-utils/lsfd-unkn.c +++ b/misc-utils/lsfd-unkn.c @@ -444,6 +444,7 @@ static const struct anon_ops anon_eventfd_ops = { struct anon_eventpoll_data { size_t count; int *tfds; + struct list_head siblings; }; static bool anon_eventpoll_probe(const char *str) @@ -453,7 +454,9 @@ static bool anon_eventpoll_probe(const char *str) static void anon_eventpoll_init(struct unkn *unkn) { - unkn->anon_data = xcalloc(1, sizeof(struct anon_eventpoll_data)); + struct anon_eventpoll_data *data = xcalloc(1, sizeof(struct anon_eventpoll_data)); + INIT_LIST_HEAD(&data->siblings); + unkn->anon_data = data; } static void anon_eventpoll_free(struct unkn *unkn) @@ -496,6 +499,9 @@ static void anon_eventpoll_attach_xinfo(struct unkn *unkn) struct anon_eventpoll_data *data = (struct anon_eventpoll_data *)unkn->anon_data; qsort(data->tfds, data->count, sizeof(data->tfds[0]), intcmp); + if (data->count > 0) + list_add_tail(&data->siblings, + &unkn->file.proc->eventpolls); } static char *anon_eventpoll_make_tfds_string(struct anon_eventpoll_data *data, @@ -555,6 +561,26 @@ static const struct anon_ops anon_eventpoll_ops = { .attach_xinfo = anon_eventpoll_attach_xinfo, }; +static int numcomp(const void *a, const void *b) +{ + return *(int *)a - *(int *)b; +} + +bool is_multiplexed_by_eventpoll(int fd, struct list_head *eventpolls) +{ + struct list_head *t; + list_for_each (t, eventpolls) { + struct anon_eventpoll_data *data = list_entry(t, struct anon_eventpoll_data, siblings); + if (data->count) { + if (bsearch(&fd, data->tfds, + data->count, sizeof (data->tfds[0]), + numcomp)) + return true; + } + } + return false; +} + /* * timerfd */ diff --git a/misc-utils/lsfd.1.adoc b/misc-utils/lsfd.1.adoc index 681e112573..720be374f0 100644 --- a/misc-utils/lsfd.1.adoc +++ b/misc-utils/lsfd.1.adoc @@ -498,6 +498,10 @@ locked or leased. _l_ represents a read, a shared lock or a read lease. _L_ represents a write or an exclusive lock or a write lease. If both read/shared and write/exclusive locks or leases are taken by a file descriptor, _L_ is used as the flag. ++ +[-m]::: +Multiplexed. If the file descriptor is targeted by a eventpoll file, +this bit flag is set. == FILTER EXPRESSION diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index f423fbbddf..4a7bb5c57c 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -700,6 +700,7 @@ static struct proc *new_process(pid_t pid, struct proc *leader) INIT_LIST_HEAD(&proc->files); INIT_LIST_HEAD(&proc->procs); + INIT_LIST_HEAD(&proc->eventpolls); proc->kthread = 0; return proc; @@ -1847,6 +1848,23 @@ static void attach_xinfos(struct list_head *procs) } } +static void set_multiplexed_flags(struct list_head *procs) +{ + struct list_head *p; + list_for_each (p, procs) { + struct proc *proc = list_entry(p, struct proc, procs); + struct list_head *f; + list_for_each (f, &proc->files) { + struct file *file = list_entry(f, struct file, files); + if (is_opened_file(file) && !file->multiplexed) { + int fd = file->association; + if (is_multiplexed_by_eventpoll(fd, &proc->eventpolls)) + file->multiplexed = 1; + } + } + } +} + /* Filter expressions for implementing -i option. * * To list up the protocol names, use the following command line @@ -2078,6 +2096,9 @@ int main(int argc, char *argv[]) free(pids); attach_xinfos(&ctl.procs); + if (scols_table_get_column_by_name(ctl.tb, "XMODE")) + set_multiplexed_flags(&ctl.procs); + convert(&ctl.procs, &ctl); diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index ef02d4c3b4..be4cc55d80 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -149,6 +149,7 @@ struct proc { struct list_head procs; struct list_head files; unsigned int kthread: 1; + struct list_head eventpolls; }; struct proc *get_proc(pid_t pid); @@ -175,6 +176,7 @@ struct file { struct { uint8_t read:1, write:1; } locked; + uint8_t multiplexed; }; #define is_opened_file(_f) ((_f)->association >= 0) @@ -285,4 +287,9 @@ bool is_nsfs_dev(dev_t dev); /* 0 is assumed as the major dev for DEV. */ bool is_mqueue_dev(dev_t dev); +/* + * Eventpoll + */ +bool is_multiplexed_by_eventpoll(int fd, struct list_head *eventpolls); + #endif /* UTIL_LINUX_LSFD_H */