Skip to content

Commit 0cf72f7

Browse files
hmynenimpe
authored andcommitted
powerpc/pseries/vas: Migration suspend waits for no in-progress open windows
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 window migration_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 window lock 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: 37e6764 ("powerpc/pseries/vas: Add VAS migration handler") Signed-off-by: Haren Myneni <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://msgid.link/[email protected]
1 parent 4b3338a commit 0cf72f7

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

arch/powerpc/platforms/pseries/vas.c

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,15 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
385385
* same fault IRQ is not freed by the OS before.
386386
*/
387387
mutex_lock(&vas_pseries_mutex);
388-
if (migration_in_progress)
388+
if (migration_in_progress) {
389389
rc = -EBUSY;
390-
else
390+
} else {
391391
rc = allocate_setup_window(txwin, (u64 *)&domain[0],
392392
cop_feat_caps->win_type);
393+
if (!rc)
394+
caps->nr_open_wins_progress++;
395+
}
396+
393397
mutex_unlock(&vas_pseries_mutex);
394398
if (rc)
395399
goto out;
@@ -404,18 +408,29 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
404408
goto out_free;
405409

406410
txwin->win_type = cop_feat_caps->win_type;
407-
mutex_lock(&vas_pseries_mutex);
411+
408412
/*
413+
* The migration SUSPEND thread sets migration_in_progress and
414+
* closes all open windows from the list. But the window is
415+
* added to the list after open and modify HCALLs. So possible
416+
* that migration_in_progress is set before modify HCALL which
417+
* may cause some windows are still open when the hypervisor
418+
* initiates the migration.
419+
* So checks the migration_in_progress flag again and close all
420+
* open windows.
421+
*
409422
* Possible to lose the acquired credit with DLPAR core
410423
* removal after the window is opened. So if there are any
411424
* closed windows (means with lost credits), do not give new
412425
* window to user space. New windows will be opened only
413426
* after the existing windows are reopened when credits are
414427
* available.
415428
*/
416-
if (!caps->nr_close_wins) {
429+
mutex_lock(&vas_pseries_mutex);
430+
if (!caps->nr_close_wins && !migration_in_progress) {
417431
list_add(&txwin->win_list, &caps->list);
418432
caps->nr_open_windows++;
433+
caps->nr_open_wins_progress--;
419434
mutex_unlock(&vas_pseries_mutex);
420435
vas_user_win_add_mm_context(&txwin->vas_win.task_ref);
421436
return &txwin->vas_win;
@@ -433,6 +448,12 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
433448
*/
434449
free_irq_setup(txwin);
435450
h_deallocate_vas_window(txwin->vas_win.winid);
451+
/*
452+
* Hold mutex and reduce nr_open_wins_progress counter.
453+
*/
454+
mutex_lock(&vas_pseries_mutex);
455+
caps->nr_open_wins_progress--;
456+
mutex_unlock(&vas_pseries_mutex);
436457
out:
437458
atomic_dec(&cop_feat_caps->nr_used_credits);
438459
kfree(txwin);
@@ -937,14 +958,14 @@ int vas_migration_handler(int action)
937958
struct vas_caps *vcaps;
938959
int i, rc = 0;
939960

961+
pr_info("VAS migration event %d\n", action);
962+
940963
/*
941964
* NX-GZIP is not enabled. Nothing to do for migration.
942965
*/
943966
if (!copypaste_feat)
944967
return rc;
945968

946-
mutex_lock(&vas_pseries_mutex);
947-
948969
if (action == VAS_SUSPEND)
949970
migration_in_progress = true;
950971
else
@@ -990,12 +1011,27 @@ int vas_migration_handler(int action)
9901011

9911012
switch (action) {
9921013
case VAS_SUSPEND:
1014+
mutex_lock(&vas_pseries_mutex);
9931015
rc = reconfig_close_windows(vcaps, vcaps->nr_open_windows,
9941016
true);
1017+
/*
1018+
* Windows are included in the list after successful
1019+
* open. So wait for closing these in-progress open
1020+
* windows in vas_allocate_window() which will be
1021+
* done if the migration_in_progress is set.
1022+
*/
1023+
while (vcaps->nr_open_wins_progress) {
1024+
mutex_unlock(&vas_pseries_mutex);
1025+
msleep(10);
1026+
mutex_lock(&vas_pseries_mutex);
1027+
}
1028+
mutex_unlock(&vas_pseries_mutex);
9951029
break;
9961030
case VAS_RESUME:
1031+
mutex_lock(&vas_pseries_mutex);
9971032
atomic_set(&caps->nr_total_credits, new_nr_creds);
9981033
rc = reconfig_open_windows(vcaps, new_nr_creds, true);
1034+
mutex_unlock(&vas_pseries_mutex);
9991035
break;
10001036
default:
10011037
/* should not happen */
@@ -1011,8 +1047,9 @@ int vas_migration_handler(int action)
10111047
goto out;
10121048
}
10131049

1050+
pr_info("VAS migration event (%d) successful\n", action);
1051+
10141052
out:
1015-
mutex_unlock(&vas_pseries_mutex);
10161053
return rc;
10171054
}
10181055

arch/powerpc/platforms/pseries/vas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ struct vas_cop_feat_caps {
9191
struct vas_caps {
9292
struct vas_cop_feat_caps caps;
9393
struct list_head list; /* List of open windows */
94+
int nr_open_wins_progress; /* Number of open windows in */
95+
/* progress. Used in migration */
9496
int nr_close_wins; /* closed windows in the hypervisor for DLPAR */
9597
int nr_open_windows; /* Number of successful open windows */
9698
u8 feat; /* Feature type */

0 commit comments

Comments
 (0)