diff options
author | Xi Ruoyao <xry111@xry111.site> | 2024-04-03 15:46:57 +0800 |
---|---|---|
committer | Xi Ruoyao <xry111@xry111.site> | 2024-04-03 17:28:37 +0800 |
commit | b1a48efd173c7f37d8df39a84eb25b4440335661 (patch) | |
tree | f48f72bf9eaa19cc1ca437bdb8ce4155b005354c | |
parent | bf6645dc1edef09ad378cc5b9eb2c93861408735 (diff) | |
download | util-linux-b1a48efd173c7f37d8df39a84eb25b4440335661.tar.gz |
lsfd: Support pidfs
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 <xry111@xry111.site>
-rw-r--r-- | misc-utils/lsfd-file.c | 96 | ||||
-rw-r--r-- | misc-utils/lsfd.c | 3 | ||||
-rw-r--r-- | misc-utils/lsfd.h | 7 |
3 files changed, 105 insertions, 1 deletions
diff --git a/misc-utils/lsfd-file.c b/misc-utils/lsfd-file.c index 7287a1de83..35eabb3e45 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 size_t pagesize; @@ -653,6 +655,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; @@ -667,6 +685,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"); } const struct file_class file_class = { @@ -935,3 +957,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 d4d2a99bc9..f042f5caaa 100644 --- a/misc-utils/lsfd.c +++ b/misc-utils/lsfd.c @@ -667,6 +667,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 b9a402ad20..217bf45338 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -220,7 +220,7 @@ struct file_class { extern const struct file_class abst_class, readlink_error_class, stat_error_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 @@ -299,4 +299,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 */ |