[PATCH v1 11/13] kho: Allow memory preservation state updates after finalization

Pasha Tatashin posted 13 patches 2 months, 3 weeks ago
There is a newer version of this series
[PATCH v1 11/13] kho: Allow memory preservation state updates after finalization
Posted by Pasha Tatashin 2 months, 3 weeks ago
Currently, kho_preserve_* and kho_unpreserve_* return -EBUSY if
KHO is finalized. This enforces a rigid "freeze" on the KHO memory
state.

With the introduction of re-entrant finalization, this restriction is
no longer necessary. Users should be allowed to modify the preservation
set (e.g., adding new pages or freeing old ones) even after an initial
finalization.

The intended workflow for updates is now:
1. Modify state (preserve/unpreserve).
2. Call kho_finalize() again to refresh the serialized metadata.

Remove the kho_out.finalized checks to enable this dynamic behavior.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
 kernel/liveupdate/kexec_handover.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 27ef20565a5f..87e9b488237d 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -183,10 +183,6 @@ static int __kho_preserve_order(struct kho_mem_track *track, unsigned long pfn,
 	const unsigned long pfn_high = pfn >> order;
 
 	might_sleep();
-
-	if (kho_out.finalized)
-		return -EBUSY;
-
 	physxa = xa_load(&track->orders, order);
 	if (!physxa) {
 		int err;
@@ -815,9 +811,6 @@ int kho_unpreserve_folio(struct folio *folio)
 	const unsigned int order = folio_order(folio);
 	struct kho_mem_track *track = &kho_out.track;
 
-	if (kho_out.finalized)
-		return -EBUSY;
-
 	__kho_unpreserve_order(track, pfn, order);
 	return 0;
 }
@@ -885,9 +878,6 @@ int kho_unpreserve_pages(struct page *page, unsigned int nr_pages)
 	const unsigned long start_pfn = page_to_pfn(page);
 	const unsigned long end_pfn = start_pfn + nr_pages;
 
-	if (kho_out.finalized)
-		return -EBUSY;
-
 	__kho_unpreserve(track, start_pfn, end_pfn);
 
 	return 0;
@@ -1066,9 +1056,6 @@ EXPORT_SYMBOL_GPL(kho_preserve_vmalloc);
  */
 int kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
 {
-	if (kho_out.finalized)
-		return -EBUSY;
-
 	kho_vmalloc_free_chunks(preservation);
 
 	return 0;
-- 
2.52.0.rc1.455.g30608eb744-goog
Re: [PATCH v1 11/13] kho: Allow memory preservation state updates after finalization
Posted by Pratyush Yadav 2 months, 3 weeks ago
On Fri, Nov 14 2025, Pasha Tatashin wrote:

> Currently, kho_preserve_* and kho_unpreserve_* return -EBUSY if
> KHO is finalized. This enforces a rigid "freeze" on the KHO memory
> state.
>
> With the introduction of re-entrant finalization, this restriction is
> no longer necessary. Users should be allowed to modify the preservation
> set (e.g., adding new pages or freeing old ones) even after an initial
> finalization.
>
> The intended workflow for updates is now:
> 1. Modify state (preserve/unpreserve).
> 2. Call kho_finalize() again to refresh the serialized metadata.
>
> Remove the kho_out.finalized checks to enable this dynamic behavior.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> ---
>  kernel/liveupdate/kexec_handover.c | 13 -------------
>  1 file changed, 13 deletions(-)
>
> diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
> index 27ef20565a5f..87e9b488237d 100644
> --- a/kernel/liveupdate/kexec_handover.c
> +++ b/kernel/liveupdate/kexec_handover.c
> @@ -183,10 +183,6 @@ static int __kho_preserve_order(struct kho_mem_track *track, unsigned long pfn,
>  	const unsigned long pfn_high = pfn >> order;
>  
>  	might_sleep();
> -
> -	if (kho_out.finalized)
> -		return -EBUSY;
> -
>  	physxa = xa_load(&track->orders, order);
>  	if (!physxa) {
>  		int err;
> @@ -815,9 +811,6 @@ int kho_unpreserve_folio(struct folio *folio)

This can be void now. This would make consumers a bit simpler, since
right now, the memfd preservation logic does a WARN_ON() if this
function fails. That can be dropped now that the function can never
fail.

Same for kho_unpreserve_pages() and kho_unpreserve_vmalloc().

>  	const unsigned int order = folio_order(folio);
>  	struct kho_mem_track *track = &kho_out.track;
>  
> -	if (kho_out.finalized)
> -		return -EBUSY;
> -
>  	__kho_unpreserve_order(track, pfn, order);
>  	return 0;
>  }
> @@ -885,9 +878,6 @@ int kho_unpreserve_pages(struct page *page, unsigned int nr_pages)
>  	const unsigned long start_pfn = page_to_pfn(page);
>  	const unsigned long end_pfn = start_pfn + nr_pages;
>  
> -	if (kho_out.finalized)
> -		return -EBUSY;
> -
>  	__kho_unpreserve(track, start_pfn, end_pfn);
>  
>  	return 0;
> @@ -1066,9 +1056,6 @@ EXPORT_SYMBOL_GPL(kho_preserve_vmalloc);
>   */
>  int kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
>  {
> -	if (kho_out.finalized)
> -		return -EBUSY;
> -
>  	kho_vmalloc_free_chunks(preservation);
>  
>  	return 0;

-- 
Regards,
Pratyush Yadav
Re: [PATCH v1 11/13] kho: Allow memory preservation state updates after finalization
Posted by Pasha Tatashin 2 months, 3 weeks ago
On Fri, Nov 14, 2025 at 12:33 PM Pratyush Yadav <pratyush@kernel.org> wrote:
>
> On Fri, Nov 14 2025, Pasha Tatashin wrote:
>
> > Currently, kho_preserve_* and kho_unpreserve_* return -EBUSY if
> > KHO is finalized. This enforces a rigid "freeze" on the KHO memory
> > state.
> >
> > With the introduction of re-entrant finalization, this restriction is
> > no longer necessary. Users should be allowed to modify the preservation
> > set (e.g., adding new pages or freeing old ones) even after an initial
> > finalization.
> >
> > The intended workflow for updates is now:
> > 1. Modify state (preserve/unpreserve).
> > 2. Call kho_finalize() again to refresh the serialized metadata.
> >
> > Remove the kho_out.finalized checks to enable this dynamic behavior.
> >
> > Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> > ---
> >  kernel/liveupdate/kexec_handover.c | 13 -------------
> >  1 file changed, 13 deletions(-)
> >
> > diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
> > index 27ef20565a5f..87e9b488237d 100644
> > --- a/kernel/liveupdate/kexec_handover.c
> > +++ b/kernel/liveupdate/kexec_handover.c
> > @@ -183,10 +183,6 @@ static int __kho_preserve_order(struct kho_mem_track *track, unsigned long pfn,
> >       const unsigned long pfn_high = pfn >> order;
> >
> >       might_sleep();
> > -
> > -     if (kho_out.finalized)
> > -             return -EBUSY;
> > -
> >       physxa = xa_load(&track->orders, order);
> >       if (!physxa) {
> >               int err;
> > @@ -815,9 +811,6 @@ int kho_unpreserve_folio(struct folio *folio)
>
> This can be void now. This would make consumers a bit simpler, since
> right now, the memfd preservation logic does a WARN_ON() if this
> function fails. That can be dropped now that the function can never
> fail.
>
> Same for kho_unpreserve_pages() and kho_unpreserve_vmalloc().

Oh, this is a very good suggestion, really disliked those
kho_unpreserve_* errors.

>
> >       const unsigned int order = folio_order(folio);
> >       struct kho_mem_track *track = &kho_out.track;
> >
> > -     if (kho_out.finalized)
> > -             return -EBUSY;
> > -
> >       __kho_unpreserve_order(track, pfn, order);
> >       return 0;
> >  }
> > @@ -885,9 +878,6 @@ int kho_unpreserve_pages(struct page *page, unsigned int nr_pages)
> >       const unsigned long start_pfn = page_to_pfn(page);
> >       const unsigned long end_pfn = start_pfn + nr_pages;
> >
> > -     if (kho_out.finalized)
> > -             return -EBUSY;
> > -
> >       __kho_unpreserve(track, start_pfn, end_pfn);
> >
> >       return 0;
> > @@ -1066,9 +1056,6 @@ EXPORT_SYMBOL_GPL(kho_preserve_vmalloc);
> >   */
> >  int kho_unpreserve_vmalloc(struct kho_vmalloc *preservation)
> >  {
> > -     if (kho_out.finalized)
> > -             return -EBUSY;
> > -
> >       kho_vmalloc_free_chunks(preservation);
> >
> >       return 0;
>
> --
> Regards,
> Pratyush Yadav