Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: Mike Rapoport <rppt@kernel.org>
To: David Matlack <dmatlack@google.com>,
	Luca Boccassi <luca.boccassi@gmail.com>
Cc: kexec@lists.infradead.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Jason Gunthorpe <jgg@nvidia.com>,
	Pasha Tatashin <pasha.tatashin@soleen.com>,
	Pratyush Yadav <pratyush@kernel.org>,
	Samiullah Khawaja <skhawaja@google.com>,
	Shuah Khan <shuah@kernel.org>
Subject: Re: [RFC PATCH] liveupdate: Allow multiple openers for /dev/liveupdate
Date: Thu, 16 Jul 2026 09:06:53 +0300	[thread overview]
Message-ID: <alh0_aCbZITvSaox@kernel.org> (raw)
In-Reply-To: <20260714190356.190328-1-dmatlack@google.com>

(adding Luca for systemd POV)

On Tue, Jul 14, 2026 at 07:03:56PM +0000, David Matlack wrote:
> Remove the single-opener restriction for /dev/liveupdate by removing the
> atomic in_use tracking and the exclusive open check in luo_open() that
> returned -EBUSY. Protect luo_session_deserialize() with a mutex guard so
> that concurrent open attempts by multiple processes safely executes
> deserialization only once. Update liveupdate selftest to verify that
> multiple concurrent openers succeed.
> 
> LUO does not inherently require a single opener. There is some
> documentation about it simplifying state management, but the only thing
> it actually protects is the session deserialization during first open,
> which can be easily handled with a mutex.
> 
> Relaxing the single-opener requirement avoids the kernel forcing a
> design pattern on userspace that it itself does not require, e.g.
> allowing multiple userspace processes to create and manage sessions.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>
> ---
> Cc: Jason Gunthorpe <jgg@nvidia.com>
> Cc: Samiullah Khawaja <skhawaja@google.com>
> 
>  kernel/liveupdate/luo_core.c                  | 46 +++----------------
>  kernel/liveupdate/luo_session.c               |  8 +++-
>  .../testing/selftests/liveupdate/liveupdate.c | 14 +++---
>  3 files changed, 18 insertions(+), 50 deletions(-)
> 
> diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
> index 1b2bda22902d..931bb79da276 100644
> --- a/kernel/liveupdate/luo_core.c
> +++ b/kernel/liveupdate/luo_core.c
> @@ -254,19 +254,8 @@ bool liveupdate_enabled(void)
>   * which allows a userspace agent to manage the LUO state machine and its
>   * associated resources, such as preservable file descriptors.
>   *
> - * To ensure that the state machine is controlled by a single entity, access
> - * to this device is exclusive: only one process is permitted to have
> - * ``/dev/liveupdate`` open at any given time. Subsequent open attempts will
> - * fail with -EBUSY until the first process closes its file descriptor.
> - * This singleton model simplifies state management by preventing conflicting
> - * commands from multiple userspace agents.
>   */
>  
> -struct luo_device_state {
> -	struct miscdevice miscdev;
> -	atomic_t in_use;
> -};
> -
>  static int luo_ioctl_create_session(struct luo_ucmd *ucmd)
>  {
>  	struct liveupdate_ioctl_create_session *argp = ucmd->cmd;
> @@ -329,28 +318,9 @@ static int luo_ioctl_retrieve_session(struct luo_ucmd *ucmd)
>  
>  static int luo_open(struct inode *inodep, struct file *filep)
>  {
> -	struct luo_device_state *ldev = container_of(filep->private_data,
> -						     struct luo_device_state,
> -						     miscdev);
> -
> -	if (atomic_cmpxchg(&ldev->in_use, 0, 1))
> -		return -EBUSY;
> -
>  	/* Always return -EIO to user if deserialization fail */
> -	if (luo_session_deserialize()) {
> -		atomic_set(&ldev->in_use, 0);
> +	if (luo_session_deserialize())
>  		return -EIO;
> -	}
> -
> -	return 0;
> -}
> -
> -static int luo_release(struct inode *inodep, struct file *filep)
> -{
> -	struct luo_device_state *ldev = container_of(filep->private_data,
> -						     struct luo_device_state,
> -						     miscdev);
> -	atomic_set(&ldev->in_use, 0);
>  
>  	return 0;
>  }
> @@ -419,17 +389,13 @@ static long luo_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
>  static const struct file_operations luo_fops = {
>  	.owner		= THIS_MODULE,
>  	.open		= luo_open,
> -	.release	= luo_release,
>  	.unlocked_ioctl	= luo_ioctl,
>  };
>  
> -static struct luo_device_state luo_dev = {
> -	.miscdev = {
> -		.minor = MISC_DYNAMIC_MINOR,
> -		.name  = "liveupdate",
> -		.fops  = &luo_fops,
> -	},
> -	.in_use = ATOMIC_INIT(0),
> +static struct miscdevice luo_dev = {
> +	.minor = MISC_DYNAMIC_MINOR,
> +	.name  = "liveupdate",
> +	.fops  = &luo_fops,
>  };
>  
>  static int __init liveupdate_ioctl_init(void)
> @@ -437,6 +403,6 @@ static int __init liveupdate_ioctl_init(void)
>  	if (!liveupdate_enabled())
>  		return 0;
>  
> -	return misc_register(&luo_dev.miscdev);
> +	return misc_register(&luo_dev);
>  }
>  late_initcall(liveupdate_ioctl_init);
> diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
> index b79b2a488974..ca4d0639d39a 100644
> --- a/kernel/liveupdate/luo_session.c
> +++ b/kernel/liveupdate/luo_session.c
> @@ -584,13 +584,17 @@ static int luo_session_deserialize_one(struct luo_session_header *sh,
>  
>  int luo_session_deserialize(void)
>  {
> -	struct luo_session_header *sh = &luo_session_global.incoming;
> +	static DEFINE_MUTEX(luo_session_deserialize_lock);
>  	static bool is_deserialized;
> +	static int saved_err;
> +
> +	struct luo_session_header *sh = &luo_session_global.incoming;
>  	struct luo_session_ser *ser;
>  	struct kho_block_set_it it;
> -	static int saved_err;
>  	int err;
>  
> +	guard(mutex)(&luo_session_deserialize_lock);
> +
>  	/* If has been deserialized, always return the same error code */
>  	if (is_deserialized)
>  		return saved_err;
> diff --git a/tools/testing/selftests/liveupdate/liveupdate.c b/tools/testing/selftests/liveupdate/liveupdate.c
> index 502fb3567e38..a8e1a8911849 100644
> --- a/tools/testing/selftests/liveupdate/liveupdate.c
> +++ b/tools/testing/selftests/liveupdate/liveupdate.c
> @@ -11,7 +11,7 @@
>   * /dev/liveupdate character device and its session management capabilities.
>   *
>   * Tests include:
> - * - Device access: basic open/close, and enforcement of exclusive access.
> + * - Device access: basic open/close, and support for multiple openers.
>   * - Session management: creation of unique sessions, and duplicate name detection.
>   * - Resource preservation: successfully preserving individual and multiple memfds,
>   *   verifying contents remain accessible.
> @@ -70,13 +70,12 @@ TEST_F(liveupdate_device, basic_open_close)
>  }
>  
>  /*
> - * Test Case: Exclusive Open Enforcement
> + * Test Case: Multiple Open Support
>   *
> - * Verifies that the /dev/liveupdate device can only be opened by one process
> - * at a time. It checks that a second attempt to open the device fails with
> - * the EBUSY error code.
> + * Verifies that the /dev/liveupdate device can be opened by multiple openers
> + * concurrently without errors.
>   */
> -TEST_F(liveupdate_device, exclusive_open)
> +TEST_F(liveupdate_device, multiple_open)
>  {
>  	self->fd1 = open(LIVEUPDATE_DEV, O_RDWR);
>  
> @@ -85,8 +84,7 @@ TEST_F(liveupdate_device, exclusive_open)
>  
>  	ASSERT_GE(self->fd1, 0);
>  	self->fd2 = open(LIVEUPDATE_DEV, O_RDWR);
> -	EXPECT_LT(self->fd2, 0);
> -	EXPECT_EQ(errno, EBUSY);
> +	ASSERT_GE(self->fd2, 0);
>  }
>  
>  /* Helper function to create a LUO session via ioctl. */
> 
> base-commit: 10fd52dc7bbd6013e949ff1833be0821b7553fb0
> -- 
> 2.55.0.141.g00534a21ce-goog
> 

-- 
Sincerely yours,
Mike.

      parent reply	other threads:[~2026-07-16  6:06 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14 19:03 [RFC PATCH] liveupdate: Allow multiple openers for /dev/liveupdate David Matlack
2026-07-15 13:50 ` Pratyush Yadav
2026-07-15 16:07   ` David Matlack
2026-07-15 17:23   ` Jason Gunthorpe
2026-07-16  6:06 ` Mike Rapoport [this message]

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=alh0_aCbZITvSaox@kernel.org \
    --to=rppt@kernel.org \
    --cc=dmatlack@google.com \
    --cc=jgg@nvidia.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=luca.boccassi@gmail.com \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=shuah@kernel.org \
    --cc=skhawaja@google.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