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

Re: [win-pv-devel] [PATCH 3/3] Add XenDisk device upper filter



> -----Original Message-----
> From: win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx [mailto:win-pv-devel-
> bounces@xxxxxxxxxxxxxxxxxxxx] On Behalf Of Owen smith
> Sent: 22 September 2014 12:00
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith
> Subject: [win-pv-devel] [PATCH 3/3] Add XenDisk device upper filter
> 
> XenDisk intercepts and translates
> IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
> into SCSIOP_UNMAP SRBs. Storport will pass on these SCSIOP_UNMAP
> requests
> to XenVbd, which will create the appropriate BLKIF_OP_DISCARD requests.
> XenDisk is only neccessary because Storport does not do the translation
> to SCSIOP_UNMAP SRBs.
> 
> Signed-off-by: Owen smith <owen.smith@xxxxxxxxxx>
> ---
[snip]
> diff --git a/src/xendisk/pdo.c b/src/xendisk/pdo.c
> new file mode 100644
> index 0000000..c815a1e
> --- /dev/null
> +++ b/src/xendisk/pdo.c
> @@ -0,0 +1,2126 @@
> +/* Copyright (c) Citrix Systems Inc.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms,
> + * with or without modification, are permitted provided
> + * that the following conditions are met:
> + *
> + * *   Redistributions of source code must retain the above
> + *     copyright notice, this list of conditions and the
> + *     following disclaimer.
> + * *   Redistributions in binary form must reproduce the above
> + *     copyright notice, this list of conditions and the
> + *     following disclaimer in the documentation and/or other
> + *     materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#define INITGUID 1
> +
> +#include <ntddk.h>
> +#include <wdmguid.h>
> +#include <ntstrsafe.h>
> +#include <stdlib.h>
> +#include <storport.h>
> +#include <Ntddstor.h>
> +#include <Ntddscsi.h>
> +#include <names.h>
> +
> +#include "fdo.h"
> +#include "pdo.h"
> +#include "driver.h"
> +#include "thread.h"
> +#include "debug.h"
> +#include "assert.h"
> +#include "util.h"
> +
> +#define PDO_TAG 'ODP'
> +
> +struct _XENDISK_PDO {
> +    PXENDISK_DX                 Dx;
> +    PDEVICE_OBJECT              LowerDeviceObject;
> +    PDEVICE_OBJECT              PhysicalDeviceObject;
> +
> +    PXENDISK_THREAD             SystemPowerThread;
> +    PIRP                        SystemPowerIrp;
> +    PXENDISK_THREAD             DevicePowerThread;
> +    PIRP                        DevicePowerIrp;
> +
> +    PXENDISK_FDO                Fdo;
> +    BOOLEAN                     Missing;
> +    const CHAR                  *Reason;
> +
> +    ULONG                       SectorSize;
> +};
> +
> +static FORCEINLINE PVOID
> +__PdoAllocate(
> +    IN  ULONG   Length
> +    )
> +{
> +    return __AllocateNonPagedPoolWithTag(__FUNCTION__, __LINE__,
> Length, PDO_TAG);
> +}
> +
> +static FORCEINLINE VOID
> +__PdoFree(
> +    IN  PVOID   Buffer
> +    )
> +{
> +    __FreePoolWithTag(Buffer, PDO_TAG);
> +}
> +
> +static FORCEINLINE VOID
> +__PdoSetDevicePnpState(
> +    IN  PXENDISK_PDO        Pdo,
> +    IN  DEVICE_PNP_STATE    State
> +    )
> +{
> +    PXENDISK_DX             Dx = Pdo->Dx;
> +
> +    // We can never transition out of the deleted state
> +    ASSERT(Dx->DevicePnpState != Deleted || State == Deleted);
> +
> +    Dx->PreviousDevicePnpState = Dx->DevicePnpState;
> +    Dx->DevicePnpState = State;
> +}
> +
> +VOID
> +PdoSetDevicePnpState(
> +    IN  PXENDISK_PDO        Pdo,
> +    IN  DEVICE_PNP_STATE    State
> +    )
> +{
> +    __PdoSetDevicePnpState(Pdo, State);
> +}
> +
> +static FORCEINLINE VOID
> +__PdoRestoreDevicePnpState(
> +    IN  PXENDISK_PDO        Pdo,
> +    IN  DEVICE_PNP_STATE    State
> +    )
> +{
> +    PXENDISK_DX             Dx = Pdo->Dx;
> +
> +    if (Dx->DevicePnpState == State)
> +        Dx->DevicePnpState = Dx->PreviousDevicePnpState;
> +}
> +
> +static FORCEINLINE DEVICE_PNP_STATE
> +__PdoGetDevicePnpState(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    PXENDISK_DX         Dx = Pdo->Dx;
> +
> +    return Dx->DevicePnpState;
> +}
> +
> +DEVICE_PNP_STATE
> +PdoGetDevicePnpState(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    return __PdoGetDevicePnpState(Pdo);
> +}
> +
> +static FORCEINLINE VOID
> +__PdoSetDevicePowerState(
> +    IN  PXENDISK_PDO        Pdo,
> +    IN  DEVICE_POWER_STATE  State
> +    )
> +{
> +    PXENDISK_DX             Dx = Pdo->Dx;
> +
> +    Dx->DevicePowerState = State;
> +}
> +
> +static FORCEINLINE DEVICE_POWER_STATE
> +__PdoGetDevicePowerState(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    PXENDISK_DX         Dx = Pdo->Dx;
> +
> +    return Dx->DevicePowerState;
> +}
> +
> +static FORCEINLINE VOID
> +__PdoSetSystemPowerState(
> +    IN  PXENDISK_PDO        Pdo,
> +    IN  SYSTEM_POWER_STATE  State
> +    )
> +{
> +    PXENDISK_DX             Dx = Pdo->Dx;
> +
> +    Dx->SystemPowerState = State;
> +}
> +
> +static FORCEINLINE SYSTEM_POWER_STATE
> +__PdoGetSystemPowerState(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    PXENDISK_DX         Dx = Pdo->Dx;
> +
> +    return Dx->SystemPowerState;
> +}
> +
> +PDEVICE_OBJECT
> +PdoGetPhysicalDeviceObject(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    return Pdo->PhysicalDeviceObject;
> +}
> +
> +static FORCEINLINE VOID
> +__PdoSetMissing(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  const CHAR      *Reason
> +    )
> +{
> +    Pdo->Reason = Reason;
> +    Pdo->Missing = TRUE;
> +}
> +
> +VOID
> +PdoSetMissing(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  const CHAR      *Reason
> +    )
> +{
> +    __PdoSetMissing(Pdo, Reason);
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__PdoIsMissing(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    return Pdo->Missing;
> +}
> +
> +BOOLEAN
> +PdoIsMissing(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    return __PdoIsMissing(Pdo);
> +}
> +
> +static FORCEINLINE VOID
> +__PdoLink(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  PXENDISK_FDO    Fdo
> +    )
> +{
> +    Pdo->Fdo = Fdo;
> +    FdoAddPhysicalDeviceObject(Fdo, Pdo->Dx->DeviceObject);
> +}
> +
> +static FORCEINLINE VOID
> +__PdoUnlink(
> +    IN  PXENDISK_PDO    Pdo
> +    )
> +{
> +    PXENDISK_FDO        Fdo = Pdo->Fdo;
> +
> +    ASSERT(Fdo != NULL);
> +
> +    FdoRemovePhysicalDeviceObject(Fdo, Pdo->Dx->DeviceObject);
> +
> +    Pdo->Fdo = NULL;
> +}
> +
> +static FORCEINLINE PXENDISK_FDO
> +__PdoGetFdo(
> +    IN  PXENDISK_PDO Pdo
> +    )
> +{
> +    return Pdo->Fdo;
> +}
> +
> +__drv_functionClass(IO_COMPLETION_ROUTINE)
> +__drv_sameIRQL
> +static NTSTATUS
> +__PdoForwardIrpSynchronously(
> +    IN  PDEVICE_OBJECT  DeviceObject,
> +    IN  PIRP            Irp,
> +    IN  PVOID           Context
> +    )
> +{
> +    PKEVENT             Event = Context;
> +
> +    UNREFERENCED_PARAMETER(DeviceObject);
> +    UNREFERENCED_PARAMETER(Irp);
> +
> +    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
> +
> +    return STATUS_MORE_PROCESSING_REQUIRED;
> +}
> +
> +static NTSTATUS
> +PdoForwardIrpSynchronously(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  PIRP            Irp
> +    )
> +{
> +    KEVENT              Event;
> +    NTSTATUS            status;
> +
> +    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> +
> +    KeInitializeEvent(&Event, NotificationEvent, FALSE);
> +
> +    IoCopyCurrentIrpStackLocationToNext(Irp);
> +    IoSetCompletionRoutine(Irp,
> +                           __PdoForwardIrpSynchronously,
> +                           &Event,
> +                           TRUE,
> +                           TRUE,
> +                           TRUE);
> +
> +    status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
> +    if (status == STATUS_PENDING) {
> +        (VOID) KeWaitForSingleObject(&Event,
> +                                     Executive,
> +                                     KernelMode,
> +                                     FALSE,
> +                                     NULL);
> +        status = Irp->IoStatus.Status;
> +    } else {
> +        ASSERT3U(status, ==, Irp->IoStatus.Status);
> +    }
> +
> +    return status;
> +}
> +
> +__drv_functionClass(IO_COMPLETION_ROUTINE)
> +__drv_sameIRQL
> +static NTSTATUS
> +__PdoForwardIrpAndForget(
> +    IN  PDEVICE_OBJECT  DeviceObject,
> +    IN  PIRP            Irp,
> +    IN  PVOID           Context
> +    )
> +{
> +    PXENDISK_PDO        Pdo = Context;
> +
> +    UNREFERENCED_PARAMETER(DeviceObject);
> +
> +    if (Irp->PendingReturned)
> +        IoMarkIrpPending(Irp);
> +
> +    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
> +
> +    return STATUS_SUCCESS;
> +}
> +
> +static NTSTATUS
> +PdoForwardIrpAndForget(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  PIRP            Irp
> +    )
> +{
> +    IoCopyCurrentIrpStackLocationToNext(Irp);
> +    IoSetCompletionRoutine(Irp,
> +                            __PdoForwardIrpAndForget,
> +                            Pdo,
> +                            TRUE,
> +                            TRUE,
> +                            TRUE);
> +
> +    return IoCallDriver(Pdo->LowerDeviceObject, Irp);
> +}
> +
> +static NTSTATUS
> +PdoCompleteIrp(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  PIRP            Irp,
> +    IN  NTSTATUS        Status
> +    )
> +{
> +    Irp->IoStatus.Status = Status;
> +    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +    return Status;
> +}
> +
> +__drv_functionClass(IO_COMPLETION_ROUTINE)
> +__drv_sameIRQL
> +static NTSTATUS
> +__PdoQueryProperty(
> +    IN  PDEVICE_OBJECT  DeviceObject,
> +    IN  PIRP            Irp,
> +    IN  PVOID           Context
> +    )
> +{
> +    PXENDISK_PDO        Pdo = Context;
> +    PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR    Descriptor = Irp-
> >UserBuffer;
> +
> +    UNREFERENCED_PARAMETER(DeviceObject);
> +
> +    if (Irp->PendingReturned)
> +        IoMarkIrpPending(Irp);
> +
> +    if (!NT_SUCCESS(Irp->IoStatus.Status))
> +        goto done;
> +
> +    Descriptor = Irp->UserBuffer;
> +    Pdo->SectorSize = Descriptor->BytesPerLogicalSector;
> +    Verbose("%p : %u bytes per sector\n", Pdo->Dx->DeviceObject, Pdo-
> >SectorSize);
> +
> +done:
> +    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
> +
> +    return STATUS_SUCCESS;
> +}
> +
> +static DECLSPEC_NOINLINE NTSTATUS
> +PdoQueryProperty(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  PIRP            Irp
> +    )
> +{
> +    PSTORAGE_PROPERTY_QUERY Query;
> +    PDEVICE_TRIM_DESCRIPTOR Trim;
> +    NTSTATUS                status;
> +
> +    Query = Irp->AssociatedIrp.SystemBuffer;
> +
> +    switch (Query->PropertyId) {
> +    case StorageAccessAlignmentProperty:
> +        IoCopyCurrentIrpStackLocationToNext(Irp);
> +        IoSetCompletionRoutine(Irp,
> +                                __PdoQueryProperty,
> +                                Pdo,
> +                                TRUE,
> +                                TRUE,
> +                                TRUE);
> +
> +        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
> +        break;
> +
> +    case StorageDeviceTrimProperty:
> +        Trim = Irp->AssociatedIrp.SystemBuffer;
> +
> +        Trim->Version = 0;
> +        Trim->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
> +        Trim->TrimEnabled = TRUE;
> +
> +        Irp->IoStatus.Information =
> (ULONG_PTR)sizeof(DEVICE_TRIM_DESCRIPTOR);
> +        status = PdoCompleteIrp(Pdo, Irp, STATUS_SUCCESS);
> +        break;
> +
> +    default:
> +        status = PdoForwardIrpAndForget(Pdo, Irp);
> +        break;
> +    }
> +
> +    return status;
> +}
> +
> +__drv_functionClass(IO_COMPLETION_ROUTINE)
> +__drv_sameIRQL
> +static NTSTATUS
> +__PdoSendAwaitSrb(
> +    IN  PDEVICE_OBJECT          DeviceObject,
> +    IN  PIRP                    Irp,
> +    IN  PVOID                   Context
> +    )
> +{
> +    UNREFERENCED_PARAMETER(DeviceObject);
> +    UNREFERENCED_PARAMETER(Context);
> +
> +    *(Irp->UserIosb) = Irp->IoStatus;
> +
> +    if (Irp->MdlAddress) {
> +        MmUnlockPages(Irp->MdlAddress);
> +        IoFreeMdl(Irp->MdlAddress);
> +    }
> +
> +    KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);
> +
> +    IoFreeIrp(Irp);
> +    return STATUS_MORE_PROCESSING_REQUIRED;
> +}
> +
> +static NTSTATUS
> +PdoSendAwaitSrb(
> +    IN  PXENDISK_PDO            Pdo,
> +    IN  PSCSI_REQUEST_BLOCK     Srb
> +    )
> +{
> +    PIRP                        Irp;
> +    IO_STATUS_BLOCK             IoStatus;
> +    KEVENT                      Event;
> +    PIO_STACK_LOCATION          Stack;
> +    NTSTATUS                    status;
> +
> +    KeInitializeEvent(&Event, NotificationEvent, FALSE);
> +
> +    status = STATUS_NO_MEMORY;
> +    Irp = IoAllocateIrp((CCHAR)(Pdo->LowerDeviceObject->StackSize + 1),
> FALSE);
> +    if (Irp == NULL)
> +        goto fail1;
> +
> +    Stack = IoGetNextIrpStackLocation(Irp);
> +    Stack->MajorFunction = IRP_MJ_SCSI;
> +    Stack->Parameters.Scsi.Srb = Srb;
> +
> +    IoSetCompletionRoutine(Irp,
> +                            __PdoSendAwaitSrb,
> +                            Srb,
> +                            TRUE,
> +                            TRUE,
> +                            TRUE);
> +    Irp->UserIosb = &IoStatus;
> +    Irp->UserEvent = &Event;
> +
> +    Irp->MdlAddress = IoAllocateMdl(Srb->DataBuffer,
> +                                    Srb->DataTransferLength,
> +                                    FALSE,
> +                                    FALSE,
> +                                    Irp);
> +    if (Irp->MdlAddress == NULL)
> +        goto fail2;
> +
> +#pragma warning(disable:6320)
> +    try {
> +        MmProbeAndLockPages(Irp->MdlAddress, KernelMode,
> IoReadAccess);
> +    } except (EXCEPTION_EXECUTE_HANDLER) {
> +        status = GetExceptionCode();
> +
> +        goto fail3;
> +    }
> +#pragma warning(default:6320)
> +
> +    Srb->OriginalRequest = Irp;
> +
> +    status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
> +    if (status == STATUS_PENDING) {
> +        (VOID) KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE,
> NULL);
> +        status = IoStatus.Status;
> +    }
> +
> +    return status;
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    IoFreeMdl(Irp->MdlAddress);
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    IoFreeIrp(Irp);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +static FORCEINLINE VOID
> +__Set8Bytes(
> +    IN  PUCHAR                  Bytes,
> +    IN  ULONGLONG               Value
> +    )
> +{
> +    Bytes[0] = (UCHAR)(Value >> 56);
> +    Bytes[1] = (UCHAR)(Value >> 48);
> +    Bytes[2] = (UCHAR)(Value >> 40);
> +    Bytes[3] = (UCHAR)(Value >> 32);
> +    Bytes[4] = (UCHAR)(Value >> 24);
> +    Bytes[5] = (UCHAR)(Value >> 16);
> +    Bytes[6] = (UCHAR)(Value >> 8);
> +    Bytes[7] = (UCHAR)(Value);
> +}
> +
> +static FORCEINLINE VOID
> +__Set4Bytes(
> +    IN  PUCHAR                  Bytes,
> +    IN  ULONG                   Value
> +    )
> +{
> +    Bytes[0] = (UCHAR)(Value >> 24);
> +    Bytes[1] = (UCHAR)(Value >> 16);
> +    Bytes[2] = (UCHAR)(Value >> 8);
> +    Bytes[3] = (UCHAR)(Value);
> +}
> +
> +static FORCEINLINE VOID
> +__Set2Bytes(
> +    IN  PUCHAR                  Bytes,
> +    IN  USHORT                  Value
> +    )
> +{
> +    Bytes[0] = (UCHAR)(Value << 8);
> +    Bytes[1] = (UCHAR)(Value);
> +}
> +

I think you should use intrinsics for the above 3 functions.

> +static FORCEINLINE VOID
> +__SetUnmap(
> +    IN  PUNMAP_LIST_HEADER      Unmap,
> +    IN  ULONG                   Length,
> +    IN  PDEVICE_DATA_SET_RANGE  Ranges,
> +    IN  ULONG                   Count,
> +    IN  ULONG                   SectorSize
> +    )
> +{
> +    ULONG       Index;
> +
> +    __Set2Bytes(Unmap->DataLength, (USHORT)Length);
> +    __Set2Bytes(Unmap->BlockDescrDataLength,
> (USHORT)sizeof(UNMAP_BLOCK_DESCRIPTOR));
> +
> +    for (Index = 0; Index < Count; ++Index) {
> +        Trace("TRIM[%x] %x @ %llx\n",
> +                        Index,
> +                        (ULONG)(Ranges[Index].LengthInBytes / SectorSize),
> +                        (ULONG64)(Ranges[Index].StartingOffset / 
> SectorSize));
> +
> +        __Set8Bytes(Unmap->Descriptors[Index].StartingLba,
> +                        (ULONG64)(Ranges[Index].StartingOffset / 
> SectorSize));
> +        __Set4Bytes(Unmap->Descriptors[Index].LbaCount,
> +                        (ULONG)(Ranges[Index].LengthInBytes / SectorSize));
> +    }
> +}
> +
> +static NTSTATUS
> +PdoSendTrimSynchronous(
> +    IN  PXENDISK_PDO            Pdo,
> +    IN  PDEVICE_DATA_SET_RANGE  Ranges,
> +    IN  ULONG                   Count
> +    )
> +{
> +    SCSI_REQUEST_BLOCK          Srb;
> +    PCDB                        Cdb;
> +    PUNMAP_LIST_HEADER          Unmap;
> +    ULONG                       Length;
> +    NTSTATUS                    status;
> +
> +    Length = sizeof(UNMAP_LIST_HEADER) + Count *
> sizeof(UNMAP_BLOCK_DESCRIPTOR);

I know they are not necessary, but could we have brackets around the 
multiplication?

> +
> +    status = STATUS_NO_MEMORY;
> +    Unmap = __PdoAllocate(Length);
> +    if (Unmap == NULL)
> +        goto fail1;
> +
> +    RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
> +    Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
> +    Srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE |
> SRB_FLAGS_NO_QUEUE_FREEZE;

Do we want to bypass a frozen queue here?

  Paul

> +    Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
> +    Srb.DataBuffer = Unmap;
> +    Srb.DataTransferLength = Length;
> +    Srb.TimeOutValue = (ULONG)-1;
> +    Srb.CdbLength = 10;
> +
> +    Cdb = (PCDB)&Srb.Cdb[0];
> +    Cdb->UNMAP.OperationCode = SCSIOP_UNMAP;
> +    __Set2Bytes(Cdb->UNMAP.AllocationLength, (USHORT)Length);
> +
> +    __SetUnmap(Unmap, Length, Ranges, Count, Pdo->SectorSize);
> +
> +    status = PdoSendAwaitSrb(Pdo, &Srb);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    __PdoFree(Unmap);
> +    return status;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    __PdoFree(Unmap);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +static DECLSPEC_NOINLINE NTSTATUS
> +PdoManageDataSetAttributes(
> +    IN  PXENDISK_PDO    Pdo,
> +    IN  PIRP            Irp
> +    )
> +{
> +    PDEVICE_MANAGE_DATA_SET_ATTRIBUTES  Attributes;
> +    PDEVICE_DATA_SET_RANGE              Ranges;
> +    ULONG                               NumRanges;
> +    NTSTATUS                            status;
> +
> +    Attributes = Irp->AssociatedIrp.SystemBuffer;
> +
> +    switch (Attributes->Action) {
> +    case DeviceDsmAction_Trim:
> +        Ranges = (PDEVICE_DATA_SET_RANGE)((PUCHAR)Attributes +
> Attributes->DataSetRangesOffset);
> +        NumRanges = Attributes->DataSetRangesLength /
> sizeof(DEVICE_DATA_SET_RANGE);
> +
> +        status = PdoSendTrimSynchronous(Pdo, Ranges, NumRanges);
> +
> +        status = PdoCompleteIrp(Pdo, Irp, status);
> +        break;
> +
> +    default:
> +        status = PdoForwardIrpAndForget(Pdo, Irp);
> +        break;
> +    }
> +
> +    return status;
> +}
> +
[snip]
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://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®.