Mark failures in shmem_luo_retrieve() before it starts restoring the folios as retryable. If no retrieve succeeds, finish() frees the preserved state, like it does for a file that was never retrieved. Until the folios are restored, nothing has consumed the preserved state. Leave it for another retrieve, which may succeed, e.g. if memfd_alloc_file() failed with -ENOMEM. The exception is a preserved file that this kernel can't restore, e.g. because it has seals that this kernel doesn't support. Retrying can't help, so keep that failure permanent, so that every later retrieve returns the same error. Signed-off-by: David Matlack Acked-by: Pasha Tatashin --- mm/shmem_luo.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mm/shmem_luo.c b/mm/shmem_luo.c index b48d7f460493..dc6ede528822 100644 --- a/mm/shmem_luo.c +++ b/mm/shmem_luo.c @@ -552,6 +552,14 @@ static int shmem_luo_retrieve(struct liveupdate_file_op_args *args) if (ser->seals & ~SHMEM_LUO_ALL_SEALS) return -EOPNOTSUPP; + /* + * Nothing consumes the preserved state until the folios are restored + * below. If the retrieve fails before that, leave the state for another + * retrieve, or for finish() to free. The checks above can't succeed on + * a retry, so they fail permanently. + */ + args->retryable = true; + /* * The seals are preserved. Allow sealing here so they can be added * later. @@ -571,6 +579,9 @@ 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; + err = shmem_luo_restore_folios(file, ser); if (err) goto put_file; -- 2.56.0.542.g3ef89b7020-goog