Linux Input/HID development
 help / color / mirror / Atom feed
From: Christian Brauner <brauner@kernel.org>
To: linux-fsdevel@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	 Jann Horn <jannh@google.com>, Josef Bacik <josef@toxicpanda.com>,
	 Chris Mason <mason@kernel.org>, Jeff Layton <jlayton@kernel.org>,
	 NeilBrown <neil@brown.name>, Eric Dumazet <edumazet@kernel.org>,
	 Thomas Gleixner <tglx@kernel.org>,
	Al Viro <viro@zeniv.linux.org.uk>,
	 Jonathan Corbet <corbet@lwn.net>, Christoph Hellwig <hch@lst.de>,
	 Greg Kroah-Hartman <gregkh@suse.de>,
	 Joel Granados <joel.granados@kernel.org>,
	Kees Cook <kees@kernel.org>,  Jan Kara <jack@suse.cz>,
	Jan Kara <jack@suse.com>,
	 linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org,
	 linux-acpi@vger.kernel.org, linux-kselftest@vger.kernel.org,
	 linux-s390@vger.kernel.org, linux-scsi@vger.kernel.org,
	 linux-um@lists.infradead.org, linux-wireless@vger.kernel.org,
	 linuxppc-dev@lists.ozlabs.org, netdev@vger.kernel.org,
	 ntfs3@lists.linux.dev, platform-driver-x86@vger.kernel.org,
	 coreteam@netfilter.org, kexec@lists.infradead.org,
	 linux-pci@vger.kernel.org, linux-sound@vger.kernel.org,
	 netfilter-devel@vger.kernel.org,
	dri-devel@lists.freedesktop.org,
	 ibm-acpi-devel@lists.sourceforge.net,
	jfs-discussion@lists.sourceforge.net,
	 linux-alpha@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	 linux-cifs@vger.kernel.org, linux-fbdev@vger.kernel.org,
	 linux-hwmon@vger.kernel.org, linux-mm@kvack.org,
	linux-sh@vger.kernel.org,  linux-usb@vger.kernel.org,
	samba-technical@lists.samba.org,  sparclinux@vger.kernel.org,
	linux-m68k@lists.linux-m68k.org,  linux-doc@vger.kernel.org,
	linux-serial@vger.kernel.org,
	 linux-atm-general@lists.sourceforge.net,
	Takashi Iwai <tiwai@suse.de>,
	 linux-input@vger.kernel.org, linux-raid@vger.kernel.org,
	 linux-ext4@vger.kernel.org, linux-modules@vger.kernel.org,
	 linux-debuggers@vger.kernel.org,
	 "Christian Brauner (Amutable)" <brauner@kernel.org>,
	 Chuck Lever <cel@kernel.org>,
	stable@vger.kernel.org
Subject: [PATCH RFC 35/38] proc: sysctl: don't hold the tables while readdir copies to userspace
Date: Mon, 02 Nov 2026 15:21:50 +0100	[thread overview]
Message-ID: <20261102-work-procfs-bugfixes-v1-35-59422ed3e465@kernel.org> (raw)
In-Reply-To: <20261102-work-procfs-bugfixes-v1-0-59422ed3e465@kernel.org>

proc_sys_readdir() holds the directory's table for the whole readdir
and the table of each entry while dir_emit() copies its name to
userspace. Unregistering a table waits until nobody uses it anymore. So
a getdents64() whose buffer faults for as long as it wants keeps
unregister_sysctl_table() waiting, just like a stalled read() does.
Listing /proc/sys/net/ipv6/conf/<dev>/ that way holds up the removal of
the device under RTNL.

So don't take any table into use for a listing. A header counts what
refers to its memory, the inodes made for it, and unregistering doesn't
wait for those. readdir takes one of those references on the entry it
is at instead, which keeps the header around and nothing else. Under
sysctl_lock, where unregistering erases an entry, it finds the entry,
copies its name and mode, follows a link to the entry it stands for and
pins that. Then it looks the dentry up, creates the inode if there is
none, which checks for itself under sysctl_lock that the table is still
registered, and emits the entry with nothing held at all. The next
entry is the first live one after that name, which is where a listing
resumes between calls since "proc: sysctl: resume readdir after the
last name it returned" anyway. kernfs_fop_readdir() and
proc_readdir_de() work the same way, a reference on the entry and the
lock only to find the next one.

While the entry is still registered its node is still in the tree and
the next one is right behind it, like kernfs_dir_next_pos() continues
from the node it holds. Only once it went away, and to resume, is the
next entry found by name. That's one trip through sysctl_lock per entry
like before, and the link entries of /proc/sys/net no longer take two
more. The directory isn't
taken into use either, an entry keeps its directory registered while
it is used and readdir looks at the directory under the lock. So the
dots don't wait for anything, a directory that went away lists them and
then fails with -ENOENT. A seek to an arbitrary position counts the
entries from the start like before, one trip per entry.

Fixes: 77b14db502cb ("[PATCH] sysctl: reimplement the sysctl proc support")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
 fs/proc/proc_sysctl.c | 307 +++++++++++++++++++++++++++-----------------------
 1 file changed, 166 insertions(+), 141 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a1242247f492..0b7a1e487ed6 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -91,6 +91,8 @@ static void drop_sysctl_table(struct ctl_table_header *header);
 static int sysctl_follow_link(struct ctl_table_header **phead,
 	const struct ctl_table **pentry);
 static int insert_links(struct ctl_table_header *head);
+static struct ctl_table_set *lookup_header_set(struct ctl_table_root *root);
+static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir);
 static void put_links(struct ctl_table_header *header);
 
 static void sysctl_print_dir(struct ctl_dir *dir)
@@ -367,86 +369,97 @@ static const struct ctl_table *lookup_entry(struct ctl_table_header **phead,
 	return entry;
 }
 
-static struct ctl_node *first_usable_entry(struct rb_node *node)
-{
-	struct ctl_node *ctl_node;
+/*
+ * What readdir takes along for an entry between the trips through
+ * sysctl_lock: the header pinned, which keeps its memory and nothing else,
+ * the entry, its name and mode. For a link the header and entry are the
+ * ones it stands for in the caller's set.
+ */
+struct sysctl_dirent {
+	struct ctl_table_header *head;
+	const struct ctl_table *table;
+	struct ctl_node *node;		/* the entry's node in the directory, NULL for a link */
+	ino_t ino;
+	unsigned int type;
+	umode_t mode;
+	bool skip;
+	int len;
+	char name[NAME_MAX + 1];
+};
 
-	for (;node; node = rb_next(node)) {
-		ctl_node = rb_entry(node, struct ctl_node, node);
-		if (use_table(ctl_node->header))
-			return ctl_node;
-	}
-	return NULL;
+/* A reference on the memory of @head, like an inode made for it holds. */
+static void sysctl_pin(struct ctl_table_header *head)
+{
+	lockdep_assert_held(&sysctl_lock);
+	head->count++;
 }
 
-static void first_entry(struct ctl_dir *dir,
-	struct ctl_table_header **phead, const struct ctl_table **pentry)
+static void sysctl_unpin(struct ctl_table_header *head)
 {
-	struct ctl_table_header *head = NULL;
-	const struct ctl_table *entry = NULL;
-	struct ctl_node *ctl_node;
-
-	spin_lock(&sysctl_lock);
-	ctl_node = first_usable_entry(rb_first(&dir->root));
-	spin_unlock(&sysctl_lock);
-	if (ctl_node) {
-		head = ctl_node->header;
-		entry = &head->ctl_table[ctl_node - head->node];
-	}
-	*phead = head;
-	*pentry = entry;
+	lockdep_assert_held(&sysctl_lock);
+	if (!--head->count)
+		kfree_rcu(head, rcu);
 }
 
-static void next_entry(struct ctl_table_header **phead, const struct ctl_table **pentry)
+/* the first entry from @node on whose table isn't being unregistered */
+static struct ctl_node *first_live_entry(struct rb_node *node)
 {
-	struct ctl_table_header *head = *phead;
-	const struct ctl_table *entry = *pentry;
-	struct ctl_node *ctl_node = &head->node[entry - head->ctl_table];
-
-	spin_lock(&sysctl_lock);
-	unuse_table(head);
+	struct ctl_node *ctl_node;
 
-	ctl_node = first_usable_entry(rb_next(&ctl_node->node));
-	spin_unlock(&sysctl_lock);
-	head = NULL;
-	if (ctl_node) {
-		head = ctl_node->header;
-		entry = &head->ctl_table[ctl_node - head->node];
+	lockdep_assert_held(&sysctl_lock);
+	for (; node; node = rb_next(node)) {
+		ctl_node = rb_entry(node, struct ctl_node, node);
+		if (!ctl_node->header->unregistering)
+			return ctl_node;
 	}
-	*phead = head;
-	*pentry = entry;
+	return NULL;
 }
 
 /*
- * The first usable entry of @dir after @name, or the first one at all for a
- * NULL @name. The entries are sorted by name, so that is where a listing
- * resumes when entries in front of it came or went in between. -ENOENT if
- * the directory is being unregistered.
+ * Fill @d with the entry of @dir behind the one it holds, letting go of that
+ * one, or with the first live entry after @name, or the first one at all for
+ * a NULL @name. While the entry @d holds is still registered its node is
+ * still in the tree and the next one is right behind it. Once it is gone the
+ * entries are found by name, they are sorted by it, so that is also where a
+ * listing resumes when entries in front of it came or went in between.
+ * 1 with the next entry pinned in @d, 0 at the end of the directory and
+ * -ENOENT once @dir itself is being unregistered.
+ *
+ * Everything that reads the tables happens under sysctl_lock, where an entry
+ * is erased when it is unregistered, since nothing holds the tables in use.
  */
-static int entry_after(struct ctl_dir *dir, const char *name, int namelen,
-		       struct ctl_table_header **phead,
-		       const struct ctl_table **pentry)
+static int sysctl_dir_next(struct ctl_dir *dir, struct sysctl_dirent *d,
+			   const char *name, int namelen)
 {
-	struct ctl_table_header *head = NULL;
-	const struct ctl_table *entry = NULL;
 	struct rb_node *node, *after = NULL;
+	struct ctl_table_header *head;
+	const struct ctl_table *entry;
 	struct ctl_node *ctl_node;
+	bool by_name = true;
+	int ret = 0;
 
 	spin_lock(&sysctl_lock);
+	if (d->head) {
+		if (d->node && !d->head->unregistering) {
+			after = rb_next(&d->node->node);
+			by_name = false;
+		}
+		sysctl_unpin(d->head);
+		d->head = NULL;
+	}
 	if (unlikely(dir->header.unregistering)) {
-		spin_unlock(&sysctl_lock);
-		return -ENOENT;
+		ret = -ENOENT;
+		goto out;
 	}
-	if (!name) {
+	if (!by_name) {
+		/* behind the entry @d held */
+	} else if (!name) {
 		after = rb_first(&dir->root);
 	} else for (node = dir->root.rb_node; node;) {
-		const struct ctl_table *table;
-		struct ctl_table_header *h;
-
 		ctl_node = rb_entry(node, struct ctl_node, node);
-		h = ctl_node->header;
-		table = &h->ctl_table[ctl_node - h->node];
-		if (namecmp(table->procname, strlen(table->procname),
+		head = ctl_node->header;
+		entry = &head->ctl_table[ctl_node - head->node];
+		if (namecmp(entry->procname, strlen(entry->procname),
 			    name, namelen) > 0) {
 			after = node;
 			node = node->rb_left;
@@ -454,15 +467,56 @@ static int entry_after(struct ctl_dir *dir, const char *name, int namelen,
 			node = node->rb_right;
 		}
 	}
-	ctl_node = first_usable_entry(after);
-	spin_unlock(&sysctl_lock);
-	if (ctl_node) {
-		head = ctl_node->header;
-		entry = &head->ctl_table[ctl_node - head->node];
+	ctl_node = first_live_entry(after);
+	if (!ctl_node)
+		goto out;
+	head = ctl_node->header;
+	entry = &head->ctl_table[ctl_node - head->node];
+
+	d->len = strlen(entry->procname);
+	if (d->len > NAME_MAX) {
+		ret = -ENAMETOOLONG;
+		goto out;
 	}
-	*phead = head;
-	*pentry = entry;
-	return 0;
+	memcpy(d->name, entry->procname, d->len);
+	d->mode = entry->mode;
+	d->skip = false;
+	d->node = ctl_node;
+	if (unlikely(S_ISLNK(entry->mode))) {
+		/* the entry it stands for in the caller's set, or nothing */
+		struct ctl_table_root *root = entry->data;
+		struct ctl_table_set *set = lookup_header_set(root);
+		struct ctl_dir *xdir = xlate_dir(set, head->parent);
+		struct ctl_table_header *xhead = NULL;
+		const struct ctl_table *xentry = NULL;
+
+		if (!IS_ERR(xdir))
+			xentry = find_entry(&xhead, xdir, d->name, d->len);
+		if (!xentry || xhead->unregistering) {
+			d->skip = true;
+		} else {
+			head = xhead;
+			entry = xentry;
+		}
+		d->node = NULL;
+	}
+	sysctl_pin(head);
+	d->head = head;
+	d->table = entry;
+	ret = 1;
+out:
+	spin_unlock(&sysctl_lock);
+	return ret;
+}
+
+static void sysctl_dir_done(struct sysctl_dirent *d)
+{
+	if (!d->head)
+		return;
+	spin_lock(&sysctl_lock);
+	sysctl_unpin(d->head);
+	spin_unlock(&sysctl_lock);
+	d->head = NULL;
 }
 
 /*
@@ -765,29 +819,29 @@ static void sysctl_cursor_set(struct file *file, const char *name, int len,
 	memcpy(cursor->name, name, len);
 }
 
-static bool proc_sys_fill_cache(struct file *file,
-				struct dir_context *ctx,
-				struct ctl_table_header *head,
-				const struct ctl_table *table)
+/*
+ * The inode number and type of the entry @d holds, instantiating its dentry
+ * if there is none. Needs the header pinned, proc_sys_make_inode() checks
+ * for itself that the table is still registered.
+ */
+static int proc_sys_fill_dirent(struct file *file, struct sysctl_dirent *d)
 {
 	struct dentry *child, *dir = file->f_path.dentry;
 	struct inode *inode;
 	struct qstr qname;
-	ino_t ino = 0;
-	unsigned type = DT_UNKNOWN;
 
-	qname.name = table->procname;
-	qname.len  = strlen(table->procname);
+	qname.name = d->name;
+	qname.len  = d->len;
 	qname.hash = full_name_hash(dir, qname.name, qname.len);
 
 	child = d_lookup(dir, &qname);
 	if (!child) {
 		child = d_alloc_parallel(dir, &qname);
 		if (IS_ERR(child))
-			return false;
+			return PTR_ERR(child);
 		if (d_in_lookup(child)) {
 			struct dentry *res;
-			inode = proc_sys_make_inode(dir->d_sb, head, table);
+			inode = proc_sys_make_inode(dir->d_sb, d->head, d->table);
 			res = d_splice_alias_ops(inode, child,
 						 &proc_sys_dentry_operations);
 			d_lookup_done(child);
@@ -795,79 +849,41 @@ static bool proc_sys_fill_cache(struct file *file,
 				dput(child);
 
 				if (IS_ERR(res))
-					return false;
+					return PTR_ERR(res);
 
 				child = res;
 			}
 		}
 	}
 	inode = d_inode(child);
-	ino  = inode->i_ino;
-	type = inode->i_mode >> 12;
+	d->ino = inode->i_ino;
+	d->type = inode->i_mode >> 12;
 	dput(child);
-	return dir_emit(ctx, qname.name, qname.len, ino, type);
-}
-
-static bool proc_sys_link_fill_cache(struct file *file,
-				    struct dir_context *ctx,
-				    struct ctl_table_header *head,
-				    const struct ctl_table *table)
-{
-	bool ret = true;
-
-	head = sysctl_head_grab(head);
-	if (IS_ERR(head))
-		return false;
-
-	/* It is not an error if we can not follow the link ignore it */
-	if (sysctl_follow_link(&head, &table))
-		goto out;
-
-	ret = proc_sys_fill_cache(file, ctx, head, table);
-out:
-	sysctl_head_finish(head);
-	return ret;
-}
-
-static int scan(struct ctl_table_header *head, const struct ctl_table *table,
-		unsigned long *pos, struct file *file,
-		struct dir_context *ctx)
-{
-	bool res;
-
-	if ((*pos)++ < ctx->pos)
-		return true;
-
-	if (unlikely(S_ISLNK(table->mode)))
-		res = proc_sys_link_fill_cache(file, ctx, head, table);
-	else
-		res = proc_sys_fill_cache(file, ctx, head, table);
-
-	if (res) {
-		ctx->pos = *pos;
-		sysctl_cursor_set(file, table->procname, strlen(table->procname),
-				  ctx->pos);
-	}
-
-	return res;
+	return 0;
 }
 
+/*
+ * Unregistering a table waits until nobody uses it anymore and a copy to
+ * userspace can take as long as userspace wants. So a listing doesn't take
+ * any table into use. It pins the memory of the entry it is at, finds the
+ * next one under sysctl_lock and emits with nothing held, like
+ * kernfs_fop_readdir() and proc_readdir_de() do. Between calls a listing
+ * resumes after the name of the last entry it emitted.
+ */
 static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
 {
-	struct ctl_table_header *head = grab_header(file_inode(file));
+	struct ctl_table_header *head = PROC_I(file_inode(file))->sysctl;
 	struct sysctl_cursor *cursor = file->private_data;
-	struct ctl_table_header *h = NULL;
-	const struct ctl_table *entry;
+	struct sysctl_dirent d = {};
 	struct ctl_dir *ctl_dir;
-	unsigned long pos;
-
-	if (IS_ERR(head))
-		return PTR_ERR(head);
+	int err;
 
+	if (!head)
+		head = &sysctl_table_root.default_set.dir.header;
 	ctl_dir = container_of(head, struct ctl_dir, header);
 
 	if (!dir_emit_dots(file, ctx))
-		goto out;
+		return 0;
 
 	/*
 	 * Resume after the last entry the previous call emitted. Only a seek
@@ -875,21 +891,30 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
 	 * seeking to an arbitrary position always did.
 	 */
 	if (cursor && cursor->pos == ctx->pos) {
-		entry_after(ctl_dir, cursor->name, cursor->len, &h, &entry);
-		pos = ctx->pos;
+		err = sysctl_dir_next(ctl_dir, &d, cursor->name, cursor->len);
 	} else {
-		first_entry(ctl_dir, &h, &entry);
-		pos = 2;
+		loff_t pos = 2;
+
+		err = sysctl_dir_next(ctl_dir, &d, NULL, 0);
+		while (err > 0 && pos++ < ctx->pos)
+			err = sysctl_dir_next(ctl_dir, &d, d.name, d.len);
 	}
+	if (err < 0)
+		return err;
 
-	for (; h; next_entry(&h, &entry)) {
-		if (!scan(h, entry, &pos, file, ctx)) {
-			sysctl_head_finish(h);
-			break;
+	while (err > 0) {
+		if (!d.skip) {
+			err = proc_sys_fill_dirent(file, &d);
+			if (err)
+				break;
+			if (!dir_emit(ctx, d.name, d.len, d.ino, d.type))
+				break;
 		}
+		ctx->pos++;
+		sysctl_cursor_set(file, d.name, d.len, ctx->pos);
+		err = sysctl_dir_next(ctl_dir, &d, d.name, d.len);
 	}
-out:
-	sysctl_head_finish(head);
+	sysctl_dir_done(&d);
 	return 0;
 }
 

-- 
2.53.0


  parent reply	other threads:[~2026-11-02 14:30 UTC|newest]

Thread overview: 160+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 14:19 [PATCH RFC 0/7] proc: move procfs to what kernfs does Christian Brauner
2026-11-02 14:21 ` [PATCH RFC 00/38] proc: fix a few old bugs in /proc handlers Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 01/38] PCI/proc: don't truncate the position of config space accesses Christian Brauner
2026-11-02 17:58     ` Linus Torvalds
2026-11-02 14:21   ` [PATCH RFC 02/38] PNP: isapnp: don't read past the end of the buffer on a large pread() Christian Brauner
2026-11-02 14:51     ` Rafael J. Wysocki (Intel)
2026-11-02 14:21   ` [PATCH RFC 03/38] netfilter: xt_recent: don't remove the proc entries under a spinlock Christian Brauner
2026-11-02 14:41     ` Florian Westphal
2026-11-02 14:21   ` [PATCH RFC 04/38] s390/dasd: don't look in front of the buffer on an empty write Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 05/38] platform/x86: toshiba_acpi: reject malformed brightness and fan writes Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 06/38] xtensa: simdisk: don't read the file name without the lock Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 07/38] powerpc/rtas_flash: don't read past the validate message Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 08/38] powerpc/rtasd: zero the error log buffer Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 09/38] ALSA: info: don't write past the end of a data entry Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 10/38] scsi: BusLogic: don't return 0 from writes to the proc file Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 11/38] scsi: ips: " Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 12/38] wifi: libipw: don't return 0 from writes to debug_level Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 13/38] scsi: core: NUL-terminate what is written to the host proc files Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 14/38] um: NUL-terminate what is written to /proc/exitcode Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 15/38] ntfs3: don't warn when a huge label is written Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 16/38] proc: don't walk through a non-directory when resolving a name Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 17/38] net: pktgen: reject device names with a '/' Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 18/38] proc: don't WARN about a name that is already registered Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 19/38] proc: resume readdir after the last name it returned Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 20/38] selftests/proc: check a /proc listing while entries come and go Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 21/38] proc: let proc_remove() remove the entry it was given Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 22/38] proc: warn about entries left in /proc/net of a dying namespace Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 23/38] proc: don't let NOMMU map procfs files Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 24/38] proc/vmcore: don't let vmcore_cleanup() run twice at once Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 25/38] powerpc/crash_dump: check ioremap_cache() in copy_oldmem_page() Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 26/38] powerpc/crash_dump: recover from a machine check " Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 27/38] sunrpc: make queue_wait a global wait queue again Christian Brauner
2026-11-02 15:12     ` Chuck Lever
2026-11-02 14:21   ` [PATCH RFC 28/38] scsi: esas2r: bound the lengths of the HBA, SMP and firmware ioctls Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 29/38] powerpc/pseries: bound the lengths in the ofdt property parser Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 30/38] powerpc/pseries/lparcfg: return h_get_ppp()'s status as a long Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 31/38] proc: sysctl: resume readdir after the last name it returned Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 32/38] selftests/proc: check a sysctl listing while entries come and go Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 33/38] proc: sysctl: copy to and from userspace without holding the table Christian Brauner
2026-11-02 14:21   ` [PATCH RFC 34/38] proc: sysctl: look at the table under sysctl_lock when creating an inode Christian Brauner
2026-11-02 14:21   ` Christian Brauner [this message]
2026-11-02 14:43   ` [PATCH RFC 36/38] selftests/proc: check that faulting sysctl accesses don't hold up removal Christian Brauner
2026-11-02 14:43   ` [PATCH RFC 37/38] proc: don't pin a symlink's entry while readlink() copies it out Christian Brauner
2026-11-02 14:43   ` [PATCH RFC 38/38] selftests/proc: check that a faulting readlink() doesn't hold up removal Christian Brauner
2026-11-02 14:48 ` [PATCH RFC 00/16] proc: let procfs own the data path Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 01/16] proc: drop the compat file operations Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 02/16] proc: add pde_pin() and pde_unpin() Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 03/16] proc: make room for more entry flags Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 04/16] proc: let procfs own the seq_file of seq_file entries Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 05/16] proc: let procfs own the seq_file of proc_create_seq() and friends Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 06/16] proc: let procfs own the seq_file of DEFINE_PROC_SHOW_ATTRIBUTE() files Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 07/16] treewide: let procfs own the seq_file of simple proc entries Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 08/16] selftests/proc: check that a faulting reader doesn't hold up removal Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 09/16] seq_file: add seq_preallocate() Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 10/16] proc: let procfs own the seq_file of /proc/stat Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 11/16] proc: let procfs copy in writes before pinning the entry Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 12/16] proc: copy in writes to the network namespace entries before pinning Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 13/16] proc: let procfs copy out reads that don't go through seq_file Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 14/16] fs/proc/vmcore: let procfs copy out reads Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 15/16] proc: let procfs copy ioctl arguments in and out Christian Brauner
2026-11-02 14:48   ` [PATCH RFC 16/16] Documentation: seq_file: describe how a /proc file uses seq_file Christian Brauner
2026-11-02 15:01 ` [PATCH RFC 00/22] proc: convert the arch and platform entries Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 01/22] alpha: srm_env: let procfs copy in writes Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 02/22] ARM: alignment: " Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 03/22] ARM: atags: let procfs copy out reads of /proc/atags Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 04/22] m68k/bootinfo: let procfs copy out reads of /proc/bootinfo Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 05/22] powerpc/rtas: let procfs copy in writes Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 06/22] powerpc/rtas: let procfs copy out reads Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 07/22] powerpc/pseries: let procfs copy in writes Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 08/22] powerpc/procfs: let procfs copy out reads of /proc/powerpc/systemcfg Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 09/22] sh: alignment: let procfs copy in writes Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 10/22] sparc: led: " Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 11/22] um: " Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 12/22] x86/mtrr: let procfs own the seq_file of /proc/mtrr Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 13/22] x86/mtrr: let procfs copy in writes to /proc/mtrr Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 14/22] x86/mtrr: let procfs copy the ioctl arguments of /proc/mtrr Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 15/22] xtensa: simdisk: let procfs copy in writes Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 16/22] xtensa: simdisk: let procfs copy out reads Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 17/22] ACPI: proc: let procfs copy in writes to /proc/acpi/wakeup Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 18/22] macintosh/via-pmu: let procfs copy in writes to the options file Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 19/22] platform/x86: thinkpad_acpi: let procfs copy in writes Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 20/22] platform/x86: toshiba_acpi: " Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 21/22] PNP: pnpbios: " Christian Brauner
2026-11-02 15:01   ` [PATCH RFC 22/22] PNP: isapnp: let procfs copy out reads Christian Brauner
2026-11-02 15:07 ` [PATCH RFC 00/23] proc: convert the driver entries Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 01/23] nubus: let procfs own the seq_file of the resource files Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 02/23] zorro: let procfs copy out reads Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 03/23] PCI/proc: let procfs copy in config space writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 04/23] PCI/proc: let procfs copy out config space reads Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 05/23] PCI/proc: let procfs handle the ioctls Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 06/23] md: let procfs own the seq_file of /proc/mdstat Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 07/23] s390/dasd: let procfs copy in writes to /proc/dasd/statistics Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 08/23] s390/cio: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 09/23] scsi: let procfs own the seq_file of the host files Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 10/23] scsi: core: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 11/23] selftests/proc: check that a faulting writer doesn't hold up removal Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 12/23] scsi: sg: let procfs own the seq_file of allow_dio and def_reserved_size Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 13/23] scsi: sg: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 14/23] scsi: esas2r: let procfs copy the ioctl argument of the ATTONode file Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 15/23] hwmon: (dell-smm) let procfs copy the i8k ioctl arguments Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 16/23] fbdev: viafb: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 17/23] usb: gadget: function: rndis: " Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 18/23] wifi: ipw2x00: let procfs copy in writes to the debug level Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 19/23] tty: sysrq: let procfs copy in writes to /proc/sysrq-trigger Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 20/23] ALSA: info: let procfs own the seq_file of text entries Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 21/23] ALSA: info: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 22/23] ALSA: info: let procfs copy out reads of data entries Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 23/23] ALSA: info: drop the ioctl hook " Christian Brauner
2026-11-02 15:07 ` [PATCH RFC 00/27] proc: convert the fs, kernel and mm entries Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 01/27] jbd2: let procfs own the seq_file of the info file Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 02/27] jfs: let procfs copy in writes to the loglevel file Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 03/27] lockd: let procfs copy in writes to nlm_end_grace Christian Brauner
2026-11-02 15:23     ` Chuck Lever
2026-11-02 15:07   ` [PATCH RFC 04/27] lockd: let procfs copy out reads of nlm_end_grace Christian Brauner
2026-11-02 15:24     ` Chuck Lever
2026-11-02 15:07   ` [PATCH RFC 05/27] nfsd: factor out setting up the exports seq_file Christian Brauner
2026-11-02 21:14     ` Chuck Lever
2026-11-02 15:07   ` [PATCH RFC 06/27] nfsd: let procfs own the seq_file of /proc/fs/nfs/exports Christian Brauner
2026-11-02 21:14     ` Chuck Lever
2026-11-02 15:07   ` [PATCH RFC 07/27] ntfs3: let procfs copy in writes to the label file Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 08/27] smb: client: let procfs own the seq_file of the smbdirect files Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 09/27] smb: client: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 10/27] genirq/proc: let procfs copy in the affinity masks Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 11/27] latencytop: let procfs copy in writes to /proc/latency_stats Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 12/27] locking/lockdep: let procfs own the seq_file of /proc/lock_stat Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 13/27] locking/lockdep: let procfs copy in writes to /proc/lock_stat Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 14/27] profiling: let procfs copy in writes to /proc/profile Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 15/27] profiling: mark /proc/profile permanent Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 16/27] sched/psi: let procfs own the seq_file of the pressure files Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 17/27] sched/psi: let procfs copy in trigger writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 18/27] sched/psi: mark the pressure files permanent Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 19/27] kallsyms: let procfs own the seq_file of /proc/kallsyms Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 20/27] module: procfs: let procfs own the seq_file of /proc/modules Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 21/27] dyndbg: let procfs copy in writes to /proc/dynamic_debug/control Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 22/27] ipc: let procfs own the seq_file of the sysvipc files Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 23/27] alloc_tag: let procfs own the seq_file of /proc/allocinfo Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 24/27] alloc_tag: let procfs copy the ioctl arguments " Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 25/27] mm/swapfile: let procfs own the seq_file of /proc/swaps Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 26/27] kernel/configs: let procfs copy out reads of /proc/config.gz Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 27/27] selftests/proc: check that unloading configs doesn't wait for a reader Christian Brauner
2026-11-02 15:07 ` [PATCH RFC 00/11] proc: convert the net entries and the kfifo samples Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 01/11] atm: let procfs copy out reads of the device files Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 02/11] l2tp: let procfs own the seq_file of /proc/net/pppol2tp Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 03/11] net: pktgen: let procfs copy in commands Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 04/11] netfilter: xt_recent: let procfs own the seq_file Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 05/11] netfilter: xt_recent: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 06/11] SUNRPC: let procfs own the seq_file of the cache content file Christian Brauner
2026-11-02 21:11     ` Chuck Lever
2026-11-02 15:07   ` [PATCH RFC 07/11] SUNRPC: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 08/11] SUNRPC: let procfs copy out reads Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 09/11] SUNRPC: drop the ioctl of the procfs channel files Christian Brauner
2026-11-02 21:11     ` Chuck Lever
2026-11-02 15:07   ` [PATCH RFC 10/11] samples/kfifo: let procfs copy in writes Christian Brauner
2026-11-02 15:07   ` [PATCH RFC 11/11] samples/kfifo: let procfs copy out reads Christian Brauner
2026-11-02 15:15 ` [PATCH RFC 0/5] proc: drop the __user methods Christian Brauner
2026-11-02 15:15   ` [PATCH RFC 1/5] proc: drop ->proc_write() Christian Brauner
2026-11-02 15:15   ` [PATCH RFC 2/5] proc: drop ->proc_ioctl() and ->proc_compat_ioctl() Christian Brauner
2026-11-02 15:15   ` [PATCH RFC 3/5] proc: only let permanent entries read straight into userspace Christian Brauner
2026-11-02 15:15   ` [PATCH RFC 4/5] proc: rename ->proc_read() and ->proc_read_iter() Christian Brauner
2026-11-02 15:15   ` [PATCH RFC 5/5] proc: drop the _buf suffix from the new methods Christian Brauner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261102-work-procfs-bugfixes-v1-35-59422ed3e465@kernel.org \
    --to=brauner@kernel.org \
    --cc=cel@kernel.org \
    --cc=corbet@lwn.net \
    --cc=coreteam@netfilter.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=edumazet@kernel.org \
    --cc=gregkh@suse.de \
    --cc=hch@lst.de \
    --cc=ibm-acpi-devel@lists.sourceforge.net \
    --cc=jack@suse.com \
    --cc=jack@suse.cz \
    --cc=jannh@google.com \
    --cc=jfs-discussion@lists.sourceforge.net \
    --cc=jlayton@kernel.org \
    --cc=joel.granados@kernel.org \
    --cc=josef@toxicpanda.com \
    --cc=kees@kernel.org \
    --cc=kexec@lists.infradead.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-alpha@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-atm-general@lists.sourceforge.net \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-debuggers@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-m68k@lists.linux-m68k.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=linux-um@lists.infradead.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=mason@kernel.org \
    --cc=neil@brown.name \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=ntfs3@lists.linux.dev \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=samba-technical@lists.samba.org \
    --cc=sparclinux@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tglx@kernel.org \
    --cc=tiwai@suse.de \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox