|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |