[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 4/5] Rationalize SCSIOP_* handlers



From: Owen Smith <owen.smith@xxxxxxxxxx>

* Use same error handling for invalid buffers, etc.
* Allow for SCSIOP_MODE_SENSE10
* Correctly report VDISK_READONLY flag

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/frontend.c |  40 ++++
 src/xenvbd/frontend.h |   5 +
 src/xenvbd/target.c   | 555 +++++++++++++++++++++++++++-----------------------
 3 files changed, 348 insertions(+), 252 deletions(-)

diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
index d7fff89..b7e61c2 100644
--- a/src/xenvbd/frontend.c
+++ b/src/xenvbd/frontend.c
@@ -1889,5 +1889,45 @@ FrontendGetDiskInfo(
 {
     return &Frontend->DiskInfo;
 }
+//FRONTEND_GET_PROPERTY(Connected, BOOLEAN)
+BOOLEAN
+FrontendGetConnected(
+    IN  PXENVBD_FRONTEND    Frontend
+    )
+{
+    return Frontend->Caps.Connected;
+}
+//FRONTEND_GET_PROPERTY(ReadOnly, BOOLEAN)
+BOOLEAN
+FrontendGetReadOnly(
+    IN  PXENVBD_FRONTEND    Frontend
+    )
+{
+    return !!(Frontend->DiskInfo.DiskInfo & VDISK_READONLY);
+}
+//FRONTEND_GET_PROPERTY(Discard, BOOLEAN)
+BOOLEAN
+FrontendGetDiscard(
+    IN  PXENVBD_FRONTEND    Frontend
+    )
+{
+    return Frontend->DiskInfo.Discard;
+}
+//FRONTEND_GET_PROPERTY(FlushCache, BOOLEAN)
+BOOLEAN
+FrontendGetFlushCache(
+    IN  PXENVBD_FRONTEND    Frontend
+    )
+{
+    return Frontend->DiskInfo.FlushCache;
+}
+//FRONTEND_GET_PROPERTY(Barrier, BOOLEAN)
+BOOLEAN
+FrontendGetBarrier(
+    IN  PXENVBD_FRONTEND    Frontend
+    )
+{
+    return Frontend->DiskInfo.Barrier;
+}
 
 #undef FRONTEND_GET_PROPERTY
diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h
index 46f2e39..1488476 100644
--- a/src/xenvbd/frontend.h
+++ b/src/xenvbd/frontend.h
@@ -162,6 +162,11 @@ FRONTEND_GET_PROPERTY(FrontendPath, PCHAR)
 FRONTEND_GET_PROPERTY(Caps, PXENVBD_CAPS)
 FRONTEND_GET_PROPERTY(Features, PXENVBD_FEATURES)
 FRONTEND_GET_PROPERTY(DiskInfo, PXENVBD_DISKINFO)
+FRONTEND_GET_PROPERTY(Connected, BOOLEAN)
+FRONTEND_GET_PROPERTY(ReadOnly, BOOLEAN)
+FRONTEND_GET_PROPERTY(Discard, BOOLEAN)
+FRONTEND_GET_PROPERTY(FlushCache, BOOLEAN)
+FRONTEND_GET_PROPERTY(Barrier, BOOLEAN)
 
 #undef FRONTEND_GET_PROPERTY
 
diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c
index e624979..0956662 100644
--- a/src/xenvbd/target.c
+++ b/src/xenvbd/target.c
@@ -209,323 +209,354 @@ TargetSetDeviceObject(
     Target->DeviceObject = DeviceObject;
 }
 
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSectors(
-    __in ULONG64                 SectorCount,
-    __in ULONG64                 Start,
-    __in ULONG                   Length
+static DECLSPEC_NOINLINE BOOLEAN
+TargetReadWrite(
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    // Deal with overflow
-    return (Start < SectorCount) && ((Start + Length) <= SectorCount);
-}
+    PXENVBD_SRBEXT          SrbExt = Srb->SrbExtension;
+    PXENVBD_FRONTEND        Frontend = Target->Frontend;
+    PXENVBD_RING            Ring = FrontendGetRing(Frontend);
+    ULONG64                 SectorCount;
+    ULONG64                 SectorStart;
+    ULONG                   NumSectors;
 
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSrbBuffer(
-    __in PCHAR                  Caller,
-    __in PSCSI_REQUEST_BLOCK    Srb,
-    __in ULONG                  MinLength
-    )
-{
-    if (Srb->DataBuffer == NULL) {
-        Error("%s: Srb[0x%p].DataBuffer = NULL\n", Caller, Srb);
-        return FALSE;
-    }
-    if (MinLength) {
-        if (Srb->DataTransferLength < MinLength) {
-            Error("%s: Srb[0x%p].DataTransferLength < %d\n", Caller, Srb, 
MinLength);
-            return FALSE;
-        }
-    } else {
-        if (Srb->DataTransferLength == 0) {
-            Error("%s: Srb[0x%p].DataTransferLength = 0\n", Caller, Srb);
-            return FALSE;
-        }
-    }
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    if (!FrontendGetConnected(Frontend))
+        goto fail1;
 
-    return TRUE;
-}
+    // disallow writes to read-only disks
+    if (FrontendGetReadOnly(Frontend) &&
+        Cdb_OperationEx(Srb) == SCSIOP_WRITE)
+        goto fail2;
 
-__checkReturn
-static DECLSPEC_NOINLINE BOOLEAN
-TargetReadWrite(
-    __in PXENVBD_TARGET            Target,
-    __in PSCSI_REQUEST_BLOCK    Srb
-    )
-{
-    PXENVBD_DISKINFO    DiskInfo = FrontendGetDiskInfo(Target->Frontend);
-    PXENVBD_SRBEXT      SrbExt = Srb->SrbExtension;
-    PXENVBD_RING        Ring = FrontendGetRing(Target->Frontend);
-
-    if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
-        Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT;
-        return TRUE;
-    }
+    // check Sectors requested is on the disk
+    SectorCount = FrontendGetDiskInfo(Frontend)->SectorCount;
+    SectorStart = Cdb_LogicalBlock(Srb);
+    NumSectors = Cdb_TransferBlock(Srb);
 
-    // check valid sectors
-    if (!__ValidateSectors(DiskInfo->SectorCount, Cdb_LogicalBlock(Srb), 
Cdb_TransferBlock(Srb))) {
-        Trace("Target[%d] : Invalid Sector (%d @ %lld < %lld)\n", 
TargetGetTargetId(Target), Cdb_TransferBlock(Srb), Cdb_LogicalBlock(Srb), 
DiskInfo->SectorCount);
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT
-        return TRUE; // Complete now
-    }
+    if (SectorStart >= SectorCount)
+        goto fail3;
+    if ((SectorStart + NumSectors) > SectorCount)
+        goto fail4;
 
+    Srb->SrbStatus = SRB_STATUS_PENDING;
     RingQueueRequest(Ring, SrbExt);
     return FALSE;
+
+fail4:
+     Error("fail4\n");
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1\n");
+    return TRUE;
 }
 
-__checkReturn
 static DECLSPEC_NOINLINE BOOLEAN
 TargetSyncCache(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    PXENVBD_SRBEXT      SrbExt = Srb->SrbExtension;
-    PXENVBD_RING        Ring = FrontendGetRing(Target->Frontend);
+    PXENVBD_SRBEXT          SrbExt = Srb->SrbExtension;
+    PXENVBD_FRONTEND        Frontend = Target->Frontend;
+    PXENVBD_RING            Ring = FrontendGetRing(Frontend);
 
-    if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
-        Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT;
-        return TRUE;
-    }
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    if (!FrontendGetConnected(Frontend))
+        goto fail1;
 
-    if (FrontendGetDiskInfo(Target->Frontend)->FlushCache == FALSE &&
-        FrontendGetDiskInfo(Target->Frontend)->Barrier == FALSE) {
-        Trace("Target[%d] : FLUSH and BARRIER not supported, suppressing\n", 
TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x00; // SCSI_GOOD
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        return TRUE;
-    }
+    if (FrontendGetReadOnly(Frontend))
+        goto fail2;
+
+    // If neither FLUSH or BARRIER is supported, just succceed the SRB
+    if (!(FrontendGetFlushCache(Frontend) ||
+          FrontendGetBarrier(Frontend)))
+        goto succeed;
 
+    Srb->SrbStatus = SRB_STATUS_PENDING;
     RingQueueRequest(Ring, SrbExt);
     return FALSE;
+
+succeed:
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return TRUE;
+
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1\n");
+    return TRUE;
 }
 
-__checkReturn
 static DECLSPEC_NOINLINE BOOLEAN
 TargetUnmap(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    PXENVBD_SRBEXT      SrbExt = Srb->SrbExtension;
-    PXENVBD_RING        Ring = FrontendGetRing(Target->Frontend);
+    PXENVBD_SRBEXT          SrbExt = Srb->SrbExtension;
+    PXENVBD_FRONTEND        Frontend = Target->Frontend;
+    PXENVBD_RING            Ring = FrontendGetRing(Frontend);
 
-    if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
-        Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT;
-        return TRUE;
-    }
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    if (!FrontendGetConnected(Frontend))
+        goto fail1;
 
-    if (FrontendGetDiskInfo(Target->Frontend)->Discard == FALSE) {
-        Trace("Target[%d] : DISCARD not supported, suppressing\n", 
TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x00; // SCSI_GOOD
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        return TRUE;
-    }
+    if (FrontendGetReadOnly(Frontend))
+        goto fail2;
 
+    if (!FrontendGetDiscard(Frontend))
+        goto succeed;
+
+    Srb->SrbStatus = SRB_STATUS_PENDING;
     RingQueueRequest(Ring, SrbExt);
     return FALSE;
+
+succeed:
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+    return TRUE;
+
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1\n");
+    return TRUE;
 }
 
-#define MODE_CACHING_PAGE_LENGTH 20
-static DECLSPEC_NOINLINE VOID
-TargetModeSense(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+static FORCEINLINE VOID
+__TargetModeSense(
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb,
+    IN  PVOID               Data,
+    IN  ULONG               Length,
+    OUT PULONG              Size,
+    OUT PULONG              ModeDataLength,
+    OUT PULONG              BlockDescrLength
     )
 {
-    PMODE_PARAMETER_HEADER  Header  = Srb->DataBuffer;
-    const UCHAR PageCode            = Cdb_PageCode(Srb);
-    ULONG LengthLeft                = Cdb_AllocationLength(Srb);
-    PVOID CurrentPage               = Srb->DataBuffer;
-
-    UNREFERENCED_PARAMETER(Target);
-
-    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
-
-    if (!__ValidateSrbBuffer(__FUNCTION__, Srb, (ULONG)sizeof(struct 
_MODE_SENSE))) {
-        Srb->ScsiStatus = 0x40;
-        Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-        Srb->DataTransferLength = 0;
-        return;
-    }
-
-    // TODO : CDROM requires more ModePage entries
-    // Header
-    Header->ModeDataLength  = sizeof(MODE_PARAMETER_HEADER) - 1;
-    Header->MediumType      = 0;
-    Header->DeviceSpecificParameter = 0;
-    Header->BlockDescriptorLength   = 0;
-    LengthLeft -= sizeof(MODE_PARAMETER_HEADER);
-    CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_PARAMETER_HEADER));
+    const UCHAR             PageCode = Cdb_PageCode(Srb);
 
     // Fill in Block Parameters (if Specified and space)
     // when the DBD (Disable Block Descriptor) is set, ignore the block page
     if (Cdb_Dbd(Srb) == 0 &&
-        LengthLeft >= sizeof(MODE_PARAMETER_BLOCK)) {
-        PMODE_PARAMETER_BLOCK Block = (PMODE_PARAMETER_BLOCK)CurrentPage;
-        // Fill in BlockParams
-        Block->DensityCode                  =   0;
-        Block->NumberOfBlocks[0]            =   0;
-        Block->NumberOfBlocks[1]            =   0;
-        Block->NumberOfBlocks[2]            =   0;
-        Block->BlockLength[0]               =   0;
-        Block->BlockLength[1]               =   0;
-        Block->BlockLength[2]               =   0;
-
-        Header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
-        Header->ModeDataLength += sizeof(MODE_PARAMETER_BLOCK);
-        LengthLeft -= sizeof(MODE_PARAMETER_BLOCK);
-        CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_PARAMETER_BLOCK));
+        Length - *Size >= sizeof(MODE_PARAMETER_BLOCK)) {
+        // PMODE_PARAMETER_BLOCK Block = (PMODE_PARAMETER_BLOCK)((PUCHAR)Data 
+ *Size);
+
+        // Fill in BlockParams - All Zeroes
+
+        *BlockDescrLength   = sizeof(MODE_PARAMETER_BLOCK);
+        *ModeDataLength     += sizeof(MODE_PARAMETER_BLOCK);
+        *Size               += sizeof(MODE_PARAMETER_BLOCK);
     }
 
     // Fill in Cache Parameters (if Specified and space)
     if ((PageCode == MODE_PAGE_CACHING || PageCode == MODE_SENSE_RETURN_ALL) &&
-        LengthLeft >= MODE_CACHING_PAGE_LENGTH) {
-        PMODE_CACHING_PAGE Caching = (PMODE_CACHING_PAGE)CurrentPage;
+        Length - *Size >= sizeof(MODE_CACHING_PAGE)) {
+        PMODE_CACHING_PAGE Caching = (PMODE_CACHING_PAGE)((PUCHAR)Data + 
*Size);
+
         // Fill in CachingParams
-        Caching->PageCode                   = MODE_PAGE_CACHING;
-        Caching->PageSavable                = 0;
-        Caching->PageLength                 = MODE_CACHING_PAGE_LENGTH;
-        Caching->ReadDisableCache           = 0;
-        Caching->MultiplicationFactor       = 0;
-        Caching->WriteCacheEnable           = 
FrontendGetDiskInfo(Target->Frontend)->FlushCache ? 1 : 0;
-        Caching->WriteRetensionPriority     = 0;
-        Caching->ReadRetensionPriority      = 0;
-        Caching->DisablePrefetchTransfer[0] = 0;
-        Caching->DisablePrefetchTransfer[1] = 0;
-        Caching->MinimumPrefetch[0]         = 0;
-        Caching->MinimumPrefetch[1]         = 0;
-        Caching->MaximumPrefetch[0]         = 0;
-        Caching->MaximumPrefetch[1]         = 0;
-        Caching->MaximumPrefetchCeiling[0]  = 0;
-        Caching->MaximumPrefetchCeiling[1]  = 0;
-
-        Header->ModeDataLength += MODE_CACHING_PAGE_LENGTH;
-        LengthLeft -= MODE_CACHING_PAGE_LENGTH;
-        CurrentPage = ((PUCHAR)CurrentPage + MODE_CACHING_PAGE_LENGTH);
+        Caching->PageCode           = MODE_PAGE_CACHING;
+        Caching->PageLength         = sizeof(MODE_CACHING_PAGE);
+        Caching->WriteCacheEnable   = FrontendGetFlushCache(Target->Frontend) 
? 1 : 0;
+
+        *ModeDataLength += sizeof(MODE_CACHING_PAGE);
+        *Size           += sizeof(MODE_CACHING_PAGE);
     }
 
     // Fill in Informational Exception Parameters (if Specified and space)
     if ((PageCode == MODE_PAGE_FAULT_REPORTING || PageCode == 
MODE_SENSE_RETURN_ALL) &&
-        LengthLeft >= sizeof(MODE_INFO_EXCEPTIONS)) {
-        PMODE_INFO_EXCEPTIONS Exceptions = (PMODE_INFO_EXCEPTIONS)CurrentPage;
+        Length - *Size >= sizeof(MODE_INFO_EXCEPTIONS)) {
+        PMODE_INFO_EXCEPTIONS Exceptions = 
(PMODE_INFO_EXCEPTIONS)((PUCHAR)Data + *Size);
+
         // Fill in Exceptions
-        Exceptions->PageCode                = MODE_PAGE_FAULT_REPORTING;
-        Exceptions->PSBit                   = 0;
-        Exceptions->PageLength              = sizeof(MODE_INFO_EXCEPTIONS);
-        Exceptions->Flags                   = 0;
-        Exceptions->Dexcpt                  = 1; // disabled
-        Exceptions->ReportMethod            = 0;
-        Exceptions->IntervalTimer[0]        = 0;
-        Exceptions->IntervalTimer[1]        = 0;
-        Exceptions->IntervalTimer[2]        = 0;
-        Exceptions->IntervalTimer[3]        = 0;
-        Exceptions->ReportCount[0]          = 0;
-        Exceptions->ReportCount[1]          = 0;
-        Exceptions->ReportCount[2]          = 0;
-        Exceptions->ReportCount[3]          = 0;
-
-        Header->ModeDataLength += sizeof(MODE_INFO_EXCEPTIONS);
-        LengthLeft -= sizeof(MODE_INFO_EXCEPTIONS);
-        CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_INFO_EXCEPTIONS));
+        Exceptions->PageCode    = MODE_PAGE_FAULT_REPORTING;
+        Exceptions->PageLength  = sizeof(MODE_INFO_EXCEPTIONS);
+        Exceptions->Dexcpt      = 1; // disabled
+
+        *ModeDataLength += sizeof(MODE_INFO_EXCEPTIONS);
+        *Size           += sizeof(MODE_INFO_EXCEPTIONS);
     }
+}
+
+static DECLSPEC_NOINLINE VOID
+TargetModeSense(
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
+    )
+{
+    PMODE_PARAMETER_HEADER  Data  = Srb->DataBuffer;
+    ULONG                   Length = Srb->DataTransferLength;
+    ULONG                   BlockDescrLength = 0;
+    ULONG                   ModeDataLength = 0;
+    ULONG                   Size;
+
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
+        return;
+    RtlZeroMemory(Data, Length);
+
+    if (Length < sizeof(MODE_PARAMETER_HEADER))
+        return;
+
+    // Header
+    Data->MediumType                = 0;
+    Data->DeviceSpecificParameter   = FrontendGetReadOnly(Target->Frontend) ? 
+                                                    MODE_DSP_WRITE_PROTECT : 0;
+    Size = sizeof(MODE_PARAMETER_HEADER);
+
+    __TargetModeSense(Target,
+                      Srb,
+                      Data,
+                      Length,
+                      &Size,
+                      &ModeDataLength,
+                      &BlockDescrLength);
+    ASSERT3U(ModeDataLength, <=, 255 - (sizeof(MODE_PARAMETER_HEADER) - 1));
+    ASSERT3U(BlockDescrLength, <=, 255);
+
+    Data->ModeDataLength = (UCHAR)(ModeDataLength + 
sizeof(MODE_PARAMETER_HEADER) - 1);
+    Data->BlockDescriptorLength = (UCHAR)BlockDescrLength;
+
+    ASSERT3U(Size, <=, Length);
+    Srb->DataTransferLength = Size;
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static DECLSPEC_NOINLINE VOID
+TargetModeSense10(
+    IN  PXENVBD_TARGET          Target,
+    IN  PSCSI_REQUEST_BLOCK     Srb
+    )
+{
+    PMODE_PARAMETER_HEADER10    Data  = Srb->DataBuffer;
+    ULONG                       Length = Srb->DataTransferLength;
+    ULONG                       BlockDescrLength = 0;
+    ULONG                       ModeDataLength = 0;
+    ULONG                       Size;
+
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
+        return;
+    RtlZeroMemory(Data, Length);
+
+    if (Length < sizeof(MODE_PARAMETER_HEADER10))
+        return;
 
-    // Finish this SRB
+    // Header
+    Data->MediumType                = 0;
+    Data->DeviceSpecificParameter   = FrontendGetReadOnly(Target->Frontend) ? 
+                                                    MODE_DSP_WRITE_PROTECT : 0;
+    Size = sizeof(MODE_PARAMETER_HEADER10);
+
+    __TargetModeSense(Target,
+                      Srb,
+                      Data,
+                      Length,
+                      &Size,
+                      &ModeDataLength,
+                      &BlockDescrLength);
+    ASSERT3U(ModeDataLength, <=, 65535 - (sizeof(MODE_PARAMETER_HEADER10) - 
2));
+    ASSERT3U(BlockDescrLength, <=, 65535);
+
+    *(PUSHORT)Data->ModeDataLength = _byteswap_ushort((USHORT)ModeDataLength + 
+                                                      
sizeof(MODE_PARAMETER_HEADER10) - 2);
+    *(PUSHORT)Data->BlockDescriptorLength = 
_byteswap_ushort((USHORT)BlockDescrLength);
+
+    ASSERT3U(Size, <=, Length);
+    Srb->DataTransferLength = Size;
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
-    Srb->DataTransferLength = __min(Cdb_AllocationLength(Srb), 
(ULONG)(Header->ModeDataLength + 1));
 }
 
 static DECLSPEC_NOINLINE VOID
 TargetRequestSense(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    PSENSE_DATA         Sense = Srb->DataBuffer;
+    PSENSE_DATA             Data = Srb->DataBuffer;
+    ULONG                   Length = Srb->DataTransferLength;
 
     UNREFERENCED_PARAMETER(Target);
 
-    if (!__ValidateSrbBuffer(__FUNCTION__, Srb, (ULONG)sizeof(SENSE_DATA))) {
-        Srb->ScsiStatus = 0x40;
-        Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
         return;
-    }
+    RtlZeroMemory(Data, Length);
 
-    RtlZeroMemory(Sense, sizeof(SENSE_DATA));
+    if (Length < sizeof(SENSE_DATA))
+        return;
+
+    Data->ErrorCode            = 0x70;
+    Data->Valid                = 1;
+    Data->AdditionalSenseCodeQualifier = 0;
+    Data->SenseKey             = SCSI_SENSE_NO_SENSE;
+    Data->AdditionalSenseCode  = SCSI_ADSENSE_NO_SENSE;
 
-    Sense->ErrorCode            = 0x70;
-    Sense->Valid                = 1;
-    Sense->AdditionalSenseCodeQualifier = 0;
-    Sense->SenseKey             = SCSI_SENSE_NO_SENSE;
-    Sense->AdditionalSenseCode  = SCSI_ADSENSE_NO_SENSE;
     Srb->DataTransferLength     = sizeof(SENSE_DATA);
     Srb->SrbStatus              = SRB_STATUS_SUCCESS;
 }
 
 static DECLSPEC_NOINLINE VOID
 TargetReportLuns(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    ULONG           Length;
-    ULONG           Offset;
-    ULONG           AllocLength = Cdb_AllocationLength(Srb);
-    PUCHAR          Buffer = Srb->DataBuffer;
+    PLUN_LIST               Data = Srb->DataBuffer;
+    ULONG                   Length = Srb->DataTransferLength;
 
     UNREFERENCED_PARAMETER(Target);
 
-    if (!__ValidateSrbBuffer(__FUNCTION__, Srb, 8)) {
-        Srb->ScsiStatus = 0x40;
-        Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-        Srb->DataTransferLength = 0;
-        return;
-    }
-
-    RtlZeroMemory(Buffer, AllocLength);
-
-    Length = 0;
-    Offset = 8;
+    Srb->SrbStatus = SRB_STATUS_ERROR;
 
-    if (Offset + 8 <= AllocLength) {
-        Buffer[Offset] = 0;
-        Offset += 8;
-        Length += 8;
-    }
+    if (Data == NULL)
+        return;
+    RtlZeroMemory(Data, Length);
 
-    if (Offset + 8 <= AllocLength) {
-        Buffer[Offset] = XENVBD_MAX_TARGETS;
-        Offset += 8;
-        Length += 8;
-    }
+    if (Length < 16)
+        return;
 
-    REVERSE_BYTES(Buffer, &Length);
+    // UCHAR[4] @ Data
+    *(PULONG)Data->LunListLength = _byteswap_ulong(8);
+    // UCHAR[8] @ Data + 8
+    *(PULONG64)Data->Lun[0] = _byteswap_uint64(XENVBD_MAX_TARGETS);
 
-    Srb->DataTransferLength = __min(Length, AllocLength);
+    Srb->DataTransferLength = 16;
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
 static DECLSPEC_NOINLINE VOID
 TargetReadCapacity(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    PREAD_CAPACITY_DATA     Capacity = Srb->DataBuffer;
+    PREAD_CAPACITY_DATA     Data = Srb->DataBuffer;
+    ULONG                   Length = Srb->DataTransferLength;
     PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Target->Frontend);
     ULONG64                 SectorCount;
     ULONG                   SectorSize;
     ULONG                   LastBlock;
 
-    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
-        Srb->ScsiStatus = 0x02; // CHECK_CONDITION
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
+        return;
+    RtlZeroMemory(Data, Length);
+
+    if (Length < sizeof(READ_CAPACITY_DATA))
+        return;
+
+    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
         return;
-    }
 
     SectorCount = DiskInfo->SectorCount;
     SectorSize = DiskInfo->SectorSize;
@@ -535,21 +566,21 @@ TargetReadCapacity(
     else
         LastBlock = ~(ULONG)0;
 
-    if (Capacity) {
-        Capacity->LogicalBlockAddress = _byteswap_ulong(LastBlock);
-        Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
-    }
+    Data->LogicalBlockAddress = _byteswap_ulong(LastBlock);
+    Data->BytesPerBlock = _byteswap_ulong(SectorSize);
 
+    Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
 static DECLSPEC_NOINLINE VOID
 TargetReadCapacity16(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+    IN  PXENVBD_TARGET      Target,
+    IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    PREAD_CAPACITY16_DATA   Capacity = Srb->DataBuffer;
+    PREAD_CAPACITY16_DATA   Data = Srb->DataBuffer;
+    ULONG                   Length = Srb->DataTransferLength;
     PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Target->Frontend);
     ULONG64                 SectorCount;
     ULONG                   SectorSize;
@@ -557,10 +588,17 @@ TargetReadCapacity16(
     ULONG                   LogicalPerPhysical;
     ULONG                   LogicalPerPhysicalExponent;
 
-    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
-        Srb->ScsiStatus = 0x02; // CHECK_CONDITION
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
+        return;
+    RtlZeroMemory(Data, Length);
+
+    if (Length < sizeof(READ_CAPACITY16_DATA))
+        return;
+
+    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
         return;
-    }
 
     SectorCount = DiskInfo->SectorCount;
     SectorSize = DiskInfo->SectorSize;
@@ -571,12 +609,11 @@ TargetReadCapacity16(
     if (!_BitScanReverse(&LogicalPerPhysicalExponent, LogicalPerPhysical))
         LogicalPerPhysicalExponent = 0;
 
-    if (Capacity) {
-        Capacity->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount 
- 1);
-        Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
-        Capacity->LogicalPerPhysicalExponent = 
(UCHAR)LogicalPerPhysicalExponent;
-    }
+    Data->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount - 1);
+    Data->BytesPerBlock = _byteswap_ulong(SectorSize);
+    Data->LogicalPerPhysicalExponent = (UCHAR)LogicalPerPhysicalExponent;
 
+    Srb->DataTransferLength = sizeof(READ_CAPACITY16_DATA);
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
@@ -592,6 +629,11 @@ TargetInquiryStd(
     UNREFERENCED_PARAMETER(Target);
 
     Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
+        return;
+    RtlZeroMemory(Data, Length);
+
     if (Length < INQUIRYDATABUFFERSIZE)
         return;
 
@@ -621,9 +663,12 @@ TargetInquiry00(
 
     UNREFERENCED_PARAMETER(Target);
 
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+
+    if (Data == NULL)
+        return;
     RtlZeroMemory(Data, Length);
 
-    Srb->SrbStatus = SRB_STATUS_ERROR;
     if (Length < 7)
         return;
 
@@ -647,18 +692,18 @@ TargetInquiry80(
     PVOID                   Page;
     ULONG                   Size;
 
-    Page = FrontendGetInquiryOverride(Target->Frontend, 0x80, &Size);
+    Srb->SrbStatus = SRB_STATUS_ERROR;
 
+    if (Data == NULL)
+        return;
     RtlZeroMemory(Data, Length);
 
-    Srb->SrbStatus = SRB_STATUS_ERROR;
+    Page = FrontendGetInquiryOverride(Target->Frontend, 0x80, &Size);
     if (Page && Size) {
         if (Length < Size)
             return;
 
         RtlCopyMemory(Data, Page, Size);
-
-        Srb->DataTransferLength = Size;
     } else {
         CHAR                Serial[5];
 
@@ -673,9 +718,10 @@ TargetInquiry80(
                                   TargetGetTargetId(Target));
         RtlCopyMemory(Data->SerialNumber, Serial, 4);
 
-        Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
+        Size = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
     }
 
+    Srb->DataTransferLength = Size;
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
@@ -690,18 +736,18 @@ TargetInquiry83(
     PVOID                       Page;
     ULONG                       Size;
 
-    Page = FrontendGetInquiryOverride(Target->Frontend, 0x83, &Size);
+    Srb->SrbStatus = SRB_STATUS_ERROR;
 
+    if (Data == NULL)
+        return;
     RtlZeroMemory(Data, Length);
 
-    Srb->SrbStatus = SRB_STATUS_ERROR;
+    Page = FrontendGetInquiryOverride(Target->Frontend, 0x83, &Size);
     if (Page && Size) {
         if (Length < Size)
             return;
 
         RtlCopyMemory(Data, Page, Size);
-
-        Srb->DataTransferLength = Size;
     } else {
         PVPD_IDENTIFICATION_DESCRIPTOR  Id = 
(PVPD_IDENTIFICATION_DESCRIPTOR)&Data->Descriptors[0];
         CHAR                            Identifier[17];
@@ -722,10 +768,11 @@ TargetInquiry83(
                                   TargetGetTargetId(Target));
         RtlCopyMemory(Id->Identifier, Identifier, 16);
 
-        Srb->DataTransferLength = sizeof(VPD_IDENTIFICATION_PAGE) +
-                                  sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+        Size = sizeof(VPD_IDENTIFICATION_PAGE) +
+               sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
     }
 
+    Srb->DataTransferLength = Size;
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
@@ -845,6 +892,10 @@ TargetStartIo(
         TargetModeSense(Target, Srb);
         break;
 
+    case SCSIOP_MODE_SENSE10:
+        TargetModeSense10(Target, Srb);
+        break;
+
     case SCSIOP_REQUEST_SENSE:
         TargetRequestSense(Target, Srb);
         break;
-- 
2.8.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.