[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 |