Major refactoring: WIP

This commit is contained in:
Bill Zissimopoulos 2015-12-20 14:23:58 -08:00
parent e08e44d5f9
commit 7ef68a6688
3 changed files with 129 additions and 144 deletions

View File

@ -33,11 +33,12 @@ static NTSTATUS FspFsctlCreate(
PAGED_CODE(); PAGED_CODE();
FSP_FSCTL_FILE_CONTEXT2 *FsContext2; FSP_FSCTL_FILE_CONTEXT2 *FsContext2;
FsContext2 = FspAlloc(sizeof *FsContext2); FsContext2 = FspAllocNonPaged(sizeof *FsContext2);
if (0 == FsContext2) if (0 == FsContext2)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(FsContext2, sizeof *FsContext2); RtlZeroMemory(FsContext2, sizeof *FsContext2);
ExInitializeFastMutex(&FsContext2->FastMutex);
IrpSp->FileObject->FsContext2 = FsContext2; IrpSp->FileObject->FsContext2 = FsContext2;
Irp->IoStatus.Information = FILE_OPENED; Irp->IoStatus.Information = FILE_OPENED;

View File

@ -411,6 +411,7 @@ VOID FspDeviceDeleteAll(VOID);
/* fsctl file objects */ /* fsctl file objects */
typedef struct typedef struct
{ {
FAST_MUTEX FastMutex;
PDEVICE_OBJECT FsvolDeviceObject; PDEVICE_OBJECT FsvolDeviceObject;
} FSP_FSCTL_FILE_CONTEXT2; } FSP_FSCTL_FILE_CONTEXT2;

View File

@ -69,7 +69,6 @@ static NTSTATUS FspFsctlCreateVolume(
{ {
PAGED_CODE(); PAGED_CODE();
#if 0
/* check parameters */ /* check parameters */
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
@ -114,24 +113,22 @@ static NTSTATUS FspFsctlCreateVolume(
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]); Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
ASSERT(NT_SUCCESS(Result)); ASSERT(NT_SUCCESS(Result));
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); FSP_FSCTL_FILE_CONTEXT2 *FsContext2 = IrpSp->FileObject->FsContext2;
ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE); ExAcquireFastMutex(&FsContext2->FastMutex);
try try
{ {
HANDLE MupHandle = 0; /* check to see if we already have a volume */
PDEVICE_OBJECT FsvrtDeviceObject = 0; if (0 != FsContext2->FsvolDeviceObject)
PDEVICE_OBJECT FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
BOOLEAN Inserted;
/* quick check to see if we already have a volume */
FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject);
if (0 != FsvolDeviceObject)
{ {
Result = STATUS_ACCESS_DENIED; Result = STATUS_ACCESS_DENIED;
goto exit; goto exit;
} }
HANDLE MupHandle = 0;
PDEVICE_OBJECT FsvrtDeviceObject = 0;
PDEVICE_OBJECT FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
/* create the volume (and virtual disk) device(s) */ /* create the volume (and virtual disk) device(s) */
Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0, Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0,
DeviceObject->DeviceType, DeviceObject->DeviceType,
@ -175,9 +172,7 @@ static NTSTATUS FspFsctlCreateVolume(
} }
/* associate the new volume device with our file object */ /* associate the new volume device with our file object */
FspDeviceInsertContext(DeviceObject, (UINT_PTR)IrpSp->FileObject, FsvolDeviceObject, FsContext2->FsvolDeviceObject = FsvolDeviceObject;
&FsvolDeviceExtension->ElementStorage, &Inserted);
ASSERT(Inserted);
Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR); Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR);
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;
@ -186,13 +181,10 @@ static NTSTATUS FspFsctlCreateVolume(
} }
finally finally
{ {
ExReleaseResourceLite(&DeviceExtension->Resource); ExReleaseFastMutex(&FsContext2->FastMutex);
} }
return Result; return Result;
#else
return STATUS_INVALID_DEVICE_REQUEST;
#endif
} }
static NTSTATUS FspFsctlMountVolume( static NTSTATUS FspFsctlMountVolume(
@ -200,51 +192,51 @@ static NTSTATUS FspFsctlMountVolume(
{ {
PAGED_CODE(); PAGED_CODE();
#if 0
NTSTATUS Result; NTSTATUS Result;
PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb;
PDEVICE_OBJECT FsvrtDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
PDEVICE_OBJECT FsvolDeviceObject = 0;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = 0;
PDEVICE_OBJECT *DeviceObjects = 0;
ULONG DeviceObjectCount = 0;
KIRQL Irql;
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); /* check the passed in device object; it must be our own and not marked delete pending */
ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE); Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
try if (NT_SUCCESS(Result))
{ {
PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb; Result = STATUS_UNRECOGNIZED_VOLUME;
PDEVICE_OBJECT FsvrtDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject; for (ULONG i = 0; DeviceObjectCount > i; i++)
PDEVICE_OBJECT FsvolDeviceObject; if (FspDeviceRetain(DeviceObjects[i]))
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; {
if (FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObjects[i])->Kind)
/* quick check to see if we already have a volume */ {
FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject); FsvolDeviceObject = DeviceObjects[i];
if (0 != FsvolDeviceObject) FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
{ if (FsvolDeviceExtension->FsvrtDeviceObject == FsvrtDeviceObject &&
Result = STATUS_UNRECOGNIZED_VOLUME; !FsvolDeviceExtension->DeletePending)
goto exit; {
} Result = STATUS_SUCCESS;
break;
FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); }
if (FsvolDeviceExtension->DeletePending || }
FsvolDeviceExtension->FsvrtDeviceObject != FsvrtDeviceObject) FspDeviceRelease(DeviceObjects[i]);
{ }
Result = STATUS_UNRECOGNIZED_VOLUME; FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
goto exit;
}
Vpb->DeviceObject = FsvolDeviceObject;
Vpb->SerialNumber = FsvolDeviceExtension->VolumeParams.SerialNumber;
Irp->IoStatus.Information = 0;
Result = STATUS_SUCCESS;
exit:;
}
finally
{
ExReleaseResourceLite(&DeviceExtension->Resource);
} }
if (!NT_SUCCESS(Result))
return Result;
return Result; /* our volume device object has been FspDeviceRetain'ed */
#else ASSERT(0 != FsvolDeviceObject && 0 != FsvolDeviceExtension);
return STATUS_INVALID_DEVICE_REQUEST; IoAcquireVpbSpinLock(&Irql);
#endif Vpb->ReferenceCount++;
Vpb->DeviceObject = FsvolDeviceObject;
Vpb->SerialNumber = FsvolDeviceExtension->VolumeParams.SerialNumber;
IoReleaseVpbSpinLock(Irql);
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
} }
VOID FspFsctlDeleteVolume( VOID FspFsctlDeleteVolume(
@ -253,107 +245,99 @@ VOID FspFsctlDeleteVolume(
/* performed during IRP_MJ_CLEANUP! */ /* performed during IRP_MJ_CLEANUP! */
PAGED_CODE(); PAGED_CODE();
#if 0 FSP_FSCTL_FILE_CONTEXT2 *FsContext2 = IrpSp->FileObject->FsContext2;
PDEVICE_OBJECT FsvolDeviceObject = 0; PDEVICE_OBJECT FsvolDeviceObject = 0;
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); /*
ExAcquireResourceExclusiveLite(&DeviceExtension->Resource, TRUE); * Check to see if we have a volume. There is no need to protect this
try * access in FsContext2->FastMutex, because we are called during IRP_MJ_CLEANUP.
*/
FsvolDeviceObject = FsContext2->FsvolDeviceObject;
if (0 == FsvolDeviceObject)
return;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
/* mark the volume device as pending delete */
FsvolDeviceExtension->DeletePending = TRUE;
/* stop the I/O queue */
FspIoqStop(&FsvolDeviceExtension->Ioq);
/* do we have a virtual disk device or a MUP handle? */
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
{ {
FsvolDeviceObject = FspDeviceLookupContext(DeviceObject, (UINT_PTR)IrpSp->FileObject); PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
if (0 != FsvolDeviceObject) PVPB OldVpb;
FspDeviceDeleteContext(DeviceObject, (UINT_PTR)IrpSp->FileObject, 0); KIRQL Irql;
} BOOLEAN DeleteVpb = FALSE;
finally BOOLEAN DeleteDly = FALSE;
{ LARGE_INTEGER DelayTimeout;
ExReleaseResourceLite(&DeviceExtension->Resource);
}
if (0 != FsvolDeviceObject) /* swap the virtual disk device VPB with the preallocated one */
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
/* mark the volume device as pending delete */
FsvolDeviceExtension->DeletePending = TRUE;
/* stop the I/O queue */
FspIoqStop(&FsvolDeviceExtension->Ioq);
/* do we have a virtual disk device or a MUP handle? */
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
{
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
PVPB OldVpb;
KIRQL Irql;
BOOLEAN DeleteVpb = FALSE;
BOOLEAN DeleteDelayed = FALSE;
LARGE_INTEGER DelayTimeout;
/* swap the virtual disk device VPB with the preallocated one */
#pragma prefast(push) #pragma prefast(push)
#pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb") #pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb")
IoAcquireVpbSpinLock(&Irql); IoAcquireVpbSpinLock(&Irql);
OldVpb = FsvrtDeviceObject->Vpb; OldVpb = FsvrtDeviceObject->Vpb;
if (0 != OldVpb) if (0 != OldVpb)
{ {
FsvrtDeviceObject->Vpb = FsvolDeviceExtension->SwapVpb; FsvrtDeviceObject->Vpb = FsvolDeviceExtension->SwapVpb;
FsvrtDeviceObject->Vpb->Size = sizeof *FsvrtDeviceObject->Vpb; FsvrtDeviceObject->Vpb->Size = sizeof *FsvrtDeviceObject->Vpb;
FsvrtDeviceObject->Vpb->Type = IO_TYPE_VPB; FsvrtDeviceObject->Vpb->Type = IO_TYPE_VPB;
FsvrtDeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING); FsvrtDeviceObject->Vpb->Flags = FlagOn(OldVpb->Flags, VPB_REMOVE_PENDING);
FsvrtDeviceObject->Vpb->RealDevice = OldVpb->RealDevice; FsvrtDeviceObject->Vpb->RealDevice = OldVpb->RealDevice;
FsvrtDeviceObject->Vpb->RealDevice->Vpb = FsvrtDeviceObject->Vpb; FsvrtDeviceObject->Vpb->RealDevice->Vpb = FsvrtDeviceObject->Vpb;
DeleteVpb = 0 == OldVpb->ReferenceCount; DeleteVpb = 0 == OldVpb->ReferenceCount;
DeleteDelayed = !DeleteVpb; DeleteDly = 2 <= OldVpb->ReferenceCount;
if (DeleteDelayed) }
{ IoReleaseVpbSpinLock(Irql);
/* keep VPB around for delayed delete */ if (DeleteVpb)
OldVpb->ReferenceCount++; {
FsvolDeviceExtension->SwapVpb = OldVpb; /* no more references to the old VPB; delete now! */
} FspFreeExternal(OldVpb);
else FsvolDeviceExtension->SwapVpb = 0;
FsvolDeviceExtension->SwapVpb = 0; }
} else if (!DeleteDly)
IoReleaseVpbSpinLock(Irql); {
if (DeleteDelayed) /* there is only the reference from IRP_MN_MOUNT_VOLUME */
/* keep volume device object around for delayed delete */ FspFreeExternal(OldVpb);
FspDeviceRetain(FsvolDeviceObject); FsvolDeviceExtension->SwapVpb = 0;
else if (DeleteVpb) FspDeviceRelease(FsvolDeviceObject);
/* no more references to the old VPB; delete now! */ }
FspFreeExternal(OldVpb); else
/* keep VPB around for delayed delete */
FsvolDeviceExtension->SwapVpb = OldVpb;
#pragma prefast(pop) #pragma prefast(pop)
/* release the virtual disk and volume device objects */ /* release the virtual disk and volume device objects */
FspDeviceRelease(FsvrtDeviceObject); FspDeviceRelease(FsvrtDeviceObject);
FspDeviceRelease(FsvolDeviceObject); FspDeviceRelease(FsvolDeviceObject);
/* are we doing delayed delete of VPB and volume device object? */ /* are we doing delayed delete of VPB and volume device object? */
if (DeleteDelayed) if (DeleteDly)
{
DelayTimeout.QuadPart = 300/*ms*/ * -10000;
FspInitializeWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem,
FspFsctlDeleteVolumeDelayed, FsvolDeviceObject);
FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout);
}
}
else if (0 != FsvolDeviceExtension->MupHandle)
{ {
HANDLE MupHandle = FsvolDeviceExtension->MupHandle; DelayTimeout.QuadPart = 300/*ms*/ * -10000;
FspInitializeWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem,
FsRtlDeregisterUncProvider(MupHandle); FspFsctlDeleteVolumeDelayed, FsvolDeviceObject);
FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout);
/* release the volume device object */
FspDeviceRelease(FsvolDeviceObject);
} }
} }
#endif else if (0 != FsvolDeviceExtension->MupHandle)
{
HANDLE MupHandle = FsvolDeviceExtension->MupHandle;
FsRtlDeregisterUncProvider(MupHandle);
FsvolDeviceExtension->MupHandle = 0;
/* release the volume device object */
FspDeviceRelease(FsvolDeviceObject);
}
} }
static VOID FspFsctlDeleteVolumeDelayed(PVOID Context) static VOID FspFsctlDeleteVolumeDelayed(PVOID Context)
{ {
PAGED_CODE(); PAGED_CODE();
#if 0
PDEVICE_OBJECT FsvolDeviceObject = Context; PDEVICE_OBJECT FsvolDeviceObject = Context;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
KIRQL Irql; KIRQL Irql;
@ -377,7 +361,6 @@ static VOID FspFsctlDeleteVolumeDelayed(PVOID Context)
DelayTimeout.QuadPart = 300/*ms*/ * -10000; DelayTimeout.QuadPart = 300/*ms*/ * -10000;
FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout); FspQueueWorkItemWithDelay(&FsvolDeviceExtension->DeleteVolumeWorkItem, DelayTimeout);
} }
#endif
} }
static NTSTATUS FspFsctlTransact( static NTSTATUS FspFsctlTransact(