Re: [PATCH v5] powerpc/pseries/vas: Migration suspend waits for no in-progress open windows

2023-12-21 Thread Michael Ellerman
On Sat, 25 Nov 2023 15:51:04 -0800, Haren Myneni wrote:
> The hypervisor returns migration failure if all VAS windows are not
> closed. During pre-migration stage, vas_migration_handler() sets
> migration_in_progress flag and closes all windows from the list.
> The allocate VAS window routine checks the migration flag, setup
> the window and then add it to the list. So there is possibility of
> the migration handler missing the window that is still in the
> process of setup.
> 
> [...]

Applied to powerpc/fixes.

[1/1] powerpc/pseries/vas: Migration suspend waits for no in-progress open 
windows
  https://git.kernel.org/powerpc/c/0cf72f7f14d12cb065c3d01954cf42fc5638aa69

cheers


[PATCH v5] powerpc/pseries/vas: Migration suspend waits for no in-progress open windows

2023-11-25 Thread Haren Myneni
The hypervisor returns migration failure if all VAS windows are not
closed. During pre-migration stage, vas_migration_handler() sets
migration_in_progress flag and closes all windows from the list.
The allocate VAS window routine checks the migration flag, setup
the window and then add it to the list. So there is possibility of
the migration handler missing the window that is still in the
process of setup.

t1: Allocate and open VAS   t2: Migration event
window

lock vas_pseries_mutex
If migration_in_progress set
  unlock vas_pseries_mutex
  return
open window HCALL
unlock vas_pseries_mutex
Modify window HCALL lock vas_pseries_mutex
setup windowmigration_in_progress=true
Closes all windows from the list
// May miss windows that are
// not in the list
unlock vas_pseries_mutex
lock vas_pseries_mutex  return
if nr_closed_windows == 0
  // No DLPAR CPU or migration
  add window to the list
  // Window will be added to the
  // list after the setup is completed
  unlock vas_pseries_mutex
  return
unlock vas_pseries_mutex
Close VAS window
// due to DLPAR CPU or migration
return -EBUSY

This patch resolves the issue with the following steps:
- Set the migration_in_progress flag without holding mutex.
- Introduce nr_open_wins_progress counter in VAS capabilities
  struct
- This counter tracks the number of open windows are still in
  progress
- The allocate setup window thread closes windows if the migration
  is set and decrements nr_open_window_progress counter
- The migration handler waits for no in-progress open windows.

The code flow with the fix is as follows:

t1: Allocate and open VAS   t2: Migration event
window

lock vas_pseries_mutex
If migration_in_progress set
   unlock vas_pseries_mutex
   return
open window HCALL
nr_open_wins_progress++
// Window opened, but not
// added to the list yet
unlock vas_pseries_mutex
Modify window HCALL migration_in_progress=true
setup windowlock vas_pseries_mutex
Closes all windows from the list
While nr_open_wins_progress {
unlock vas_pseries_mutex
lock vas_pseries_mutex  sleep
if nr_closed_windows == 0   // Wait if any open window in
or migration is not started // progress. The open window
   // No DLPAR CPU or migration // thread closes the window without
   add window to the list   // adding to the list and return if
   nr_open_wins_progress--  // the migration is in progress.
   unlock vas_pseries_mutex
   return
Close VAS window
nr_open_wins_progress--
unlock vas_pseries_mutex
return -EBUSY   lock vas_pseries_mutex
}
unlock vas_pseries_mutex
return

Fixes: 37e6764895ef ("powerpc/pseries/vas: Add VAS migration handler")
Signed-off-by: Haren Myneni 

---
v1 -> v2:
- Do not define the migration_in_progress flag as atomic as
  suggested by Nathan

v2 -> v3:
- Use wait_event() instead of wait_event_interruptible() so that
  returns after all windows are closed as suggested by Nathan

v3 -> v4:
- remove atomic for nr_open_wins_progress counter as suggested by
  Nathan and Michael Ellerman
- Use sleep instead of wait_event_interruptible() to check
  nr_open_wins_progress counter under mutex.

v4 -> v5:
- Update the commit message with comments in the code flow and added
  the second code flow with the fix as suggested by Michael Ellerman
---
 arch/powerpc/platforms/pseries/vas.c | 51 
 arch/powerpc/platforms/pseries/vas.h |  2 ++
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/vas.c 
b/arch/powerpc/platforms/pseries/vas.c
index b1f25bac280b..71d52a670d95 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -385,11 +385,15 @@ static struct vas_window *vas_allocate_window(int vas_id, 
u64 flags,
 * same fault IRQ is not freed by the OS before.
 */
mutex_lock(_pseries_mutex);
-   if (migration_in_progress)
+   if (migration_in_progress) {
rc = -EBUSY;
-   else
+   } else {
rc = allocate_setup_window(txwin, (u64 *)[0],
   cop_feat_caps->win_type);
+   if (!rc)
+   caps->nr_open_wins_progress++;
+   }
+
mutex_unlock(_pseries_mutex);
if (rc)
goto out;
@@ -404,8 +408,17 @@ static struct vas_window *vas_allocate_window(int vas_id, 
u64 flags,
goto out_free;
 
txwin->win_type = cop_feat_caps->win_type;
-   mutex_lock(_pseries_mutex);
+
/*
+* The migration SUSPEND thread sets