Re: [PATCH v2 06/10] mm/shmem_luo: Don't make early retrieve failures permanent
From: Pasha Tatashin
Date: Wed Oct 28 2026 - 17:18:08 EST
> If shmem_luo_retrieve() fails before it starts restoring the folios,
> mark the failure as retryable and return the error without freeing the
> serialized state. Nothing has consumed the preserved state at that
> point, so the retrieve can be tried again. If no retrieve succeeds,
> finish() frees the preserved folios, like it does for a file that was
> never retrieved.
>
> This fixes leaking the preserved folios when one of these early steps
> fails, e.g. because the file has seals that this kernel doesn't support.
> The retrieve freed the serialized state but not the folios, and finish()
> then skipped the file because its retrieve had failed.
You should also note that args->retryable was introduced in this
series, so there is no fixup required for this since this was
previously not possible.
> Assisted-by: LLM
> Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx>
> Link: https://patch.msgid.link/20261022225035.377445-7-dmatlack@xxxxxxxxxx
>
> diff --git a/mm/shmem_luo.c b/mm/shmem_luo.c
> index b8d86055912d..bcac1bbb3db3 100644
> --- a/mm/shmem_luo.c
> +++ b/mm/shmem_luo.c
> @@ -390,9 +390,9 @@ static void shmem_luo_finish(struct liveupdate_file_op_args *args)
> struct shmem_luo_ser *ser;
>
> /*
> - * If retrieve was successful, nothing to do. If it failed, retrieve()
> - * already cleaned up everything it could. So nothing to do there
> - * either. Only need to clean up when retrieve was not called.
> + * If retrieve was successful, nothing to do. If it failed permanently,
> + * retrieve() already cleaned up everything it could. So nothing to do
> + * there either. Only need to clean up when the file was not retrieved.
> */
> if (args->retrieve_status)
> return;
> @@ -526,11 +526,16 @@ static int shmem_luo_retrieve(struct liveupdate_file_op_args *args)
> if (!ser)
> return -EINVAL;
>
> + /*
> + * Nothing has consumed the preserved state until the folios are
> + * restored below, so failures before that can be retried. If no
> + * retrieve succeeds, finish() frees the preserved state.
> + */
> + args->retryable = true;
> +
> /* Make sure the file only has seals supported by this version. */
> - if (ser->seals & ~SHMEM_LUO_ALL_SEALS) {
> - err = -EOPNOTSUPP;
> - goto free_ser;
> - }
> + if (ser->seals & ~SHMEM_LUO_ALL_SEALS)
> + return -EOPNOTSUPP;
>
> /*
> * The seals are preserved. Allow sealing here so they can be added
> @@ -539,8 +544,7 @@ static int shmem_luo_retrieve(struct liveupdate_file_op_args *args)
> file = memfd_alloc_file("", MFD_ALLOW_SEALING);
> if (IS_ERR(file)) {
> pr_err("failed to setup file: %pe\n", file);
> - err = PTR_ERR(file);
> - goto free_ser;
> + return PTR_ERR(file);
> }
>
> err = memfd_add_seals(file, ser->seals);
> @@ -552,17 +556,20 @@ static int shmem_luo_retrieve(struct liveupdate_file_op_args *args)
> vfs_setpos(file, ser->pos, MAX_LFS_FILESIZE);
> i_size_write(file_inode(file), ser->size);
>
> + /* The preserved state is consumed from here on. */
> + args->retryable = false;
> +
> if (ser->nr_folios) {
> folios_ser = kho_restore_vmalloc(&ser->folios);
> if (!folios_ser) {
> err = -EINVAL;
> - goto put_file;
> + goto free_ser;
> }
>
> err = shmem_luo_retrieve_folios(file, folios_ser, ser->nr_folios);
> vfree(folios_ser);
> if (err)
> - goto put_file;
> + goto free_ser;
> }
>
> args->file = file;
> @@ -570,10 +577,10 @@ static int shmem_luo_retrieve(struct liveupdate_file_op_args *args)
>
> return 0;
>
> -put_file:
> - fput(file);
> free_ser:
> kho_restore_free(ser);
> +put_file:
> + fput(file);
> return err;
> }
>
Acked-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
--
Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>