Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

Storport miniport: Win8 does not respect "MAXIMUM TRANSFER LENGTH" in Block Limits VPD

Bill_ZissimopoulosBill_Zissimopoulos Member Posts: 110

I have found that Windows (at least version 8) issues a Block Limits VPD inquiry to a Storport virtual miniport, but ignores the value returned in "MAXIMUM TRANSFER LENGTH". I regularly get READ/WRITE SRB's with DataTransferLength's greater than the value I advertise. (Please note that I am aware that "MAXIMUM TRANSFER LENGTH" is measured in blocks and I set it correctly.)

I have also found out that Windows does respect the value set in PPORT_CONFIGURATION_INFORMATION::MaximumTransferLength during HwFindAdapter. Because my virtual adapter purports to support multiple different virtual targets I set this value to SP_UNINITIALIZED_VALUE and was hoping to limit the DataTransferLength per target via the Block Limits VPD. Unfortunately this does not seem possible.

It looks like that if I want to limit data transfer lengths to different targets, I will have to break up I/O in my own miniport. I am wondering if any of the experts in this forum have any input on this.

Comments

  • Jamey_KirbyJamey_Kirby Member - All Emails Posts: 433
    via Email
    I usually fail all VPD inquiry requests with zero bytes transferred, and
    a SCSISTAT_CHECK_CONDITION. I don't quite remember why I had to do this,
    but I did have some issues between OS versions. So, I only return the
    standard inquiry data requests:

    Properly implementing READ_CAPACITY and READ_CAPACITY16 seemed to solve
    issues for me with getting out of bound read/write requests. It's been a
    while since i've worked on virtual storport drivers, so I am reaching back
    a few years.

    On Thu, Jan 10, 2019 at 4:23 PM Bill_Zissimopoulos
    wrote:

    > OSR https://community.osr.com/
    > Bill_Zissimopoulos started a new discussion: Storport miniport: Win8 does
    > not respect "MAXIMUM TRANSFER LENGTH" in Block Limits VPD
    >
    > I have found that Windows (at least version 8) issues a Block Limits VPD
    > inquiry to a Storport virtual miniport, but ignores the value returned in
    > "MAXIMUM TRANSFER LENGTH". I regularly get READ/WRITE SRB's with
    > DataTransferLength's greater than the value I advertise. (Please note that
    > I am aware that "MAXIMUM TRANSFER LENGTH" is measured in blocks and I set
    > it correctly.)
    >
    > I have also found out that Windows does respect the value set in
    > PPORT_CONFIGURATION_INFORMATION::MaximumTransferLength during
    > HwFindAdapter. Because my virtual adapter purports to support multiple
    > different virtual targets I set this value to SP_UNINITIALIZED_VALUE and
    > was hoping to limit the DataTransferLength per target via the Block Limits
    > VPD. Unfortunately this does not seem possible.
    >
    > It looks like that if I want to limit data transfer lengths to different
    > targets, I will have to break up I/O in my own miniport. I am wondering if
    > any of the experts in this forum have any input on this.
    >
    > --
    > Reply to this email directly or follow the link below to check it out:
    >
    > https://community.osr.com/discussion/290929/storport-miniport-win8-does-not-respect-maximum-transfer-length-in-block-limits-vpd
    >
    > Check it out:
    > https://community.osr.com/discussion/290929/storport-miniport-win8-does-not-respect-maximum-transfer-length-in-block-limits-vpd
    >
  • Peter_Viscarola_via_gmail_(OSR)Peter_Viscarola_via_gmail_(OSR) Member - All Emails Posts: 9

    Hmmmm…

    The maximum transfer limit is enforced by the Disk Class Driver. You can see the code in ClassPnP's UTILS.C module to build the request for VPD page 0xB0 (if BlockLimits is supported, of course). Look at ClasspDeviceGetBlockLimitsVPDPage. The code there shows how the request for the Block Limits page is sent and interpreted. Likewise, look in CLASS.C at the function ServiceTransferRequest and XFERPKT.C for InitializeTransferPackets where you'll see the Maximum Transfer Length enforced and the value returned by your Miniport taken into account.

    You should be able to debug this live on the system. The code for the Disk Class Driver is available in the WDK. Build the Disk.sys code, set some breakpoints and get to the root of the problem!

    Peter

  • Bill_ZissimopoulosBill_Zissimopoulos Member Posts: 110

    Peter Viscarola wrote:

    You can see the code in ClassPnP's UTILS.C module to build the request for VPD page 0xB0...

    Peter, these are great pointers. Thank you. I will study the relevant source code and see if I can figure out the problem.

    Jamie Kirby wrote:

    Properly implementing READ_CAPACITY and READ_CAPACITY16 seemed to solve
    issues for me with getting out of bound read/write requests.

    To clarify the issue is not getting LBA's out of bounds, but getting DataTransferLength's greater that what I have advertised (using the Block Limits VPD).

    Bill

  • Bill_ZissimopoulosBill_Zissimopoulos Member Posts: 110

    My analysis of the source code in ServiceTransferRequest indicates that the routine uses the Fdo->DeviceExtension->PrivateFdoData->HwMaxXferLen field to determine the Maximum Transfer Length and whether to split the request.

    This field is initialized in a few places:

    • InitializeTransferPackets in WDK8
    • InitializeTransferPackets and ClassReadDriveCapacity in current GitHub release

    In all cases the value returned by "Block Limits VPD" is ignored. So unless I am missing something it looks like I have to split I/O in my own miniport.

    Source code pointers to GitHub:

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 7,345

    Hmmm... Not so sure:

        hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
    
        fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
    

    adapterDesc->MaximumTransferLength is from the VPD... unless I'm mistaken.

    But, regardless, you'll see what's up for sure in the debugger. Take you 30 minutes and you'll have your answer.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Bill_ZissimopoulosBill_Zissimopoulos Member Posts: 110

    adapterDesc->MaximumTransferLength is from the VPD... unless I'm mistaken.

    I believe this comes from HwFindAdapter and PORT_CONFIGURATION_INFORMATION.

    Here is evidence from WinDbg that HwMaxXferLen is not related to the BlockLimitsVPD:

    kd> ?? ((_FUNCTIONAL_DEVICE_EXTENSION *)0xfffffa80032b4890)->PrivateFdoData->HwMaxXferLen
    unsigned long 0xffffe000
    kd> ?? ((_FUNCTIONAL_DEVICE_EXTENSION *)0xfffffa80032b4890)->FunctionSupportInfo->BlockLimitsData.MaximumTransferLength
    unsigned long 0x80
    

    (My miniport sets PORT_CONFIGURATION_INFORMATION:: MaximumTransferLength = SP_UNINITIALIZED_VALUE.)

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 7,345

    My head hurts.

    But the code doesn't lie, and you're looking right at it in the debugger. This is definitely not what I would have expected.

    OTOH, I've never returned SP_UNINITIALIZED_VALUE to StorPort either. And this VPD page is "relatively new" (you know, like... what... only 15 years old or something).

    Thanks for tracing along, AND getting back to us here on the forum. Sad, but it seems that you're going to have to do exactly as you proposed at the outset: Handle the max transfer length yourself, in your miniport. Yuck! That's something you're specifically not supposed to have to handle.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Bill_ZissimopoulosBill_Zissimopoulos Member Posts: 110

    Peter, thanks for confirming my understanding.

    Thanks for tracing along, AND getting back to us here on the forum.

    No problem, the NTDEV and NTFSD forums have been extremely helpful to me, so it is the least I can do.

    Sad, but it seems that you're going to have to do exactly as you proposed at the outset: Handle the max transfer length yourself, in your miniport. Yuck! That's something you're specifically not supposed to have to handle.

    I ended up doing exactly this and somehow it ended up not being very hairy. (Of course I may change my mind on this when I get some weird data corruption 2 years from now when I will have completely forgotten this discussion...)

    Thanks for your help!

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
Developing Minifilters 29 July 2019 OSR Seminar Space
Writing WDF Drivers 23 Sept 2019 OSR Seminar Space
Kernel Debugging 21 Oct 2019 OSR Seminar Space
Internals & Software Drivers 18 Nov 2019 Dulles, VA