2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
21 #pragma alloc_text(PAGE, Ext2AllocateFcb)
22 #pragma alloc_text(PAGE, Ext2FreeFcb)
23 #pragma alloc_text(PAGE, Ext2AllocateInode)
24 #pragma alloc_text(PAGE, Ext2DestroyInode)
25 #pragma alloc_text(PAGE, Ext2CheckBitmapConsistency)
26 #pragma alloc_text(PAGE, Ext2CheckSetBlock)
27 #pragma alloc_text(PAGE, Ext2InitializeVcb)
28 #pragma alloc_text(PAGE, Ext2FreeCcb)
29 #pragma alloc_text(PAGE, Ext2AllocateCcb)
30 #pragma alloc_text(PAGE, Ext2TearDownStream)
31 #pragma alloc_text(PAGE, Ext2DestroyVcb)
32 #pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap)
33 #pragma alloc_text(PAGE, Ext2ReaperThread)
34 #pragma alloc_text(PAGE, Ext2StartReaperThread)
38 Ext2AllocateIrpContext (IN PDEVICE_OBJECT DeviceObject
,
41 PIO_STACK_LOCATION irpSp
;
42 PEXT2_IRP_CONTEXT IrpContext
;
44 ASSERT(DeviceObject
!= NULL
);
47 irpSp
= IoGetCurrentIrpStackLocation(Irp
);
49 IrpContext
= (PEXT2_IRP_CONTEXT
) (
50 ExAllocateFromNPagedLookasideList(
51 &(Ext2Global
->Ext2IrpContextLookasideList
)));
53 if (IrpContext
== NULL
) {
57 RtlZeroMemory(IrpContext
, sizeof(EXT2_IRP_CONTEXT
) );
59 IrpContext
->Identifier
.Type
= EXT2ICX
;
60 IrpContext
->Identifier
.Size
= sizeof(EXT2_IRP_CONTEXT
);
62 IrpContext
->Irp
= Irp
;
63 IrpContext
->MajorFunction
= irpSp
->MajorFunction
;
64 IrpContext
->MinorFunction
= irpSp
->MinorFunction
;
65 IrpContext
->DeviceObject
= DeviceObject
;
66 IrpContext
->FileObject
= irpSp
->FileObject
;
67 if (NULL
!= IrpContext
->FileObject
) {
68 IrpContext
->Fcb
= (PEXT2_FCB
)IrpContext
->FileObject
->FsContext
;
69 IrpContext
->Ccb
= (PEXT2_CCB
)IrpContext
->FileObject
->FsContext2
;
72 if (IrpContext
->FileObject
!= NULL
) {
73 IrpContext
->RealDevice
= IrpContext
->FileObject
->DeviceObject
;
74 } else if (IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
) {
75 if (irpSp
->Parameters
.MountVolume
.Vpb
) {
76 IrpContext
->RealDevice
= irpSp
->Parameters
.MountVolume
.Vpb
->RealDevice
;
80 if (IsFlagOn(irpSp
->Flags
, SL_WRITE_THROUGH
)) {
81 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WRITE_THROUGH
);
84 if (IsFlagOn(irpSp
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
)) {
85 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_VERIFY_READ
);
88 if (IrpContext
->MajorFunction
== IRP_MJ_CLEANUP
||
89 IrpContext
->MajorFunction
== IRP_MJ_CLOSE
||
90 IrpContext
->MajorFunction
== IRP_MJ_SHUTDOWN
||
91 IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
||
92 IrpContext
->MajorFunction
== IRP_MJ_PNP
) {
94 if (IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
||
95 IrpContext
->MajorFunction
== IRP_MJ_PNP
) {
96 if (IoGetCurrentIrpStackLocation(Irp
)->FileObject
== NULL
||
97 IoIsOperationSynchronous(Irp
)) {
98 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
);
101 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
);
104 } else if (IoIsOperationSynchronous(Irp
)) {
106 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
);
109 IrpContext
->IsTopLevel
= (IoGetTopLevelIrp() == Irp
);
110 IrpContext
->ExceptionInProgress
= FALSE
;
111 INC_IRP_COUNT(IrpContext
);
117 Ext2FreeIrpContext (IN PEXT2_IRP_CONTEXT IrpContext
)
119 ASSERT(IrpContext
!= NULL
);
121 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
122 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
124 /* free the IrpContext to NonPagedList */
125 IrpContext
->Identifier
.Type
= 0;
126 IrpContext
->Identifier
.Size
= 0;
128 DEC_IRP_COUNT(IrpContext
);
129 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2IrpContextLookasideList
), IrpContext
);
141 ASSERT(!IsMcbSymLink(Mcb
));
143 Fcb
= (PEXT2_FCB
) ExAllocateFromNPagedLookasideList(
144 &(Ext2Global
->Ext2FcbLookasideList
));
150 RtlZeroMemory(Fcb
, sizeof(EXT2_FCB
));
151 Fcb
->Identifier
.Type
= EXT2FCB
;
152 Fcb
->Identifier
.Size
= sizeof(EXT2_FCB
);
154 #ifndef _WIN2K_TARGET_
155 ExInitializeFastMutex(&Fcb
->Mutex
);
156 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->Mutex
);
159 FsRtlInitializeOplock(&Fcb
->Oplock
);
160 FsRtlInitializeFileLock (
161 &Fcb
->FileLockAnchor
,
165 Fcb
->OpenHandleCount
= 0;
166 Fcb
->ReferenceCount
= 0;
168 Fcb
->Inode
= &Mcb
->Inode
;
170 ASSERT(Mcb
->Fcb
== NULL
);
175 DEBUG(DL_RES
, ("Ext2AllocateFcb: Fcb %p created: %wZ.\n",
176 Fcb
, &Fcb
->Mcb
->FullName
));
178 RtlZeroMemory(&Fcb
->Header
, sizeof(FSRTL_COMMON_FCB_HEADER
));
179 Fcb
->Header
.NodeTypeCode
= (USHORT
) EXT2FCB
;
180 Fcb
->Header
.NodeByteSize
= sizeof(EXT2_FCB
);
181 Fcb
->Header
.IsFastIoPossible
= FastIoIsNotPossible
;
182 Fcb
->Header
.Resource
= &(Fcb
->MainResource
);
183 Fcb
->Header
.PagingIoResource
= &(Fcb
->PagingIoResource
);
185 Fcb
->Header
.FileSize
.QuadPart
= Mcb
->Inode
.i_size
;
186 Fcb
->Header
.ValidDataLength
.QuadPart
= Mcb
->Inode
.i_size
;
187 Fcb
->Header
.AllocationSize
.QuadPart
= CEILING_ALIGNED(ULONGLONG
,
188 Fcb
->Header
.FileSize
.QuadPart
, (ULONGLONG
)Vcb
->BlockSize
);
190 Fcb
->SectionObject
.DataSectionObject
= NULL
;
191 Fcb
->SectionObject
.SharedCacheMap
= NULL
;
192 Fcb
->SectionObject
.ImageSectionObject
= NULL
;
194 ExInitializeResourceLite(&(Fcb
->MainResource
));
195 ExInitializeResourceLite(&(Fcb
->PagingIoResource
));
197 Ext2InsertFcb(Vcb
, Fcb
);
199 INC_MEM_COUNT(PS_FCB
, Fcb
, sizeof(EXT2_FCB
));
205 Ext2FreeFcb (IN PEXT2_FCB Fcb
)
207 PEXT2_VCB Vcb
= Fcb
->Vcb
;
209 ASSERT((Fcb
!= NULL
) && (Fcb
->Identifier
.Type
== EXT2FCB
) &&
210 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
211 ASSERT((Fcb
->Mcb
->Identifier
.Type
== EXT2MCB
) &&
212 (Fcb
->Mcb
->Identifier
.Size
== sizeof(EXT2_MCB
)));
214 #ifndef _WIN2K_TARGET_
215 FsRtlTeardownPerStreamContexts(&Fcb
->Header
);
218 if ((Fcb
->Mcb
->Identifier
.Type
== EXT2MCB
) &&
219 (Fcb
->Mcb
->Identifier
.Size
== sizeof(EXT2_MCB
))) {
221 ASSERT (Fcb
->Mcb
->Fcb
== Fcb
);
222 if (IsMcbSpecialFile(Fcb
->Mcb
) || IsFileDeleted(Fcb
->Mcb
)) {
224 ASSERT(!IsRoot(Fcb
));
225 Ext2RemoveMcb(Fcb
->Vcb
, Fcb
->Mcb
);
226 Fcb
->Mcb
->Fcb
= NULL
;
228 Ext2UnlinkMcb(Vcb
, Fcb
->Mcb
);
229 Ext2DerefMcb(Fcb
->Mcb
);
230 Ext2LinkHeadMcb(Vcb
, Fcb
->Mcb
);
234 Fcb
->Mcb
->Fcb
= NULL
;
235 Ext2DerefMcb(Fcb
->Mcb
);
242 Ext2RemoveFcb(Fcb
->Vcb
, Fcb
);
244 FsRtlUninitializeFileLock(&Fcb
->FileLockAnchor
);
245 FsRtlUninitializeOplock(&Fcb
->Oplock
);
246 ExDeleteResourceLite(&Fcb
->MainResource
);
247 ExDeleteResourceLite(&Fcb
->PagingIoResource
);
249 DEBUG(DL_RES
, ( "Ext2FreeFcb: Fcb (%p) is being released: %wZ.\n",
250 Fcb
, &Fcb
->Mcb
->FullName
));
252 Fcb
->Identifier
.Type
= 0;
253 Fcb
->Identifier
.Size
= 0;
255 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2FcbLookasideList
), Fcb
);
256 DEC_MEM_COUNT(PS_FCB
, Fcb
, sizeof(EXT2_FCB
));
259 /* Insert Fcb to Vcb->FcbList queue */
262 Ext2InsertFcb(PEXT2_VCB Vcb
, PEXT2_FCB Fcb
)
264 ExInterlockedInsertTailList(&Vcb
->FcbList
, &Fcb
->Next
, &Vcb
->FcbLock
);
265 Ext2ReferXcb(&Vcb
->FcbCount
);
268 /* Remove Fcb from Vcb->FcbList queue */
271 Ext2RemoveFcb(PEXT2_VCB Vcb
, PEXT2_FCB Fcb
)
275 KeAcquireSpinLock(&Vcb
->FcbLock
, &irql
);
276 RemoveEntryList(&(Fcb
->Next
));
277 if (Vcb
->FcbCount
> 0) {
278 Ext2DerefXcb(&Vcb
->FcbCount
);
282 KeReleaseSpinLock(&Vcb
->FcbLock
, irql
);
286 Ext2AllocateCcb (PEXT2_MCB SymLink
)
290 Ccb
= (PEXT2_CCB
) (ExAllocateFromNPagedLookasideList(
291 &(Ext2Global
->Ext2CcbLookasideList
)));
296 DEBUG(DL_RES
, ( "ExtAllocateCcb: Ccb created: %ph.\n", Ccb
));
298 RtlZeroMemory(Ccb
, sizeof(EXT2_CCB
));
300 Ccb
->Identifier
.Type
= EXT2CCB
;
301 Ccb
->Identifier
.Size
= sizeof(EXT2_CCB
);
303 Ccb
->SymLink
= SymLink
;
305 ASSERT(SymLink
->Refercount
> 0);
306 Ext2ReferMcb(SymLink
);
307 DEBUG(DL_INF
, ( "ExtAllocateCcb: Ccb SymLink: %wZ.\n",
308 &Ccb
->SymLink
->FullName
));
311 Ccb
->DirectorySearchPattern
.Length
= 0;
312 Ccb
->DirectorySearchPattern
.MaximumLength
= 0;
313 Ccb
->DirectorySearchPattern
.Buffer
= 0;
315 INC_MEM_COUNT(PS_CCB
, Ccb
, sizeof(EXT2_CCB
));
321 Ext2FreeCcb (IN PEXT2_VCB Vcb
, IN PEXT2_CCB Ccb
)
325 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
326 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
328 DEBUG(DL_RES
, ( "Ext2FreeCcb: Ccb = %ph.\n", Ccb
));
331 DEBUG(DL_INF
, ( "Ext2FreeCcb: Ccb SymLink: %wZ.\n",
332 &Ccb
->SymLink
->FullName
));
333 if (IsFileDeleted(Ccb
->SymLink
->Target
)) {
334 Ext2UnlinkMcb(Vcb
, Ccb
->SymLink
);
335 Ext2DerefMcb(Ccb
->SymLink
);
336 Ext2LinkHeadMcb(Vcb
, Ccb
->SymLink
);
338 Ext2DerefMcb(Ccb
->SymLink
);
342 if (Ccb
->DirectorySearchPattern
.Buffer
!= NULL
) {
343 DEC_MEM_COUNT(PS_DIR_PATTERN
, Ccb
->DirectorySearchPattern
.Buffer
,
344 Ccb
->DirectorySearchPattern
.MaximumLength
);
345 Ext2FreePool(Ccb
->DirectorySearchPattern
.Buffer
, EXT2_DIRSP_MAGIC
);
348 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2CcbLookasideList
), Ccb
);
349 DEC_MEM_COUNT(PS_CCB
, Ccb
, sizeof(EXT2_CCB
));
353 Ext2AllocateInode (PEXT2_VCB Vcb
)
357 inode
= ExAllocateFromNPagedLookasideList(
358 &(Vcb
->InodeLookasideList
));
363 RtlZeroMemory(inode
, INODE_SIZE
);
365 DEBUG(DL_INF
, ("ExtAllocateInode: Inode created: %ph.\n", inode
));
366 INC_MEM_COUNT(PS_EXT2_INODE
, inode
, INODE_SIZE
);
372 Ext2DestroyInode (IN PEXT2_VCB Vcb
, IN PEXT2_INODE inode
)
374 ASSERT(inode
!= NULL
);
376 DEBUG(DL_INF
, ("Ext2FreeInode: Inode = %ph.\n", inode
));
378 ExFreeToNPagedLookasideList(&(Vcb
->InodeLookasideList
), inode
);
379 DEC_MEM_COUNT(PS_EXT2_INODE
, inode
, INODE_SIZE
);
382 struct dentry
* Ext2AllocateEntry()
386 de
= (struct dentry
*)ExAllocateFromNPagedLookasideList(
387 &(Ext2Global
->Ext2DentryLookasideList
));
392 RtlZeroMemory(de
, sizeof(struct dentry
));
393 INC_MEM_COUNT(PS_DENTRY
, de
, sizeof(struct dentry
));
398 VOID
Ext2FreeEntry (IN
struct dentry
*de
)
403 ExFreePool(de
->d_name
.name
);
405 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2DentryLookasideList
), de
);
406 DEC_MEM_COUNT(PS_DENTRY
, de
, sizeof(struct dentry
));
410 struct dentry
*Ext2BuildEntry(PEXT2_VCB Vcb
, PEXT2_MCB Dcb
, PUNICODE_STRING FileName
)
412 OEM_STRING Oem
= { 0 };
413 struct dentry
*de
= NULL
;
414 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
418 de
= Ext2AllocateEntry();
420 DEBUG(DL_ERR
, ("Ext2BuildEntry: failed to allocate dentry.\n"));
425 de
->d_parent
= Dcb
->de
;
427 Oem
.MaximumLength
= (USHORT
)Ext2UnicodeToOEMSize(Vcb
, FileName
) + 1;
428 Oem
.Buffer
= ExAllocatePool(PagedPool
, Oem
.MaximumLength
);
430 DEBUG(DL_ERR
, ( "Ex2BuildEntry: failed to allocate OEM name.\n"));
433 de
->d_name
.name
= Oem
.Buffer
;
434 RtlZeroMemory(Oem
.Buffer
, Oem
.MaximumLength
);
435 Status
= Ext2UnicodeToOEM(Vcb
, &Oem
, FileName
);
436 if (!NT_SUCCESS(Status
)) {
437 DEBUG(DL_CP
, ("Ext2BuildEntry: failed to convert %S to OEM.\n", FileName
->Buffer
));
440 de
->d_name
.len
= Oem
.Length
;
444 if (!NT_SUCCESS(Status
)) {
454 Ext2AllocateExtent ()
458 Extent
= (PEXT2_EXTENT
)ExAllocateFromNPagedLookasideList(
459 &(Ext2Global
->Ext2ExtLookasideList
));
464 RtlZeroMemory(Extent
, sizeof(EXT2_EXTENT
));
465 INC_MEM_COUNT(PS_EXTENT
, Extent
, sizeof(EXT2_EXTENT
));
471 Ext2FreeExtent (IN PEXT2_EXTENT Extent
)
473 ASSERT(Extent
!= NULL
);
474 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2ExtLookasideList
), Extent
);
475 DEC_MEM_COUNT(PS_EXTENT
, Extent
, sizeof(EXT2_EXTENT
));
479 Ext2CountExtents(IN PEXT2_EXTENT Chain
)
482 PEXT2_EXTENT List
= Chain
;
494 IN PEXT2_EXTENT Chain
,
495 IN PEXT2_EXTENT Extent
501 PEXT2_EXTENT List
= Chain
;
512 Ext2DestroyExtentChain(IN PEXT2_EXTENT Chain
)
514 PEXT2_EXTENT Extent
= NULL
, List
= Chain
;
518 Ext2FreeExtent(List
);
524 Ext2ListExtents(PLARGE_MCB Extents
)
526 if (FsRtlNumberOfRunsInLargeMcb(Extents
) != 0) {
530 LONGLONG DirtyLength
;
533 for (i
= 0; FsRtlGetNextLargeMcbEntry(
534 Extents
, i
, &DirtyVba
,
535 &DirtyLba
, &DirtyLength
); i
++) {
536 if (DirtyVba
> 0 && DirtyLba
!= -1) {
537 DEBUG(DL_EXT
, ("Vba:%I64xh Lba:%I64xh Len:%I64xh.\n", DirtyVba
, DirtyLba
, DirtyLength
));
542 return n
? TRUE
: FALSE
;
563 BOOLEAN bFound
= FALSE
;
565 bFound
= FsRtlLookupLargeMcbEntry(
574 if (!bAdded
&& (!bFound
|| DirtyLbn
== -1)) {
578 if ( !bFound
|| (DirtyLbn
== -1) ||
580 (DirtyLen
< Length
)) {
584 for (Index
= 0; TRUE
; Index
++) {
586 if (!FsRtlGetNextLargeMcbEntry(
595 DEBUG(DL_EXT
, ("Index = %xh Vbn = %I64xh Lbn = %I64xh Len = %I64xh\n",
596 Index
, Vbn
, Lbn
, Length
));
603 Ext2ClearAllExtents(PLARGE_MCB Zone
)
606 FsRtlTruncateLargeMcb(Zone
, (LONGLONG
)0);
607 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
620 ULONG TriedTimes
= 0;
625 Offset
= Vbn
& (~(Vcb
->IoUnitSize
- 1));
626 Length
= (Vbn
- Offset
+ Length
+ Vcb
->IoUnitSize
- 1) &
627 ~(Vcb
->IoUnitSize
- 1);
629 ASSERT ((Offset
& (Vcb
->IoUnitSize
- 1)) == 0);
630 ASSERT ((Length
& (Vcb
->IoUnitSize
- 1)) == 0);
632 Offset
= (Offset
>> Vcb
->IoUnitBits
) + 1;
633 Length
= (Length
>> Vcb
->IoUnitBits
);
638 rc
= FsRtlAddLargeMcbEntry(
644 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
649 if (!rc
&& ++TriedTimes
< 10) {
650 Ext2Sleep(TriedTimes
* 100);
654 DEBUG(DL_EXT
, ("Ext2AddVcbExtent: Vbn=%I64xh Length=%I64xh,"
655 " rc=%d Runs=%u\n", Offset
, Length
, rc
,
656 FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
659 Ext2CheckExtent(&Vcb
->Extents
, Offset
, Offset
, Length
, TRUE
);
666 Ext2RemoveVcbExtent (
672 ULONG TriedTimes
= 0;
676 Offset
= Vbn
& (~(Vcb
->IoUnitSize
- 1));
677 Length
= (Length
+ Vbn
- Offset
+ Vcb
->IoUnitSize
- 1) & (~(Vcb
->IoUnitSize
- 1));
679 ASSERT ((Offset
& (Vcb
->IoUnitSize
- 1)) == 0);
680 ASSERT ((Length
& (Vcb
->IoUnitSize
- 1)) == 0);
682 Offset
= (Offset
>> Vcb
->IoUnitBits
) + 1;
683 Length
= (Length
>> Vcb
->IoUnitBits
);
688 FsRtlRemoveLargeMcbEntry(
693 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
698 if (!rc
&& ++TriedTimes
< 10) {
699 Ext2Sleep(TriedTimes
* 100);
703 DEBUG(DL_EXT
, ("Ext2RemoveVcbExtent: Vbn=%I64xh Length=%I64xh Runs=%u\n",
704 Offset
, Length
, FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
706 Ext2CheckExtent(&Vcb
->Extents
, Offset
, 0, Length
, FALSE
);
713 Ext2LookupVcbExtent (
723 offset
= Vbn
& (~(Vcb
->IoUnitSize
- 1));
724 ASSERT ((offset
& (Vcb
->IoUnitSize
- 1)) == 0);
725 offset
= (offset
>> Vcb
->IoUnitBits
) + 1;
727 rc
= FsRtlLookupLargeMcbEntry(
739 if (Lbn
&& ((*Lbn
) != -1)) {
741 (*Lbn
) = (((*Lbn
) - 1) << Vcb
->IoUnitBits
);
742 (*Lbn
) += ((Vbn
) & (Vcb
->IoUnitSize
- 1));
745 if (Length
&& *Length
) {
746 (*Length
) <<= Vcb
->IoUnitBits
;
747 (*Length
) -= ((Vbn
) & (Vcb
->IoUnitSize
- 1));
764 ULONG TriedTimes
= 0;
769 Base
= (LONGLONG
)BLOCK_SIZE
;
770 Bits
= (UCHAR
)BLOCK_BITS
;
772 ASSERT ((Vbn
& (Base
- 1)) == 0);
773 ASSERT ((Lbn
& (Base
- 1)) == 0);
774 ASSERT ((Length
& (Base
- 1)) == 0);
776 Vbn
= (Vbn
>> Bits
) + 1;
777 Lbn
= (Lbn
>> Bits
) + 1;
778 Length
= (Length
>> Bits
);
784 rc
= FsRtlAddLargeMcbEntry(
791 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
797 if (!rc
&& ++TriedTimes
< 10) {
798 Ext2Sleep(TriedTimes
* 100);
802 DEBUG(DL_EXT
, ("Ext2AddMcbExtent: Vbn=%I64xh Lbn=%I64xh Length=%I64xh,"
803 " rc=%d Runs=%u\n", Vbn
, Lbn
, Length
, rc
,
804 FsRtlNumberOfRunsInLargeMcb(&Mcb
->Extents
)));
807 Ext2CheckExtent(&Mcb
->Extents
, Vbn
, Lbn
, Length
, TRUE
);
814 Ext2RemoveMcbExtent (
821 ULONG TriedTimes
= 0;
826 Base
= (LONGLONG
)BLOCK_SIZE
;
827 Bits
= (UCHAR
)BLOCK_BITS
;
829 ASSERT ((Vbn
& (Base
- 1)) == 0);
830 ASSERT ((Length
& (Base
- 1)) == 0);
832 Vbn
= (Vbn
>> Bits
) + 1;
833 Length
= (Length
>> Bits
);
838 FsRtlRemoveLargeMcbEntry(
843 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
848 if (!rc
&& ++TriedTimes
< 10) {
849 Ext2Sleep(TriedTimes
* 100);
853 DEBUG(DL_EXT
, ("Ext2RemoveMcbExtent: Vbn=%I64xh Length=%I64xh Runs=%u\n",
854 Vbn
, Length
, FsRtlNumberOfRunsInLargeMcb(&Mcb
->Extents
)));
856 Ext2CheckExtent(&Mcb
->Extents
, Vbn
, 0, Length
, FALSE
);
863 Ext2LookupMcbExtent (
874 offset
= Vbn
& (~((LONGLONG
)BLOCK_SIZE
- 1));
875 ASSERT ((offset
& (BLOCK_SIZE
- 1)) == 0);
876 offset
= (offset
>> BLOCK_BITS
) + 1;
878 rc
= FsRtlLookupLargeMcbEntry(
890 if (Lbn
&& ((*Lbn
) != -1)) {
892 (*Lbn
) = (((*Lbn
) - 1) << BLOCK_BITS
);
893 (*Lbn
) += ((Vbn
) & ((LONGLONG
)BLOCK_SIZE
- 1));
896 if (Length
&& *Length
) {
897 (*Length
) <<= BLOCK_BITS
;
898 (*Length
) -= ((Vbn
) & ((LONGLONG
)BLOCK_SIZE
- 1));
914 ULONG TriedTimes
= 0;
915 LONGLONG Lbn
= Block
+ 1;
922 rc
= FsRtlAddLargeMcbEntry(
929 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
935 if (!rc
&& ++TriedTimes
< 10) {
936 Ext2Sleep(TriedTimes
* 100);
940 DEBUG(DL_EXT
, ("Ext2AddMcbMetaExts: Block: %xh-%xh rc=%d Runs=%u\n", Block
,
941 Length
, rc
, FsRtlNumberOfRunsInLargeMcb(&Mcb
->MetaExts
)));
944 Ext2CheckExtent(&Mcb
->MetaExts
, Lbn
, Lbn
, Length
, TRUE
);
951 Ext2RemoveMcbMetaExts (
958 ULONG TriedTimes
= 0;
959 LONGLONG Lbn
= Block
+ 1;
966 FsRtlRemoveLargeMcbEntry(
972 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
977 if (!rc
&& ++TriedTimes
< 10) {
978 Ext2Sleep(TriedTimes
* 100);
982 DEBUG(DL_EXT
, ("Ext2RemoveMcbMetaExts: Block: %xh-%xhh Runs=%u\n", Block
,
983 Length
, FsRtlNumberOfRunsInLargeMcb(&Mcb
->MetaExts
)));
985 Ext2CheckExtent(&Mcb
->MetaExts
, Lbn
, 0, Length
, FALSE
);
1003 LONGLONG Length
= 0;
1005 Vbn
= ((LONGLONG
) Start
) << BLOCK_BITS
;
1006 Lbn
= ((LONGLONG
) Block
) << BLOCK_BITS
;
1007 Length
= ((LONGLONG
)Number
<< BLOCK_BITS
);
1011 ULONG _block
= 0, _mapped
= 0;
1012 BOOLEAN _rc
= Ext2LookupBlockExtent(Vcb
, Mcb
, Start
, &_block
, &_mapped
);
1013 if (_rc
&& _block
!= 0 && (_block
!= Block
)) {
1017 return Ext2AddMcbExtent(Vcb
, Mcb
, Vbn
, Lbn
, Length
);
1021 ASSERT(Start
== Block
);
1022 return Ext2AddVcbExtent(Vcb
, Vbn
, Length
);
1027 Ext2LookupBlockExtent(
1037 LONGLONG Length
= 0;
1041 Vbn
= ((LONGLONG
) Start
) << BLOCK_BITS
;
1044 rc
= Ext2LookupMcbExtent(Vcb
, Mcb
, Vbn
, &Lbn
, &Length
);
1046 rc
= Ext2LookupVcbExtent(Vcb
, Vbn
, &Lbn
, &Length
);
1050 *Mapped
= (ULONG
)(Length
>> BLOCK_BITS
);
1051 if (Lbn
!= -1 && Length
> 0) {
1052 *Block
= (ULONG
)(Lbn
>> BLOCK_BITS
);
1063 Ext2RemoveBlockExtent(
1071 LONGLONG Length
= 0;
1074 Vbn
= ((LONGLONG
) Start
) << BLOCK_BITS
;
1075 Length
= ((LONGLONG
)Number
<< BLOCK_BITS
);
1078 rc
= Ext2RemoveMcbExtent(Vcb
, Mcb
, Vbn
, Length
);
1080 rc
= Ext2RemoveVcbExtent(Vcb
, Vbn
, Length
);
1088 IN PEXT2_IRP_CONTEXT IrpContext
,
1093 NTSTATUS Status
= STATUS_SUCCESS
;
1100 Ext2ClearAllExtents(&Mcb
->Extents
);
1101 Ext2ClearAllExtents(&Mcb
->MetaExts
);
1103 ASSERT(Mcb
!= NULL
);
1104 End
= (ULONG
)((Mcb
->Inode
.i_size
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
1106 while (Start
< End
) {
1110 /* mapping file offset to ext2 block */
1111 if (INODE_HAS_EXTENT(&Mcb
->Inode
)) {
1112 Status
= Ext2MapExtent(
1122 Status
= Ext2MapIndirect(
1133 if (!NT_SUCCESS(Status
)) {
1137 /* skip wrong blocks, in case wrongly treating symlink
1138 target names as blocks, silly */
1139 if (Block
>= TOTAL_BLOCKS
) {
1144 if (!Ext2AddBlockExtent(Vcb
, Mcb
, Start
, Block
, Mapped
)) {
1146 ClearFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1147 Ext2ClearAllExtents(&Mcb
->Extents
);
1148 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1151 DEBUG(DL_MAP
, ("Ext2InitializeZone %wZ: Block = %xh Mapped = %xh\n",
1152 &Mcb
->FullName
, Block
, Mapped
));
1155 /* Mapped is total number of continous blocks or NULL blocks */
1159 /* set mcb zone as initialized */
1160 SetLongFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1164 if (!IsZoneInited(Mcb
)) {
1165 Ext2ClearAllExtents(&Mcb
->Extents
);
1166 Ext2ClearAllExtents(&Mcb
->MetaExts
);
1174 IN PEXT2_IRP_CONTEXT IrpContext
,
1177 IN ULONGLONG Offset
,
1180 OUT PEXT2_EXTENT
* Chain
1187 NTSTATUS Status
= STATUS_SUCCESS
;
1189 PEXT2_EXTENT Extent
= NULL
;
1190 PEXT2_EXTENT List
= *Chain
;
1192 if (!IsZoneInited(Mcb
)) {
1193 Status
= Ext2InitializeZone(IrpContext
, Vcb
, Mcb
);
1194 if (!NT_SUCCESS(Status
)) {
1199 if ((IrpContext
&& IrpContext
->Irp
) &&
1200 ((IrpContext
->Irp
->Flags
& IRP_NOCACHE
) ||
1201 (IrpContext
->Irp
->Flags
& IRP_PAGING_IO
))) {
1202 Size
= (Size
+ SECTOR_SIZE
- 1) & (~(SECTOR_SIZE
- 1));
1205 Start
= (ULONG
)(Offset
>> BLOCK_BITS
);
1206 End
= (ULONG
)((Size
+ Offset
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
1208 if (End
> (ULONG
)((Mcb
->Inode
.i_size
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
) ) {
1209 End
= (ULONG
)((Mcb
->Inode
.i_size
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
1212 while (Size
> 0 && Start
< End
) {
1220 /* try to map file offset to ext2 block upon Extents cache */
1221 if (IsZoneInited(Mcb
)) {
1222 rc
= Ext2LookupBlockExtent(
1230 /* we likely get a sparse file here */
1236 /* try to BlockMap in case failed to access Extents cache */
1237 if (!IsZoneInited(Mcb
) || (bAlloc
&& Block
== 0)) {
1239 Status
= Ext2BlockMap(
1248 if (!NT_SUCCESS(Status
)) {
1252 /* skip wrong blocks, in case wrongly treating symlink
1253 target names as blocks, silly */
1254 if (Block
>= TOTAL_BLOCKS
) {
1258 /* add new allocated blocks to Mcb zone */
1259 if (IsZoneInited(Mcb
) && Block
) {
1260 if (!Ext2AddBlockExtent(Vcb
, Mcb
, Start
, Block
, Mapped
)) {
1262 ClearFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1263 Ext2ClearAllExtents(&Mcb
->Extents
);
1268 /* calculate i/o extent */
1269 Lba
= ((LONGLONG
)Block
<< BLOCK_BITS
) + Offset
- ((LONGLONG
)Start
<< BLOCK_BITS
);
1270 Length
= (ULONG
)(((LONGLONG
)(Start
+ Mapped
) << BLOCK_BITS
) - Offset
);
1271 if (Length
> Size
) {
1276 Offset
= (ULONGLONG
)Start
<< BLOCK_BITS
;
1280 if (List
&& List
->Lba
+ List
->Length
== Lba
) {
1282 /* it's continuous upon previous Extent */
1283 List
->Length
+= Length
;
1287 /* have to allocate a new Extent */
1288 Extent
= Ext2AllocateExtent();
1290 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1295 Extent
->Length
= Length
;
1296 Extent
->Offset
= Total
;
1298 /* insert new Extent to chain */
1300 List
->Next
= Extent
;
1303 *Chain
= List
= Extent
;
1320 IN OUT PUNICODE_STRING Target
,
1321 IN PUNICODE_STRING File
,
1322 IN PUNICODE_STRING Parent
1326 USHORT ParentLen
= 0;
1327 BOOLEAN bBackslash
= TRUE
;
1329 /* free the original buffer */
1330 if (Target
->Buffer
) {
1331 DEC_MEM_COUNT(PS_MCB_NAME
, Target
->Buffer
, Target
->MaximumLength
);
1332 Ext2FreePool(Target
->Buffer
, EXT2_FNAME_MAGIC
);
1333 Target
->Length
= Target
->MaximumLength
= 0;
1336 /* check the parent directory's name and backslash */
1337 if (Parent
&& Parent
->Buffer
&& Parent
->Length
> 0) {
1338 ParentLen
= Parent
->Length
/ sizeof(WCHAR
);
1339 if (Parent
->Buffer
[ParentLen
- 1] == L
'\\') {
1344 if (Parent
== NULL
|| File
->Buffer
[0] == L
'\\') {
1345 /* must be root inode */
1346 ASSERT(ParentLen
== 0);
1350 /* allocate and initialize new name buffer */
1351 Length
= File
->Length
;
1352 Length
+= (ParentLen
+ (bBackslash
? 1 : 0)) * sizeof(WCHAR
);
1354 Target
->Buffer
= Ext2AllocatePool(
1360 if (!Target
->Buffer
) {
1361 DEBUG(DL_ERR
, ( "Ex2BuildName: failed to allocate name bufer.\n"));
1364 RtlZeroMemory(Target
->Buffer
, Length
+ 2);
1367 RtlCopyMemory(&Target
->Buffer
[0],
1369 ParentLen
* sizeof(WCHAR
));
1373 Target
->Buffer
[ParentLen
++] = L
'\\';
1376 RtlCopyMemory( &Target
->Buffer
[ParentLen
],
1380 INC_MEM_COUNT(PS_MCB_NAME
, Target
->Buffer
, Length
+ 2);
1381 Target
->Length
= Length
;
1382 Target
->MaximumLength
= Length
+ 2;
1390 IN PUNICODE_STRING FileName
,
1391 IN PUNICODE_STRING Parent
,
1395 PEXT2_MCB Mcb
= NULL
;
1396 NTSTATUS Status
= STATUS_SUCCESS
;
1398 /* need wake the reaper thread if there are many Mcb allocated */
1399 if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 4)) {
1400 KeSetEvent(&Ext2Global
->Reaper
.Wait
, 0, FALSE
);
1403 /* allocate Mcb from LookasideList */
1404 Mcb
= (PEXT2_MCB
) (ExAllocateFromNPagedLookasideList(
1405 &(Ext2Global
->Ext2McbLookasideList
)));
1411 /* initialize Mcb header */
1412 RtlZeroMemory(Mcb
, sizeof(EXT2_MCB
));
1413 Mcb
->Identifier
.Type
= EXT2MCB
;
1414 Mcb
->Identifier
.Size
= sizeof(EXT2_MCB
);
1415 Mcb
->FileAttr
= FileAttr
;
1417 Mcb
->Inode
.i_priv
= (PVOID
)Mcb
;
1418 Mcb
->Inode
.i_sb
= &Vcb
->sb
;
1420 /* initialize Mcb names */
1424 if ( FileName
->Length
== 2 &&
1425 FileName
->Buffer
[0] == L
'\\') {
1426 DEBUG(DL_RES
, ( "Ext2AllocateMcb: Root Mcb is to be created !\n"));
1429 if ( FileName
->Length
== 2 &&
1430 FileName
->Buffer
[0] == L
'.') {
1434 if ( FileName
->Length
== 4 &&
1435 FileName
->Buffer
[0] == L
'.' &&
1436 FileName
->Buffer
[1] == L
'.' ) {
1441 if (( FileName
->Length
>= 4 && FileName
->Buffer
[0] == L
'.') &&
1442 ((FileName
->Length
== 4 && FileName
->Buffer
[1] != L
'.') ||
1443 FileName
->Length
>= 6 )) {
1444 SetFlag(Mcb
->FileAttr
, FILE_ATTRIBUTE_HIDDEN
);
1447 if (!Ext2BuildName(&Mcb
->ShortName
, FileName
, NULL
)) {
1450 if (!Ext2BuildName(&Mcb
->FullName
, FileName
, Parent
)) {
1455 /* initialize Mcb Extents, it will raise an expcetion if failed */
1457 FsRtlInitializeLargeMcb(&(Mcb
->Extents
), NonPagedPool
);
1458 FsRtlInitializeLargeMcb(&(Mcb
->MetaExts
), NonPagedPool
);
1459 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
1460 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1464 if (!NT_SUCCESS(Status
)) {
1468 INC_MEM_COUNT(PS_MCB
, Mcb
, sizeof(EXT2_MCB
));
1469 DEBUG(DL_INF
, ( "Ext2AllocateMcb: Mcb %wZ created.\n", &Mcb
->FullName
));
1477 if (Mcb
->ShortName
.Buffer
) {
1478 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->ShortName
.Buffer
,
1479 Mcb
->ShortName
.MaximumLength
);
1480 Ext2FreePool(Mcb
->ShortName
.Buffer
, EXT2_FNAME_MAGIC
);
1483 if (Mcb
->FullName
.Buffer
) {
1484 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->FullName
.Buffer
,
1485 Mcb
->FullName
.MaximumLength
);
1486 Ext2FreePool(Mcb
->FullName
.Buffer
, EXT2_FNAME_MAGIC
);
1489 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2McbLookasideList
), Mcb
);
1496 Ext2FreeMcb (IN PEXT2_VCB Vcb
, IN PEXT2_MCB Mcb
)
1499 PEXT2_MCB Parent
= Mcb
->Parent
;
1501 ASSERT(Mcb
!= NULL
);
1503 ASSERT((Mcb
->Identifier
.Type
== EXT2MCB
) &&
1504 (Mcb
->Identifier
.Size
== sizeof(EXT2_MCB
)));
1506 if ((Mcb
->Identifier
.Type
!= EXT2MCB
) ||
1507 (Mcb
->Identifier
.Size
!= sizeof(EXT2_MCB
))) {
1511 DEBUG(DL_INF
, ( "Ext2FreeMcb: Mcb %wZ will be freed.\n", &Mcb
->FullName
));
1513 if (IsMcbSymLink(Mcb
) && Mcb
->Target
) {
1514 Ext2DerefMcb(Mcb
->Target
);
1517 if (FsRtlNumberOfRunsInLargeMcb(&Mcb
->Extents
)) {
1518 DEBUG(DL_EXT
, ("List data extents for: %wZ\n", &Mcb
->FullName
));
1519 Ext2ListExtents(&Mcb
->Extents
);
1521 FsRtlUninitializeLargeMcb(&(Mcb
->Extents
));
1522 if (FsRtlNumberOfRunsInLargeMcb(&Mcb
->MetaExts
)) {
1523 DEBUG(DL_EXT
, ("List meta extents for: %wZ\n", &Mcb
->FullName
));
1524 Ext2ListExtents(&Mcb
->MetaExts
);
1526 FsRtlUninitializeLargeMcb(&(Mcb
->MetaExts
));
1527 ClearLongFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1529 if (Mcb
->ShortName
.Buffer
) {
1530 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->ShortName
.Buffer
,
1531 Mcb
->ShortName
.MaximumLength
);
1532 Ext2FreePool(Mcb
->ShortName
.Buffer
, EXT2_FNAME_MAGIC
);
1535 if (Mcb
->FullName
.Buffer
) {
1536 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->FullName
.Buffer
,
1537 Mcb
->FullName
.MaximumLength
);
1538 Ext2FreePool(Mcb
->FullName
.Buffer
, EXT2_FNAME_MAGIC
);
1543 Ext2FreeEntry(Mcb
->de
);
1546 Mcb
->Identifier
.Type
= 0;
1547 Mcb
->Identifier
.Size
= 0;
1549 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2McbLookasideList
), Mcb
);
1550 DEC_MEM_COUNT(PS_MCB
, Mcb
, sizeof(EXT2_MCB
));
1558 PUNICODE_STRING FileName
1561 BOOLEAN LockAcquired
= FALSE
;
1562 PEXT2_MCB Mcb
= NULL
;
1565 ExAcquireResourceSharedLite(&Vcb
->McbLock
, TRUE
);
1566 LockAcquired
= TRUE
;
1567 Mcb
= Ext2SearchMcbWithoutLock(Parent
, FileName
);
1570 ExReleaseResourceLite(&Vcb
->McbLock
);
1579 Ext2SearchMcbWithoutLock(
1581 PUNICODE_STRING FileName
1584 PEXT2_MCB TmpMcb
= NULL
;
1586 DEBUG(DL_RES
, ("Ext2SearchMcb: %wZ\n", FileName
));
1590 Ext2ReferMcb(Parent
);
1592 if (Ext2IsDot(FileName
)) {
1594 Ext2ReferMcb(Parent
);
1598 if (Ext2IsDotDot(FileName
)) {
1599 if (IsMcbRoot(Parent
)) {
1602 TmpMcb
= Parent
->Parent
;
1605 Ext2ReferMcb(TmpMcb
);
1610 if (IsMcbSymLink(Parent
)) {
1611 if (Parent
->Target
) {
1612 TmpMcb
= Parent
->Target
->Child
;
1613 ASSERT(!IsMcbSymLink(Parent
->Target
));
1619 TmpMcb
= Parent
->Child
;
1624 if (!RtlCompareUnicodeString(
1625 &(TmpMcb
->ShortName
),
1627 Ext2ReferMcb(TmpMcb
);
1631 TmpMcb
= TmpMcb
->Next
;
1636 Ext2DerefMcb(Parent
);
1649 BOOLEAN LockAcquired
= FALSE
;
1650 PEXT2_MCB Mcb
= NULL
;
1654 ExAcquireResourceExclusiveLite(
1657 LockAcquired
= TRUE
;
1659 /* use it's target if it's a symlink */
1660 if (IsMcbSymLink(Parent
)) {
1661 Parent
= Parent
->Target
;
1662 ASSERT(!IsMcbSymLink(Parent
));
1665 Mcb
= Parent
->Child
;
1674 /* already attached in the list */
1675 DEBUG(DL_ERR
, ( "Ext2InsertMcb: Child Mcb is alreay attached.\n"));
1676 if (!IsFlagOn(Mcb
->Flags
, MCB_ENTRY_TREE
)) {
1677 SetLongFlag(Child
->Flags
, MCB_ENTRY_TREE
);
1678 DEBUG(DL_ERR
, ( "Ext2InsertMcb: Child Mcb's flag isn't set.\n"));
1685 /* insert this Mcb into the head */
1686 Child
->Next
= Parent
->Child
;
1687 Parent
->Child
= Child
;
1688 Child
->Parent
= Parent
;
1689 Child
->de
->d_parent
= Parent
->de
;
1690 Ext2ReferMcb(Parent
);
1691 SetLongFlag(Child
->Flags
, MCB_ENTRY_TREE
);
1697 ExReleaseResourceLite(&Vcb
->McbLock
);
1708 PEXT2_MCB TmpMcb
= NULL
;
1709 BOOLEAN LockAcquired
= FALSE
;
1710 BOOLEAN bLinked
= FALSE
;
1714 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
1715 LockAcquired
= TRUE
;
1719 if (Mcb
->Parent
->Child
== Mcb
) {
1720 Mcb
->Parent
->Child
= Mcb
->Next
;
1723 TmpMcb
= Mcb
->Parent
->Child
;
1725 while (TmpMcb
&& TmpMcb
->Next
!= Mcb
) {
1726 TmpMcb
= TmpMcb
->Next
;
1730 TmpMcb
->Next
= Mcb
->Next
;
1733 /* we got errors: link broken */
1738 if (IsFlagOn(Mcb
->Flags
, MCB_ENTRY_TREE
)) {
1739 DEBUG(DL_RES
, ("Mcb %p %wZ removed from Mcb %p %wZ\n", Mcb
,
1740 &Mcb
->FullName
, Mcb
->Parent
, &Mcb
->Parent
->FullName
));
1741 Ext2DerefMcb(Mcb
->Parent
);
1742 ClearLongFlag(Mcb
->Flags
, MCB_ENTRY_TREE
);
1747 if (IsFlagOn(Mcb
->Flags
, MCB_ENTRY_TREE
)) {
1748 ClearLongFlag(Mcb
->Flags
, MCB_ENTRY_TREE
);
1753 Mcb
->de
->d_parent
= NULL
;
1759 ExReleaseResourceLite(&Vcb
->McbLock
);
1767 Ext2CleanupAllMcbs(PEXT2_VCB Vcb
)
1769 BOOLEAN LockAcquired
= FALSE
;
1770 PEXT2_MCB Mcb
= NULL
;
1774 ExAcquireResourceExclusiveLite(
1777 LockAcquired
= TRUE
;
1779 while ((Mcb
= Ext2FirstUnusedMcb(Vcb
, TRUE
, Vcb
->NumOfMcb
)) != 0) {
1781 PEXT2_MCB Next
= Mcb
->Next
;
1782 if (IsMcbSymLink(Mcb
)) {
1785 Ext2FreeMcb(Vcb
, Mcb
);
1789 Ext2FreeMcb(Vcb
, Vcb
->McbTree
);
1790 Vcb
->McbTree
= NULL
;
1795 ExReleaseResourceLite(&Vcb
->McbLock
);
1801 Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext
, PEXT2_VCB Vcb
, LONGLONG Block
)
1803 PEXT2_GROUP_DESC gd
;
1804 ULONG Group
, dwBlk
, Length
;
1806 RTL_BITMAP BlockBitmap
;
1810 LARGE_INTEGER Offset
;
1812 BOOLEAN bModified
= FALSE
;
1815 Group
= (ULONG
)(Block
- EXT2_FIRST_DATA_BLOCK
) / BLOCKS_PER_GROUP
;
1816 dwBlk
= (ULONG
)(Block
- EXT2_FIRST_DATA_BLOCK
) % BLOCKS_PER_GROUP
;
1818 gd
= ext4_get_group_desc(&Vcb
->sb
, Group
, NULL
);
1822 Offset
.QuadPart
= ext4_block_bitmap(&Vcb
->sb
, gd
);
1823 Offset
.QuadPart
<<= BLOCK_BITS
;
1825 if (Group
== Vcb
->sbi
.s_groups_count
- 1) {
1826 Length
= (ULONG
)(TOTAL_BLOCKS
% BLOCKS_PER_GROUP
);
1828 /* s_blocks_count is integer multiple of s_blocks_per_group */
1830 Length
= BLOCKS_PER_GROUP
;
1832 Length
= BLOCKS_PER_GROUP
;
1835 if (dwBlk
>= Length
)
1838 if (!CcPinRead( Vcb
->Volume
,
1845 DEBUG(DL_ERR
, ( "Ext2CheckSetBlock: Failed to PinLock block %xh ...\n",
1846 ext4_block_bitmap(&Vcb
->sb
, gd
)));
1850 RtlInitializeBitMap( &BlockBitmap
,
1854 if (RtlCheckBit(&BlockBitmap
, dwBlk
) == 0) {
1856 RtlSetBits(&BlockBitmap
, dwBlk
, 1);
1861 CcSetDirtyPinnedData(BitmapBcb
, NULL
);
1862 Ext2AddVcbExtent(Vcb
, Offset
.QuadPart
, (LONGLONG
)BLOCK_SIZE
);
1866 CcUnpinData(BitmapBcb
);
1870 RtlZeroMemory(&BlockBitmap
, sizeof(RTL_BITMAP
));
1873 return (!bModified
);
1877 Ext2CheckBitmapConsistency(PEXT2_IRP_CONTEXT IrpContext
, PEXT2_VCB Vcb
)
1879 ULONG i
, j
, InodeBlocks
;
1881 for (i
= 0; i
< Vcb
->sbi
.s_groups_count
; i
++) {
1883 PEXT2_GROUP_DESC gd
;
1885 gd
= ext4_get_group_desc(&Vcb
->sb
, i
, NULL
);
1888 Ext2CheckSetBlock(IrpContext
, Vcb
, ext4_block_bitmap(&Vcb
->sb
, gd
));
1889 Ext2CheckSetBlock(IrpContext
, Vcb
, ext4_inode_bitmap(&Vcb
->sb
, gd
));
1892 if (i
== Vcb
->sbi
.s_groups_count
- 1) {
1893 InodeBlocks
= ((INODES_COUNT
% INODES_PER_GROUP
) *
1894 Vcb
->InodeSize
+ Vcb
->BlockSize
- 1) /
1897 InodeBlocks
= (INODES_PER_GROUP
* Vcb
->InodeSize
+
1898 Vcb
->BlockSize
- 1) / (Vcb
->BlockSize
);
1901 for (j
= 0; j
< InodeBlocks
; j
++ )
1902 Ext2CheckSetBlock(IrpContext
, Vcb
, ext4_inode_table(&Vcb
->sb
, gd
) + j
);
1908 /* Ext2Global->Resource should be already acquired */
1910 Ext2InsertVcb(PEXT2_VCB Vcb
)
1912 InsertTailList(&(Ext2Global
->VcbList
), &Vcb
->Next
);
1916 /* Ext2Global->Resource should be already acquired */
1918 Ext2RemoveVcb(PEXT2_VCB Vcb
)
1920 RemoveEntryList(&Vcb
->Next
);
1921 InitializeListHead(&Vcb
->Next
);
1925 Ext2QueryVolumeParams(IN PEXT2_VCB Vcb
, IN PUNICODE_STRING Params
)
1928 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1930 UNICODE_STRING UniName
;
1931 PUSHORT UniBuffer
= NULL
;
1939 RtlZeroMemory(Params
, sizeof(UNICODE_STRING
));
1941 /* constructing volume UUID name */
1942 memset(UUID
, 0, sizeof(USHORT
) * 50);
1943 for (i
=0; i
< 16; i
++) {
1945 swprintf((wchar_t *)&UUID
[len
], L
"{%2.2X",Vcb
->SuperBlock
->s_uuid
[i
]);
1947 } else if (i
== 15) {
1948 swprintf((wchar_t *)&UUID
[len
], L
"-%2.2X}", Vcb
->SuperBlock
->s_uuid
[i
]);
1951 swprintf((wchar_t *)&UUID
[len
], L
"-%2.2X", Vcb
->SuperBlock
->s_uuid
[i
]);
1956 /* allocating memory for UniBuffer */
1957 UniBuffer
= Ext2AllocatePool(PagedPool
, 1024, EXT2_PARAM_MAGIC
);
1958 if (NULL
== UniBuffer
) {
1959 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1962 RtlZeroMemory(UniBuffer
, 1024);
1964 /* querying volume parameter string */
1965 RtlZeroMemory(&QueryTable
[0], sizeof(RTL_QUERY_REGISTRY_TABLE
) * 2);
1966 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1967 QueryTable
[0].Name
= UUID
;
1968 QueryTable
[0].EntryContext
= &(UniName
);
1969 UniName
.MaximumLength
= 1024;
1971 UniName
.Buffer
= UniBuffer
;
1973 Status
= RtlQueryRegistryValues(
1974 RTL_REGISTRY_ABSOLUTE
,
1975 Ext2Global
->RegistryPath
.Buffer
,
1981 if (!NT_SUCCESS(Status
)) {
1987 if (NT_SUCCESS(Status
)) {
1991 Ext2FreePool(UniBuffer
, EXT2_PARAM_MAGIC
);
1999 Ext2ParseRegistryVolumeParams(
2000 IN PUNICODE_STRING Params
,
2001 OUT PEXT2_VOLUME_PROPERTY2 Property
2004 WCHAR Codepage
[CODEPAGE_MAXLEN
];
2005 WCHAR Prefix
[HIDINGPAT_LEN
];
2006 WCHAR Suffix
[HIDINGPAT_LEN
];
2007 USHORT MountPoint
[4];
2010 BOOLEAN bWriteSupport
= FALSE
,
2011 bCheckBitmap
= FALSE
,
2013 bMountPoint
= FALSE
;
2015 PWCHAR Name
; /* parameters name */
2016 PBOOLEAN bExist
; /* is it contained in params */
2017 USHORT Length
; /* parameter value length */
2018 PWCHAR uValue
; /* value buffer in unicode */
2019 PCHAR aValue
; /* value buffer in ansi */
2020 } ParamPattern
[] = {
2021 /* writing support */
2022 {READING_ONLY
, &Property
->bReadonly
, 0, NULL
, NULL
},
2023 {WRITING_SUPPORT
, &bWriteSupport
, 0, NULL
, NULL
},
2024 {EXT3_FORCEWRITING
, &Property
->bExt3Writable
, 0, NULL
, NULL
},
2026 /* need check bitmap */
2027 {CHECKING_BITMAP
, &bCheckBitmap
, 0, NULL
, NULL
},
2029 {CODEPAGE_NAME
, &bCodeName
, CODEPAGE_MAXLEN
,
2030 &Codepage
[0], Property
->Codepage
},
2031 /* filter prefix and suffix */
2032 {HIDING_PREFIX
, &Property
->bHidingPrefix
, HIDINGPAT_LEN
,
2033 &Prefix
[0], Property
->sHidingPrefix
},
2034 {HIDING_SUFFIX
, &Property
->bHidingSuffix
, HIDINGPAT_LEN
,
2035 &Suffix
[0], Property
->sHidingSuffix
},
2036 {MOUNT_POINT
, &bMountPoint
, 4,
2037 &MountPoint
[0], &DrvLetter
[0]},
2040 {NULL
, NULL
, 0, NULL
}
2045 RtlZeroMemory(Codepage
, CODEPAGE_MAXLEN
);
2046 RtlZeroMemory(Prefix
, HIDINGPAT_LEN
);
2047 RtlZeroMemory(Suffix
, HIDINGPAT_LEN
);
2048 RtlZeroMemory(MountPoint
, sizeof(USHORT
) * 4);
2049 RtlZeroMemory(DrvLetter
, sizeof(CHAR
) * 4);
2051 RtlZeroMemory(Property
, sizeof(EXT2_VOLUME_PROPERTY2
));
2052 Property
->Magic
= EXT2_VOLUME_PROPERTY_MAGIC
;
2053 Property
->Command
= APP_CMD_SET_PROPERTY2
;
2055 for (i
=0; ParamPattern
[i
].Name
!= NULL
; i
++) {
2057 UNICODE_STRING Name1
=*Params
, Name2
;
2058 RtlInitUnicodeString(&Name2
, ParamPattern
[i
].Name
);
2059 *ParamPattern
[i
].bExist
= FALSE
;
2061 for (j
=0; j
* sizeof(WCHAR
) + Name2
.Length
<= Params
->Length
; j
++) {
2063 Name1
.MaximumLength
= Params
->Length
- j
* sizeof(WCHAR
);
2064 Name1
.Length
= Name2
.Length
;
2065 Name1
.Buffer
= &Params
->Buffer
[j
];
2067 if (!RtlCompareUnicodeString(&Name1
, &Name2
, TRUE
)) {
2068 if (j
* sizeof(WCHAR
) + Name2
.Length
== Params
->Length
||
2069 Name1
.Buffer
[Name2
.Length
/sizeof(WCHAR
)] == L
';' ||
2070 Name1
.Buffer
[Name2
.Length
/sizeof(WCHAR
)] == L
',' ) {
2071 *(ParamPattern
[i
].bExist
) = TRUE
;
2072 } else if ((j
* 2 + Name2
.Length
< Params
->Length
+ 2) ||
2073 (Name1
.Buffer
[Name2
.Length
/sizeof(WCHAR
)] == L
'=' )) {
2074 j
+= Name2
.Length
/sizeof(WCHAR
) + 1;
2076 while ( j
+ k
< Params
->Length
/2 &&
2077 k
< ParamPattern
[i
].Length
&&
2078 Params
->Buffer
[j
+k
] != L
';' &&
2079 Params
->Buffer
[j
+k
] != L
',' ) {
2080 ParamPattern
[i
].uValue
[k
] = Params
->Buffer
[j
+ k
++];
2084 ANSI_STRING AnsiName
;
2085 AnsiName
.Length
= 0;
2086 AnsiName
.MaximumLength
=ParamPattern
[i
].Length
;
2087 AnsiName
.Buffer
= ParamPattern
[i
].aValue
;
2089 Name2
.Buffer
= ParamPattern
[i
].uValue
;
2090 Name2
.MaximumLength
= Name2
.Length
= k
* sizeof(WCHAR
);
2091 status
= RtlUnicodeStringToAnsiString(
2092 &AnsiName
, &Name2
, FALSE
);
2093 if (NT_SUCCESS(status
)) {
2094 *(ParamPattern
[i
].bExist
) = TRUE
;
2096 *ParamPattern
[i
].bExist
= FALSE
;
2106 Property
->DrvLetter
= DrvLetter
[0];
2107 Property
->DrvLetter
|= 0x80;
2112 Ext2PerformRegistryVolumeParams(IN PEXT2_VCB Vcb
)
2115 UNICODE_STRING VolumeParams
;
2117 Status
= Ext2QueryVolumeParams(Vcb
, &VolumeParams
);
2118 if (NT_SUCCESS(Status
)) {
2120 /* set Vcb settings from registery */
2121 EXT2_VOLUME_PROPERTY2 Property
;
2122 Ext2ParseRegistryVolumeParams(&VolumeParams
, &Property
);
2123 Ext2ProcessVolumeProperty(Vcb
, &Property
, sizeof(Property
));
2127 /* don't support auto mount */
2128 if (IsFlagOn(Ext2Global
->Flags
, EXT2_AUTO_MOUNT
)) {
2129 Status
= STATUS_SUCCESS
;
2131 Status
= STATUS_UNSUCCESSFUL
;
2135 /* set Vcb settings from Ext2Global */
2136 if (IsFlagOn(Ext2Global
->Flags
, EXT2_SUPPORT_WRITING
)) {
2137 if (Vcb
->IsExt3fs
) {
2138 if (IsFlagOn(Ext2Global
->Flags
, EXT3_FORCE_WRITING
)) {
2139 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2141 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2144 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2147 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2150 /* set the default codepage */
2151 Vcb
->Codepage
.PageTable
= Ext2Global
->Codepage
.PageTable
;
2152 memcpy(Vcb
->Codepage
.AnsiName
, Ext2Global
->Codepage
.AnsiName
, CODEPAGE_MAXLEN
);
2153 Vcb
->Codepage
.PageTable
= Ext2Global
->Codepage
.PageTable
;
2155 if ((Vcb
->bHidingPrefix
= Ext2Global
->bHidingPrefix
) != 0) {
2156 RtlCopyMemory( Vcb
->sHidingPrefix
,
2157 Ext2Global
->sHidingPrefix
,
2160 RtlZeroMemory( Vcb
->sHidingPrefix
,
2164 if ((Vcb
->bHidingSuffix
= Ext2Global
->bHidingSuffix
) != 0) {
2165 RtlCopyMemory( Vcb
->sHidingSuffix
,
2166 Ext2Global
->sHidingSuffix
,
2169 RtlZeroMemory( Vcb
->sHidingSuffix
,
2176 if (VolumeParams
.Buffer
) {
2177 Ext2FreePool(VolumeParams
.Buffer
, EXT2_PARAM_MAGIC
);
2184 Ext2InitializeLabel(
2186 IN PEXT2_SUPER_BLOCK Sb
2192 UNICODE_STRING Label
;
2195 Label
.MaximumLength
= 16 * sizeof(WCHAR
);
2197 Label
.Buffer
= Vcb
->Vpb
->VolumeLabel
;
2198 Vcb
->Vpb
->VolumeLabelLength
= 0;
2199 RtlZeroMemory(Label
.Buffer
, Label
.MaximumLength
);
2202 while ( (Length
> 0) &&
2203 ((Sb
->s_volume_name
[Length
-1] == 0x00) ||
2204 (Sb
->s_volume_name
[Length
- 1] == 0x20) )
2210 return STATUS_SUCCESS
;
2213 OemName
.Buffer
= Sb
->s_volume_name
;
2214 OemName
.MaximumLength
= 16;
2215 OemName
.Length
= Length
;
2217 status
= Ext2OEMToUnicode(Vcb
, &Label
, &OemName
);
2218 if (NT_SUCCESS(status
)) {
2219 Vcb
->Vpb
->VolumeLabelLength
= Label
.Length
;
2225 static __inline BOOLEAN
Ext2IsNullUuid (__u8
* uuid
)
2228 for (i
= 0; i
< 16; i
++) {
2237 #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
2240 Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext
,
2242 IN PEXT2_SUPER_BLOCK sb
,
2243 IN PDEVICE_OBJECT TargetDevice
,
2244 IN PDEVICE_OBJECT VolumeDevice
,
2247 NTSTATUS Status
= STATUS_UNRECOGNIZED_VOLUME
;
2251 UNICODE_STRING RootNode
;
2253 ULONG ChangeCount
= 0, features
;
2254 CC_FILE_SIZES FileSizes
;
2255 int i
, has_huge_files
;
2257 BOOLEAN VcbResourceInitialized
= FALSE
;
2258 BOOLEAN NotifySyncInitialized
= FALSE
;
2259 BOOLEAN ExtentsInitialized
= FALSE
;
2260 BOOLEAN InodeLookasideInitialized
= FALSE
;
2265 Status
= STATUS_DEVICE_NOT_READY
;
2269 /* checking in/compat features */
2270 if (IsFlagOn(sb
->s_feature_compat
, EXT3_FEATURE_COMPAT_HAS_JOURNAL
)) {
2271 Vcb
->IsExt3fs
= TRUE
;
2274 /* don't mount any volumes with external journal devices */
2275 if (IsFlagOn(sb
->s_feature_incompat
, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)) {
2276 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2280 /* check block size */
2281 Vcb
->BlockSize
= (EXT2_MIN_BLOCK_SIZE
<< sb
->s_log_block_size
);
2282 /* we cannot handle volume with block size bigger than 64k */
2283 if (Vcb
->BlockSize
> EXT2_MAX_USER_BLKSIZE
) {
2284 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2288 if (Vcb
->BlockSize
>= PAGE_SIZE
) {
2289 Vcb
->IoUnitBits
= PAGE_SHIFT
;
2290 Vcb
->IoUnitSize
= PAGE_SIZE
;
2292 Vcb
->IoUnitSize
= Vcb
->BlockSize
;
2293 Vcb
->IoUnitBits
= Ext2Log2(Vcb
->BlockSize
);
2296 /* initialize vcb header members ... */
2297 Vcb
->Header
.IsFastIoPossible
= FastIoIsNotPossible
;
2298 Vcb
->Header
.Resource
= &(Vcb
->MainResource
);
2299 Vcb
->Header
.PagingIoResource
= &(Vcb
->PagingIoResource
);
2300 Vcb
->OpenVolumeCount
= 0;
2301 Vcb
->OpenHandleCount
= 0;
2302 Vcb
->ReferenceCount
= 0;
2304 /* initialize eresources */
2305 ExInitializeResourceLite(&Vcb
->MainResource
);
2306 ExInitializeResourceLite(&Vcb
->PagingIoResource
);
2307 ExInitializeResourceLite(&Vcb
->MetaLock
);
2308 ExInitializeResourceLite(&Vcb
->McbLock
);
2309 #ifndef _WIN2K_TARGET_
2310 ExInitializeFastMutex(&Vcb
->Mutex
);
2311 FsRtlSetupAdvancedHeader(&Vcb
->Header
, &Vcb
->Mutex
);
2313 VcbResourceInitialized
= TRUE
;
2315 /* initialize Fcb list head */
2316 InitializeListHead(&Vcb
->FcbList
);
2317 KeInitializeSpinLock(&Vcb
->FcbLock
);
2319 /* initialize Mcb list head */
2320 InitializeListHead(&(Vcb
->McbList
));
2322 /* initialize directory notify list */
2323 InitializeListHead(&Vcb
->NotifyList
);
2324 FsRtlNotifyInitializeSync(&Vcb
->NotifySync
);
2325 NotifySyncInitialized
= TRUE
;
2327 /* superblock checking */
2328 Vcb
->SuperBlock
= sb
;
2330 /* initialize Vpb and Label */
2331 Vcb
->DeviceObject
= VolumeDevice
;
2332 Vcb
->TargetDeviceObject
= TargetDevice
;
2334 Vcb
->RealDevice
= Vpb
->RealDevice
;
2335 Vpb
->DeviceObject
= VolumeDevice
;
2337 /* set inode size */
2338 Vcb
->InodeSize
= (ULONG
)sb
->s_inode_size
;
2339 if (Vcb
->InodeSize
== 0) {
2340 Vcb
->InodeSize
= EXT2_GOOD_OLD_INODE_SIZE
;
2343 /* initialize inode lookaside list */
2344 ExInitializeNPagedLookasideList(&(Vcb
->InodeLookasideList
),
2345 NULL
, NULL
, 0, sizeof(EXT2_INODE
),
2348 InodeLookasideInitialized
= TRUE
;
2350 /* initialize label in Vpb */
2351 Status
= Ext2InitializeLabel(Vcb
, sb
);
2352 if (!NT_SUCCESS(Status
)) {
2356 /* check device characteristics flags */
2357 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
2358 SetLongFlag(Vcb
->Flags
, VCB_REMOVABLE_MEDIA
);
2361 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_FLOPPY_DISKETTE
)) {
2362 SetLongFlag(Vcb
->Flags
, VCB_FLOPPY_DISK
);
2365 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_READ_ONLY_DEVICE
)) {
2366 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2369 if (IsFlagOn(TargetDevice
->Characteristics
, FILE_READ_ONLY_DEVICE
)) {
2370 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2373 /* verify device is writable ? */
2374 if (Ext2IsMediaWriteProtected(IrpContext
, TargetDevice
)) {
2375 SetFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2378 /* initialize UUID and serial number */
2379 if (Ext2IsNullUuid(sb
->s_uuid
)) {
2380 ExUuidCreate((UUID
*)sb
->s_uuid
);
2382 /* query parameters from registry */
2383 if (!NT_SUCCESS(Ext2PerformRegistryVolumeParams(Vcb
))) {
2384 /* don't mount this volume */
2385 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2390 Vpb
->SerialNumber
= ((ULONG
*)sb
->s_uuid
)[0] +
2391 ((ULONG
*)sb
->s_uuid
)[1] +
2392 ((ULONG
*)sb
->s_uuid
)[2] +
2393 ((ULONG
*)sb
->s_uuid
)[3];
2395 /* query partition size and disk geometry parameters */
2396 DiskSize
= Vcb
->DiskGeometry
.Cylinders
.QuadPart
*
2397 Vcb
->DiskGeometry
.TracksPerCylinder
*
2398 Vcb
->DiskGeometry
.SectorsPerTrack
*
2399 Vcb
->DiskGeometry
.BytesPerSector
;
2401 IoctlSize
= sizeof(PARTITION_INFORMATION
);
2402 Status
= Ext2DiskIoControl(
2404 IOCTL_DISK_GET_PARTITION_INFO
,
2407 &Vcb
->PartitionInformation
,
2409 if (NT_SUCCESS(Status
)) {
2410 PartSize
= Vcb
->PartitionInformation
.PartitionLength
.QuadPart
;
2412 Vcb
->PartitionInformation
.StartingOffset
.QuadPart
= 0;
2413 Vcb
->PartitionInformation
.PartitionLength
.QuadPart
= DiskSize
;
2414 PartSize
= DiskSize
;
2415 Status
= STATUS_SUCCESS
;
2417 Vcb
->Header
.AllocationSize
.QuadPart
=
2418 Vcb
->Header
.FileSize
.QuadPart
= PartSize
;
2420 Vcb
->Header
.ValidDataLength
.QuadPart
=
2421 Vcb
->Header
.FileSize
.QuadPart
;
2424 IoctlSize
= sizeof(ULONG
);
2425 Status
= Ext2DiskIoControl(
2427 IOCTL_DISK_CHECK_VERIFY
,
2433 if (!NT_SUCCESS(Status
)) {
2436 Vcb
->ChangeCount
= ChangeCount
;
2438 /* create the stream object for ext2 volume */
2439 Vcb
->Volume
= IoCreateStreamFileObject(NULL
, Vcb
->Vpb
->RealDevice
);
2441 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2445 /* initialize streaming object file */
2446 Vcb
->Volume
->SectionObjectPointer
= &(Vcb
->SectionObject
);
2447 Vcb
->Volume
->ReadAccess
= TRUE
;
2448 Vcb
->Volume
->WriteAccess
= TRUE
;
2449 Vcb
->Volume
->DeleteAccess
= TRUE
;
2450 Vcb
->Volume
->FsContext
= (PVOID
) Vcb
;
2451 Vcb
->Volume
->FsContext2
= NULL
;
2452 Vcb
->Volume
->Vpb
= Vcb
->Vpb
;
2454 FileSizes
.AllocationSize
.QuadPart
=
2455 FileSizes
.FileSize
.QuadPart
=
2456 FileSizes
.ValidDataLength
.QuadPart
=
2457 Vcb
->Header
.AllocationSize
.QuadPart
;
2459 CcInitializeCacheMap( Vcb
->Volume
,
2462 &(Ext2Global
->CacheManagerNoOpCallbacks
),
2465 /* initialize disk block LargetMcb and entry Mcb,
2466 it will raise an expcetion if failed */
2468 FsRtlInitializeLargeMcb(&(Vcb
->Extents
), PagedPool
);
2469 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
2470 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2473 if (!NT_SUCCESS(Status
)) {
2476 ExtentsInitialized
= TRUE
;
2478 /* set block device */
2479 Vcb
->bd
.bd_dev
= Vcb
->RealDevice
;
2480 Vcb
->bd
.bd_geo
= Vcb
->DiskGeometry
;
2481 Vcb
->bd
.bd_part
= Vcb
->PartitionInformation
;
2482 Vcb
->bd
.bd_volume
= Vcb
->Volume
;
2483 Vcb
->bd
.bd_priv
= (void *) Vcb
;
2484 memset(&Vcb
->bd
.bd_bh_root
, 0, sizeof(struct rb_root
));
2485 spin_lock_init(&Vcb
->bd
.bd_bh_lock
);
2486 Vcb
->bd
.bd_bh_cache
= kmem_cache_create("bd_bh_buffer",
2487 Vcb
->BlockSize
, 0, 0, NULL
);
2488 if (!Vcb
->bd
.bd_bh_cache
) {
2489 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2493 Vcb
->SectorBits
= Ext2Log2(SECTOR_SIZE
);
2494 Vcb
->sb
.s_magic
= sb
->s_magic
;
2495 Vcb
->sb
.s_bdev
= &Vcb
->bd
;
2496 Vcb
->sb
.s_blocksize
= BLOCK_SIZE
;
2497 Vcb
->sb
.s_blocksize_bits
= BLOCK_BITS
;
2498 Vcb
->sb
.s_priv
= (void *) Vcb
;
2499 Vcb
->sb
.s_fs_info
= &Vcb
->sbi
;
2502 Vcb
->sbi
.s_blocks_per_group
= sb
->s_blocks_per_group
;
2503 Vcb
->sbi
.s_first_ino
= sb
->s_first_ino
;
2504 Vcb
->sbi
.s_desc_size
= sb
->s_desc_size
;
2506 if (EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, EXT4_FEATURE_INCOMPAT_64BIT
)) {
2507 if (Vcb
->sbi
.s_desc_size
< EXT4_MIN_DESC_SIZE_64BIT
||
2508 Vcb
->sbi
.s_desc_size
> EXT4_MAX_DESC_SIZE
||
2509 !is_power_of_2(Vcb
->sbi
.s_desc_size
)) {
2510 DEBUG(DL_ERR
, ("EXT4-fs: unsupported descriptor size %lu\n", Vcb
->sbi
.s_desc_size
));
2511 Status
= STATUS_DISK_CORRUPT_ERROR
;
2515 Vcb
->sbi
.s_desc_size
= EXT4_MIN_DESC_SIZE
;
2518 Vcb
->sbi
.s_blocks_per_group
= sb
->s_blocks_per_group
;
2519 Vcb
->sbi
.s_inodes_per_group
= sb
->s_inodes_per_group
;
2520 if (EXT3_INODES_PER_GROUP(&Vcb
->sb
) == 0) {
2521 Status
= STATUS_DISK_CORRUPT_ERROR
;
2524 Vcb
->sbi
.s_inodes_per_block
= BLOCK_SIZE
/ Vcb
->InodeSize
;
2525 if (Vcb
->sbi
.s_inodes_per_block
== 0) {
2526 Status
= STATUS_DISK_CORRUPT_ERROR
;
2529 Vcb
->sbi
.s_itb_per_group
= Vcb
->sbi
.s_inodes_per_group
/
2530 Vcb
->sbi
.s_inodes_per_block
;
2533 Vcb
->sbi
.s_desc_per_block
= BLOCK_SIZE
/ GROUP_DESC_SIZE
;
2534 Vcb
->sbi
.s_desc_per_block_bits
= ilog2(Vcb
->sbi
.s_desc_per_block
);
2536 for (i
=0; i
< 4; i
++) {
2537 Vcb
->sbi
.s_hash_seed
[i
] = sb
->s_hash_seed
[i
];
2539 Vcb
->sbi
.s_def_hash_version
= sb
->s_def_hash_version
;
2541 if (le32_to_cpu(sb
->s_rev_level
) == EXT3_GOOD_OLD_REV
&&
2542 (EXT3_HAS_COMPAT_FEATURE(&Vcb
->sb
, ~0U) ||
2543 EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, ~0U) ||
2544 EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, ~0U))) {
2546 "EXT3-fs warning: feature flags set on rev 0 fs, "
2547 "running e2fsck is recommended\n");
2551 * Check feature flags regardless of the revision level, since we
2552 * previously didn't change the revision level when setting the flags,
2553 * so there is a chance incompat flags are set on a rev 0 filesystem.
2555 features
= EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, ~EXT4_FEATURE_INCOMPAT_SUPP
);
2556 if (features
& EXT4_FEATURE_INCOMPAT_DIRDATA
) {
2557 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2558 ClearFlag(features
, EXT4_FEATURE_INCOMPAT_DIRDATA
);
2561 printk(KERN_ERR
"EXT3-fs: %s: couldn't mount because of "
2562 "unsupported optional features (%x).\n",
2563 Vcb
->sb
.s_id
, le32_to_cpu(features
));
2564 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2568 features
= EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, ~EXT4_FEATURE_RO_COMPAT_SUPP
);
2570 printk(KERN_ERR
"EXT3-fs: %s: unsupported optional features in this volume: (%x).\n",
2571 Vcb
->sb
.s_id
, le32_to_cpu(features
));
2572 if (CanIWrite(Vcb
)) {
2574 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2578 has_huge_files
= EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, EXT4_FEATURE_RO_COMPAT_HUGE_FILE
);
2580 Vcb
->sb
.s_maxbytes
= ext3_max_size(BLOCK_BITS
, has_huge_files
);
2581 Vcb
->max_bitmap_bytes
= ext3_max_bitmap_size(BLOCK_BITS
,
2583 Vcb
->max_bytes
= ext3_max_size(BLOCK_BITS
, has_huge_files
);
2585 /* calculate maximum file bocks ... */
2587 ULONG dwData
[EXT2_BLOCK_TYPES
] = {EXT2_NDIR_BLOCKS
, 1, 1, 1};
2590 ASSERT(BLOCK_BITS
== Ext2Log2(BLOCK_SIZE
));
2592 Vcb
->sbi
.s_groups_count
= (ULONG
)(ext3_blocks_count(sb
) - sb
->s_first_data_block
+
2593 sb
->s_blocks_per_group
- 1) / sb
->s_blocks_per_group
;
2595 Vcb
->max_data_blocks
= 0;
2596 for (i
= 0; i
< EXT2_BLOCK_TYPES
; i
++) {
2597 if (BLOCK_BITS
>= 12 && i
== (EXT2_BLOCK_TYPES
- 1)) {
2598 dwData
[i
] = 0x40000000;
2600 dwData
[i
] = dwData
[i
] << ((BLOCK_BITS
- 2) * i
);
2602 Vcb
->max_blocks_per_layer
[i
] = dwData
[i
];
2603 Vcb
->max_data_blocks
+= Vcb
->max_blocks_per_layer
[i
];
2607 Vcb
->sbi
.s_gdb_count
= (Vcb
->sbi
.s_groups_count
+ Vcb
->sbi
.s_desc_per_block
- 1) /
2608 Vcb
->sbi
.s_desc_per_block
;
2609 /* load all gorup desc */
2610 if (!Ext2LoadGroup(Vcb
)) {
2611 Status
= STATUS_UNSUCCESSFUL
;
2615 /* recovery journal since it's ext3 */
2616 if (Vcb
->IsExt3fs
) {
2617 Ext2RecoverJournal(IrpContext
, Vcb
);
2618 if (IsFlagOn(Vcb
->Flags
, VCB_JOURNAL_RECOVER
)) {
2619 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2623 /* Now allocating the mcb for root ... */
2626 RootNode
.Buffer
= Buffer
;
2627 RootNode
.MaximumLength
= RootNode
.Length
= 2;
2628 Vcb
->McbTree
= Ext2AllocateMcb(
2629 Vcb
, &RootNode
, NULL
,
2630 FILE_ATTRIBUTE_DIRECTORY
2632 if (!Vcb
->McbTree
) {
2634 Status
= STATUS_UNSUCCESSFUL
;
2638 Vcb
->sb
.s_root
= Ext2BuildEntry(Vcb
, NULL
, &RootNode
);
2639 if (!Vcb
->sb
.s_root
) {
2641 Status
= STATUS_UNSUCCESSFUL
;
2644 Vcb
->sb
.s_root
->d_sb
= &Vcb
->sb
;
2645 Vcb
->sb
.s_root
->d_inode
= &Vcb
->McbTree
->Inode
;
2646 Vcb
->McbTree
->de
= Vcb
->sb
.s_root
;
2648 /* load root inode */
2649 Vcb
->McbTree
->Inode
.i_ino
= EXT2_ROOT_INO
;
2650 Vcb
->McbTree
->Inode
.i_sb
= &Vcb
->sb
;
2651 if (!Ext2LoadInode(Vcb
, &Vcb
->McbTree
->Inode
)) {
2653 Status
= STATUS_CANT_WAIT
;
2657 /* initializeroot node */
2658 Vcb
->McbTree
->CreationTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_ctime
);
2659 Vcb
->McbTree
->LastAccessTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_atime
);
2660 Vcb
->McbTree
->LastWriteTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_mtime
);
2661 Vcb
->McbTree
->ChangeTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_mtime
);
2663 /* check bitmap if user specifies it */
2664 if (IsFlagOn(Ext2Global
->Flags
, EXT2_CHECKING_BITMAP
)) {
2665 Ext2CheckBitmapConsistency(IrpContext
, Vcb
);
2668 /* get anything doen, then refer target device */
2669 ObReferenceObject(Vcb
->TargetDeviceObject
);
2670 SetLongFlag(Vcb
->Flags
, VCB_INITIALIZED
);
2674 if (!NT_SUCCESS(Status
)) {
2677 Ext2FreeMcb(Vcb
, Vcb
->McbTree
);
2680 if (InodeLookasideInitialized
) {
2681 ExDeleteNPagedLookasideList(&(Vcb
->InodeLookasideList
));
2684 if (ExtentsInitialized
) {
2686 if (Vcb
->bd
.bd_bh_cache
)
2687 kmem_cache_destroy(Vcb
->bd
.bd_bh_cache
);
2688 FsRtlUninitializeLargeMcb(&(Vcb
->Extents
));
2692 if (Vcb
->Volume
->PrivateCacheMap
) {
2693 Ext2SyncUninitializeCacheMap(Vcb
->Volume
);
2695 ObDereferenceObject(Vcb
->Volume
);
2698 if (NotifySyncInitialized
) {
2699 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
2702 if (VcbResourceInitialized
) {
2703 ExDeleteResourceLite(&Vcb
->McbLock
);
2704 ExDeleteResourceLite(&Vcb
->MetaLock
);
2705 ExDeleteResourceLite(&Vcb
->MainResource
);
2706 ExDeleteResourceLite(&Vcb
->PagingIoResource
);
2716 Ext2TearDownStream(IN PEXT2_VCB Vcb
)
2718 PFILE_OBJECT Stream
= Vcb
->Volume
;
2719 IO_STATUS_BLOCK IoStatus
;
2721 ASSERT(Vcb
!= NULL
);
2722 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2723 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2729 if (IsFlagOn(Stream
->Flags
, FO_FILE_MODIFIED
)) {
2730 CcFlushCache(&(Vcb
->SectionObject
), NULL
, 0, &IoStatus
);
2731 ClearFlag(Stream
->Flags
, FO_FILE_MODIFIED
);
2734 if (Stream
->PrivateCacheMap
) {
2735 Ext2SyncUninitializeCacheMap(Stream
);
2738 ObDereferenceObject(Stream
);
2743 Ext2DestroyVcb (IN PEXT2_VCB Vcb
)
2745 ASSERT(Vcb
!= NULL
);
2746 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2747 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2749 DEBUG(DL_FUN
, ("Ext2DestroyVcb ...\n"));
2752 Ext2TearDownStream(Vcb
);
2754 ASSERT(NULL
== Vcb
->Volume
);
2756 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
2757 Ext2ListExtents(&Vcb
->Extents
);
2758 FsRtlUninitializeLargeMcb(&(Vcb
->Extents
));
2760 Ext2CleanupAllMcbs(Vcb
);
2764 if (Vcb
->bd
.bd_bh_cache
)
2765 kmem_cache_destroy(Vcb
->bd
.bd_bh_cache
);
2767 if (Vcb
->SuperBlock
) {
2768 Ext2FreePool(Vcb
->SuperBlock
, EXT2_SB_MAGIC
);
2769 Vcb
->SuperBlock
= NULL
;
2772 if (IsFlagOn(Vcb
->Flags
, VCB_NEW_VPB
)) {
2773 ASSERT(Vcb
->Vpb2
!= NULL
);
2774 Ext2FreePool(Vcb
->Vpb2
, TAG_VPB
);
2775 DEC_MEM_COUNT(PS_VPB
, Vcb
->Vpb2
, sizeof(VPB
));
2779 ObDereferenceObject(Vcb
->TargetDeviceObject
);
2781 ExDeleteNPagedLookasideList(&(Vcb
->InodeLookasideList
));
2782 ExDeleteResourceLite(&Vcb
->McbLock
);
2783 ExDeleteResourceLite(&Vcb
->MetaLock
);
2784 ExDeleteResourceLite(&Vcb
->PagingIoResource
);
2785 ExDeleteResourceLite(&Vcb
->MainResource
);
2787 DEBUG(DL_DBG
, ("Ext2DestroyVcb: DevObject=%p Vcb=%p\n", Vcb
->DeviceObject
, Vcb
));
2788 IoDeleteDevice(Vcb
->DeviceObject
);
2789 DEC_MEM_COUNT(PS_VCB
, Vcb
->DeviceObject
, sizeof(EXT2_VCB
));
2793 /* uninitialize cache map */
2796 Ext2SyncUninitializeCacheMap (
2797 IN PFILE_OBJECT FileObject
2800 CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent
;
2801 NTSTATUS WaitStatus
;
2802 LARGE_INTEGER Ext2LargeZero
= {0,0};
2805 KeInitializeEvent( &UninitializeCompleteEvent
.Event
,
2806 SynchronizationEvent
,
2809 CcUninitializeCacheMap( FileObject
,
2811 &UninitializeCompleteEvent
);
2813 WaitStatus
= KeWaitForSingleObject( &UninitializeCompleteEvent
.Event
,
2819 ASSERT (NT_SUCCESS(WaitStatus
));
2822 /* Link Mcb to tail of Vcb->McbList queue */
2825 Ext2LinkTailMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2827 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2831 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2833 if (IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2834 DEBUG(DL_RES
, ( "Ext2LinkTailMcb: %wZ already linked.\n",
2837 InsertTailList(&Vcb
->McbList
, &Mcb
->Link
);
2838 SetLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2839 Ext2ReferXcb(&Vcb
->NumOfMcb
);
2842 ExReleaseResourceLite(&Vcb
->McbLock
);
2845 /* Link Mcb to head of Vcb->McbList queue */
2848 Ext2LinkHeadMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2850 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2854 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2856 if (!IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2857 InsertHeadList(&Vcb
->McbList
, &Mcb
->Link
);
2858 SetLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2859 Ext2ReferXcb(&Vcb
->NumOfMcb
);
2861 DEBUG(DL_RES
, ( "Ext2LinkHeadMcb: %wZ already linked.\n",
2864 ExReleaseResourceLite(&Vcb
->McbLock
);
2867 /* Unlink Mcb from Vcb->McbList queue */
2870 Ext2UnlinkMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2872 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2876 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2878 if (IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2879 RemoveEntryList(&(Mcb
->Link
));
2880 ClearLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2881 Ext2DerefXcb(&Vcb
->NumOfMcb
);
2883 DEBUG(DL_RES
, ( "Ext2UnlinkMcb: %wZ already unlinked.\n",
2886 ExReleaseResourceLite(&Vcb
->McbLock
);
2889 /* get the first Mcb record in Vcb->McbList */
2892 Ext2FirstUnusedMcb(PEXT2_VCB Vcb
, BOOLEAN Wait
, ULONG Number
)
2894 PEXT2_MCB Head
= NULL
;
2895 PEXT2_MCB Tail
= NULL
;
2896 PEXT2_MCB Mcb
= NULL
;
2897 PLIST_ENTRY List
= NULL
;
2900 if (!ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, Wait
)) {
2906 if (!IsListEmpty(&Vcb
->McbList
)) {
2908 while (i
++ < Vcb
->NumOfMcb
) {
2910 List
= RemoveHeadList(&Vcb
->McbList
);
2911 Mcb
= CONTAINING_RECORD(List
, EXT2_MCB
, Link
);
2912 ASSERT(IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
));
2914 if (Mcb
->Fcb
== NULL
&& !IsMcbRoot(Mcb
) &&
2915 Mcb
->Refercount
== 0 &&
2916 (Mcb
->Child
== NULL
|| IsMcbSymLink(Mcb
))) {
2918 Ext2RemoveMcb(Vcb
, Mcb
);
2919 ClearLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2920 Ext2DerefXcb(&Vcb
->NumOfMcb
);
2922 /* attach all Mcb into a chain*/
2924 ASSERT(Tail
!= NULL
);
2934 InsertTailList(&Vcb
->McbList
, &Mcb
->Link
);
2940 ExReleaseResourceLite(&Vcb
->McbLock
);
2946 /* Reaper thread to release unused Mcb blocks */
2952 BOOLEAN GlobalAcquired
= FALSE
;
2954 BOOLEAN DidNothing
= TRUE
;
2955 BOOLEAN LastState
= TRUE
;
2958 PLIST_ENTRY List
= NULL
;
2959 LARGE_INTEGER Timeout
;
2961 PEXT2_VCB Vcb
= NULL
;
2962 PEXT2_MCB Mcb
= NULL
;
2968 /* wake up DirverEntry */
2969 KeSetEvent(&Ext2Global
->Reaper
.Engine
, 0, FALSE
);
2971 /* now process looping */
2976 /* calculate how long we need wait */
2977 if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 128)) {
2978 Timeout
.QuadPart
= (LONGLONG
)-1000*1000; /* 0.1 second */
2979 NumOfMcbs
= Ext2Global
->MaxDepth
* 4;
2981 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 32)) {
2982 Timeout
.QuadPart
= (LONGLONG
)-1000*1000*5; /* 0.5 second */
2983 NumOfMcbs
= Ext2Global
->MaxDepth
* 2;
2985 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 8)) {
2986 Timeout
.QuadPart
= (LONGLONG
)-1000*1000*10; /* 1 second */
2987 NumOfMcbs
= Ext2Global
->MaxDepth
;
2988 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 2)) {
2989 Timeout
.QuadPart
= (LONGLONG
)-2*1000*1000*10; /* 2 second */
2990 NumOfMcbs
= Ext2Global
->MaxDepth
/ 4;
2991 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (ULONG
)Ext2Global
->MaxDepth
) {
2992 Timeout
.QuadPart
= (LONGLONG
)-4*1000*1000*10; /* 4 seconds */
2993 NumOfMcbs
= Ext2Global
->MaxDepth
/ 8;
2994 } else if (DidNothing
) {
2995 Timeout
.QuadPart
= (LONGLONG
)-8*1000*1000*10; /* 8 seconds */
2997 Timeout
.QuadPart
*= 2;
2999 NumOfMcbs
= Ext2Global
->MaxDepth
/ 16;
3001 Timeout
.QuadPart
= (LONGLONG
)-5*1000*1000*10; /* 5 seconds */
3003 Timeout
.QuadPart
*= 2;
3005 NumOfMcbs
= Ext2Global
->MaxDepth
/ 32;
3011 LastState
= DidNothing
;
3013 /* wait until it is waken or it times out */
3014 KeWaitForSingleObject(
3015 &(Ext2Global
->Reaper
.Wait
),
3024 /* acquire global exclusive lock */
3025 if (!ExAcquireResourceSharedLite(&Ext2Global
->Resource
, WaitLock
)) {
3028 GlobalAcquired
= TRUE
;
3030 /* search all Vcb to get unused resources freed to system */
3031 for (List
= Ext2Global
->VcbList
.Flink
;
3032 List
!= &(Ext2Global
->VcbList
);
3033 List
= List
->Flink
) {
3035 Vcb
= CONTAINING_RECORD(List
, EXT2_VCB
, Next
);
3037 Mcb
= Ext2FirstUnusedMcb(Vcb
, WaitLock
, NumOfMcbs
);
3039 PEXT2_MCB Next
= Mcb
->Next
;
3040 DEBUG(DL_RES
, ( "Ext2ReaperThread: releasing Mcb (%p): %wZ"
3041 " Total: %xh\n", Mcb
, &Mcb
->FullName
,
3042 Ext2Global
->PerfStat
.Current
.Mcb
));
3043 Ext2FreeMcb(Vcb
, Mcb
);
3045 LastState
= DidNothing
= FALSE
;
3049 if (GlobalAcquired
) {
3050 ExReleaseResourceLite(&Ext2Global
->Resource
);
3051 GlobalAcquired
= FALSE
;
3057 if (GlobalAcquired
) {
3058 ExReleaseResourceLite(&Ext2Global
->Resource
);
3062 PsTerminateSystemThread(STATUS_SUCCESS
);
3067 Ext2StartReaperThread()
3069 NTSTATUS status
= STATUS_SUCCESS
;
3070 OBJECT_ATTRIBUTES oa
;
3073 /* initialize wait event */
3075 &Ext2Global
->Reaper
.Wait
,
3076 SynchronizationEvent
, FALSE
3080 InitializeObjectAttributes(
3083 OBJ_CASE_INSENSITIVE
|
3089 /* start a new system thread */
3090 status
= PsCreateSystemThread(
3100 if (NT_SUCCESS(status
)) {