From: Xi Ruoyao Date: Wed, 3 Apr 2024 15:46:57 +0800 Subject: lsfd: Support pidfs Git-repo: https://github.com/util-linux/util-linux.git Git-commit: b1a48efd173c7f37d8df39a84eb25b4440335661 Patch-mainline: yes References: kernel 6.9 In Linux 6.9 pidfds are moved from the anonymous inode infrastructure to a tiny pseudo filesystem named pidfs. Recognize it properly. Fixes #2865. Signed-off-by: Xi Ruoyao Signed-off-by: Jiri Slaby --- misc-utils/lsfd-file.c | 96 ++++++++++++++++++++++++++++++++++++++++++ misc-utils/lsfd.c | 3 ++ misc-utils/lsfd.h | 7 ++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/misc-utils/lsfd-file.c b/misc-utils/lsfd-file.c index 9b91462d..3f330146 100644 --- a/misc-utils/lsfd-file.c +++ b/misc-utils/lsfd-file.c @@ -45,6 +45,8 @@ #include "procfs.h" #include "lsfd.h" +#include "lsfd-pidfd.h" +#include "pidfd-utils.h" static struct idcache *username_cache; @@ -492,6 +494,22 @@ static unsigned long get_minor_for_mqueue(void) return minor(sb.st_dev); } +static unsigned long get_minor_for_pidfs(void) +{ + int fd = pidfd_open(getpid(), 0); + struct stat sb; + unsigned long ret = 0; + + if (fd < 0) + return 0; + + if (fstat(fd, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFREG) + ret = minor(sb.st_dev); + + close(fd); + return ret; +} + static void file_class_initialize(void) { unsigned long m; @@ -510,6 +528,10 @@ static void file_class_initialize(void) m = get_minor_for_mqueue(); if (m) add_nodev(m, "mqueue"); + + m = get_minor_for_pidfs(); + if (m) + add_nodev(m, "pidfs"); } static void file_class_finalize(void) @@ -783,3 +805,77 @@ const struct file_class mqueue_file_class = { .fill_column = mqueue_file_fill_column, .get_ipc_class = mqueue_file_get_ipc_class, }; + +struct pidfs_file { + struct file file; + struct pidfd_data data; +}; + +static void init_pidfs_file_content(struct file *file) +{ + struct pidfs_file *pidfs_file = (struct pidfs_file *)file; + + memset(&pidfs_file->data, 0, sizeof(pidfs_file->data)); +} + +static int pidfs_file_handle_fdinfo(struct file *file, const char *key, const char *value) +{ + struct pidfs_file *pidfs_file = (struct pidfs_file *)file; + + return pidfd_handle_fdinfo(&pidfs_file->data, key, value); +} + +static void pidfs_file_free_content(struct file *file) +{ + struct pidfs_file *pidfs_file = (struct pidfs_file *)file; + + pidfd_free(&pidfs_file->data); +} + +static bool pidfs_file_fill_column(struct proc *proc __attribute__((__unused__)), + struct file *file, + struct libscols_line *ln, + int column_id, + size_t column_index) +{ + struct pidfs_file *pidfs_file = (struct pidfs_file *)file; + char *buf = NULL; + + switch(column_id) { + case COL_TYPE: + if (scols_line_set_data(ln, column_index, "pidfd")) + err(EXIT_FAILURE, _("failed to add output data")); + return true; + case COL_NAME: + buf = pidfd_get_name(&pidfs_file->data); + break; + default: + if (!pidfd_fill_column(&pidfs_file->data, column_id, &buf)) + return false; + } + + if (buf && + scols_line_refer_data(ln, column_index, buf)) + err(EXIT_FAILURE, _("failed to add output data")); + + return true; +} + +const struct file_class pidfs_file_class = { + .super = &file_class, + .size = sizeof(struct pidfs_file), + .initialize_content = init_pidfs_file_content, + .handle_fdinfo = pidfs_file_handle_fdinfo, + .fill_column = pidfs_file_fill_column, + .free_content = pidfs_file_free_content, +}; + +bool is_pidfs_dev(dev_t dev) +{ + const char *fs = get_nodev_filesystem(minor(dev)); + + if (fs && (strcmp (fs, "pidfs") == 0)) + return true; + + return false; +} diff --git a/misc-utils/lsfd.c b/misc-utils/lsfd.c index 98820ee8..01e88d51 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -683,6 +683,9 @@ static const struct file_class *stat2class(struct stat *sb) if (is_mqueue_dev(dev)) return &mqueue_file_class; + if (is_pidfs_dev(dev)) + return &pidfs_file_class; + return &file_class; default: break; diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index e646758c..f0f17d5b 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -228,7 +228,7 @@ struct file_class { }; extern const struct file_class file_class, cdev_class, bdev_class, sock_class, unkn_class, fifo_class, - nsfs_file_class, mqueue_file_class; + nsfs_file_class, mqueue_file_class, pidfs_file_class; /* * IPC @@ -307,4 +307,9 @@ bool is_mqueue_dev(dev_t dev); */ bool is_multiplexed_by_eventpoll(int fd, struct list_head *eventpolls); +/* + * Pidfs + */ +bool is_pidfs_dev(dev_t dev); + #endif /* UTIL_LINUX_LSFD_H */ -- 2.45.0