mirror of
https://github.com/reactos/reactos.git
synced 2025-05-01 11:39:58 +00:00

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)) { ^~
1675 lines
43 KiB
C
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));
|
|
}
|