File 0003-lsfd-Support-pidfs.patch of Package util-linux

From: Xi Ruoyao <xry111@xry111.site>
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 <xry111@xry111.site>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 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

openSUSE Build Service is sponsored by