From 4963603d0f7a37a1a8b59547f802a6a143e2ab30 Mon Sep 17 00:00:00 2001 From: scottr Date: Wed, 16 Sep 1998 05:35:50 +0000 Subject: [PATCH] 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. --- sys/dev/scsipi/scsipi_base.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sys/dev/scsipi/scsipi_base.c b/sys/dev/scsipi/scsipi_base.c index 84c10266e827..5fbb0f743ca8 100644 --- a/sys/dev/scsipi/scsipi_base.c +++ b/sys/dev/scsipi/scsipi_base.c @@ -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. @@ -417,19 +417,30 @@ retry: #endif switch (scsipi_command_direct(xs)) { 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) { /* * The request will complete asynchronously. In this * case, we need scsipi_done() to free the scsipi_xfer. */ xs->flags |= SCSI_ASYNCREQ; + splx(s); return (EJUSTRETURN); } #ifdef DIAGNOSTIC if (xs->flags & SCSI_NOSLEEP) panic("scsipi_execute_xs: NOSLEEP and POLL"); #endif - s = splbio(); while ((xs->flags & ITSDONE) == 0) tsleep(xs, PRIBIO + 1, "scsipi_cmd", 0); splx(s);