linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Pasha Tatashin <pasha.tatashin@soleen.com>
To: luca.boccassi@gmail.com
Cc: kexec@lists.infradead.org, linux-mm@kvack.org, graf@amazon.com,
	 rppt@kernel.org, pratyush@kernel.org, brauner@kernel.org,
	 linux-kernel@vger.kernel.org, pasha.tatashin@soleen.com
Subject: Re: [PATCH v3] liveupdate: add LUO_SESSION_MAGIC magic inode type
Date: Fri, 17 Apr 2026 20:53:28 +0000	[thread overview]
Message-ID: <547dc4f7xmafywo7jfeuordj5uwaq5lq4zfdupvswxy5yn5osj@v67ia535jnfw> (raw)
In-Reply-To: <20260417204039.1827319-1-luca.boccassi@gmail.com>

On 04-17 21:40, luca.boccassi@gmail.com wrote:
> From: Luca Boccassi <luca.boccassi@gmail.com>
> 
> In userspace when managing LUO sessions we want to be able to identify
> a FD as a LUO session, in order to be able to do the special handling
> that they require in order to function as intended on kexec.
> 
> Currently this requires scraping procfs and doing string matching on
> the prefix of the dname, which is not an ideal interface.
> 
> Add a singleton inode type with a magic value, so that we can
> programmatically identify a fd as a LUO session via fstat().
> 
> Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
> ---
> This was requested by Lennart and Christian when discussing integration
> with systemd for LUO management.
> 
> v2: apply one fix from bot review about cleanup on error path:
>     https://sashiko.dev/#/patchset/20260415184536.1155220-1-luca.boccassi%40gmail.com
>     the other comments are invalid: luo is not a kmod, and the write hooks are not set up
> v3: add test case to liveupdate selftest

This should be split into two patches, also please CC:
linux-kernel@vger.kernel.org

> 
>  include/uapi/linux/magic.h                    |  1 +
>  kernel/liveupdate/luo_core.c                  | 10 ++-
>  kernel/liveupdate/luo_internal.h              |  2 +
>  kernel/liveupdate/luo_session.c               | 73 +++++++++++++++++--
>  .../testing/selftests/liveupdate/liveupdate.c | 40 ++++++++++
>  5 files changed, 120 insertions(+), 6 deletions(-)
> 
> diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
> index 4f2da935a76cc..4f51005522ffe 100644
> --- a/include/uapi/linux/magic.h
> +++ b/include/uapi/linux/magic.h
> @@ -105,5 +105,6 @@
>  #define PID_FS_MAGIC		0x50494446	/* "PIDF" */
>  #define GUEST_MEMFD_MAGIC	0x474d454d	/* "GMEM" */
>  #define NULL_FS_MAGIC		0x4E554C4C	/* "NULL" */
> +#define LUO_SESSION_MAGIC	0x4c554f53	/* "LUOS" */
>  
>  #endif /* __LINUX_MAGIC_H__ */
> diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
> index dda7bb57d421c..f1a63ebe4fa44 100644
> --- a/kernel/liveupdate/luo_core.c
> +++ b/kernel/liveupdate/luo_core.c
> @@ -197,9 +197,17 @@ static int __init luo_late_startup(void)
>  	if (!liveupdate_enabled())
>  		return 0;
>  
> +	err = luo_session_fs_init();
> +	if (err) {
> +		luo_global.enabled = false;
> +		return err;
> +	}
> +
>  	err = luo_fdt_setup();
> -	if (err)
> +	if (err) {
> +		luo_session_fs_cleanup();
>  		luo_global.enabled = false;
> +	}
>  
>  	return err;
>  }
> diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
> index 8083d8739b093..d4ac7b4c58829 100644
> --- a/kernel/liveupdate/luo_internal.h
> +++ b/kernel/liveupdate/luo_internal.h
> @@ -79,6 +79,8 @@ struct luo_session {
>  
>  int luo_session_create(const char *name, struct file **filep);
>  int luo_session_retrieve(const char *name, struct file **filep);
> +int __init luo_session_fs_init(void);
> +void __init luo_session_fs_cleanup(void);
>  int __init luo_session_setup_outgoing(void *fdt);
>  int __init luo_session_setup_incoming(void *fdt);
>  int luo_session_serialize(void);
> diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
> index af9e498206d24..f30151c37bd43 100644
> --- a/kernel/liveupdate/luo_session.c
> +++ b/kernel/liveupdate/luo_session.c
> @@ -50,7 +50,6 @@
>  
>  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>  
> -#include <linux/anon_inodes.h>
>  #include <linux/cleanup.h>
>  #include <linux/err.h>
>  #include <linux/errno.h>
> @@ -62,7 +61,10 @@
>  #include <linux/libfdt.h>
>  #include <linux/list.h>
>  #include <linux/liveupdate.h>
> +#include <linux/magic.h>
> +#include <linux/mount.h>
>  #include <linux/mutex.h>
> +#include <linux/pseudo_fs.h>
>  #include <linux/rwsem.h>
>  #include <linux/slab.h>
>  #include <linux/unaligned.h>
> @@ -376,18 +378,58 @@ static const struct file_operations luo_session_fops = {
>  	.unlocked_ioctl = luo_session_ioctl,
>  };
>  
> +static struct vfsmount *luo_session_mnt __ro_after_init;
> +static struct inode *luo_session_inode __ro_after_init;
> +
> +static char *luo_session_dname(struct dentry *dentry, char *buffer, int buflen)
> +{
> +	return dynamic_dname(buffer, buflen, "luo_session:%s",
> +			     dentry->d_name.name);
> +}
> +
> +static const struct dentry_operations luo_session_dentry_operations = {
> +	.d_dname	= luo_session_dname,
> +};
> +
> +static int luo_session_init_fs_context(struct fs_context *fc)
> +{
> +	struct pseudo_fs_context *ctx;
> +
> +	ctx = init_pseudo(fc, LUO_SESSION_MAGIC);
> +	if (!ctx)
> +		return -ENOMEM;
> +
> +	fc->s_iflags |= SB_I_NOEXEC;
> +	fc->s_iflags |= SB_I_NODEV;
> +	ctx->dops = &luo_session_dentry_operations;
> +	return 0;
> +}
> +
> +static struct file_system_type luo_session_fs_type = {
> +	.name = "luo_session",
> +	.init_fs_context = luo_session_init_fs_context,
> +	.kill_sb = kill_anon_super,
> +};
> +
>  /* Create a "struct file" for session */
>  static int luo_session_getfile(struct luo_session *session, struct file **filep)
>  {
> -	char name_buf[128];
> +	char name_buf[LIVEUPDATE_SESSION_NAME_LENGTH + 1];
>  	struct file *file;
>  
>  	lockdep_assert_held(&session->mutex);
> -	snprintf(name_buf, sizeof(name_buf), "[luo_session] %s", session->name);
> -	file = anon_inode_getfile(name_buf, &luo_session_fops, session, O_RDWR);
> -	if (IS_ERR(file))
> +
> +	ihold(luo_session_inode);
> +
> +	snprintf(name_buf, sizeof(name_buf), "%s", session->name);
> +	file = alloc_file_pseudo(luo_session_inode, luo_session_mnt, name_buf,
> +				 O_RDWR, &luo_session_fops);
> +	if (IS_ERR(file)) {
> +		iput(luo_session_inode);
>  		return PTR_ERR(file);
> +	}
>  
> +	file->private_data = session;
>  	*filep = file;
>  
>  	return 0;
> @@ -662,3 +704,24 @@ void luo_session_resume(void)
>  	up_write(&luo_session_global.outgoing.rwsem);
>  	up_write(&luo_session_global.incoming.rwsem);
>  }
> +
> +int __init luo_session_fs_init(void)
> +{
> +	luo_session_mnt = kern_mount(&luo_session_fs_type);
> +	if (IS_ERR(luo_session_mnt))
> +		return PTR_ERR(luo_session_mnt);
> +
> +	luo_session_inode = alloc_anon_inode(luo_session_mnt->mnt_sb);
> +	if (IS_ERR(luo_session_inode)) {
> +		kern_unmount(luo_session_mnt);
> +		return PTR_ERR(luo_session_inode);
> +	}
> +
> +	return 0;
> +}
> +
> +void __init luo_session_fs_cleanup(void)
> +{
> +	iput(luo_session_inode);
> +	kern_unmount(luo_session_mnt);
> +}
> diff --git a/tools/testing/selftests/liveupdate/liveupdate.c b/tools/testing/selftests/liveupdate/liveupdate.c
> index bdc1cedc4f944..27b3cbff6c739 100644
> --- a/tools/testing/selftests/liveupdate/liveupdate.c
> +++ b/tools/testing/selftests/liveupdate/liveupdate.c
> @@ -22,9 +22,12 @@
>  #include <fcntl.h>
>  #include <string.h>
>  #include <sys/ioctl.h>
> +#include <sys/stat.h>
> +#include <sys/vfs.h>
>  #include <unistd.h>
>  
>  #include <linux/liveupdate.h>
> +#include <linux/magic.h>
>  
>  #include "../kselftest.h"
>  #include "../kselftest_harness.h"
> @@ -416,4 +419,41 @@ TEST_F(liveupdate_device, get_session_name_max_length)
>  	ASSERT_EQ(close(session_fd), 0);
>  }
>  
> +/*
> + * Test Case: Session fstat
> + *
> + * Verifies that fstatfs() on a session file descriptor reports the
> + * LUO_SESSION_MAGIC filesystem type, and that fstat() returns consistent
> + * inode numbers across different sessions (shared singleton inode).
> + */
> +TEST_F(liveupdate_device, session_fstat)
> +{
> +	int session_fd1, session_fd2;
> +	struct statfs sfs;
> +	struct stat st1, st2;

Reverse-christmast-tree order please.

> +
> +	self->fd1 = open(LIVEUPDATE_DEV, O_RDWR);
> +	if (self->fd1 < 0 && errno == ENOENT)
> +		SKIP(return, "%s does not exist", LIVEUPDATE_DEV);
> +	ASSERT_GE(self->fd1, 0);
> +
> +	session_fd1 = create_session(self->fd1, "fstat-session-1");
> +	ASSERT_GE(session_fd1, 0);
> +
> +	session_fd2 = create_session(self->fd1, "fstat-session-2");
> +	ASSERT_GE(session_fd2, 0);
> +
> +	/* Verify the filesystem type is LUO_SESSION_MAGIC */
> +	ASSERT_EQ(fstatfs(session_fd1, &sfs), 0);
> +	EXPECT_EQ(sfs.f_type, LUO_SESSION_MAGIC);
> +
> +	/* Verify both sessions share the same inode number */
> +	ASSERT_EQ(fstat(session_fd1, &st1), 0);
> +	ASSERT_EQ(fstat(session_fd2, &st2), 0);
> +	EXPECT_EQ(st1.st_ino, st2.st_ino);
> +
> +	ASSERT_EQ(close(session_fd1), 0);
> +	ASSERT_EQ(close(session_fd2), 0);
> +}
> +
>  TEST_HARNESS_MAIN
> -- 
> 2.47.3
> 


  reply	other threads:[~2026-04-17 20:53 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-17 20:40 luca.boccassi
2026-04-17 20:53 ` Pasha Tatashin [this message]
2026-04-17 20:59   ` Luca Boccassi

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=547dc4f7xmafywo7jfeuordj5uwaq5lq4zfdupvswxy5yn5osj@v67ia535jnfw \
    --to=pasha.tatashin@soleen.com \
    --cc=brauner@kernel.org \
    --cc=graf@amazon.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luca.boccassi@gmail.com \
    --cc=pratyush@kernel.org \
    --cc=rppt@kernel.org \
    /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