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
',' ) {
2081 ParamPattern
[i
].uValue
[k
] = Params
->Buffer
[j
+ k
];
2084 ParamPattern
[i
].uValue
[k
] = Params
->Buffer
[j
+ k
++];
2089 ANSI_STRING AnsiName
;
2090 AnsiName
.Length
= 0;
2091 AnsiName
.MaximumLength
=ParamPattern
[i
].Length
;
2092 AnsiName
.Buffer
= ParamPattern
[i
].aValue
;
2094 Name2
.Buffer
= ParamPattern
[i
].uValue
;
2095 Name2
.MaximumLength
= Name2
.Length
= k
* sizeof(WCHAR
);
2096 status
= RtlUnicodeStringToAnsiString(
2097 &AnsiName
, &Name2
, FALSE
);
2098 if (NT_SUCCESS(status
)) {
2099 *(ParamPattern
[i
].bExist
) = TRUE
;
2101 *ParamPattern
[i
].bExist
= FALSE
;
2111 Property
->DrvLetter
= DrvLetter
[0];
2112 Property
->DrvLetter
|= 0x80;
2117 Ext2PerformRegistryVolumeParams(IN PEXT2_VCB Vcb
)
2120 UNICODE_STRING VolumeParams
;
2122 Status
= Ext2QueryVolumeParams(Vcb
, &VolumeParams
);
2123 if (NT_SUCCESS(Status
)) {
2125 /* set Vcb settings from registery */
2126 EXT2_VOLUME_PROPERTY2 Property
;
2127 Ext2ParseRegistryVolumeParams(&VolumeParams
, &Property
);
2128 Ext2ProcessVolumeProperty(Vcb
, &Property
, sizeof(Property
));
2132 /* don't support auto mount */
2133 if (IsFlagOn(Ext2Global
->Flags
, EXT2_AUTO_MOUNT
)) {
2134 Status
= STATUS_SUCCESS
;
2136 Status
= STATUS_UNSUCCESSFUL
;
2140 /* set Vcb settings from Ext2Global */
2141 if (IsFlagOn(Ext2Global
->Flags
, EXT2_SUPPORT_WRITING
)) {
2142 if (Vcb
->IsExt3fs
) {
2143 if (IsFlagOn(Ext2Global
->Flags
, EXT3_FORCE_WRITING
)) {
2144 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2146 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2149 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2152 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2155 /* set the default codepage */
2156 Vcb
->Codepage
.PageTable
= Ext2Global
->Codepage
.PageTable
;
2157 memcpy(Vcb
->Codepage
.AnsiName
, Ext2Global
->Codepage
.AnsiName
, CODEPAGE_MAXLEN
);
2158 Vcb
->Codepage
.PageTable
= Ext2Global
->Codepage
.PageTable
;
2160 if ((Vcb
->bHidingPrefix
= Ext2Global
->bHidingPrefix
) != 0) {
2161 RtlCopyMemory( Vcb
->sHidingPrefix
,
2162 Ext2Global
->sHidingPrefix
,
2165 RtlZeroMemory( Vcb
->sHidingPrefix
,
2169 if ((Vcb
->bHidingSuffix
= Ext2Global
->bHidingSuffix
) != 0) {
2170 RtlCopyMemory( Vcb
->sHidingSuffix
,
2171 Ext2Global
->sHidingSuffix
,
2174 RtlZeroMemory( Vcb
->sHidingSuffix
,
2181 if (VolumeParams
.Buffer
) {
2182 Ext2FreePool(VolumeParams
.Buffer
, EXT2_PARAM_MAGIC
);
2189 Ext2InitializeLabel(
2191 IN PEXT2_SUPER_BLOCK Sb
2197 UNICODE_STRING Label
;
2200 Label
.MaximumLength
= 16 * sizeof(WCHAR
);
2202 Label
.Buffer
= Vcb
->Vpb
->VolumeLabel
;
2203 Vcb
->Vpb
->VolumeLabelLength
= 0;
2204 RtlZeroMemory(Label
.Buffer
, Label
.MaximumLength
);
2207 while ( (Length
> 0) &&
2208 ((Sb
->s_volume_name
[Length
-1] == 0x00) ||
2209 (Sb
->s_volume_name
[Length
- 1] == 0x20) )
2215 return STATUS_SUCCESS
;
2218 OemName
.Buffer
= Sb
->s_volume_name
;
2219 OemName
.MaximumLength
= 16;
2220 OemName
.Length
= Length
;
2222 status
= Ext2OEMToUnicode(Vcb
, &Label
, &OemName
);
2223 if (NT_SUCCESS(status
)) {
2224 Vcb
->Vpb
->VolumeLabelLength
= Label
.Length
;
2230 static __inline BOOLEAN
Ext2IsNullUuid (__u8
* uuid
)
2233 for (i
= 0; i
< 16; i
++) {
2242 #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
2245 Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext
,
2247 IN PEXT2_SUPER_BLOCK sb
,
2248 IN PDEVICE_OBJECT TargetDevice
,
2249 IN PDEVICE_OBJECT VolumeDevice
,
2252 NTSTATUS Status
= STATUS_UNRECOGNIZED_VOLUME
;
2256 UNICODE_STRING RootNode
;
2258 ULONG ChangeCount
= 0, features
;
2259 CC_FILE_SIZES FileSizes
;
2260 int i
, has_huge_files
;
2262 BOOLEAN VcbResourceInitialized
= FALSE
;
2263 BOOLEAN NotifySyncInitialized
= FALSE
;
2264 BOOLEAN ExtentsInitialized
= FALSE
;
2265 BOOLEAN InodeLookasideInitialized
= FALSE
;
2270 Status
= STATUS_DEVICE_NOT_READY
;
2274 /* checking in/compat features */
2275 if (IsFlagOn(sb
->s_feature_compat
, EXT3_FEATURE_COMPAT_HAS_JOURNAL
)) {
2276 Vcb
->IsExt3fs
= TRUE
;
2279 /* don't mount any volumes with external journal devices */
2280 if (IsFlagOn(sb
->s_feature_incompat
, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)) {
2281 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2285 /* check block size */
2286 Vcb
->BlockSize
= (EXT2_MIN_BLOCK_SIZE
<< sb
->s_log_block_size
);
2287 /* we cannot handle volume with block size bigger than 64k */
2288 if (Vcb
->BlockSize
> EXT2_MAX_USER_BLKSIZE
) {
2289 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2293 if (Vcb
->BlockSize
>= PAGE_SIZE
) {
2294 Vcb
->IoUnitBits
= PAGE_SHIFT
;
2295 Vcb
->IoUnitSize
= PAGE_SIZE
;
2297 Vcb
->IoUnitSize
= Vcb
->BlockSize
;
2298 Vcb
->IoUnitBits
= Ext2Log2(Vcb
->BlockSize
);
2301 /* initialize vcb header members ... */
2302 Vcb
->Header
.IsFastIoPossible
= FastIoIsNotPossible
;
2303 Vcb
->Header
.Resource
= &(Vcb
->MainResource
);
2304 Vcb
->Header
.PagingIoResource
= &(Vcb
->PagingIoResource
);
2305 Vcb
->OpenVolumeCount
= 0;
2306 Vcb
->OpenHandleCount
= 0;
2307 Vcb
->ReferenceCount
= 0;
2309 /* initialize eresources */
2310 ExInitializeResourceLite(&Vcb
->MainResource
);
2311 ExInitializeResourceLite(&Vcb
->PagingIoResource
);
2312 ExInitializeResourceLite(&Vcb
->MetaLock
);
2313 ExInitializeResourceLite(&Vcb
->McbLock
);
2314 #ifndef _WIN2K_TARGET_
2315 ExInitializeFastMutex(&Vcb
->Mutex
);
2316 FsRtlSetupAdvancedHeader(&Vcb
->Header
, &Vcb
->Mutex
);
2318 VcbResourceInitialized
= TRUE
;
2320 /* initialize Fcb list head */
2321 InitializeListHead(&Vcb
->FcbList
);
2322 KeInitializeSpinLock(&Vcb
->FcbLock
);
2324 /* initialize Mcb list head */
2325 InitializeListHead(&(Vcb
->McbList
));
2327 /* initialize directory notify list */
2328 InitializeListHead(&Vcb
->NotifyList
);
2329 FsRtlNotifyInitializeSync(&Vcb
->NotifySync
);
2330 NotifySyncInitialized
= TRUE
;
2332 /* superblock checking */
2333 Vcb
->SuperBlock
= sb
;
2335 /* initialize Vpb and Label */
2336 Vcb
->DeviceObject
= VolumeDevice
;
2337 Vcb
->TargetDeviceObject
= TargetDevice
;
2339 Vcb
->RealDevice
= Vpb
->RealDevice
;
2340 Vpb
->DeviceObject
= VolumeDevice
;
2342 /* set inode size */
2343 Vcb
->InodeSize
= (ULONG
)sb
->s_inode_size
;
2344 if (Vcb
->InodeSize
== 0) {
2345 Vcb
->InodeSize
= EXT2_GOOD_OLD_INODE_SIZE
;
2348 /* initialize inode lookaside list */
2349 ExInitializeNPagedLookasideList(&(Vcb
->InodeLookasideList
),
2350 NULL
, NULL
, 0, sizeof(EXT2_INODE
),
2353 InodeLookasideInitialized
= TRUE
;
2355 /* initialize label in Vpb */
2356 Status
= Ext2InitializeLabel(Vcb
, sb
);
2357 if (!NT_SUCCESS(Status
)) {
2361 /* check device characteristics flags */
2362 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
2363 SetLongFlag(Vcb
->Flags
, VCB_REMOVABLE_MEDIA
);
2366 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_FLOPPY_DISKETTE
)) {
2367 SetLongFlag(Vcb
->Flags
, VCB_FLOPPY_DISK
);
2370 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_READ_ONLY_DEVICE
)) {
2371 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2374 if (IsFlagOn(TargetDevice
->Characteristics
, FILE_READ_ONLY_DEVICE
)) {
2375 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2378 /* verify device is writable ? */
2379 if (Ext2IsMediaWriteProtected(IrpContext
, TargetDevice
)) {
2380 SetFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2383 /* initialize UUID and serial number */
2384 if (Ext2IsNullUuid(sb
->s_uuid
)) {
2385 ExUuidCreate((UUID
*)sb
->s_uuid
);
2387 /* query parameters from registry */
2388 if (!NT_SUCCESS(Ext2PerformRegistryVolumeParams(Vcb
))) {
2389 /* don't mount this volume */
2390 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2395 Vpb
->SerialNumber
= ((ULONG
*)sb
->s_uuid
)[0] +
2396 ((ULONG
*)sb
->s_uuid
)[1] +
2397 ((ULONG
*)sb
->s_uuid
)[2] +
2398 ((ULONG
*)sb
->s_uuid
)[3];
2400 /* query partition size and disk geometry parameters */
2401 DiskSize
= Vcb
->DiskGeometry
.Cylinders
.QuadPart
*
2402 Vcb
->DiskGeometry
.TracksPerCylinder
*
2403 Vcb
->DiskGeometry
.SectorsPerTrack
*
2404 Vcb
->DiskGeometry
.BytesPerSector
;
2406 IoctlSize
= sizeof(PARTITION_INFORMATION
);
2407 Status
= Ext2DiskIoControl(
2409 IOCTL_DISK_GET_PARTITION_INFO
,
2412 &Vcb
->PartitionInformation
,
2414 if (NT_SUCCESS(Status
)) {
2415 PartSize
= Vcb
->PartitionInformation
.PartitionLength
.QuadPart
;
2417 Vcb
->PartitionInformation
.StartingOffset
.QuadPart
= 0;
2418 Vcb
->PartitionInformation
.PartitionLength
.QuadPart
= DiskSize
;
2419 PartSize
= DiskSize
;
2420 Status
= STATUS_SUCCESS
;
2422 Vcb
->Header
.AllocationSize
.QuadPart
=
2423 Vcb
->Header
.FileSize
.QuadPart
= PartSize
;
2425 Vcb
->Header
.ValidDataLength
.QuadPart
=
2426 Vcb
->Header
.FileSize
.QuadPart
;
2429 IoctlSize
= sizeof(ULONG
);
2430 Status
= Ext2DiskIoControl(
2432 IOCTL_DISK_CHECK_VERIFY
,
2438 if (!NT_SUCCESS(Status
)) {
2441 Vcb
->ChangeCount
= ChangeCount
;
2443 /* create the stream object for ext2 volume */
2444 Vcb
->Volume
= IoCreateStreamFileObject(NULL
, Vcb
->Vpb
->RealDevice
);
2446 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2450 /* initialize streaming object file */
2451 Vcb
->Volume
->SectionObjectPointer
= &(Vcb
->SectionObject
);
2452 Vcb
->Volume
->ReadAccess
= TRUE
;
2453 Vcb
->Volume
->WriteAccess
= TRUE
;
2454 Vcb
->Volume
->DeleteAccess
= TRUE
;
2455 Vcb
->Volume
->FsContext
= (PVOID
) Vcb
;
2456 Vcb
->Volume
->FsContext2
= NULL
;
2457 Vcb
->Volume
->Vpb
= Vcb
->Vpb
;
2459 FileSizes
.AllocationSize
.QuadPart
=
2460 FileSizes
.FileSize
.QuadPart
=
2461 FileSizes
.ValidDataLength
.QuadPart
=
2462 Vcb
->Header
.AllocationSize
.QuadPart
;
2464 CcInitializeCacheMap( Vcb
->Volume
,
2467 &(Ext2Global
->CacheManagerNoOpCallbacks
),
2470 /* initialize disk block LargetMcb and entry Mcb,
2471 it will raise an expcetion if failed */
2473 FsRtlInitializeLargeMcb(&(Vcb
->Extents
), PagedPool
);
2474 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
2475 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2478 if (!NT_SUCCESS(Status
)) {
2481 ExtentsInitialized
= TRUE
;
2483 /* set block device */
2484 Vcb
->bd
.bd_dev
= Vcb
->RealDevice
;
2485 Vcb
->bd
.bd_geo
= Vcb
->DiskGeometry
;
2486 Vcb
->bd
.bd_part
= Vcb
->PartitionInformation
;
2487 Vcb
->bd
.bd_volume
= Vcb
->Volume
;
2488 Vcb
->bd
.bd_priv
= (void *) Vcb
;
2489 memset(&Vcb
->bd
.bd_bh_root
, 0, sizeof(struct rb_root
));
2490 spin_lock_init(&Vcb
->bd
.bd_bh_lock
);
2491 Vcb
->bd
.bd_bh_cache
= kmem_cache_create("bd_bh_buffer",
2492 Vcb
->BlockSize
, 0, 0, NULL
);
2493 if (!Vcb
->bd
.bd_bh_cache
) {
2494 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2498 Vcb
->SectorBits
= Ext2Log2(SECTOR_SIZE
);
2499 Vcb
->sb
.s_magic
= sb
->s_magic
;
2500 Vcb
->sb
.s_bdev
= &Vcb
->bd
;
2501 Vcb
->sb
.s_blocksize
= BLOCK_SIZE
;
2502 Vcb
->sb
.s_blocksize_bits
= BLOCK_BITS
;
2503 Vcb
->sb
.s_priv
= (void *) Vcb
;
2504 Vcb
->sb
.s_fs_info
= &Vcb
->sbi
;
2507 Vcb
->sbi
.s_blocks_per_group
= sb
->s_blocks_per_group
;
2508 Vcb
->sbi
.s_first_ino
= sb
->s_first_ino
;
2509 Vcb
->sbi
.s_desc_size
= sb
->s_desc_size
;
2511 if (EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, EXT4_FEATURE_INCOMPAT_64BIT
)) {
2512 if (Vcb
->sbi
.s_desc_size
< EXT4_MIN_DESC_SIZE_64BIT
||
2513 Vcb
->sbi
.s_desc_size
> EXT4_MAX_DESC_SIZE
||
2514 !is_power_of_2(Vcb
->sbi
.s_desc_size
)) {
2515 DEBUG(DL_ERR
, ("EXT4-fs: unsupported descriptor size %lu\n", Vcb
->sbi
.s_desc_size
));
2516 Status
= STATUS_DISK_CORRUPT_ERROR
;
2520 Vcb
->sbi
.s_desc_size
= EXT4_MIN_DESC_SIZE
;
2523 Vcb
->sbi
.s_blocks_per_group
= sb
->s_blocks_per_group
;
2524 Vcb
->sbi
.s_inodes_per_group
= sb
->s_inodes_per_group
;
2525 if (EXT3_INODES_PER_GROUP(&Vcb
->sb
) == 0) {
2526 Status
= STATUS_DISK_CORRUPT_ERROR
;
2529 Vcb
->sbi
.s_inodes_per_block
= BLOCK_SIZE
/ Vcb
->InodeSize
;
2530 if (Vcb
->sbi
.s_inodes_per_block
== 0) {
2531 Status
= STATUS_DISK_CORRUPT_ERROR
;
2534 Vcb
->sbi
.s_itb_per_group
= Vcb
->sbi
.s_inodes_per_group
/
2535 Vcb
->sbi
.s_inodes_per_block
;
2538 Vcb
->sbi
.s_desc_per_block
= BLOCK_SIZE
/ GROUP_DESC_SIZE
;
2539 Vcb
->sbi
.s_desc_per_block_bits
= ilog2(Vcb
->sbi
.s_desc_per_block
);
2541 for (i
=0; i
< 4; i
++) {
2542 Vcb
->sbi
.s_hash_seed
[i
] = sb
->s_hash_seed
[i
];
2544 Vcb
->sbi
.s_def_hash_version
= sb
->s_def_hash_version
;
2546 if (le32_to_cpu(sb
->s_rev_level
) == EXT3_GOOD_OLD_REV
&&
2547 (EXT3_HAS_COMPAT_FEATURE(&Vcb
->sb
, ~0U) ||
2548 EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, ~0U) ||
2549 EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, ~0U))) {
2551 "EXT3-fs warning: feature flags set on rev 0 fs, "
2552 "running e2fsck is recommended\n");
2556 * Check feature flags regardless of the revision level, since we
2557 * previously didn't change the revision level when setting the flags,
2558 * so there is a chance incompat flags are set on a rev 0 filesystem.
2560 features
= EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, ~EXT4_FEATURE_INCOMPAT_SUPP
);
2561 if (features
& EXT4_FEATURE_INCOMPAT_DIRDATA
) {
2562 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2563 ClearFlag(features
, EXT4_FEATURE_INCOMPAT_DIRDATA
);
2566 printk(KERN_ERR
"EXT3-fs: %s: couldn't mount because of "
2567 "unsupported optional features (%x).\n",
2568 Vcb
->sb
.s_id
, le32_to_cpu(features
));
2569 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2573 features
= EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, ~EXT4_FEATURE_RO_COMPAT_SUPP
);
2575 printk(KERN_ERR
"EXT3-fs: %s: unsupported optional features in this volume: (%x).\n",
2576 Vcb
->sb
.s_id
, le32_to_cpu(features
));
2577 if (CanIWrite(Vcb
)) {
2579 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2583 has_huge_files
= EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, EXT4_FEATURE_RO_COMPAT_HUGE_FILE
);
2585 Vcb
->sb
.s_maxbytes
= ext3_max_size(BLOCK_BITS
, has_huge_files
);
2586 Vcb
->max_bitmap_bytes
= ext3_max_bitmap_size(BLOCK_BITS
,
2588 Vcb
->max_bytes
= ext3_max_size(BLOCK_BITS
, has_huge_files
);
2590 /* calculate maximum file bocks ... */
2592 ULONG dwData
[EXT2_BLOCK_TYPES
] = {EXT2_NDIR_BLOCKS
, 1, 1, 1};
2595 ASSERT(BLOCK_BITS
== Ext2Log2(BLOCK_SIZE
));
2597 Vcb
->sbi
.s_groups_count
= (ULONG
)(ext3_blocks_count(sb
) - sb
->s_first_data_block
+
2598 sb
->s_blocks_per_group
- 1) / sb
->s_blocks_per_group
;
2600 Vcb
->max_data_blocks
= 0;
2601 for (i
= 0; i
< EXT2_BLOCK_TYPES
; i
++) {
2602 if (BLOCK_BITS
>= 12 && i
== (EXT2_BLOCK_TYPES
- 1)) {
2603 dwData
[i
] = 0x40000000;
2605 dwData
[i
] = dwData
[i
] << ((BLOCK_BITS
- 2) * i
);
2607 Vcb
->max_blocks_per_layer
[i
] = dwData
[i
];
2608 Vcb
->max_data_blocks
+= Vcb
->max_blocks_per_layer
[i
];
2612 Vcb
->sbi
.s_gdb_count
= (Vcb
->sbi
.s_groups_count
+ Vcb
->sbi
.s_desc_per_block
- 1) /
2613 Vcb
->sbi
.s_desc_per_block
;
2614 /* load all gorup desc */
2615 if (!Ext2LoadGroup(Vcb
)) {
2616 Status
= STATUS_UNSUCCESSFUL
;
2620 /* recovery journal since it's ext3 */
2621 if (Vcb
->IsExt3fs
) {
2622 Ext2RecoverJournal(IrpContext
, Vcb
);
2623 if (IsFlagOn(Vcb
->Flags
, VCB_JOURNAL_RECOVER
)) {
2624 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2628 /* Now allocating the mcb for root ... */
2631 RootNode
.Buffer
= Buffer
;
2632 RootNode
.MaximumLength
= RootNode
.Length
= 2;
2633 Vcb
->McbTree
= Ext2AllocateMcb(
2634 Vcb
, &RootNode
, NULL
,
2635 FILE_ATTRIBUTE_DIRECTORY
2637 if (!Vcb
->McbTree
) {
2639 Status
= STATUS_UNSUCCESSFUL
;
2643 Vcb
->sb
.s_root
= Ext2BuildEntry(Vcb
, NULL
, &RootNode
);
2644 if (!Vcb
->sb
.s_root
) {
2646 Status
= STATUS_UNSUCCESSFUL
;
2649 Vcb
->sb
.s_root
->d_sb
= &Vcb
->sb
;
2650 Vcb
->sb
.s_root
->d_inode
= &Vcb
->McbTree
->Inode
;
2651 Vcb
->McbTree
->de
= Vcb
->sb
.s_root
;
2653 /* load root inode */
2654 Vcb
->McbTree
->Inode
.i_ino
= EXT2_ROOT_INO
;
2655 Vcb
->McbTree
->Inode
.i_sb
= &Vcb
->sb
;
2656 if (!Ext2LoadInode(Vcb
, &Vcb
->McbTree
->Inode
)) {
2658 Status
= STATUS_CANT_WAIT
;
2662 /* initializeroot node */
2663 Vcb
->McbTree
->CreationTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_ctime
);
2664 Vcb
->McbTree
->LastAccessTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_atime
);
2665 Vcb
->McbTree
->LastWriteTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_mtime
);
2666 Vcb
->McbTree
->ChangeTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_mtime
);
2668 /* check bitmap if user specifies it */
2669 if (IsFlagOn(Ext2Global
->Flags
, EXT2_CHECKING_BITMAP
)) {
2670 Ext2CheckBitmapConsistency(IrpContext
, Vcb
);
2673 /* get anything doen, then refer target device */
2674 ObReferenceObject(Vcb
->TargetDeviceObject
);
2675 SetLongFlag(Vcb
->Flags
, VCB_INITIALIZED
);
2679 if (!NT_SUCCESS(Status
)) {
2682 Ext2FreeMcb(Vcb
, Vcb
->McbTree
);
2685 if (InodeLookasideInitialized
) {
2686 ExDeleteNPagedLookasideList(&(Vcb
->InodeLookasideList
));
2689 if (ExtentsInitialized
) {
2691 if (Vcb
->bd
.bd_bh_cache
)
2692 kmem_cache_destroy(Vcb
->bd
.bd_bh_cache
);
2693 FsRtlUninitializeLargeMcb(&(Vcb
->Extents
));
2697 if (Vcb
->Volume
->PrivateCacheMap
) {
2698 Ext2SyncUninitializeCacheMap(Vcb
->Volume
);
2700 ObDereferenceObject(Vcb
->Volume
);
2703 if (NotifySyncInitialized
) {
2704 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
2707 if (VcbResourceInitialized
) {
2708 ExDeleteResourceLite(&Vcb
->McbLock
);
2709 ExDeleteResourceLite(&Vcb
->MetaLock
);
2710 ExDeleteResourceLite(&Vcb
->MainResource
);
2711 ExDeleteResourceLite(&Vcb
->PagingIoResource
);
2721 Ext2TearDownStream(IN PEXT2_VCB Vcb
)
2723 PFILE_OBJECT Stream
= Vcb
->Volume
;
2724 IO_STATUS_BLOCK IoStatus
;
2726 ASSERT(Vcb
!= NULL
);
2727 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2728 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2734 if (IsFlagOn(Stream
->Flags
, FO_FILE_MODIFIED
)) {
2735 CcFlushCache(&(Vcb
->SectionObject
), NULL
, 0, &IoStatus
);
2736 ClearFlag(Stream
->Flags
, FO_FILE_MODIFIED
);
2739 if (Stream
->PrivateCacheMap
) {
2740 Ext2SyncUninitializeCacheMap(Stream
);
2743 ObDereferenceObject(Stream
);
2748 Ext2DestroyVcb (IN PEXT2_VCB Vcb
)
2750 ASSERT(Vcb
!= NULL
);
2751 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2752 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2754 DEBUG(DL_FUN
, ("Ext2DestroyVcb ...\n"));
2757 Ext2TearDownStream(Vcb
);
2759 ASSERT(NULL
== Vcb
->Volume
);
2761 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
2762 Ext2ListExtents(&Vcb
->Extents
);
2763 FsRtlUninitializeLargeMcb(&(Vcb
->Extents
));
2765 Ext2CleanupAllMcbs(Vcb
);
2769 if (Vcb
->bd
.bd_bh_cache
)
2770 kmem_cache_destroy(Vcb
->bd
.bd_bh_cache
);
2772 if (Vcb
->SuperBlock
) {
2773 Ext2FreePool(Vcb
->SuperBlock
, EXT2_SB_MAGIC
);
2774 Vcb
->SuperBlock
= NULL
;
2777 if (IsFlagOn(Vcb
->Flags
, VCB_NEW_VPB
)) {
2778 ASSERT(Vcb
->Vpb2
!= NULL
);
2779 Ext2FreePool(Vcb
->Vpb2
, TAG_VPB
);
2780 DEC_MEM_COUNT(PS_VPB
, Vcb
->Vpb2
, sizeof(VPB
));
2784 ObDereferenceObject(Vcb
->TargetDeviceObject
);
2786 ExDeleteNPagedLookasideList(&(Vcb
->InodeLookasideList
));
2787 ExDeleteResourceLite(&Vcb
->McbLock
);
2788 ExDeleteResourceLite(&Vcb
->MetaLock
);
2789 ExDeleteResourceLite(&Vcb
->PagingIoResource
);
2790 ExDeleteResourceLite(&Vcb
->MainResource
);
2792 DEBUG(DL_DBG
, ("Ext2DestroyVcb: DevObject=%p Vcb=%p\n", Vcb
->DeviceObject
, Vcb
));
2793 IoDeleteDevice(Vcb
->DeviceObject
);
2794 DEC_MEM_COUNT(PS_VCB
, Vcb
->DeviceObject
, sizeof(EXT2_VCB
));
2798 /* uninitialize cache map */
2801 Ext2SyncUninitializeCacheMap (
2802 IN PFILE_OBJECT FileObject
2805 CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent
;
2806 NTSTATUS WaitStatus
;
2807 LARGE_INTEGER Ext2LargeZero
= {0,0};
2810 KeInitializeEvent( &UninitializeCompleteEvent
.Event
,
2811 SynchronizationEvent
,
2814 CcUninitializeCacheMap( FileObject
,
2816 &UninitializeCompleteEvent
);
2818 WaitStatus
= KeWaitForSingleObject( &UninitializeCompleteEvent
.Event
,
2824 ASSERT (NT_SUCCESS(WaitStatus
));
2827 /* Link Mcb to tail of Vcb->McbList queue */
2830 Ext2LinkTailMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2832 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2836 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2838 if (IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2839 DEBUG(DL_RES
, ( "Ext2LinkTailMcb: %wZ already linked.\n",
2842 InsertTailList(&Vcb
->McbList
, &Mcb
->Link
);
2843 SetLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2844 Ext2ReferXcb(&Vcb
->NumOfMcb
);
2847 ExReleaseResourceLite(&Vcb
->McbLock
);
2850 /* Link Mcb to head of Vcb->McbList queue */
2853 Ext2LinkHeadMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2855 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2859 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2861 if (!IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2862 InsertHeadList(&Vcb
->McbList
, &Mcb
->Link
);
2863 SetLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2864 Ext2ReferXcb(&Vcb
->NumOfMcb
);
2866 DEBUG(DL_RES
, ( "Ext2LinkHeadMcb: %wZ already linked.\n",
2869 ExReleaseResourceLite(&Vcb
->McbLock
);
2872 /* Unlink Mcb from Vcb->McbList queue */
2875 Ext2UnlinkMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2877 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2881 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2883 if (IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2884 RemoveEntryList(&(Mcb
->Link
));
2885 ClearLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2886 Ext2DerefXcb(&Vcb
->NumOfMcb
);
2888 DEBUG(DL_RES
, ( "Ext2UnlinkMcb: %wZ already unlinked.\n",
2891 ExReleaseResourceLite(&Vcb
->McbLock
);
2894 /* get the first Mcb record in Vcb->McbList */
2897 Ext2FirstUnusedMcb(PEXT2_VCB Vcb
, BOOLEAN Wait
, ULONG Number
)
2899 PEXT2_MCB Head
= NULL
;
2900 PEXT2_MCB Tail
= NULL
;
2901 PEXT2_MCB Mcb
= NULL
;
2902 PLIST_ENTRY List
= NULL
;
2905 if (!ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, Wait
)) {
2911 if (!IsListEmpty(&Vcb
->McbList
)) {
2913 while (i
++ < Vcb
->NumOfMcb
) {
2915 List
= RemoveHeadList(&Vcb
->McbList
);
2916 Mcb
= CONTAINING_RECORD(List
, EXT2_MCB
, Link
);
2917 ASSERT(IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
));
2919 if (Mcb
->Fcb
== NULL
&& !IsMcbRoot(Mcb
) &&
2920 Mcb
->Refercount
== 0 &&
2921 (Mcb
->Child
== NULL
|| IsMcbSymLink(Mcb
))) {
2923 Ext2RemoveMcb(Vcb
, Mcb
);
2924 ClearLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2925 Ext2DerefXcb(&Vcb
->NumOfMcb
);
2927 /* attach all Mcb into a chain*/
2929 ASSERT(Tail
!= NULL
);
2939 InsertTailList(&Vcb
->McbList
, &Mcb
->Link
);
2945 ExReleaseResourceLite(&Vcb
->McbLock
);
2951 /* Reaper thread to release unused Mcb blocks */
2957 BOOLEAN GlobalAcquired
= FALSE
;
2959 BOOLEAN DidNothing
= TRUE
;
2960 BOOLEAN LastState
= TRUE
;
2963 PLIST_ENTRY List
= NULL
;
2964 LARGE_INTEGER Timeout
;
2966 PEXT2_VCB Vcb
= NULL
;
2967 PEXT2_MCB Mcb
= NULL
;
2973 /* wake up DirverEntry */
2974 KeSetEvent(&Ext2Global
->Reaper
.Engine
, 0, FALSE
);
2976 /* now process looping */
2981 /* calculate how long we need wait */
2982 if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 128)) {
2983 Timeout
.QuadPart
= (LONGLONG
)-1000*1000; /* 0.1 second */
2984 NumOfMcbs
= Ext2Global
->MaxDepth
* 4;
2986 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 32)) {
2987 Timeout
.QuadPart
= (LONGLONG
)-1000*1000*5; /* 0.5 second */
2988 NumOfMcbs
= Ext2Global
->MaxDepth
* 2;
2990 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 8)) {
2991 Timeout
.QuadPart
= (LONGLONG
)-1000*1000*10; /* 1 second */
2992 NumOfMcbs
= Ext2Global
->MaxDepth
;
2993 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 2)) {
2994 Timeout
.QuadPart
= (LONGLONG
)-2*1000*1000*10; /* 2 second */
2995 NumOfMcbs
= Ext2Global
->MaxDepth
/ 4;
2996 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (ULONG
)Ext2Global
->MaxDepth
) {
2997 Timeout
.QuadPart
= (LONGLONG
)-4*1000*1000*10; /* 4 seconds */
2998 NumOfMcbs
= Ext2Global
->MaxDepth
/ 8;
2999 } else if (DidNothing
) {
3000 Timeout
.QuadPart
= (LONGLONG
)-8*1000*1000*10; /* 8 seconds */
3002 Timeout
.QuadPart
*= 2;
3004 NumOfMcbs
= Ext2Global
->MaxDepth
/ 16;
3006 Timeout
.QuadPart
= (LONGLONG
)-5*1000*1000*10; /* 5 seconds */
3008 Timeout
.QuadPart
*= 2;
3010 NumOfMcbs
= Ext2Global
->MaxDepth
/ 32;
3016 LastState
= DidNothing
;
3018 /* wait until it is waken or it times out */
3019 KeWaitForSingleObject(
3020 &(Ext2Global
->Reaper
.Wait
),
3029 /* acquire global exclusive lock */
3030 if (!ExAcquireResourceSharedLite(&Ext2Global
->Resource
, WaitLock
)) {
3033 GlobalAcquired
= TRUE
;
3035 /* search all Vcb to get unused resources freed to system */
3036 for (List
= Ext2Global
->VcbList
.Flink
;
3037 List
!= &(Ext2Global
->VcbList
);
3038 List
= List
->Flink
) {
3040 Vcb
= CONTAINING_RECORD(List
, EXT2_VCB
, Next
);
3042 Mcb
= Ext2FirstUnusedMcb(Vcb
, WaitLock
, NumOfMcbs
);
3044 PEXT2_MCB Next
= Mcb
->Next
;
3045 DEBUG(DL_RES
, ( "Ext2ReaperThread: releasing Mcb (%p): %wZ"
3046 " Total: %xh\n", Mcb
, &Mcb
->FullName
,
3047 Ext2Global
->PerfStat
.Current
.Mcb
));
3048 Ext2FreeMcb(Vcb
, Mcb
);
3050 LastState
= DidNothing
= FALSE
;
3054 if (GlobalAcquired
) {
3055 ExReleaseResourceLite(&Ext2Global
->Resource
);
3056 GlobalAcquired
= FALSE
;
3062 if (GlobalAcquired
) {
3063 ExReleaseResourceLite(&Ext2Global
->Resource
);
3067 PsTerminateSystemThread(STATUS_SUCCESS
);
3072 Ext2StartReaperThread()
3074 NTSTATUS status
= STATUS_SUCCESS
;
3075 OBJECT_ATTRIBUTES oa
;
3078 /* initialize wait event */
3080 &Ext2Global
->Reaper
.Wait
,
3081 SynchronizationEvent
, FALSE
3085 InitializeObjectAttributes(
3088 OBJ_CASE_INSENSITIVE
|
3094 /* start a new system thread */
3095 status
= PsCreateSystemThread(
3105 if (NT_SUCCESS(status
)) {