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

[win-pv-devel] [PATCH 07/26] Move ScatterGather list iteration to adapter.c



From: Owen Smith <owen.smith@xxxxxxxxxx>

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/adapter.c |  63 ++++++++++++++--
 src/xenvbd/adapter.h |   9 +++
 src/xenvbd/srbext.h  |   4 ++
 src/xenvbd/target.c  | 198 ++++++++++++---------------------------------------
 4 files changed, 118 insertions(+), 156 deletions(-)

diff --git a/src/xenvbd/adapter.c b/src/xenvbd/adapter.c
index 4ce9711..31b526f 100644
--- a/src/xenvbd/adapter.c
+++ b/src/xenvbd/adapter.c
@@ -1405,9 +1405,21 @@ AdapterPullupSrb(
     IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    // walk ScatterGather list, add bounces where needed
-    UNREFERENCED_PARAMETER(Adapter);
-    UNREFERENCED_PARAMETER(Srb);
+    PXENVBD_SRBEXT          SrbExt = Srb->SrbExtension;
+    UCHAR                   Operation;
+
+    Operation = Cdb_OperationEx(Srb);
+    switch (Operation) {
+    case SCSIOP_READ:
+    case SCSIOP_WRITE:
+        break;
+    default:
+        // only need to pullup for read/write
+        return TRUE;
+    }
+
+    SrbExt->SGList = StorPortGetScatterGatherList(Adapter, Srb);
+
     return TRUE;
 }
 
@@ -1417,9 +1429,50 @@ AdapterPulldownSrb(
     IN  PSCSI_REQUEST_BLOCK Srb
     )
 {
-    // foreach ScatterGather entry, unbounce it
+    PXENVBD_SRBEXT          SrbExt = Srb->SrbExtension;
+
     UNREFERENCED_PARAMETER(Adapter);
-    UNREFERENCED_PARAMETER(Srb);
+
+    SrbExt->SGList = NULL;
+    SrbExt->SGIndex = 0;
+    SrbExt->SGOffset = 0;
+}
+
+VOID
+AdapterGetNextSGEntry(
+    IN  PXENVBD_SRBEXT              SrbExt,
+    IN  ULONG                       ExistingLength,
+    OUT PPFN_NUMBER                 Pfn,
+    OUT PULONG                      Offset,
+    OUT PULONG                      Length
+    )
+{
+    PSTOR_SCATTER_GATHER_LIST       SGList;
+    PSTOR_SCATTER_GATHER_ELEMENT    SGElement;
+    STOR_PHYSICAL_ADDRESS           Addr;
+
+    SGList = SrbExt->SGList;
+    ASSERT(SGList != NULL);
+
+    ASSERT3U(SrbExt->SGIndex, <, SGList->NumberOfElements);
+
+    SGElement = &SGList->List[SrbExt->SGIndex];
+
+    Addr.QuadPart = SGElement->PhysicalAddress.QuadPart + SrbExt->SGOffset;
+
+    *Pfn    = (PFN_NUMBER)(Addr.QuadPart >> PAGE_SHIFT);
+    *Offset = (ULONG)(Addr.QuadPart & (PAGE_SIZE - 1));
+    *Length = __min(PAGE_SIZE - *Offset - ExistingLength,
+                    SGElement->Length - SrbExt->SGOffset);
+
+    ASSERT3U(*Length, <=, PAGE_SIZE);
+    ASSERT3U(SrbExt->SGOffset, <, SGElement->Length);
+
+    SrbExt->SGOffset += *Length;
+    if (SrbExt->SGOffset >= SGElement->Length) {
+        SrbExt->SGIndex++;
+        SrbExt->SGOffset = 0;
+    }
 }
 
 VOID
diff --git a/src/xenvbd/adapter.h b/src/xenvbd/adapter.h
index de8b691..133a09e 100644
--- a/src/xenvbd/adapter.h
+++ b/src/xenvbd/adapter.h
@@ -65,6 +65,15 @@ AdapterIsTargetEmulated(
     );
 
 extern VOID
+AdapterGetNextSGEntry(
+    IN  PXENVBD_SRBEXT  SrbExt,
+    IN  ULONG           ExistingLength,
+    OUT PPFN_NUMBER     Pfn,
+    OUT PULONG          Offset,
+    OUT PULONG          Length
+    );
+
+extern VOID
 AdapterCompleteSrb(
     IN  PXENVBD_ADAPTER Adapter,
     IN  PXENVBD_SRBEXT  SrbExt
diff --git a/src/xenvbd/srbext.h b/src/xenvbd/srbext.h
index 2e79de8..3380542 100644
--- a/src/xenvbd/srbext.h
+++ b/src/xenvbd/srbext.h
@@ -41,6 +41,10 @@ typedef struct _XENVBD_SRBEXT {
     PSCSI_REQUEST_BLOCK     Srb;
     LIST_ENTRY              ListEntry;
     LONG                    RequestCount;
+    // ScatterGather
+    PVOID                   SGList;
+    ULONG                   SGIndex;
+    ULONG                   SGOffset;
 } XENVBD_SRBEXT, *PXENVBD_SRBEXT;
 
 typedef struct _XENVBD_REQUEST {
diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c
index 5b14a73..6e5cb0d 100644
--- a/src/xenvbd/target.c
+++ b/src/xenvbd/target.c
@@ -123,92 +123,6 @@ struct _XENVBD_TARGET {
     NPAGED_LOOKASIDE_LIST       IndirectList;
 };
 
-typedef struct _XENVBD_SG_LIST {
-    // SGList from SRB
-    PSTOR_SCATTER_GATHER_LIST   SGList;
-    // "current" values
-    STOR_PHYSICAL_ADDRESS       PhysAddr;
-    ULONG                       PhysLen;
-    // iteration
-    ULONG                       Index;
-    ULONG                       Offset;
-    ULONG                       Length;
-} XENVBD_SG_LIST, *PXENVBD_SG_LIST;
-
-static FORCEINLINE VOID
-SGListInit(
-    IN OUT  PXENVBD_SG_LIST     SGList,
-    IN  PVOID                   Adapter,
-    IN  PSCSI_REQUEST_BLOCK     Srb
-    )
-{
-    RtlZeroMemory(SGList, sizeof(XENVBD_SG_LIST));
-    SGList->SGList = StorPortGetScatterGatherList(Adapter, Srb);
-}
-
-static FORCEINLINE VOID
-SGListGet(
-    IN OUT  PXENVBD_SG_LIST         SGList
-    )
-{
-    PSTOR_SCATTER_GATHER_ELEMENT    SGElement;
-    ULONG                           Offset;
-
-    ASSERT3U(SGList->Index, <, SGList->SGList->NumberOfElements);
-
-    SGElement = &SGList->SGList->List[SGList->Index];
-
-    SGList->PhysAddr.QuadPart = SGElement->PhysicalAddress.QuadPart + 
SGList->Offset;
-    Offset = (ULONG)(SGList->PhysAddr.QuadPart & (PAGE_SIZE - 1));
-    SGList->PhysLen           = __min(PAGE_SIZE - Offset - SGList->Length,
-                                      SGElement->Length - SGList->Offset);
-
-    ASSERT3U(SGList->PhysLen, <=, PAGE_SIZE);
-    ASSERT3U(SGList->Offset, <, SGElement->Length);
-
-    SGList->Length = SGList->PhysLen; // gets reset every time for Granted, 
every 1or2 times for Bounced
-    SGList->Offset = SGList->Offset + SGList->PhysLen;
-    if (SGList->Offset >= SGElement->Length) {
-        SGList->Index  = SGList->Index + 1;
-        SGList->Offset = 0;
-    }
-}
-
-static FORCEINLINE BOOLEAN
-SGListNext(
-    IN OUT  PXENVBD_SG_LIST         SGList,
-    IN  ULONG                       AlignmentMask
-    )
-{
-    SGList->Length = 0;
-    SGListGet(SGList);  // get next PhysAddr and PhysLen
-    return !((SGList->PhysAddr.QuadPart & AlignmentMask) || (SGList->PhysLen & 
AlignmentMask));
-}
-
-static FORCEINLINE PFN_NUMBER
-SGListPfn(
-    IN  PXENVBD_SG_LIST SGList
-    )
-{
-    return (PFN_NUMBER)(SGList->PhysAddr.QuadPart >> PAGE_SHIFT);
-}
-
-static FORCEINLINE ULONG
-SGListOffset(
-    IN  PXENVBD_SG_LIST SGList
-    )
-{
-    return (ULONG)(SGList->PhysAddr.QuadPart & (PAGE_SIZE - 1));
-}
-
-static FORCEINLINE ULONG
-SGListLength(
-    IN  PXENVBD_SG_LIST SGList
-    )
-{
-    return SGList->PhysLen;
-}
-
 static FORCEINLINE PVOID
 __TargetAllocate(
     IN  ULONG   Size
@@ -476,58 +390,6 @@ TargetPutRequest(
     ExFreeToNPagedLookasideList(&Target->RequestList, Request);
 }
 
-static FORCEINLINE BOOLEAN
-BufferMap(
-    IN  PXENVBD_SEGMENT Segment,
-    IN  PXENVBD_SG_LIST SGList,
-    IN  ULONG           Length
-    )
-{
-    // map PhysAddr to 1 or 2 pages and lock for VirtAddr
-#pragma warning(push)
-#pragma warning(disable:28145)
-    Segment->Mdl.Next           = NULL;
-    Segment->Mdl.Size           = (SHORT)(sizeof(MDL) + sizeof(PFN_NUMBER));
-    Segment->Mdl.MdlFlags       = MDL_PAGES_LOCKED;
-    Segment->Mdl.Process        = NULL;
-    Segment->Mdl.MappedSystemVa = NULL;
-    Segment->Mdl.StartVa        = NULL;
-    Segment->Mdl.ByteCount      = SGListLength(SGList);
-    Segment->Mdl.ByteOffset     = SGListOffset(SGList);
-    Segment->Pfn[0]             = SGListPfn(SGList);
-
-    if (Segment->Mdl.ByteCount < Length) {
-        // need part of next page
-        SGListGet(SGList);
-        Segment->Mdl.Size       += sizeof(PFN_NUMBER);
-        Segment->Mdl.ByteCount  = Segment->Mdl.ByteCount + 
SGListLength(SGList);
-        Segment->Pfn[1]         = SGListPfn(SGList);
-    }
-#pragma warning(pop)
-
-    ASSERT3U(Segment->Mdl.ByteCount, <=, PAGE_SIZE);
-    ASSERT3U(Segment->Mdl.ByteCount, ==, Length);
-                
-    Segment->Length = min(Segment->Mdl.ByteCount, PAGE_SIZE);
-    Segment->Buffer = MmMapLockedPagesSpecifyCache(&Segment->Mdl,
-                                                   KernelMode,
-                                                   MmCached,
-                                                   NULL,
-                                                   FALSE,
-                                                   NormalPagePriority);
-    if (Segment->Buffer == NULL)
-        goto fail;
-
-    ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[0], ==, Segment->Pfn[0]);
-    // if only 1 Pfn is used, this triggers an array-out-of-bounds condition!
-    //ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[1], ==, Segment->Pfn[1]);
- 
-    return TRUE;
-
-fail:
-    return FALSE;
-}
-
 static BOOLEAN
 TargetPrepareRW(
     IN  PXENVBD_TARGET  Target,
@@ -539,16 +401,12 @@ TargetPrepareRW(
     ULONG64             SectorStart = Cdb_LogicalBlock(Srb);
     ULONG               SectorsLeft = Cdb_TransferBlock(Srb);
     LIST_ENTRY          List;
-    XENVBD_SG_LIST      SGList;
     KIRQL               Irql;
     const ULONG         SectorSize = Target->SectorSize;
     const ULONG         SectorMask = SectorSize - 1;
     const ULONG         SectorsPerPage = PAGE_SIZE / SectorSize;
 
     InitializeListHead(&List);
-    SGListInit(&SGList, TargetGetAdapter(Target), Srb);
-
-    // validate SectorStart, SectorsLeft fits in this target (prevent 
read/write beyond extents)
 
     while (SectorsLeft > 0) {
         PXENVBD_REQUEST Request;
@@ -576,6 +434,8 @@ TargetPrepareRW(
             PXENVBD_SEGMENT Segment;
             ULONG           SectorsNow;
             PFN_NUMBER      Pfn;
+            ULONG           Offset;
+            ULONG           Length;
             NTSTATUS        status;
 
             if (SectorsLeft == 0)
@@ -587,24 +447,60 @@ TargetPrepareRW(
             InsertTailList(&Request->Segments, &Segment->ListEntry);
             ++Request->NrSegments;
 
-            if (SGListNext(&SGList, SectorMask)) {
-                ASSERT((SGListOffset(&SGList) & SectorMask) == 0);
-
-                Segment->FirstSector = (UCHAR)(SGListOffset(&SGList) / 
SectorSize);
+            AdapterGetNextSGEntry(SrbExt,
+                                  0,
+                                  &Pfn,
+                                  &Offset,
+                                  &Length);
+            if ((Offset & SectorMask) == 0 && (Length & SectorMask) == 0) {
+                Segment->FirstSector = (UCHAR)(Offset / SectorSize);
                 SectorsNow           = min(SectorsLeft, SectorsPerPage - 
Segment->FirstSector);
                 Segment->LastSector  = (UCHAR)(Segment->FirstSector + 
SectorsNow - 1);
-
-                Pfn = SGListPfn(&SGList);
             } else {
-                ASSERT((SGListOffset(&SGList) & SectorMask) != 0);
-
                 Segment->FirstSector = (UCHAR)0;
                 SectorsNow           = min(SectorsLeft, SectorsPerPage);
                 Segment->LastSector  = (UCHAR)(SectorsNow - 1);
 
-                if (!BufferMap(Segment, &SGList, SectorsNow * SectorSize))
+                // map PhysAddr to 1 or 2 pages and lock for VirtAddr
+#pragma warning(push)
+#pragma warning(disable:28145)
+                Segment->Mdl.Size           = (SHORT)(sizeof(MDL) + 
sizeof(PFN_NUMBER));
+                Segment->Mdl.MdlFlags       = MDL_PAGES_LOCKED;
+                Segment->Mdl.ByteCount      = Length;
+                Segment->Mdl.ByteOffset     = Offset;
+                Segment->Pfn[0]             = Pfn;
+
+                if (Segment->Mdl.ByteCount < SectorsNow * SectorSize) {
+                    // need part of next page
+                    AdapterGetNextSGEntry(SrbExt,
+                                          Length,
+                                          &Pfn,
+                                          &Offset,
+                                          &Length);
+                    ASSERT(Offset == 0);
+                    Segment->Mdl.Size       += sizeof(PFN_NUMBER);
+                    Segment->Mdl.ByteCount  = Segment->Mdl.ByteCount + Length;
+                    Segment->Pfn[1]         = Pfn;
+                }
+#pragma warning(pop)
+
+                ASSERT3U(Segment->Mdl.ByteCount, <=, PAGE_SIZE);
+                ASSERT3U(Segment->Mdl.ByteCount, ==, SectorsNow * SectorSize);
+
+                Segment->Length = Segment->Mdl.ByteCount;
+                Segment->Buffer = MmMapLockedPagesSpecifyCache(&Segment->Mdl,
+                                                               KernelMode,
+                                                               MmCached,
+                                                               NULL,
+                                                               FALSE,
+                                                               
NormalPagePriority);
+                if (Segment->Buffer == NULL)
                     goto fail3;
 
+                ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[0], ==, 
Segment->Pfn[0]);
+                // if only 1 Pfn is used, this triggers an array-out-of-bounds 
condition!
+                //ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[1], ==, 
Segment->Pfn[1]);
+
                 if (!BufferGet(Segment, &Segment->BufferId, &Pfn))
                     goto fail4;
 
-- 
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®.