Skip to content

Commit d6e18a4

Browse files
shayshyiawilliam
authored andcommitted
vfio/mlx5: Fallback to STOP_COPY upon specific PRE_COPY error
Before a SAVE command is issued, a QUERY command is issued in order to know the device data size. In case PRE_COPY is used, the above commands are issued while the device is running. Thus, it is possible that between the QUERY and the SAVE commands the state of the device will be changed significantly and thus the SAVE will fail. Currently, if a SAVE command is failing, the driver will fail the migration. In the above case, don't fail the migration, but don't allow for new SAVEs to be executed while the device is in a RUNNING state. Once the device will be moved to STOP_COPY, SAVE can be executed again and the full device state will be read. Signed-off-by: Shay Drory <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Yishai Hadas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent 34e2f27 commit d6e18a4

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

drivers/vfio/pci/mlx5/cmd.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ int mlx5vf_cmd_query_vhca_migration_state(struct mlx5vf_pci_core_device *mvdev,
8484
ret = wait_for_completion_interruptible(&mvdev->saving_migf->save_comp);
8585
if (ret)
8686
return ret;
87+
if (mvdev->saving_migf->state ==
88+
MLX5_MIGF_STATE_PRE_COPY_ERROR) {
89+
/*
90+
* In case we had a PRE_COPY error, only query full
91+
* image for final image
92+
*/
93+
if (!(query_flags & MLX5VF_QUERY_FINAL)) {
94+
*state_size = 0;
95+
complete(&mvdev->saving_migf->save_comp);
96+
return 0;
97+
}
98+
query_flags &= ~MLX5VF_QUERY_INC;
99+
}
87100
}
88101

89102
MLX5_SET(query_vhca_migration_state_in, in, opcode,
@@ -442,7 +455,10 @@ void mlx5vf_mig_file_cleanup_cb(struct work_struct *_work)
442455
mlx5vf_put_data_buffer(async_data->buf);
443456
if (async_data->header_buf)
444457
mlx5vf_put_data_buffer(async_data->header_buf);
445-
migf->state = MLX5_MIGF_STATE_ERROR;
458+
if (async_data->status == MLX5_CMD_STAT_BAD_RES_STATE_ERR)
459+
migf->state = MLX5_MIGF_STATE_PRE_COPY_ERROR;
460+
else
461+
migf->state = MLX5_MIGF_STATE_ERROR;
446462
wake_up_interruptible(&migf->poll_wait);
447463
}
448464
mutex_unlock(&migf->lock);
@@ -511,6 +527,8 @@ static void mlx5vf_save_callback(int status, struct mlx5_async_work *context)
511527
* The error and the cleanup flows can't run from an
512528
* interrupt context
513529
*/
530+
if (status == -EREMOTEIO)
531+
status = MLX5_GET(save_vhca_state_out, async_data->out, status);
514532
async_data->status = status;
515533
queue_work(migf->mvdev->cb_wq, &async_data->work);
516534
}
@@ -534,6 +552,13 @@ int mlx5vf_cmd_save_vhca_state(struct mlx5vf_pci_core_device *mvdev,
534552
if (err)
535553
return err;
536554

555+
if (migf->state == MLX5_MIGF_STATE_PRE_COPY_ERROR)
556+
/*
557+
* In case we had a PRE_COPY error, SAVE is triggered only for
558+
* the final image, read device full image.
559+
*/
560+
inc = false;
561+
537562
MLX5_SET(save_vhca_state_in, in, opcode,
538563
MLX5_CMD_OP_SAVE_VHCA_STATE);
539564
MLX5_SET(save_vhca_state_in, in, op_mod, 0);

drivers/vfio/pci/mlx5/cmd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
enum mlx5_vf_migf_state {
1919
MLX5_MIGF_STATE_ERROR = 1,
20+
MLX5_MIGF_STATE_PRE_COPY_ERROR,
2021
MLX5_MIGF_STATE_PRE_COPY,
2122
MLX5_MIGF_STATE_SAVE_LAST,
2223
MLX5_MIGF_STATE_COMPLETE,
@@ -157,6 +158,7 @@ struct mlx5vf_pci_core_device {
157158

158159
enum {
159160
MLX5VF_QUERY_INC = (1UL << 0),
161+
MLX5VF_QUERY_FINAL = (1UL << 1),
160162
};
161163

162164
int mlx5vf_cmd_suspend_vhca(struct mlx5vf_pci_core_device *mvdev, u16 op_mod);

drivers/vfio/pci/mlx5/main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ static ssize_t mlx5vf_save_read(struct file *filp, char __user *buf, size_t len,
219219
if (wait_event_interruptible(migf->poll_wait,
220220
!list_empty(&migf->buf_list) ||
221221
migf->state == MLX5_MIGF_STATE_ERROR ||
222+
migf->state == MLX5_MIGF_STATE_PRE_COPY_ERROR ||
222223
migf->state == MLX5_MIGF_STATE_PRE_COPY ||
223224
migf->state == MLX5_MIGF_STATE_COMPLETE))
224225
return -ERESTARTSYS;
@@ -238,7 +239,8 @@ static ssize_t mlx5vf_save_read(struct file *filp, char __user *buf, size_t len,
238239
if (first_loop_call) {
239240
first_loop_call = false;
240241
/* Temporary end of file as part of PRE_COPY */
241-
if (end_of_data && migf->state == MLX5_MIGF_STATE_PRE_COPY) {
242+
if (end_of_data && (migf->state == MLX5_MIGF_STATE_PRE_COPY ||
243+
migf->state == MLX5_MIGF_STATE_PRE_COPY_ERROR)) {
242244
done = -ENOMSG;
243245
goto out_unlock;
244246
}
@@ -431,7 +433,7 @@ static int mlx5vf_pci_save_device_inc_data(struct mlx5vf_pci_core_device *mvdev)
431433
return -ENODEV;
432434

433435
ret = mlx5vf_cmd_query_vhca_migration_state(mvdev, &length,
434-
MLX5VF_QUERY_INC);
436+
MLX5VF_QUERY_INC | MLX5VF_QUERY_FINAL);
435437
if (ret)
436438
goto err;
437439

0 commit comments

Comments
 (0)