Found a race in scsipi_execute_xs(): if an asynchronous transfer completes
(probably due to an interrupt) between the time it is scheduled and the time we get around to setting the SCSI_ASYNCREQ flag, we can lose the xs. Fix this by checking to see if the transfer has already completed after the scsi_cmd function returns SUCCESSFULLY_QUEUED, and just return to the caller if so.
This commit is contained in:
parent
43f5b65e23
commit
4963603d0f
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: scsipi_base.c,v 1.9 1998/09/14 05:49:21 scottr Exp $ */
|
/* $NetBSD: scsipi_base.c,v 1.10 1998/09/16 05:35:50 scottr Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -417,19 +417,30 @@ retry:
|
||||||
#endif
|
#endif
|
||||||
switch (scsipi_command_direct(xs)) {
|
switch (scsipi_command_direct(xs)) {
|
||||||
case SUCCESSFULLY_QUEUED:
|
case SUCCESSFULLY_QUEUED:
|
||||||
|
s = splbio();
|
||||||
|
if (xs->flags & ITSDONE) {
|
||||||
|
/*
|
||||||
|
* The request has already completed, probably due
|
||||||
|
* to an interrupt arriving between the time the
|
||||||
|
* request was scheduled and when we arrived at this
|
||||||
|
* point.
|
||||||
|
*/
|
||||||
|
splx(s);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
if ((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP) {
|
if ((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP) {
|
||||||
/*
|
/*
|
||||||
* The request will complete asynchronously. In this
|
* The request will complete asynchronously. In this
|
||||||
* case, we need scsipi_done() to free the scsipi_xfer.
|
* case, we need scsipi_done() to free the scsipi_xfer.
|
||||||
*/
|
*/
|
||||||
xs->flags |= SCSI_ASYNCREQ;
|
xs->flags |= SCSI_ASYNCREQ;
|
||||||
|
splx(s);
|
||||||
return (EJUSTRETURN);
|
return (EJUSTRETURN);
|
||||||
}
|
}
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (xs->flags & SCSI_NOSLEEP)
|
if (xs->flags & SCSI_NOSLEEP)
|
||||||
panic("scsipi_execute_xs: NOSLEEP and POLL");
|
panic("scsipi_execute_xs: NOSLEEP and POLL");
|
||||||
#endif
|
#endif
|
||||||
s = splbio();
|
|
||||||
while ((xs->flags & ITSDONE) == 0)
|
while ((xs->flags & ITSDONE) == 0)
|
||||||
tsleep(xs, PRIBIO + 1, "scsipi_cmd", 0);
|
tsleep(xs, PRIBIO + 1, "scsipi_cmd", 0);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
Loading…
Reference in New Issue