mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Josef Bacik <josef@toxicpanda.com>
To: Christian Brauner <brauner@kernel.org>,
	 James Bottomley <James.Bottomley@HansenPartnership.com>,
	 Andrew Halaney <andrew@amutable.com>,
	Jeremy Bingham <jbingham@gmail.com>,
	 Tahera Fahimi <taherafahimi@linux.microsoft.com>,
	 Serge Hallyn <sergeh@kernel.org>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH RFC v3 41/90] pidfd: add pidfd_configure()
Date: Thu, 05 Nov 2026 15:02:33 +0000	[thread overview]
Message-ID: <20261105-b4-cells-v3-41-bc9095937a84@toxicpanda.com> (raw)
In-Reply-To: <20261105-b4-cells-v3-0-bc9095937a84@toxicpanda.com>

Add the system call that describes the task of an empty pidfd and starts
it. It is modelled on fsconfig(): it takes a command, a key and a value,
and data only flows into the kernel.

    pidfd = pidfd_open(cellfd, PIDFD_EMPTY);
    pidfd_configure(pidfd, PIDFD_SET_STRING, "exec", "/sbin/init", 0);
    pidfd_configure(pidfd, PIDFD_SET_BINARY, "argv", "init\0-v", 8);
    pidfd_configure(pidfd, PIDFD_CMD_START, NULL, NULL, 0);

This patch adds the keys "exec", "argv" and "envp", and PIDFD_CMD_START.
The start command creates the task, applies the configuration in the
context of the task, lets it exec, and waits for the exec to finish. If
anything fails, PIDFD_CMD_START returns the error, and the task is killed
if it already exists. A pidfd can only be started once.

The task gets default signal dispositions and its own session.
CLONE_CLEAR_SIGHAND would keep signals ignored that the caller ignores, so
the handlers are flushed the way they are for a usermode helper. Nobody
has to wait for the task. It is reaped automatically, and the pidfd
reports how it exited.

The pidfd may be kept open for a long time after the start, so the
configuration is freed as soon as it has been used.

The LSM hooks for exec run in the context of the new task, as for any
exec. Seccomp filters apply to the system calls of the new program. But
the work that the start command does is not a system call of the new task,
so the filters are not consulted for it. A filter that denies execve() to
stop a task from running another program must also deny pidfd_configure(),
just as such filters once had to learn about execveat().

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 include/uapi/linux/pidfd.h |   7 ++
 kernel/embryo.c            | 258 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 265 insertions(+)

diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h
index eb3704687c04..c01bce5e17ad 100644
--- a/include/uapi/linux/pidfd.h
+++ b/include/uapi/linux/pidfd.h
@@ -17,6 +17,13 @@
 #define PIDFD_AUTOKILL O_TRUNC
 #endif
 
+/* pidfd_configure(): @cmd. Data only ever goes in. */
+enum pidfd_configure_cmd {
+	PIDFD_SET_STRING	= 0,	/* Set @key to the string in @value */
+	PIDFD_SET_BINARY	= 1,	/* Set @key to the @aux bytes at @value */
+	PIDFD_SET_FD		= 2,	/* The file to have at number @key, from fd @aux */
+	PIDFD_CMD_START		= 3,	/* Make the task, apply everything and exec */
+};
 /* Flags for pidfd_send_signal(). */
 #define PIDFD_SIGNAL_THREAD		(1UL << 0)
 #define PIDFD_SIGNAL_THREAD_GROUP	(1UL << 1)
diff --git a/kernel/embryo.c b/kernel/embryo.c
index e052c09f9192..f405efb195c7 100644
--- a/kernel/embryo.c
+++ b/kernel/embryo.c
@@ -40,6 +40,10 @@
 #include <net/af_unix.h>
 #include <uapi/linux/pidfd.h>
 
+#define EMBRYO_KEY_MAX		32
+#define EMBRYO_MAX_STRINGS	4096
+#define EMBRYO_MAX_BLOCK	(256 * 1024)
+
 struct embryo_strings {
 	char		*block;		/* NUL terminated strings, back to back */
 	const char	**vec;		/* NULL terminated, points into @block */
@@ -94,6 +98,53 @@ static void embryo_put(struct embryo *e)
 	kfree_rcu(e, rcu);
 }
 
+/* The task is done being an embryo, one way or the other. */
+static void embryo_detach(struct embryo *e)
+{
+	WRITE_ONCE(current->embryo, NULL);
+	embryo_put(e);
+}
+
+static int embryo_exec(struct embryo *e)
+{
+	static const char * const no_strings[] = { NULL };
+	const char *argv0[] = { e->exec, NULL };
+
+	return kernel_execve(e->exec, e->argv.vec ?: argv0,
+			     e->envp.vec ?: no_strings);
+}
+
+static int embryo_main(void *arg)
+{
+	struct embryo *e = arg;
+	int ret;
+
+	/* CLONE_CLEAR_SIGHAND leaves what the starter ignores ignored. */
+	flush_signal_handlers(current, 1);
+
+	/* The starter's session, process group and terminal are not ours. */
+	ksys_setsid();
+	set_personality(PER_LINUX);
+
+	/* @started is set, so nobody changes anything any more. */
+	ret = embryo_exec(e);
+	embryo_drop_config(e);
+	/*
+	 * A signal to the embryo is no signal to whoever started it. Whatever
+	 * interrupted the exec, the embryo is about to be killed.
+	 */
+	if (ret && (fatal_signal_pending(current) || ret <= -ERESTARTSYS))
+		ret = -ESRCH;
+	e->result = ret;
+	complete_all(&e->done);
+	embryo_detach(e);
+	if (ret)
+		do_group_exit(SIGKILL);
+
+	/* Off to user mode. */
+	return 0;
+}
+
 /**
  * embryo_fork_finish - done creating an embryo, one way or the other
  * @args: the arguments of the clone, with @args->embryo set
@@ -242,3 +293,210 @@ void embryo_pidfd_release(struct file *file)
 		free_pid_struct(e->pid);
 	embryo_put(e);
 }
+
+static struct embryo *embryo_from_file(struct file *file)
+{
+	struct pid *pid;
+
+	pid = pidfd_pid(file);
+	if (IS_ERR(pid))
+		return ERR_CAST(pid);
+	/* Only the file pidfd_open() returned will do. Nothing else ever has this. */
+	if (!(file->f_flags & PIDFD_EMPTY))
+		return ERR_PTR(-EPERM);
+	return file->private_data;
+}
+
+static int embryo_set_strings(struct embryo_strings *s, const void __user *ublock,
+			      size_t len)
+{
+	struct embryo_strings new = {};
+	unsigned int nr = 0, i;
+	size_t off;
+
+	if (!len || len > EMBRYO_MAX_BLOCK)
+		return -E2BIG;
+
+	new.block = vmemdup_user(ublock, len);
+	if (IS_ERR(new.block))
+		return PTR_ERR(new.block);
+	if (new.block[len - 1]) {
+		kvfree(new.block);
+		return -EINVAL;
+	}
+
+	for (off = 0; off < len; off += strlen(new.block + off) + 1)
+		nr++;
+	if (nr > EMBRYO_MAX_STRINGS) {
+		kvfree(new.block);
+		return -E2BIG;
+	}
+
+	new.vec = kvmalloc_array(nr + 1, sizeof(*new.vec), GFP_KERNEL_ACCOUNT);
+	if (!new.vec) {
+		kvfree(new.block);
+		return -ENOMEM;
+	}
+	for (off = 0, i = 0; off < len; off += strlen(new.block + off) + 1)
+		new.vec[i++] = new.block + off;
+	new.vec[i] = NULL;
+
+	embryo_strings_free(s);
+	*s = new;
+	return 0;
+}
+
+static int embryo_start(struct embryo *e)
+{
+	struct kernel_clone_args args = {
+		/*
+		 * CLONE_VM only says "do not copy the mm": there is none,
+		 * copy_mm() sees to that. Nobody has to wait for the task, the
+		 * pidfd tells. The rest is what every task of a cell gets.
+		 */
+		.flags		= CLONE_VM | CLONE_UNTRACED | CLONE_AUTOREAP |
+				  CLONE_INTO_CGROUP | CLONE_NNP | CLONE_CLEAR_SIGHAND,
+		.fn		= embryo_main,
+		.fn_arg		= e,
+		.name		= "embryo",
+		.pid		= e->pid,
+		.cell		= e->cell,
+		.embryo		= e,
+	};
+	pid_t nr;
+	int ret;
+
+	/* Until embryo_fork_finish(). */
+	ret = cell_fork_prepare(e->cell);
+	if (ret)
+		return ret;
+
+	scoped_guard(mutex, &e->lock) {
+		ret = e->started ? -EBUSY : e->exec ? 0 : -EINVAL;
+		if (!ret)
+			e->started = true;
+	}
+	if (ret) {
+		cell_fork_finish(e->cell);
+		return ret;
+	}
+
+	/* For the task. */
+	refcount_inc(&e->ref);
+	nr = kernel_clone(&args);
+	/*
+	 * A signal is pending for the caller, so the fork is to be started over
+	 * once that has been seen to, as any fork is. It has not been tried.
+	 */
+	if (nr == -ERESTARTNOINTR) {
+		scoped_guard(mutex, &e->lock)
+			e->started = false;
+		return nr;
+	}
+	if (nr < 0) {
+		scoped_guard(mutex, &e->lock)
+			embryo_drop_config(e);
+		return nr;
+	}
+
+	/*
+	 * Everything up to the point of no return of the exec is reported
+	 * here. Past that it is a fatal signal, for the pidfd to tell.
+	 */
+	if (wait_for_completion_killable(&e->done))
+		return -EINTR;
+	return e->result;
+}
+
+/**
+ * sys_pidfd_configure - say what the task of an empty pidfd is to be, and start it
+ * @pidfd:  what pidfd_open() returned for PIDFD_EMPTY, and no other pidfd
+ * @cmd:    one of enum pidfd_configure_cmd
+ * @ukey:   the name of what is set, or NULL for PIDFD_CMD_START
+ * @uvalue: a string for PIDFD_SET_STRING, @aux bytes for PIDFD_SET_BINARY
+ * @aux:    a length for PIDFD_SET_BINARY, a file descriptor for PIDFD_SET_FD
+ *
+ * Shaped like fsconfig(). Data only goes in.
+ *
+ * PIDFD_CMD_START makes the task, applies everything in its context, has it exec
+ * and waits for that. Whatever goes wrong is returned here, and the task, if it
+ * got that far, is killed. It can be tried only once. Being started over because
+ * a signal is pending for the caller, as a fork is, does not count.
+ *
+ * Return: 0, -EPERM for any other pidfd, -EBUSY once it was started, -ESRCH if
+ * the task or the cell was killed, -EOPNOTSUPP for an unknown @cmd, -EINVAL for
+ * an unknown key or arguments that do not go with @cmd, or what went wrong.
+ */
+SYSCALL_DEFINE5(pidfd_configure, int, pidfd, unsigned int, cmd,
+		const char __user *, ukey, const void __user *, uvalue, int, aux)
+{
+	char *key __free(kfree) = NULL;
+	char *str __free(kfree) = NULL;
+	struct embryo *e;
+	int ret;
+
+	switch (cmd) {
+	case PIDFD_SET_STRING:
+		if (!ukey || !uvalue || aux)
+			return -EINVAL;
+		break;
+	case PIDFD_SET_BINARY:
+		if (!ukey || !uvalue || aux <= 0)
+			return -EINVAL;
+		break;
+	case PIDFD_CMD_START:
+		if (ukey || uvalue || aux)
+			return -EINVAL;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	if (ukey) {
+		key = strndup_user(ukey, EMBRYO_KEY_MAX);
+		if (IS_ERR(key))
+			return PTR_ERR(no_free_ptr(key));
+	}
+	if (cmd == PIDFD_SET_STRING) {
+		str = strndup_user(uvalue, PATH_MAX);
+		if (IS_ERR(str))
+			return PTR_ERR(no_free_ptr(str));
+	}
+
+	CLASS(fd, f)(pidfd);
+	if (fd_empty(f))
+		return -EBADF;
+	e = embryo_from_file(fd_file(f));
+	if (IS_ERR(e))
+		return PTR_ERR(e);
+
+	if (cmd == PIDFD_CMD_START)
+		return embryo_start(e);
+
+	mutex_lock(&e->lock);
+	ret = -EBUSY;
+	if (e->started)
+		goto out;
+
+	switch (cmd) {
+	case PIDFD_SET_STRING:
+		ret = -EINVAL;
+		if (strcmp(key, "exec"))
+			break;
+		kfree(e->exec);
+		e->exec = no_free_ptr(str);
+		ret = 0;
+		break;
+	case PIDFD_SET_BINARY:
+		if (!strcmp(key, "argv"))
+			ret = embryo_set_strings(&e->argv, uvalue, aux);
+		else if (!strcmp(key, "envp"))
+			ret = embryo_set_strings(&e->envp, uvalue, aux);
+		else
+			ret = -EINVAL;
+		break;
+	}
+out:
+	mutex_unlock(&e->lock);
+	return ret;
+}

-- 
2.55.0


  parent reply	other threads:[~2026-11-05 15:15 UTC|newest]

Thread overview: 93+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05 14:56 [PATCH RFC v3 00/90] cells: a container as one kernel object Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 01/90] Documentation: add a design document for cells Josef Bacik
2026-11-05 17:06   ` Serge E. Hallyn
2026-11-05 18:23     ` Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 02/90] Documentation: add examples " Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 03/90] cells: reserve a window of ids Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 04/90] user_namespace: let a cell own a user namespace Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 05/90] user_namespace: refuse setns() into a cell Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 06/90] capability: give the owner no say over " Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 07/90] ucount: count the id blocks a user holds Josef Bacik
2026-11-05 14:56 ` [PATCH RFC v3 08/90] user_namespace: let the kernel map the ids of a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 09/90] user_namespace: keep legacy maps out of the window Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 10/90] user: add uid_range_in_use() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 11/90] keys: add key_user_range_in_use() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 12/90] fs: add kuid_has_fsmapping() and kgid_has_fsmapping() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 13/90] fs: never store an id that was lent to a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 14/90] fs: take no id of a cell for a mount option Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 15/90] fs: let an idmapping pin the ids of a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 16/90] cgroup: let a cgroup become the budget " Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 17/90] cgroup: add cgroup_cell_chown() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 18/90] cgroup: give the budget of a cell back Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 19/90] cgroup: add cgroup_cell_kill() Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 20/90] cgroup: root a cgroup namespace at a given cgroup Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 21/90] fs: seal a mount namespace for a cell Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 22/90] nsfs: make open_namespace() available outside of fs/ Josef Bacik
2026-11-05 14:57 ` [PATCH RFC v3 23/90] nsproxy: build the nsproxy the tasks of a cell share Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 24/90] cells: add the cell object and cell_create() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 25/90] cells: add cell_kill() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 26/90] cells: add cell_configure() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 27/90] cells: add the "budget" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 28/90] cells: add the "root" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 29/90] cells: add the "ids" slot, for a single id Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 30/90] cells: lend a cell a block of ids Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 31/90] cells: reserve the "spawn" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 32/90] cells: add CELL_CMD_SEAL Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 33/90] cells: add cell_open() Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 34/90] pid: allocate a struct pid ahead of its numbers Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 35/90] fork: let copy_process() place a task in a cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 36/90] cgroup: fork a task of a cell into the budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 37/90] x86: give a task without an mm no user state Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 38/90] uprobes: cope with a new task that has no mm Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 39/90] fork: add tasks that start out with nothing Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 40/90] pidfd: add PIDFD_EMPTY Josef Bacik
2026-11-05 15:02 ` Josef Bacik [this message]
2026-11-05 15:02 ` [PATCH RFC v3 42/90] pidfd: let pidfd_configure() place files Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 43/90] pidfd: let pidfd_configure() set credentials Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 44/90] pidfd: let pidfd_configure() name a cgroup to start in Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 45/90] ptrace: keep everybody off an embryo Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 46/90] cells: end a cell when its init exits Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 47/90] cells: refuse a task of a cell a change of namespaces Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 48/90] fs: refuse a task of a cell a new mount namespace Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 49/90] nsproxy: refuse to enter a namespace of a cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 50/90] cgroup: keep a task of a cell within the budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 51/90] cgroup: let nothing but a spawn into a budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 52/90] kernfs: let a filesystem refuse a change to a node Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 53/90] cgroup: let a cell change nothing outside its budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 54/90] cgroup: leave the limits of a budget to who is above Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 55/90] fs: let a filesystem hold ids that go with the cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 56/90] cgroup: let a cell make cgroups below its budget Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 57/90] resctrl: let a cell change nothing Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 58/90] cred: let no id count across cells Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 59/90] ptrace: refuse PTRACE_TRACEME " Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 60/90] keys: ignore an equal uid or gid " Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 61/90] fs: accept a cellfd for MOUNT_ATTR_IDMAP Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 62/90] fs: let a cell set no set-id bits Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 63/90] fs: drop privileges from what a cell may write to Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 64/90] cells: add the "caps" slot Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 65/90] capabilities: take nothing from a file in a cell Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 66/90] capabilities: let a cell shrink its bounding sets Josef Bacik
2026-11-05 15:02 ` [PATCH RFC v3 67/90] af_unix: deliver ancillary data only within a cell Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 68/90] af_unix: tell a sender that control data will not cross Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 69/90] net: do not identify a peer in another cell Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 70/90] seccomp: let a listener put no file into a cell Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 71/90] umh: run no program for a task of " Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 72/90] coredump: let no core dump leave " Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 73/90] cells: add the "net" slot Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 74/90] net: give a cell without a network no sockets Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 75/90] net: add net_may() Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 76/90] rtnetlink: use net_may() for requests that change state Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 77/90] net: use net_may() in the configuration ioctls Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 78/90] netfilter: use net_may() for configuration Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 79/90] tun: use net_may() to create and attach to devices Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 80/90] net: use net_may() for the net sysctls Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 81/90] net: use net_may() for privileged socket options Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 82/90] net: use net_may() for raw and packet sockets Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 83/90] cells: add the "net-rights" slot Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 84/90] net: honour the rights of a cell in net_may() Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 85/90] tun: ignore an equal uid or gid across cells Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 86/90] cells: add cell_info() Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 87/90] cells: add CONFIG_CELLS Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 88/90] arch: wire up the cell system calls Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 89/90] MAINTAINERS: add an entry for cells Josef Bacik
2026-11-05 15:03 ` [PATCH RFC v3 90/90] selftests: add tests " Josef Bacik

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=20261105-b4-cells-v3-41-bc9095937a84@toxicpanda.com \
    --to=josef@toxicpanda.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=andrew@amutable.com \
    --cc=brauner@kernel.org \
    --cc=jbingham@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sergeh@kernel.org \
    --cc=taherafahimi@linux.microsoft.com \
    /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

all inboxes | Powered by JetHome®