reactos/drivers/filesystems/reiserfs/src/memory.c
Timo Kreuzer 2944d29969 [REISERFS] Convert a tab to spaces
Fixes GCC 8 warning:
drivers/filesystems/reiserfs/src/memory.c:874:5: error: this 'if' clause does not guard... [-Werror=misleading-indentation]
     if (Mcb->RfsdFcb)
     ^~
drivers/filesystems/reiserfs/src/memory.c:877:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  if (RfsdLoadInode(Vcb, &(Mcb->Key), &RfsdIno)) {
  ^~
2019-05-27 13:22:40 +02:00

1675 lines
43 KiB
C

/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: memory.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
* HOMEPAGE:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "rfsd.h"
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdAllocateIrpContext)
#pragma alloc_text(PAGE, RfsdFreeIrpContext)
#pragma alloc_text(PAGE, RfsdAllocateFcb)
#pragma alloc_text(PAGE, RfsdFreeFcb)
#pragma alloc_text(PAGE, RfsdAllocateMcb)
#pragma alloc_text(PAGE, RfsdSearchMcbTree)
#pragma alloc_text(PAGE, RfsdSearchMcb)
#pragma alloc_text(PAGE, RfsdGetFullFileName)
#pragma alloc_text(PAGE, RfsdRefreshMcb)
#pragma alloc_text(PAGE, RfsdAddMcbNode)
#pragma alloc_text(PAGE, RfsdDeleteMcbNode)
#pragma alloc_text(PAGE, RfsdFreeMcbTree)
#if !RFSD_READ_ONLY
#pragma alloc_text(PAGE, RfsdCheckBitmapConsistency)
#pragma alloc_text(PAGE, RfsdCheckSetBlock)
#endif // !RFSD_READ_ONLY
#pragma alloc_text(PAGE, RfsdInitializeVcb)
#pragma alloc_text(PAGE, RfsdFreeCcb)
#pragma alloc_text(PAGE, RfsdAllocateCcb)
#pragma alloc_text(PAGE, RfsdFreeVcb)
#pragma alloc_text(PAGE, RfsdCreateFcbFromMcb)
#pragma alloc_text(PAGE, RfsdSyncUninitializeCacheMap)
#endif
__drv_mustHoldCriticalRegion
PRFSD_IRP_CONTEXT
RfsdAllocateIrpContext (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
PIO_STACK_LOCATION IoStackLocation;
PRFSD_IRP_CONTEXT IrpContext;
PAGED_CODE();
ASSERT(DeviceObject != NULL);
ASSERT(Irp != NULL);
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
IrpContext = (PRFSD_IRP_CONTEXT) (
ExAllocateFromNPagedLookasideList(
&(RfsdGlobal->RfsdIrpContextLookasideList)));
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
if (IrpContext == NULL) {
IrpContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(RFSD_IRP_CONTEXT), RFSD_POOL_TAG);
//
// Zero out the irp context and indicate that it is from pool and
// not region allocated
//
RtlZeroMemory(IrpContext, sizeof(RFSD_IRP_CONTEXT));
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL);
} else {
//
// Zero out the irp context and indicate that it is from zone and
// not pool allocated
//
RtlZeroMemory(IrpContext, sizeof(RFSD_IRP_CONTEXT) );
}
if (!IrpContext) {
return NULL;
}
IrpContext->Identifier.Type = RFSDICX;
IrpContext->Identifier.Size = sizeof(RFSD_IRP_CONTEXT);
IrpContext->Irp = Irp;
IrpContext->MajorFunction = IoStackLocation->MajorFunction;
IrpContext->MinorFunction = IoStackLocation->MinorFunction;
IrpContext->DeviceObject = DeviceObject;
IrpContext->FileObject = IoStackLocation->FileObject;
if (IrpContext->FileObject != NULL) {
IrpContext->RealDevice = IrpContext->FileObject->DeviceObject;
} else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {
if (IoStackLocation->Parameters.MountVolume.Vpb) {
IrpContext->RealDevice =
IoStackLocation->Parameters.MountVolume.Vpb->RealDevice;
}
}
if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
IrpContext->MajorFunction == IRP_MJ_SHUTDOWN) {
IrpContext->IsSynchronous = TRUE;
} else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP ||
IrpContext->MajorFunction == IRP_MJ_CLOSE) {
IrpContext->IsSynchronous = FALSE;
}
#if (_WIN32_WINNT >= 0x0500)
else if (IrpContext->MajorFunction == IRP_MJ_PNP) {
if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {
IrpContext->IsSynchronous = TRUE;
} else {
IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
}
}
#endif //(_WIN32_WINNT >= 0x0500)
else {
IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
}
#if 0
//
// Temporary workaround for a bug in close that makes it reference a
// fileobject when it is no longer valid.
//
if (IrpContext->MajorFunction == IRP_MJ_CLOSE) {
IrpContext->IsSynchronous = TRUE;
}
#endif
IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
IrpContext->ExceptionInProgress = FALSE;
return IrpContext;
}
NTSTATUS
RfsdCompleteIrpContext (
IN PRFSD_IRP_CONTEXT IrpContext,
IN NTSTATUS Status )
{
PIRP Irp = NULL;
BOOLEAN bPrint;
Irp = IrpContext->Irp;
if (Irp != NULL) {
if (NT_ERROR(Status)) {
Irp->IoStatus.Information = 0;
}
Irp->IoStatus.Status = Status;
bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
RfsdCompleteRequest(
Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)?
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
IrpContext->Irp = NULL;
}
RfsdFreeIrpContext(IrpContext);
return Status;
}
__drv_mustHoldCriticalRegion
VOID
RfsdFreeIrpContext (IN PRFSD_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
RfsdUnpinRepinnedBcbs(IrpContext);
// Return the Irp context record to the region or to pool depending on
// its flag
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL)) {
IrpContext->Identifier.Type = 0;
IrpContext->Identifier.Size = 0;
ExFreePool( IrpContext );
} else {
IrpContext->Identifier.Type = 0;
IrpContext->Identifier.Size = 0;
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdIrpContextLookasideList), IrpContext);
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
}
}
VOID
RfsdRepinBcb (
IN PRFSD_IRP_CONTEXT IrpContext,
IN PBCB Bcb
)
{
PRFSD_REPINNED_BCBS Repinned;
Repinned = &IrpContext->Repinned;
return;
#if 0
ULONG i;
while (Repinned) {
for (i = 0; i < RFSD_REPINNED_BCBS_ARRAY_SIZE; i += 1) {
if (Repinned->Bcb[i] == Bcb) {
return;
}
}
Repinned = Repinned->Next;
}
while (TRUE) {
for (i = 0; i < RFSD_REPINNED_BCBS_ARRAY_SIZE; i += 1) {
if (Repinned->Bcb[i] == Bcb) {
return;
}
if (Repinned->Bcb[i] == NULL) {
Repinned->Bcb[i] = Bcb;
CcRepinBcb( Bcb );
return;
}
}
if (Repinned->Next == NULL) {
Repinned->Next = ExAllocatePoolWithTag(PagedPool, sizeof(RFSD_REPINNED_BCBS), RFSD_POOL_TAG);
RtlZeroMemory( Repinned->Next, sizeof(RFSD_REPINNED_BCBS) );
}
Repinned = Repinned->Next;
}
#endif
}
VOID
RfsdUnpinRepinnedBcbs (
IN PRFSD_IRP_CONTEXT IrpContext
)
{
IO_STATUS_BLOCK RaiseIosb;
PRFSD_REPINNED_BCBS Repinned;
BOOLEAN WriteThroughToDisk;
PFILE_OBJECT FileObject = NULL;
BOOLEAN ForceVerify = FALSE;
ULONG i;
Repinned = &IrpContext->Repinned;
RaiseIosb.Status = STATUS_SUCCESS;
WriteThroughToDisk = (BOOLEAN) (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY));
while (Repinned != NULL) {
for (i = 0; i < RFSD_REPINNED_BCBS_ARRAY_SIZE; i += 1) {
if (Repinned->Bcb[i] != NULL) {
IO_STATUS_BLOCK Iosb;
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) ) {
FileObject = CcGetFileObjectFromBcb( Repinned->Bcb[i] );
}
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
CcUnpinRepinnedBcb( Repinned->Bcb[i],
WriteThroughToDisk,
&Iosb );
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
if ( !NT_SUCCESS(Iosb.Status) ) {
if (RaiseIosb.Status == STATUS_SUCCESS) {
RaiseIosb = Iosb;
}
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) &&
(IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
(IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
(IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION)) {
CcPurgeCacheSection( FileObject->SectionObjectPointer,
NULL,
0,
FALSE );
ForceVerify = TRUE;
}
}
Repinned->Bcb[i] = NULL;
} else {
break;
}
}
if (Repinned != &IrpContext->Repinned)
{
PRFSD_REPINNED_BCBS Saved;
Saved = Repinned->Next;
ExFreePool( Repinned );
Repinned = Saved;
} else {
Repinned = Repinned->Next;
IrpContext->Repinned.Next = NULL;
}
}
if (!NT_SUCCESS(RaiseIosb.Status)) {
DbgBreak();
if (ForceVerify && FileObject) {
SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
FileObject->DeviceObject );
}
IrpContext->Irp->IoStatus = RaiseIosb;
RfsdNormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status );
}
return;
}
__drv_mustHoldCriticalRegion
PRFSD_FCB
RfsdAllocateFcb (IN PRFSD_VCB Vcb,
IN PRFSD_MCB RfsdMcb,
IN PRFSD_INODE Inode )
{
PRFSD_FCB Fcb;
PAGED_CODE();
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
Fcb = (PRFSD_FCB) ExAllocateFromNPagedLookasideList(
&(RfsdGlobal->RfsdFcbLookasideList));
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
if (Fcb == NULL) {
Fcb = (PRFSD_FCB) ExAllocatePoolWithTag(NonPagedPool, sizeof(RFSD_FCB), RFSD_POOL_TAG);
RtlZeroMemory(Fcb, sizeof(RFSD_FCB));
SetFlag(Fcb->Flags, FCB_FROM_POOL);
} else {
RtlZeroMemory(Fcb, sizeof(RFSD_FCB));
}
if (!Fcb) {
return NULL;
}
Fcb->Identifier.Type = RFSDFCB;
Fcb->Identifier.Size = sizeof(RFSD_FCB);
FsRtlInitializeFileLock (
&Fcb->FileLockAnchor,
NULL,
NULL );
Fcb->OpenHandleCount = 0;
Fcb->ReferenceCount = 0;
Fcb->Vcb = Vcb;
#if DBG
Fcb->AnsiFileName.MaximumLength = (USHORT)
RfsdUnicodeToOEMSize(&(RfsdMcb->ShortName)) + 1;
Fcb->AnsiFileName.Buffer = (PUCHAR)
ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, RFSD_POOL_TAG);
if (!Fcb->AnsiFileName.Buffer) {
goto errorout;
}
RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);
RfsdUnicodeToOEM( &(Fcb->AnsiFileName),
&(RfsdMcb->ShortName));
#endif
RfsdMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
if (S_ISDIR(Inode->i_mode)) {
SetFlag(RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
}
if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
RfsdIsReadOnly(Inode->i_mode)) {
SetFlag(RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
}
Fcb->Inode = Inode;
Fcb->RfsdMcb = RfsdMcb;
RfsdMcb->RfsdFcb = Fcb;
RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));
Fcb->Header.NodeTypeCode = (USHORT) RFSDFCB;
Fcb->Header.NodeByteSize = sizeof(RFSD_FCB);
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
Fcb->Header.Resource = &(Fcb->MainResource);
Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);
// NOTE: In EXT2, the low part was stored in i_size (a 32-bit value); the high part would be stored in the acl field...
// However, on ReiserFS, the i_size is a 64-bit value.
Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size;
Fcb->Header.AllocationSize.QuadPart =
CEILING_ALIGNED(Fcb->Header.FileSize.QuadPart, (ULONGLONG)Vcb->BlockSize);
Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
Fcb->SectionObject.DataSectionObject = NULL;
Fcb->SectionObject.SharedCacheMap = NULL;
Fcb->SectionObject.ImageSectionObject = NULL;
ExInitializeResourceLite(&(Fcb->MainResource));
ExInitializeResourceLite(&(Fcb->PagingIoResource));
InsertTailList(&Vcb->FcbList, &Fcb->Next);
#if DBG
ExAcquireResourceExclusiveLite(
&RfsdGlobal->CountResource,
TRUE );
RfsdGlobal->FcbAllocated++;
ExReleaseResourceForThreadLite(
&RfsdGlobal->CountResource,
ExGetCurrentResourceThread() );
#endif
return Fcb;
#if DBG
errorout:
#endif
if (Fcb) {
#if DBG
if (Fcb->AnsiFileName.Buffer)
ExFreePool(Fcb->AnsiFileName.Buffer);
#endif
if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) {
ExFreePool( Fcb );
} else {
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdFcbLookasideList), Fcb);
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
}
}
return NULL;
}
__drv_mustHoldCriticalRegion
VOID
RfsdFreeFcb (IN PRFSD_FCB Fcb)
{
PRFSD_VCB Vcb;
PAGED_CODE();
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
(Fcb->Identifier.Size == sizeof(RFSD_FCB)));
Vcb = Fcb->Vcb;
FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
ExDeleteResourceLite(&Fcb->MainResource);
ExDeleteResourceLite(&Fcb->PagingIoResource);
Fcb->RfsdMcb->RfsdFcb = NULL;
if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
if (Fcb->RfsdMcb) {
RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
RfsdFreeMcb(Fcb->RfsdMcb);
}
}
if (Fcb->LongName.Buffer) {
ExFreePool(Fcb->LongName.Buffer);
Fcb->LongName.Buffer = NULL;
}
#if DBG
ExFreePool(Fcb->AnsiFileName.Buffer);
#endif
ExFreePool(Fcb->Inode);
Fcb->Header.NodeTypeCode = (SHORT)0xCCCC;
Fcb->Header.NodeByteSize = (SHORT)0xC0C0;
if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) {
ExFreePool( Fcb );
} else {
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdFcbLookasideList), Fcb);
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
}
#if DBG
ExAcquireResourceExclusiveLite(
&RfsdGlobal->CountResource,
TRUE );
RfsdGlobal->FcbAllocated--;
ExReleaseResourceForThreadLite(
&RfsdGlobal->CountResource,
ExGetCurrentResourceThread() );
#endif
}
__drv_mustHoldCriticalRegion
PRFSD_CCB
RfsdAllocateCcb (VOID)
{
PRFSD_CCB Ccb;
PAGED_CODE();
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
Ccb = (PRFSD_CCB) (ExAllocateFromNPagedLookasideList( &(RfsdGlobal->RfsdCcbLookasideList)));
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
if (Ccb == NULL) {
Ccb = (PRFSD_CCB) ExAllocatePoolWithTag(NonPagedPool, sizeof(RFSD_CCB), RFSD_POOL_TAG);
RtlZeroMemory(Ccb, sizeof(RFSD_CCB));
SetFlag(Ccb->Flags, CCB_FROM_POOL);
} else {
RtlZeroMemory(Ccb, sizeof(RFSD_CCB));
}
if (!Ccb) {
return NULL;
}
Ccb->Identifier.Type = RFSDCCB;
Ccb->Identifier.Size = sizeof(RFSD_CCB);
Ccb->CurrentByteOffset = 0;
Ccb->DirectorySearchPattern.Length = 0;
Ccb->DirectorySearchPattern.MaximumLength = 0;
Ccb->DirectorySearchPattern.Buffer = 0;
return Ccb;
}
__drv_mustHoldCriticalRegion
VOID
RfsdFreeCcb (IN PRFSD_CCB Ccb)
{
PAGED_CODE();
ASSERT(Ccb != NULL);
ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
(Ccb->Identifier.Size == sizeof(RFSD_CCB)));
if (Ccb->DirectorySearchPattern.Buffer != NULL) {
ExFreePool(Ccb->DirectorySearchPattern.Buffer);
}
if (FlagOn(Ccb->Flags, CCB_FROM_POOL)) {
ExFreePool( Ccb );
} else {
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdCcbLookasideList), Ccb);
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
}
}
__drv_mustHoldCriticalRegion
PRFSD_MCB
RfsdAllocateMcb (PRFSD_VCB Vcb, PUNICODE_STRING FileName, ULONG FileAttr)
{
PRFSD_MCB Mcb = NULL;
PLIST_ENTRY List = NULL;
ULONG Extra = 0;
PAGED_CODE();
#define MCB_NUM_SHIFT 0x04
if (RfsdGlobal->McbAllocated > (RfsdGlobal->MaxDepth << MCB_NUM_SHIFT))
Extra = RfsdGlobal->McbAllocated -
(RfsdGlobal->MaxDepth << MCB_NUM_SHIFT) +
RfsdGlobal->MaxDepth;
RfsdPrint((DBG_INFO,
"RfsdAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n",
RfsdGlobal->McbAllocated,
RfsdGlobal->MaxDepth << MCB_NUM_SHIFT,
RfsdGlobal->FcbAllocated,
FileName->Buffer));
List = Vcb->McbList.Flink;
while ((List != &(Vcb->McbList)) && (Extra > 0)) {
Mcb = CONTAINING_RECORD(List, RFSD_MCB, Link);
List = List->Flink;
if ((!RFSD_IS_ROOT_KEY(Mcb->Key)) && (Mcb->Child == NULL) &&
(Mcb->RfsdFcb == NULL) && (!IsMcbUsed(Mcb))) {
RfsdPrint((DBG_INFO, "RfsdAllocateMcb: Mcb %S will be freed.\n",
Mcb->ShortName.Buffer));
if (RfsdDeleteMcbNode(Vcb, Vcb->McbTree, Mcb)) {
RfsdFreeMcb(Mcb);
Extra--;
}
}
}
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
Mcb = (PRFSD_MCB) (ExAllocateFromPagedLookasideList(
&(RfsdGlobal->RfsdMcbLookasideList)));
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
if (Mcb == NULL) {
Mcb = (PRFSD_MCB) ExAllocatePoolWithTag(PagedPool, sizeof(RFSD_MCB), RFSD_POOL_TAG);
RtlZeroMemory(Mcb, sizeof(RFSD_MCB));
SetFlag(Mcb->Flags, MCB_FROM_POOL);
} else {
RtlZeroMemory(Mcb, sizeof(RFSD_MCB));
}
if (!Mcb) {
return NULL;
}
Mcb->Identifier.Type = RFSDMCB;
Mcb->Identifier.Size = sizeof(RFSD_MCB);
if (FileName && FileName->Length) {
Mcb->ShortName.Length = FileName->Length;
Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2;
Mcb->ShortName.Buffer = ExAllocatePoolWithTag(PagedPool, Mcb->ShortName.MaximumLength, RFSD_POOL_TAG);
if (!Mcb->ShortName.Buffer)
goto errorout;
RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength);
RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length);
}
Mcb->FileAttr = FileAttr;
ExAcquireResourceExclusiveLite(
&RfsdGlobal->CountResource,
TRUE );
RfsdGlobal->McbAllocated++;
ExReleaseResourceForThreadLite(
&RfsdGlobal->CountResource,
ExGetCurrentResourceThread() );
return Mcb;
errorout:
if (Mcb) {
if (Mcb->ShortName.Buffer)
ExFreePool(Mcb->ShortName.Buffer);
if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) {
ExFreePool( Mcb );
} else {
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
ExFreeToPagedLookasideList(&(RfsdGlobal->RfsdMcbLookasideList), Mcb);
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
}
}
return NULL;
}
__drv_mustHoldCriticalRegion
VOID
RfsdFreeMcb (IN PRFSD_MCB Mcb)
{
#ifndef __REACTOS__
PRFSD_MCB Parent = Mcb->Parent;
#endif
ASSERT(Mcb != NULL);
ASSERT((Mcb->Identifier.Type == RFSDMCB) &&
(Mcb->Identifier.Size == sizeof(RFSD_MCB)));
RfsdPrint((DBG_INFO, "RfsdFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer));
if (Mcb->ShortName.Buffer)
ExFreePool(Mcb->ShortName.Buffer);
if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) {
ExFreePool( Mcb );
} else {
ExAcquireResourceExclusiveLite(
&RfsdGlobal->LAResource,
TRUE );
ExFreeToPagedLookasideList(&(RfsdGlobal->RfsdMcbLookasideList), Mcb);
ExReleaseResourceForThreadLite(
&RfsdGlobal->LAResource,
ExGetCurrentResourceThread() );
}
ExAcquireResourceExclusiveLite(
&RfsdGlobal->CountResource,
TRUE );
RfsdGlobal->McbAllocated--;
ExReleaseResourceForThreadLite(
&RfsdGlobal->CountResource,
ExGetCurrentResourceThread() );
}
__drv_mustHoldCriticalRegion
PRFSD_FCB
RfsdCreateFcbFromMcb(PRFSD_VCB Vcb, PRFSD_MCB Mcb)
{
PRFSD_FCB Fcb = NULL;
RFSD_INODE RfsdIno;
PAGED_CODE();
if (Mcb->RfsdFcb)
return Mcb->RfsdFcb;
if (RfsdLoadInode(Vcb, &(Mcb->Key), &RfsdIno)) {
PRFSD_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, sizeof(RFSD_INODE), RFSD_POOL_TAG);
if (!pTmpInode) {
goto errorout;
}
RtlCopyMemory(pTmpInode, &RfsdIno, sizeof(RFSD_INODE));
Fcb = RfsdAllocateFcb(Vcb, Mcb, pTmpInode);
if (!Fcb) {
ExFreePool(pTmpInode);
}
}
errorout:
return Fcb;
}
BOOLEAN
RfsdGetFullFileName(PRFSD_MCB Mcb, PUNICODE_STRING FileName)
{
USHORT Length = 0;
PRFSD_MCB TmpMcb = Mcb;
PUNICODE_STRING FileNames[256];
SHORT Count = 0 , i = 0, j = 0;
PAGED_CODE();
while(TmpMcb && Count < 256) {
if (RFSD_IS_ROOT_KEY(TmpMcb->Key))
break;
FileNames[Count++] = &TmpMcb->ShortName;
Length += (2 + TmpMcb->ShortName.Length);
TmpMcb = TmpMcb->Parent;
}
if (Count >= 256)
return FALSE;
if (Count ==0)
Length = 2;
FileName->Length = Length;
FileName->MaximumLength = Length + 2;
FileName->Buffer = ExAllocatePoolWithTag(PagedPool, Length + 2, RFSD_POOL_TAG);
if (!FileName->Buffer) {
return FALSE;
}
RtlZeroMemory(FileName->Buffer, FileName->MaximumLength);
if (Count == 0) {
FileName->Buffer[0] = L'\\';
return TRUE;
}
for (i = Count - 1; i >= 0 && j < (SHORT)(FileName->MaximumLength); i--) {
FileName->Buffer[j++] = L'\\';
RtlCopyMemory( &(FileName->Buffer[j]),
FileNames[i]->Buffer,
FileNames[i]->Length );
j += FileNames[i]->Length / 2;
}
return TRUE;
}
PRFSD_MCB
RfsdSearchMcbTree( PRFSD_VCB Vcb,
PRFSD_MCB RfsdMcb,
PRFSD_KEY_IN_MEMORY Key)
{
PRFSD_MCB Mcb = NULL;
PLIST_ENTRY List = NULL;
BOOLEAN bFind = FALSE;
PAGED_CODE();
List = Vcb->McbList.Flink;
while ((!bFind) && (List != &(Vcb->McbList))) {
Mcb = CONTAINING_RECORD(List, RFSD_MCB, Link);
List = List->Flink;
if (CompareShortKeys(&(Mcb->Key), Key) == RFSD_KEYS_MATCH) {
bFind = TRUE;
break;
}
}
if (bFind) {
ASSERT(Mcb != NULL);
RfsdRefreshMcb(Vcb, Mcb);
} else {
Mcb = NULL;
}
return Mcb;
}
/**
Returns NULL is the parent has no child, or if we search through the child's brothers and hit a NULL
Otherwise, returns the MCB of one of the the parent's children, which matches FileName.
*/
PRFSD_MCB
RfsdSearchMcb( PRFSD_VCB Vcb,
PRFSD_MCB Parent,
PUNICODE_STRING FileName )
{
PRFSD_MCB TmpMcb = Parent->Child;
PAGED_CODE();
while (TmpMcb) {
if (!RtlCompareUnicodeString(
&(TmpMcb->ShortName),
FileName, TRUE ))
break;
TmpMcb = TmpMcb->Next;
}
if (TmpMcb) {
RfsdRefreshMcb(Vcb, TmpMcb);
}
return TmpMcb;
}
VOID
RfsdRefreshMcb(PRFSD_VCB Vcb, PRFSD_MCB Mcb)
{
PAGED_CODE();
ASSERT (IsFlagOn(Mcb->Flags, MCB_IN_TREE));
RemoveEntryList(&(Mcb->Link));
InsertTailList(&(Vcb->McbList), &(Mcb->Link));
}
VOID
RfsdAddMcbNode(PRFSD_VCB Vcb, PRFSD_MCB Parent, PRFSD_MCB Child)
{
PRFSD_MCB TmpMcb = Parent->Child;
PAGED_CODE();
if(IsFlagOn(Child->Flags, MCB_IN_TREE)) {
DbgBreak();
RfsdPrint((DBG_ERROR, "RfsdAddMcbNode: Child Mcb is alreay in the tree.\n"));
return;
}
if (TmpMcb) {
ASSERT(TmpMcb->Parent == Parent);
while (TmpMcb->Next) {
TmpMcb = TmpMcb->Next;
ASSERT(TmpMcb->Parent == Parent);
}
TmpMcb->Next = Child;
Child->Parent = Parent;
Child->Next = NULL;
} else {
Parent->Child = Child;
Child->Parent = Parent;
Child->Next = NULL;
}
InsertTailList(&(Vcb->McbList), &(Child->Link));
SetFlag(Child->Flags, MCB_IN_TREE);
}
BOOLEAN
RfsdDeleteMcbNode(PRFSD_VCB Vcb, PRFSD_MCB McbTree, PRFSD_MCB RfsdMcb)
{
PRFSD_MCB TmpMcb;
PAGED_CODE();
if(!IsFlagOn(RfsdMcb->Flags, MCB_IN_TREE)) {
return TRUE;
}
if (RfsdMcb->Parent) {
if (RfsdMcb->Parent->Child == RfsdMcb) {
RfsdMcb->Parent->Child = RfsdMcb->Next;
} else {
TmpMcb = RfsdMcb->Parent->Child;
while (TmpMcb && TmpMcb->Next != RfsdMcb)
TmpMcb = TmpMcb->Next;
if (TmpMcb) {
TmpMcb->Next = RfsdMcb->Next;
} else {
// error
return FALSE;
}
}
} else if (RfsdMcb->Child) {
return FALSE;
}
RemoveEntryList(&(RfsdMcb->Link));
ClearFlag(RfsdMcb->Flags, MCB_IN_TREE);
return TRUE;
}
__drv_mustHoldCriticalRegion
VOID RfsdFreeMcbTree(PRFSD_MCB McbTree)
{
PAGED_CODE();
if (!McbTree)
return;
if (McbTree->Child) {
RfsdFreeMcbTree(McbTree->Child);
}
if (McbTree->Next) {
PRFSD_MCB Current;
PRFSD_MCB Next;
Current = McbTree->Next;
while (Current) {
Next = Current->Next;
if (Current->Child) {
RfsdFreeMcbTree(Current->Child);
}
RfsdFreeMcb(Current);
Current = Next;
}
}
RfsdFreeMcb(McbTree);
}
#if !RFSD_READ_ONLY
BOOLEAN
RfsdCheckSetBlock(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb, ULONG Block)
{
ULONG Group, dwBlk, Length;
RTL_BITMAP BlockBitmap;
PVOID BitmapCache;
PBCB BitmapBcb;
LARGE_INTEGER Offset;
BOOLEAN bModified = FALSE;
PAGED_CODE();
#if 0
Group = (Block - RFSD_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
dwBlk = (Block - RFSD_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
Offset.QuadPart = Offset.QuadPart * Vcb->GroupDesc[Group].bg_block_bitmap;
if (Group == Vcb->NumOfGroups - 1) {
Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
/* s_blocks_count is integer multiple of s_blocks_per_group */
if (Length == 0)
Length = BLOCKS_PER_GROUP;
} else {
Length = BLOCKS_PER_GROUP;
}
if (dwBlk >= Length)
return FALSE;
if (!CcPinRead( Vcb->StreamObj,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache ) ) {
RfsdPrint((DBG_ERROR, "RfsdDeleteBlock: PinReading error ...\n"));
return FALSE;
}
RtlInitializeBitMap( &BlockBitmap,
BitmapCache,
Length );
if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) {
DbgBreak();
RtlSetBits(&BlockBitmap, dwBlk, 1);
bModified = TRUE;
}
if (bModified) {
CcSetDirtyPinnedData(BitmapBcb, NULL );
RfsdRepinBcb(IrpContext, BitmapBcb);
RfsdAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
}
{
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
}
#endif // 0
return (!bModified);
}
BOOLEAN
RfsdCheckBitmapConsistency(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb)
{
ULONG i, j, InodeBlocks;
PAGED_CODE();
#if 0
for (i = 0; i < Vcb->NumOfGroups; i++) {
RfsdCheckSetBlock(IrpContext, Vcb, Vcb->GroupDesc[i].bg_block_bitmap);
RfsdCheckSetBlock(IrpContext, Vcb, Vcb->GroupDesc[i].bg_inode_bitmap);
if (i == Vcb->NumOfGroups - 1) {
InodeBlocks = ((INODES_COUNT % INODES_PER_GROUP) *
sizeof(RFSD_INODE) + Vcb->BlockSize - 1) /
(Vcb->BlockSize);
} else {
InodeBlocks = (INODES_PER_GROUP * sizeof(RFSD_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize);
}
for (j = 0; j < InodeBlocks; j++ )
RfsdCheckSetBlock(IrpContext, Vcb, Vcb->GroupDesc[i].bg_inode_table + j);
}
#endif // 0
return TRUE;
}
#endif // !RFSD_READ_ONLY
VOID
RfsdInsertVcb(PRFSD_VCB Vcb)
{
InsertTailList(&(RfsdGlobal->VcbList), &Vcb->Next);
}
VOID
RfsdRemoveVcb(PRFSD_VCB Vcb)
{
RemoveEntryList(&Vcb->Next);
}
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdInitializeVcb( IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN PRFSD_SUPER_BLOCK RfsdSb,
IN PDEVICE_OBJECT TargetDevice,
IN PDEVICE_OBJECT VolumeDevice,
IN PVPB Vpb )
{
BOOLEAN VcbResourceInitialized = FALSE;
USHORT VolumeLabelLength;
ULONG IoctlSize;
BOOLEAN NotifySyncInitialized = FALSE;
LONGLONG DiskSize;
LONGLONG PartSize;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UNICODE_STRING RootNode;
USHORT Buffer[2];
ULONG ChangeCount;
char s_volume_name[16] = "ReiserFS\0"; /* volume name */ // FUTURE: pull in from v2 superblock, if available
int templen;
PAGED_CODE();
_SEH2_TRY {
if (!Vpb) {
Status = STATUS_DEVICE_NOT_READY;
_SEH2_LEAVE;
}
RfsdPrint((DBG_ERROR, "RfsdInitializeVcb: Flink = %xh McbList = %xh\n",
Vcb->McbList.Flink, &(Vcb->McbList.Flink)));
#if RFSD_READ_ONLY
SetFlag(Vcb->Flags, VCB_READ_ONLY);
#endif //READ_ONLY
if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) {
SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA);
}
if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) {
SetFlag(Vcb->Flags, VCB_FLOPPY_DISK);
}
/*if (IsFlagOn(RfsdGlobal->Flags, RFSD_SUPPORT_WRITING)) {
if ((IsFlagOn(RfsdSb->s_feature_incompat, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) ||
IsFlagOn(RfsdSb->s_feature_incompat, EXT3_FEATURE_INCOMPAT_RECOVER) ||
IsFlagOn(RfsdSb->s_feature_compat, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) ) {
if(IsFlagOn(RfsdGlobal->Flags, EXT3_FORCE_WRITING)) {
ClearFlag(Vcb->Flags, VCB_READ_ONLY);
} else {
SetFlag(Vcb->Flags, VCB_READ_ONLY);
}
} else {
ClearFlag(Vcb->Flags, VCB_READ_ONLY);
}
} else {
SetFlag(Vcb->Flags, VCB_READ_ONLY);
}*/
// RFSD will be read only.
SetFlag(Vcb->Flags, VCB_READ_ONLY);
ExInitializeResourceLite(&Vcb->MainResource);
ExInitializeResourceLite(&Vcb->PagingIoResource);
ExInitializeResourceLite(&Vcb->McbResource);
VcbResourceInitialized = TRUE;
Vcb->Vpb = Vpb;
Vcb->RealDevice = Vpb->RealDevice;
Vpb->DeviceObject = VolumeDevice;
{
UNICODE_STRING LabelName;
OEM_STRING OemName;
LabelName.MaximumLength = 16 * 2;
LabelName.Length = 0;
LabelName.Buffer = Vcb->Vpb->VolumeLabel;
RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength);
VolumeLabelLength = 16;
while( (VolumeLabelLength > 0) &&
((s_volume_name[VolumeLabelLength-1] == '\0') ||
(s_volume_name[VolumeLabelLength-1] == ' ')) ) {
VolumeLabelLength--;
}
OemName.Buffer = s_volume_name;
OemName.MaximumLength = 16;
OemName.Length = VolumeLabelLength;
templen = RtlOemStringToUnicodeSize(&OemName);
Status = RfsdOEMToUnicode( &LabelName,
&OemName );
if (!NT_SUCCESS(Status)) {
_SEH2_LEAVE;
}
Vpb->VolumeLabelLength = LabelName.Length;
}
#if DISABLED
Vpb->SerialNumber = ((ULONG*)RfsdSb->s_uuid)[0] + ((ULONG*)RfsdSb->s_uuid)[1] +
((ULONG*)RfsdSb->s_uuid)[2] + ((ULONG*)RfsdSb->s_uuid)[3];
#endif
Vcb->StreamObj = IoCreateStreamFileObject( NULL, Vcb->Vpb->RealDevice);
if (Vcb->StreamObj) {
Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject);
Vcb->StreamObj->Vpb = Vcb->Vpb;
Vcb->StreamObj->ReadAccess = TRUE;
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
Vcb->StreamObj->WriteAccess = TRUE;
Vcb->StreamObj->DeleteAccess = TRUE;
}
else
{
Vcb->StreamObj->WriteAccess = TRUE;
Vcb->StreamObj->DeleteAccess = TRUE;
}
Vcb->StreamObj->FsContext = (PVOID) Vcb;
Vcb->StreamObj->FsContext2 = NULL;
Vcb->StreamObj->Vpb = Vcb->Vpb;
SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING);
} else {
_SEH2_LEAVE;
}
InitializeListHead(&Vcb->FcbList);
InitializeListHead(&Vcb->NotifyList);
FsRtlNotifyInitializeSync(&Vcb->NotifySync);
NotifySyncInitialized = TRUE;
Vcb->DeviceObject = VolumeDevice;
Vcb->TargetDeviceObject = TargetDevice;
Vcb->OpenFileHandleCount = 0;
Vcb->ReferenceCount = 0;
Vcb->SuperBlock = RfsdSb;
Vcb->Header.NodeTypeCode = (USHORT) RFSDVCB;
Vcb->Header.NodeByteSize = sizeof(RFSD_VCB);
Vcb->Header.IsFastIoPossible = FastIoIsNotPossible;
Vcb->Header.Resource = &(Vcb->MainResource);
Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource);
Vcb->Vpb->SerialNumber = 'MATT';
DiskSize =
Vcb->DiskGeometry.Cylinders.QuadPart *
Vcb->DiskGeometry.TracksPerCylinder *
Vcb->DiskGeometry.SectorsPerTrack *
Vcb->DiskGeometry.BytesPerSector;
IoctlSize = sizeof(PARTITION_INFORMATION);
Status = RfsdDiskIoControl(
TargetDevice,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&Vcb->PartitionInformation,
&IoctlSize );
PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart;
if (!NT_SUCCESS(Status)) {
Vcb->PartitionInformation.StartingOffset.QuadPart = 0;
Vcb->PartitionInformation.PartitionLength.QuadPart =
DiskSize;
PartSize = DiskSize;
Status = STATUS_SUCCESS;
}
IoctlSize = sizeof(ULONG);
Status = RfsdDiskIoControl(
TargetDevice,
IOCTL_DISK_CHECK_VERIFY,
NULL,
0,
&ChangeCount,
&IoctlSize );
if (!NT_SUCCESS(Status)) {
_SEH2_LEAVE;
}
Vcb->ChangeCount = ChangeCount;
Vcb->Header.AllocationSize.QuadPart =
Vcb->Header.FileSize.QuadPart = PartSize;
Vcb->Header.ValidDataLength.QuadPart =
(LONGLONG)(0x7fffffffffffffff);
/*
Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(rfsd_super_block->s_blocks_count - rfsd_super_block->s_free_blocks_count)
* (RFSD_MIN_BLOCK << rfsd_super_block->s_log_block_size);
Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart;
*/
{
CC_FILE_SIZES FileSizes;
FileSizes.AllocationSize.QuadPart =
FileSizes.FileSize.QuadPart =
Vcb->Header.AllocationSize.QuadPart;
FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff);
CcInitializeCacheMap( Vcb->StreamObj,
&FileSizes,
TRUE,
&(RfsdGlobal->CacheManagerNoOpCallbacks),
Vcb );
}
#if DISABLED // IN FFFS TOO
if (!RfsdLoadGroup(Vcb)) {
Status = STATUS_UNSUCCESSFUL;
_SEH2_LEAVE;
}
#endif
FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool);
InitializeListHead(&(Vcb->McbList));
//
// Now allocating the mcb for root ...
//
Buffer[0] = L'\\';
Buffer[1] = 0;
RootNode.Buffer = Buffer;
RootNode.MaximumLength = RootNode.Length = 2;
Vcb->McbTree = RfsdAllocateMcb( Vcb, &RootNode,
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL);
if (!Vcb->McbTree) {
_SEH2_LEAVE;
}
// Set the root of the filesystem to the root directory's inode / stat data structure
Vcb->McbTree->Key.k_dir_id = RFSD_ROOT_PARENT_ID;
Vcb->McbTree->Key.k_objectid = RFSD_ROOT_OBJECT_ID;
Vcb->McbTree->Key.k_offset = 0;
Vcb->McbTree->Key.k_type = RFSD_KEY_TYPE_v1_STAT_DATA;
#ifdef DISABLED
if (IsFlagOn(RfsdGlobal->Flags, RFSD_CHECKING_BITMAP)) {
RfsdCheckBitmapConsistency(IrpContext, Vcb);
}
{
ULONG dwData[RFSD_BLOCK_TYPES] = {RFSD_NDIR_BLOCKS, 1, 1, 1};
ULONG dwMeta[RFSD_BLOCK_TYPES] = {0, 0, 0, 0};
ULONG i;
KdPrint(("Reminder: " __FUNCTION__ ", dwData, dwMeta??\n"));
for (i = 0; i < RFSD_BLOCK_TYPES; i++) {
dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i);
if (i > 0) {
dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2));
}
Vcb->dwData[i] = dwData[i];
Vcb->dwMeta[i] = dwMeta[i];
}
}
#endif
SetFlag(Vcb->Flags, VCB_INITIALIZED);
} _SEH2_FINALLY {
if (!NT_SUCCESS(Status)) {
if (NotifySyncInitialized) {
FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
}
if (Vcb->GroupDesc) {
ExFreePool(Vcb->GroupDesc);
// CcUnpinData(Vcb->GroupDescBcb);
Vcb->GroupDesc = NULL;
}
if (Vcb->SuperBlock) {
ExFreePool(Vcb->SuperBlock);
Vcb->SuperBlock = NULL;
}
if (VcbResourceInitialized) {
ExDeleteResourceLite(&Vcb->MainResource);
ExDeleteResourceLite(&Vcb->PagingIoResource);
}
}
} _SEH2_END;
return Status;
}
__drv_mustHoldCriticalRegion
VOID
RfsdFreeVcb (IN PRFSD_VCB Vcb )
{
PAGED_CODE();
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
if (Vcb->StreamObj) {
if (IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED)) {
IO_STATUS_BLOCK IoStatus;
CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
}
if (Vcb->StreamObj->PrivateCacheMap)
RfsdSyncUninitializeCacheMap(Vcb->StreamObj);
ObDereferenceObject(Vcb->StreamObj);
Vcb->StreamObj = NULL;
}
#if DBG
if (FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) != 0) {
LONGLONG DirtyVba;
LONGLONG DirtyLba;
LONGLONG DirtyLength;
int i;
for (i = 0; FsRtlGetNextLargeMcbEntry (&(Vcb->DirtyMcbs), i, &DirtyVba, &DirtyLba, &DirtyLength); i++)
{
RfsdPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
RfsdPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
RfsdPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
}
DbgBreak();
}
#endif
FsRtlUninitializeLargeMcb(&(Vcb->DirtyMcbs));
RfsdFreeMcbTree(Vcb->McbTree);
if (Vcb->GroupDesc) {
ExFreePool(Vcb->GroupDesc);
// CcUnpinData(Vcb->GroupDescBcb);
Vcb->GroupDesc = NULL;
}
if (Vcb->SuperBlock) {
ExFreePool(Vcb->SuperBlock);
Vcb->SuperBlock = NULL;
}
ExDeleteResourceLite(&Vcb->McbResource);
ExDeleteResourceLite(&Vcb->PagingIoResource);
ExDeleteResourceLite(&Vcb->MainResource);
IoDeleteDevice(Vcb->DeviceObject);
}
VOID
RfsdSyncUninitializeCacheMap (
IN PFILE_OBJECT FileObject
)
{
CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent;
NTSTATUS WaitStatus;
LARGE_INTEGER RfsdLargeZero = {0,0};
PAGED_CODE();
KeInitializeEvent( &UninitializeCompleteEvent.Event,
SynchronizationEvent,
FALSE);
CcUninitializeCacheMap( FileObject,
&RfsdLargeZero,
&UninitializeCompleteEvent );
WaitStatus = KeWaitForSingleObject( &UninitializeCompleteEvent.Event,
Executive,
KernelMode,
FALSE,
NULL);
ASSERT (NT_SUCCESS(WaitStatus));
}