From: Stefan Hajnoczi <[email protected]> The SCSI specification says PREEMPT without a reservation removes all registrations with the given key. Try to register again after PREEMPT since our key will have been removed.
In practice some SCSI targets keep the calling I_T nexus' registration instead of removing it. Therefore we need to handle both the spec-compliant and the non-compliant behavior. Signed-off-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Paolo Bonzini <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Bonzini <[email protected]> --- hw/scsi/scsi-generic.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index f1c328e6da6..29bc952af5d 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -513,6 +513,16 @@ bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp) if (!scsi_generic_pr_preempt(s, key, resv_type, errp)) { return false; } + + /* + * Some SCSI targets, like the Linux LIO target, remove our + * registration when preempting without a reservation (resv_type is 0). + * Try to register again but ignore the error since a RESERVATION + * CONFLICT is expected if our registration remained in place. + */ + if (resv_type == 0) { + scsi_generic_pr_register(s, key, NULL); + } } return true; } -- 2.54.0
