[PATCH 3/3] scsi: register again after PREEMPT without reservation

Stefan Hajnoczi posted 3 patches 3 hours ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Fam Zheng <fam@euphon.net>
[PATCH 3/3] scsi: register again after PREEMPT without reservation
Posted by Stefan Hajnoczi 3 hours ago
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 <stefanha@redhat.com>
---
 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 349dea6bdd..5182f9236d 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.53.0
Re: [PATCH 3/3] scsi: register again after PREEMPT without reservation
Posted by Paolo Bonzini 3 hours ago
On 4/1/26 19:19, Stefan Hajnoczi wrote:
> 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 <stefanha@redhat.com>
> ---
>   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 349dea6bdd..5182f9236d 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);
> +        }

Hi Stefan,

I'm replying here for both patch 2 and patch 3.

Can this happen after the previous patch?  (Also it's conflicting to say 
  in patch 2 that LIO rejects PREEMPT, but also in this one that LIO 
unregisters the key).

And for patch 2, is a RELEASE needed after issuing PREEMPT with an 
artificial PR_TYPE_WRITE_EXCLUSIVE?

Paolo
Re: [PATCH 3/3] scsi: register again after PREEMPT without reservation
Posted by Stefan Hajnoczi 2 hours ago
On Wed, Apr 01, 2026 at 07:34:40PM +0200, Paolo Bonzini wrote:
> On 4/1/26 19:19, Stefan Hajnoczi wrote:
> > 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 <stefanha@redhat.com>
> > ---
> >   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 349dea6bdd..5182f9236d 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);
> > +        }
> 
> Hi Stefan,
> 
> I'm replying here for both patch 2 and patch 3.
> 
> Can this happen after the previous patch?  (Also it's conflicting to say  in
> patch 2 that LIO rejects PREEMPT, but also in this one that LIO unregisters
> the key).

Yes. Both patches are needed.

The first patch gets LIO to process the PREEMPT. Before LIO would just
fail the command.

But once LIO processes the PREEMPT, we hit the next problem: PREEMPT
completes but our registration has been removed. So now we need to
register again after PREEMPT.

> And for patch 2, is a RELEASE needed after issuing PREEMPT with an
> artificial PR_TYPE_WRITE_EXCLUSIVE?

No, because PREEMPT will not acquire a reservation when there is no
reservation holder with the given key. PREEMPT will only remove
registrations in that case.

Stefan