mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-24 17:23:25 -05:00
Avoid some races in vfio-ccw request handling.
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAmCmRbUSHGNvaHVja0By ZWRoYXQuY29tAAoJEN7Pa5PG8C+vfskP/2dRytW+PLjA4DSv0rQLa6Q/Z/HPZqI7 Ef9r2/GPUeYwmCkZ5l7lOn6NQrB0qgb0eo1vkO2qvIbtCEUvYk4x6t6IJNn30bkE V/DjdCDrR7yrzkHASXBwpJ0wV2NkT55bWndtYI85aN7T/5JKRtUoT8MSaWFZG2Eq dTsZVUMO1ZskXWklWKbXf1C/MgTnOnLVnwpzQocR2Pgx+kUFZK3qClzMhVLKlL+R joyfLQoMImoPre7/x+PpweWujpXYgnMt+bNYAON6FoWQGq3vMuWJ7WEc+MI7chVd sULsV3d6m/D8vjY9P4+Z6K55zTq4gGyGb/DsOhHd39LqfiV6LxUNQt5WNHVRKlA3 2MmtEbQU01ewCmfJbhi+pOfyEkWf1rk5fOG1xPiqeUi3dOEbL0tSBq5EztbPPPIi DG7uR+h/w+QJ3wD3c+xiO1AEYyFcWwXtK6FKhncRv4n3XOMXMhjt7ry27Xx8tywp Z2vYdHcCR3b+dU8uCXlIySqkAUvKrNLK4f6ZPGytwcrGTl8EmGLVjqV16K270+NR gKJRbOSd88wpKjHbgSVix9QihTK7RSohboL50QlZ3koBe7Q99U3NIXiFrhwoATS6 GibdGIY4Mcca2MeiQd1lDPYOnZ9/+174z/49tenfWDcx09kywAteGb8ByAtEil+O Hv3DNUI5ZSRt =KSlG -----END PGP SIGNATURE----- Merge tag 'vfio-ccw-20210520' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/vfio-ccw into fixes Avoid some races in vfio-ccw request handling. * tag 'vfio-ccw-20210520' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/vfio-ccw: vfio-ccw: Serialize FSM IDLE state with I/O completion vfio-ccw: Reset FSM state to IDLE inside FSM vfio-ccw: Check initialized flag in cp_init() Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
commit
ffa99c436a
4 changed files with 15 additions and 4 deletions
|
@ -638,6 +638,10 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
|
|||
static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 1);
|
||||
int ret;
|
||||
|
||||
/* this is an error in the caller */
|
||||
if (cp->initialized)
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* We only support prefetching the channel program. We assume all channel
|
||||
* programs executed by supported guests likewise support prefetching.
|
||||
|
|
|
@ -86,6 +86,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
|
|||
struct vfio_ccw_private *private;
|
||||
struct irb *irb;
|
||||
bool is_final;
|
||||
bool cp_is_finished = false;
|
||||
|
||||
private = container_of(work, struct vfio_ccw_private, io_work);
|
||||
irb = &private->irb;
|
||||
|
@ -94,14 +95,21 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
|
|||
(SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
|
||||
if (scsw_is_solicited(&irb->scsw)) {
|
||||
cp_update_scsw(&private->cp, &irb->scsw);
|
||||
if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
|
||||
if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING) {
|
||||
cp_free(&private->cp);
|
||||
cp_is_finished = true;
|
||||
}
|
||||
}
|
||||
mutex_lock(&private->io_mutex);
|
||||
memcpy(private->io_region->irb_area, irb, sizeof(*irb));
|
||||
mutex_unlock(&private->io_mutex);
|
||||
|
||||
if (private->mdev && is_final)
|
||||
/*
|
||||
* Reset to IDLE only if processing of a channel program
|
||||
* has finished. Do not overwrite a possible processing
|
||||
* state if the final interrupt was for HSCH or CSCH.
|
||||
*/
|
||||
if (private->mdev && cp_is_finished)
|
||||
private->state = VFIO_CCW_STATE_IDLE;
|
||||
|
||||
if (private->io_trigger)
|
||||
|
|
|
@ -318,6 +318,7 @@ static void fsm_io_request(struct vfio_ccw_private *private,
|
|||
}
|
||||
|
||||
err_out:
|
||||
private->state = VFIO_CCW_STATE_IDLE;
|
||||
trace_vfio_ccw_fsm_io_request(scsw->cmd.fctl, schid,
|
||||
io_region->ret_code, errstr);
|
||||
}
|
||||
|
|
|
@ -279,8 +279,6 @@ static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private,
|
|||
}
|
||||
|
||||
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_IO_REQ);
|
||||
if (region->ret_code != 0)
|
||||
private->state = VFIO_CCW_STATE_IDLE;
|
||||
ret = (region->ret_code != 0) ? region->ret_code : count;
|
||||
|
||||
out_unlock:
|
||||
|
|
Loading…
Add table
Reference in a new issue