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 Fcb
= (PEXT2_FCB
) ExAllocateFromNPagedLookasideList(
142 &(Ext2Global
->Ext2FcbLookasideList
));
148 RtlZeroMemory(Fcb
, sizeof(EXT2_FCB
));
149 Fcb
->Identifier
.Type
= EXT2FCB
;
150 Fcb
->Identifier
.Size
= sizeof(EXT2_FCB
);
152 #ifndef _WIN2K_TARGET_
153 ExInitializeFastMutex(&Fcb
->Mutex
);
154 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->Mutex
);
157 FsRtlInitializeOplock(&Fcb
->Oplock
);
158 FsRtlInitializeFileLock (
159 &Fcb
->FileLockAnchor
,
163 Fcb
->OpenHandleCount
= 0;
164 Fcb
->ReferenceCount
= 0;
166 Fcb
->Inode
= &Mcb
->Inode
;
168 ASSERT(Mcb
->Fcb
== NULL
);
173 DEBUG(DL_RES
, ("Ext2AllocateFcb: Fcb %p created: %wZ.\n",
174 Fcb
, &Fcb
->Mcb
->FullName
));
176 RtlZeroMemory(&Fcb
->Header
, sizeof(FSRTL_COMMON_FCB_HEADER
));
177 Fcb
->Header
.NodeTypeCode
= (USHORT
) EXT2FCB
;
178 Fcb
->Header
.NodeByteSize
= sizeof(EXT2_FCB
);
179 Fcb
->Header
.IsFastIoPossible
= FastIoIsNotPossible
;
180 Fcb
->Header
.Resource
= &(Fcb
->MainResource
);
181 Fcb
->Header
.PagingIoResource
= &(Fcb
->PagingIoResource
);
183 Fcb
->Header
.FileSize
.QuadPart
= Mcb
->Inode
.i_size
;
184 Fcb
->Header
.ValidDataLength
.QuadPart
= Mcb
->Inode
.i_size
;
185 Fcb
->Header
.AllocationSize
.QuadPart
= CEILING_ALIGNED(ULONGLONG
,
186 Fcb
->Header
.FileSize
.QuadPart
, (ULONGLONG
)Vcb
->BlockSize
);
188 Fcb
->SectionObject
.DataSectionObject
= NULL
;
189 Fcb
->SectionObject
.SharedCacheMap
= NULL
;
190 Fcb
->SectionObject
.ImageSectionObject
= NULL
;
192 ExInitializeResourceLite(&(Fcb
->MainResource
));
193 ExInitializeResourceLite(&(Fcb
->PagingIoResource
));
195 Ext2InsertFcb(Vcb
, Fcb
);
197 INC_MEM_COUNT(PS_FCB
, Fcb
, sizeof(EXT2_FCB
));
203 Ext2FreeFcb (IN PEXT2_FCB Fcb
)
205 PEXT2_VCB Vcb
= Fcb
->Vcb
;
207 ASSERT((Fcb
!= NULL
) && (Fcb
->Identifier
.Type
== EXT2FCB
) &&
208 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
209 ASSERT((Fcb
->Mcb
->Identifier
.Type
== EXT2MCB
) &&
210 (Fcb
->Mcb
->Identifier
.Size
== sizeof(EXT2_MCB
)));
212 #ifndef _WIN2K_TARGET_
213 FsRtlTeardownPerStreamContexts(&Fcb
->Header
);
216 if ((Fcb
->Mcb
->Identifier
.Type
== EXT2MCB
) &&
217 (Fcb
->Mcb
->Identifier
.Size
== sizeof(EXT2_MCB
))) {
219 ASSERT (Fcb
->Mcb
->Fcb
== Fcb
);
220 if (IsMcbSpecialFile(Fcb
->Mcb
) || IsFileDeleted(Fcb
->Mcb
)) {
222 ASSERT(!IsRoot(Fcb
));
223 Ext2RemoveMcb(Fcb
->Vcb
, Fcb
->Mcb
);
224 Fcb
->Mcb
->Fcb
= NULL
;
226 Ext2UnlinkMcb(Vcb
, Fcb
->Mcb
);
227 Ext2DerefMcb(Fcb
->Mcb
);
228 Ext2LinkHeadMcb(Vcb
, Fcb
->Mcb
);
232 Fcb
->Mcb
->Fcb
= NULL
;
233 Ext2DerefMcb(Fcb
->Mcb
);
240 Ext2RemoveFcb(Fcb
->Vcb
, Fcb
);
242 FsRtlUninitializeFileLock(&Fcb
->FileLockAnchor
);
243 FsRtlUninitializeOplock(&Fcb
->Oplock
);
244 ExDeleteResourceLite(&Fcb
->MainResource
);
245 ExDeleteResourceLite(&Fcb
->PagingIoResource
);
247 DEBUG(DL_RES
, ( "Ext2FreeFcb: Fcb (%p) is being released: %wZ.\n",
248 Fcb
, &Fcb
->Mcb
->FullName
));
250 Fcb
->Identifier
.Type
= 0;
251 Fcb
->Identifier
.Size
= 0;
253 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2FcbLookasideList
), Fcb
);
254 DEC_MEM_COUNT(PS_FCB
, Fcb
, sizeof(EXT2_FCB
));
257 /* Insert Fcb to Vcb->FcbList queue */
260 Ext2InsertFcb(PEXT2_VCB Vcb
, PEXT2_FCB Fcb
)
262 ExInterlockedInsertTailList(&Vcb
->FcbList
, &Fcb
->Next
, &Vcb
->FcbLock
);
263 Ext2ReferXcb(&Vcb
->FcbCount
);
266 /* Remove Fcb from Vcb->FcbList queue */
269 Ext2RemoveFcb(PEXT2_VCB Vcb
, PEXT2_FCB Fcb
)
273 KeAcquireSpinLock(&Vcb
->FcbLock
, &irql
);
274 RemoveEntryList(&(Fcb
->Next
));
275 if (Vcb
->FcbCount
> 0) {
276 Ext2DerefXcb(&Vcb
->FcbCount
);
280 KeReleaseSpinLock(&Vcb
->FcbLock
, irql
);
284 Ext2AllocateCcb (ULONG Flags
, PEXT2_MCB SymLink
)
288 Ccb
= (PEXT2_CCB
) (ExAllocateFromNPagedLookasideList(
289 &(Ext2Global
->Ext2CcbLookasideList
)));
294 DEBUG(DL_RES
, ( "ExtAllocateCcb: Ccb created: %ph.\n", Ccb
));
296 RtlZeroMemory(Ccb
, sizeof(EXT2_CCB
));
298 Ccb
->Identifier
.Type
= EXT2CCB
;
299 Ccb
->Identifier
.Size
= sizeof(EXT2_CCB
);
302 Ccb
->SymLink
= SymLink
;
304 ASSERT(SymLink
->Refercount
> 0);
305 Ext2ReferMcb(SymLink
);
306 DEBUG(DL_INF
, ( "ExtAllocateCcb: Ccb SymLink: %wZ.\n",
307 &Ccb
->SymLink
->FullName
));
310 Ccb
->DirectorySearchPattern
.Length
= 0;
311 Ccb
->DirectorySearchPattern
.MaximumLength
= 0;
312 Ccb
->DirectorySearchPattern
.Buffer
= 0;
314 INC_MEM_COUNT(PS_CCB
, Ccb
, sizeof(EXT2_CCB
));
320 Ext2FreeCcb (IN PEXT2_VCB Vcb
, IN PEXT2_CCB Ccb
)
324 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
325 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
327 DEBUG(DL_RES
, ( "Ext2FreeCcb: Ccb = %ph.\n", Ccb
));
330 DEBUG(DL_INF
, ( "Ext2FreeCcb: Ccb SymLink: %wZ.\n",
331 &Ccb
->SymLink
->FullName
));
332 if (IsFileDeleted(Ccb
->SymLink
->Target
)) {
333 Ext2UnlinkMcb(Vcb
, Ccb
->SymLink
);
334 Ext2DerefMcb(Ccb
->SymLink
);
335 Ext2LinkHeadMcb(Vcb
, Ccb
->SymLink
);
337 Ext2DerefMcb(Ccb
->SymLink
);
341 if (Ccb
->DirectorySearchPattern
.Buffer
!= NULL
) {
342 DEC_MEM_COUNT(PS_DIR_PATTERN
, Ccb
->DirectorySearchPattern
.Buffer
,
343 Ccb
->DirectorySearchPattern
.MaximumLength
);
344 Ext2FreePool(Ccb
->DirectorySearchPattern
.Buffer
, EXT2_DIRSP_MAGIC
);
347 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2CcbLookasideList
), Ccb
);
348 DEC_MEM_COUNT(PS_CCB
, Ccb
, sizeof(EXT2_CCB
));
352 Ext2AllocateInode (PEXT2_VCB Vcb
)
356 inode
= ExAllocateFromNPagedLookasideList(
357 &(Vcb
->InodeLookasideList
));
362 RtlZeroMemory(inode
, INODE_SIZE
);
364 DEBUG(DL_INF
, ("ExtAllocateInode: Inode created: %ph.\n", inode
));
365 INC_MEM_COUNT(PS_EXT2_INODE
, inode
, INODE_SIZE
);
371 Ext2DestroyInode (IN PEXT2_VCB Vcb
, IN PEXT2_INODE inode
)
373 ASSERT(inode
!= NULL
);
375 DEBUG(DL_INF
, ("Ext2FreeInode: Inode = %ph.\n", inode
));
377 ExFreeToNPagedLookasideList(&(Vcb
->InodeLookasideList
), inode
);
378 DEC_MEM_COUNT(PS_EXT2_INODE
, inode
, INODE_SIZE
);
381 struct dentry
* Ext2AllocateEntry()
385 de
= (struct dentry
*)ExAllocateFromNPagedLookasideList(
386 &(Ext2Global
->Ext2DentryLookasideList
));
391 RtlZeroMemory(de
, sizeof(struct dentry
));
392 INC_MEM_COUNT(PS_DENTRY
, de
, sizeof(struct dentry
));
397 VOID
Ext2FreeEntry (IN
struct dentry
*de
)
402 ExFreePool(de
->d_name
.name
);
404 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2DentryLookasideList
), de
);
405 DEC_MEM_COUNT(PS_DENTRY
, de
, sizeof(struct dentry
));
409 struct dentry
*Ext2BuildEntry(PEXT2_VCB Vcb
, PEXT2_MCB Dcb
, PUNICODE_STRING FileName
)
411 OEM_STRING Oem
= { 0 };
412 struct dentry
*de
= NULL
;
413 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
417 de
= Ext2AllocateEntry();
419 DEBUG(DL_ERR
, ("Ext2BuildEntry: failed to allocate dentry.\n"));
424 de
->d_parent
= Dcb
->de
;
426 Oem
.MaximumLength
= (USHORT
)Ext2UnicodeToOEMSize(Vcb
, FileName
) + 1;
427 Oem
.Buffer
= ExAllocatePool(PagedPool
, Oem
.MaximumLength
);
429 DEBUG(DL_ERR
, ( "Ex2BuildEntry: failed to allocate OEM name.\n"));
432 de
->d_name
.name
= Oem
.Buffer
;
433 RtlZeroMemory(Oem
.Buffer
, Oem
.MaximumLength
);
434 Status
= Ext2UnicodeToOEM(Vcb
, &Oem
, FileName
);
435 if (!NT_SUCCESS(Status
)) {
436 DEBUG(DL_CP
, ("Ext2BuildEntry: failed to convert %S to OEM.\n", FileName
->Buffer
));
439 de
->d_name
.len
= Oem
.Length
;
443 if (!NT_SUCCESS(Status
)) {
453 Ext2AllocateExtent ()
457 Extent
= (PEXT2_EXTENT
)ExAllocateFromNPagedLookasideList(
458 &(Ext2Global
->Ext2ExtLookasideList
));
463 RtlZeroMemory(Extent
, sizeof(EXT2_EXTENT
));
464 INC_MEM_COUNT(PS_EXTENT
, Extent
, sizeof(EXT2_EXTENT
));
470 Ext2FreeExtent (IN PEXT2_EXTENT Extent
)
472 ASSERT(Extent
!= NULL
);
473 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2ExtLookasideList
), Extent
);
474 DEC_MEM_COUNT(PS_EXTENT
, Extent
, sizeof(EXT2_EXTENT
));
478 Ext2CountExtents(IN PEXT2_EXTENT Chain
)
481 PEXT2_EXTENT List
= Chain
;
493 IN PEXT2_EXTENT Chain
,
494 IN PEXT2_EXTENT Extent
500 PEXT2_EXTENT List
= Chain
;
511 Ext2DestroyExtentChain(IN PEXT2_EXTENT Chain
)
513 PEXT2_EXTENT Extent
= NULL
, List
= Chain
;
517 Ext2FreeExtent(List
);
523 Ext2ListExtents(PLARGE_MCB Extents
)
525 if (FsRtlNumberOfRunsInLargeMcb(Extents
) != 0) {
529 LONGLONG DirtyLength
;
532 for (i
= 0; FsRtlGetNextLargeMcbEntry(
533 Extents
, i
, &DirtyVba
,
534 &DirtyLba
, &DirtyLength
); i
++) {
535 if (DirtyVba
> 0 && DirtyLba
!= -1) {
536 DEBUG(DL_EXT
, ("Vba:%I64xh Lba:%I64xh Len:%I64xh.\n", DirtyVba
, DirtyLba
, DirtyLength
));
541 return n
? TRUE
: FALSE
;
562 BOOLEAN bFound
= FALSE
;
564 bFound
= FsRtlLookupLargeMcbEntry(
573 if (!bAdded
&& (!bFound
|| DirtyLbn
== -1)) {
577 if ( !bFound
|| (DirtyLbn
== -1) ||
579 (DirtyLen
< Length
)) {
583 for (Index
= 0; TRUE
; Index
++) {
585 if (!FsRtlGetNextLargeMcbEntry(
594 DEBUG(DL_EXT
, ("Index = %xh Vbn = %I64xh Lbn = %I64xh Len = %I64xh\n",
595 Index
, Vbn
, Lbn
, Length
));
602 Ext2ClearAllExtents(PLARGE_MCB Zone
)
605 FsRtlTruncateLargeMcb(Zone
, (LONGLONG
)0);
606 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
619 ULONG TriedTimes
= 0;
624 Offset
= Vbn
& (~(Vcb
->IoUnitSize
- 1));
625 Length
= (Vbn
- Offset
+ Length
+ Vcb
->IoUnitSize
- 1) &
626 ~(Vcb
->IoUnitSize
- 1);
628 ASSERT ((Offset
& (Vcb
->IoUnitSize
- 1)) == 0);
629 ASSERT ((Length
& (Vcb
->IoUnitSize
- 1)) == 0);
631 Offset
= (Offset
>> Vcb
->IoUnitBits
) + 1;
632 Length
= (Length
>> Vcb
->IoUnitBits
);
637 rc
= FsRtlAddLargeMcbEntry(
643 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
648 if (!rc
&& ++TriedTimes
< 10) {
649 Ext2Sleep(TriedTimes
* 100);
653 DEBUG(DL_EXT
, ("Ext2AddVcbExtent: Vbn=%I64xh Length=%I64xh,"
654 " rc=%d Runs=%u\n", Offset
, Length
, rc
,
655 FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
658 Ext2CheckExtent(&Vcb
->Extents
, Offset
, Offset
, Length
, TRUE
);
665 Ext2RemoveVcbExtent (
671 ULONG TriedTimes
= 0;
675 Offset
= Vbn
& (~(Vcb
->IoUnitSize
- 1));
676 Length
= (Length
+ Vbn
- Offset
+ Vcb
->IoUnitSize
- 1) & (~(Vcb
->IoUnitSize
- 1));
678 ASSERT ((Offset
& (Vcb
->IoUnitSize
- 1)) == 0);
679 ASSERT ((Length
& (Vcb
->IoUnitSize
- 1)) == 0);
681 Offset
= (Offset
>> Vcb
->IoUnitBits
) + 1;
682 Length
= (Length
>> Vcb
->IoUnitBits
);
687 FsRtlRemoveLargeMcbEntry(
692 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
697 if (!rc
&& ++TriedTimes
< 10) {
698 Ext2Sleep(TriedTimes
* 100);
702 DEBUG(DL_EXT
, ("Ext2RemoveVcbExtent: Vbn=%I64xh Length=%I64xh Runs=%u\n",
703 Offset
, Length
, FsRtlNumberOfRunsInLargeMcb(&Vcb
->Extents
)));
705 Ext2CheckExtent(&Vcb
->Extents
, Offset
, 0, Length
, FALSE
);
712 Ext2LookupVcbExtent (
722 offset
= Vbn
& (~(Vcb
->IoUnitSize
- 1));
723 ASSERT ((offset
& (Vcb
->IoUnitSize
- 1)) == 0);
724 offset
= (offset
>> Vcb
->IoUnitBits
) + 1;
726 rc
= FsRtlLookupLargeMcbEntry(
738 if (Lbn
&& ((*Lbn
) != -1)) {
740 (*Lbn
) = (((*Lbn
) - 1) << Vcb
->IoUnitBits
);
741 (*Lbn
) += ((Vbn
) & (Vcb
->IoUnitSize
- 1));
744 if (Length
&& *Length
) {
745 (*Length
) <<= Vcb
->IoUnitBits
;
746 (*Length
) -= ((Vbn
) & (Vcb
->IoUnitSize
- 1));
763 ULONG TriedTimes
= 0;
768 Base
= (LONGLONG
)BLOCK_SIZE
;
769 Bits
= (UCHAR
)BLOCK_BITS
;
771 ASSERT ((Vbn
& (Base
- 1)) == 0);
772 ASSERT ((Lbn
& (Base
- 1)) == 0);
773 ASSERT ((Length
& (Base
- 1)) == 0);
775 Vbn
= (Vbn
>> Bits
) + 1;
776 Lbn
= (Lbn
>> Bits
) + 1;
777 Length
= (Length
>> Bits
);
783 rc
= FsRtlAddLargeMcbEntry(
790 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
796 if (!rc
&& ++TriedTimes
< 10) {
797 Ext2Sleep(TriedTimes
* 100);
801 DEBUG(DL_EXT
, ("Ext2AddMcbExtent: Vbn=%I64xh Lbn=%I64xh Length=%I64xh,"
802 " rc=%d Runs=%u\n", Vbn
, Lbn
, Length
, rc
,
803 FsRtlNumberOfRunsInLargeMcb(&Mcb
->Extents
)));
806 Ext2CheckExtent(&Mcb
->Extents
, Vbn
, Lbn
, Length
, TRUE
);
813 Ext2RemoveMcbExtent (
820 ULONG TriedTimes
= 0;
825 Base
= (LONGLONG
)BLOCK_SIZE
;
826 Bits
= (UCHAR
)BLOCK_BITS
;
828 ASSERT ((Vbn
& (Base
- 1)) == 0);
829 ASSERT ((Length
& (Base
- 1)) == 0);
831 Vbn
= (Vbn
>> Bits
) + 1;
832 Length
= (Length
>> Bits
);
837 FsRtlRemoveLargeMcbEntry(
842 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
847 if (!rc
&& ++TriedTimes
< 10) {
848 Ext2Sleep(TriedTimes
* 100);
852 DEBUG(DL_EXT
, ("Ext2RemoveMcbExtent: Vbn=%I64xh Length=%I64xh Runs=%u\n",
853 Vbn
, Length
, FsRtlNumberOfRunsInLargeMcb(&Mcb
->Extents
)));
855 Ext2CheckExtent(&Mcb
->Extents
, Vbn
, 0, Length
, FALSE
);
862 Ext2LookupMcbExtent (
873 offset
= Vbn
& (~((LONGLONG
)BLOCK_SIZE
- 1));
874 ASSERT ((offset
& (BLOCK_SIZE
- 1)) == 0);
875 offset
= (offset
>> BLOCK_BITS
) + 1;
877 rc
= FsRtlLookupLargeMcbEntry(
889 if (Lbn
&& ((*Lbn
) != -1)) {
891 (*Lbn
) = (((*Lbn
) - 1) << BLOCK_BITS
);
892 (*Lbn
) += ((Vbn
) & ((LONGLONG
)BLOCK_SIZE
- 1));
895 if (Length
&& *Length
) {
896 (*Length
) <<= BLOCK_BITS
;
897 (*Length
) -= ((Vbn
) & ((LONGLONG
)BLOCK_SIZE
- 1));
913 ULONG TriedTimes
= 0;
914 LONGLONG Lbn
= Block
+ 1;
921 rc
= FsRtlAddLargeMcbEntry(
928 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
934 if (!rc
&& ++TriedTimes
< 10) {
935 Ext2Sleep(TriedTimes
* 100);
939 DEBUG(DL_EXT
, ("Ext2AddMcbMetaExts: Block: %xh-%xh rc=%d Runs=%u\n", Block
,
940 Length
, rc
, FsRtlNumberOfRunsInLargeMcb(&Mcb
->MetaExts
)));
943 Ext2CheckExtent(&Mcb
->MetaExts
, Lbn
, Lbn
, Length
, TRUE
);
950 Ext2RemoveMcbMetaExts (
957 ULONG TriedTimes
= 0;
958 LONGLONG Lbn
= Block
+ 1;
965 FsRtlRemoveLargeMcbEntry(
971 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
976 if (!rc
&& ++TriedTimes
< 10) {
977 Ext2Sleep(TriedTimes
* 100);
981 DEBUG(DL_EXT
, ("Ext2RemoveMcbMetaExts: Block: %xh-%xhh Runs=%u\n", Block
,
982 Length
, FsRtlNumberOfRunsInLargeMcb(&Mcb
->MetaExts
)));
984 Ext2CheckExtent(&Mcb
->MetaExts
, Lbn
, 0, Length
, FALSE
);
1002 LONGLONG Length
= 0;
1004 Vbn
= ((LONGLONG
) Start
) << BLOCK_BITS
;
1005 Lbn
= ((LONGLONG
) Block
) << BLOCK_BITS
;
1006 Length
= ((LONGLONG
)Number
<< BLOCK_BITS
);
1010 ULONG _block
= 0, _mapped
= 0;
1011 BOOLEAN _rc
= Ext2LookupBlockExtent(Vcb
, Mcb
, Start
, &_block
, &_mapped
);
1012 if (_rc
&& _block
!= 0 && (_block
!= Block
)) {
1016 return Ext2AddMcbExtent(Vcb
, Mcb
, Vbn
, Lbn
, Length
);
1020 ASSERT(Start
== Block
);
1021 return Ext2AddVcbExtent(Vcb
, Vbn
, Length
);
1026 Ext2LookupBlockExtent(
1036 LONGLONG Length
= 0;
1040 Vbn
= ((LONGLONG
) Start
) << BLOCK_BITS
;
1043 rc
= Ext2LookupMcbExtent(Vcb
, Mcb
, Vbn
, &Lbn
, &Length
);
1045 rc
= Ext2LookupVcbExtent(Vcb
, Vbn
, &Lbn
, &Length
);
1049 *Mapped
= (ULONG
)(Length
>> BLOCK_BITS
);
1050 if (Lbn
!= -1 && Length
> 0) {
1051 *Block
= (ULONG
)(Lbn
>> BLOCK_BITS
);
1062 Ext2RemoveBlockExtent(
1070 LONGLONG Length
= 0;
1073 Vbn
= ((LONGLONG
) Start
) << BLOCK_BITS
;
1074 Length
= ((LONGLONG
)Number
<< BLOCK_BITS
);
1077 rc
= Ext2RemoveMcbExtent(Vcb
, Mcb
, Vbn
, Length
);
1079 rc
= Ext2RemoveVcbExtent(Vcb
, Vbn
, Length
);
1087 IN PEXT2_IRP_CONTEXT IrpContext
,
1092 NTSTATUS Status
= STATUS_SUCCESS
;
1099 Ext2ClearAllExtents(&Mcb
->Extents
);
1100 Ext2ClearAllExtents(&Mcb
->MetaExts
);
1102 ASSERT(Mcb
!= NULL
);
1103 End
= (ULONG
)((Mcb
->Inode
.i_size
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
1105 while (Start
< End
) {
1109 /* mapping file offset to ext2 block */
1110 if (INODE_HAS_EXTENT(&Mcb
->Inode
)) {
1111 Status
= Ext2MapExtent(
1121 Status
= Ext2MapIndirect(
1132 if (!NT_SUCCESS(Status
)) {
1136 /* skip wrong blocks, in case wrongly treating symlink
1137 target names as blocks, silly */
1138 if (Block
>= TOTAL_BLOCKS
) {
1143 if (!Ext2AddBlockExtent(Vcb
, Mcb
, Start
, Block
, Mapped
)) {
1145 ClearFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1146 Ext2ClearAllExtents(&Mcb
->Extents
);
1147 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1150 DEBUG(DL_MAP
, ("Ext2InitializeZone %wZ: Block = %xh Mapped = %xh\n",
1151 &Mcb
->FullName
, Block
, Mapped
));
1154 /* Mapped is total number of continous blocks or NULL blocks */
1158 /* set mcb zone as initialized */
1159 SetLongFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1163 if (!IsZoneInited(Mcb
)) {
1164 Ext2ClearAllExtents(&Mcb
->Extents
);
1165 Ext2ClearAllExtents(&Mcb
->MetaExts
);
1173 IN PEXT2_IRP_CONTEXT IrpContext
,
1176 IN ULONGLONG Offset
,
1179 OUT PEXT2_EXTENT
* Chain
1186 NTSTATUS Status
= STATUS_SUCCESS
;
1188 PEXT2_EXTENT Extent
= NULL
;
1189 PEXT2_EXTENT List
= *Chain
= NULL
;
1191 if (!IsZoneInited(Mcb
)) {
1192 Status
= Ext2InitializeZone(IrpContext
, Vcb
, Mcb
);
1193 if (!NT_SUCCESS(Status
)) {
1198 if ((IrpContext
&& IrpContext
->Irp
) &&
1199 ((IrpContext
->Irp
->Flags
& IRP_NOCACHE
) ||
1200 (IrpContext
->Irp
->Flags
& IRP_PAGING_IO
))) {
1201 Size
= (Size
+ SECTOR_SIZE
- 1) & (~(SECTOR_SIZE
- 1));
1204 Start
= (ULONG
)(Offset
>> BLOCK_BITS
);
1205 End
= (ULONG
)((Size
+ Offset
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
1207 if (End
> (ULONG
)((Mcb
->Inode
.i_size
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
) ) {
1208 End
= (ULONG
)((Mcb
->Inode
.i_size
+ BLOCK_SIZE
- 1) >> BLOCK_BITS
);
1211 while (Size
> 0 && Start
< End
) {
1219 /* try to map file offset to ext2 block upon Extents cache */
1220 if (IsZoneInited(Mcb
)) {
1221 rc
= Ext2LookupBlockExtent(
1229 /* we likely get a sparse file here */
1235 /* try to BlockMap in case failed to access Extents cache */
1236 if (!IsZoneInited(Mcb
) || (bAlloc
&& Block
== 0)) {
1238 Status
= Ext2BlockMap(
1247 if (!NT_SUCCESS(Status
)) {
1251 /* skip wrong blocks, in case wrongly treating symlink
1252 target names as blocks, silly */
1253 if (Block
>= TOTAL_BLOCKS
) {
1257 /* add new allocated blocks to Mcb zone */
1258 if (IsZoneInited(Mcb
) && Block
) {
1259 if (!Ext2AddBlockExtent(Vcb
, Mcb
, Start
, Block
, Mapped
)) {
1261 ClearFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1262 Ext2ClearAllExtents(&Mcb
->Extents
);
1267 /* calculate i/o extent */
1268 Lba
= ((LONGLONG
)Block
<< BLOCK_BITS
) + Offset
- ((LONGLONG
)Start
<< BLOCK_BITS
);
1269 Length
= (ULONG
)(((LONGLONG
)(Start
+ Mapped
) << BLOCK_BITS
) - Offset
);
1270 if (Length
> Size
) {
1280 Offset
= (ULONGLONG
)Start
<< BLOCK_BITS
;
1284 if (List
&& List
->Lba
+ List
->Length
== Lba
) {
1286 /* it's continuous upon previous Extent */
1287 List
->Length
+= Length
;
1291 /* have to allocate a new Extent */
1292 Extent
= Ext2AllocateExtent();
1294 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1300 Extent
->Length
= Length
;
1301 Extent
->Offset
= Total
;
1303 /* insert new Extent to chain */
1305 List
->Next
= Extent
;
1308 *Chain
= List
= Extent
;
1327 IN OUT PUNICODE_STRING Target
,
1328 IN PUNICODE_STRING File
,
1329 IN PUNICODE_STRING Parent
1333 USHORT ParentLen
= 0;
1334 BOOLEAN bBackslash
= TRUE
;
1336 /* free the original buffer */
1337 if (Target
->Buffer
) {
1338 DEC_MEM_COUNT(PS_MCB_NAME
, Target
->Buffer
, Target
->MaximumLength
);
1339 Ext2FreePool(Target
->Buffer
, EXT2_FNAME_MAGIC
);
1340 Target
->Length
= Target
->MaximumLength
= 0;
1343 /* check the parent directory's name and backslash */
1344 if (Parent
&& Parent
->Buffer
&& Parent
->Length
> 0) {
1345 ParentLen
= Parent
->Length
/ sizeof(WCHAR
);
1346 if (Parent
->Buffer
[ParentLen
- 1] == L
'\\') {
1351 if (Parent
== NULL
|| File
->Buffer
[0] == L
'\\') {
1352 /* must be root inode */
1353 ASSERT(ParentLen
== 0);
1357 /* allocate and initialize new name buffer */
1358 Length
= File
->Length
;
1359 Length
+= (ParentLen
+ (bBackslash
? 1 : 0)) * sizeof(WCHAR
);
1361 Target
->Buffer
= Ext2AllocatePool(
1367 if (!Target
->Buffer
) {
1368 DEBUG(DL_ERR
, ( "Ex2BuildName: failed to allocate name bufer.\n"));
1371 RtlZeroMemory(Target
->Buffer
, Length
+ 2);
1374 RtlCopyMemory(&Target
->Buffer
[0],
1376 ParentLen
* sizeof(WCHAR
));
1380 Target
->Buffer
[ParentLen
++] = L
'\\';
1383 RtlCopyMemory( &Target
->Buffer
[ParentLen
],
1387 INC_MEM_COUNT(PS_MCB_NAME
, Target
->Buffer
, Length
+ 2);
1388 Target
->Length
= Length
;
1389 Target
->MaximumLength
= Length
+ 2;
1397 IN PUNICODE_STRING FileName
,
1398 IN PUNICODE_STRING Parent
,
1402 PEXT2_MCB Mcb
= NULL
;
1403 NTSTATUS Status
= STATUS_SUCCESS
;
1405 /* need wake the reaper thread if there are many Mcb allocated */
1406 if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 4)) {
1407 KeSetEvent(&Ext2Global
->Reaper
.Wait
, 0, FALSE
);
1410 /* allocate Mcb from LookasideList */
1411 Mcb
= (PEXT2_MCB
) (ExAllocateFromNPagedLookasideList(
1412 &(Ext2Global
->Ext2McbLookasideList
)));
1418 /* initialize Mcb header */
1419 RtlZeroMemory(Mcb
, sizeof(EXT2_MCB
));
1420 Mcb
->Identifier
.Type
= EXT2MCB
;
1421 Mcb
->Identifier
.Size
= sizeof(EXT2_MCB
);
1422 Mcb
->FileAttr
= FileAttr
;
1424 Mcb
->Inode
.i_priv
= (PVOID
)Mcb
;
1425 Mcb
->Inode
.i_sb
= &Vcb
->sb
;
1427 /* initialize Mcb names */
1431 if ( FileName
->Length
== 2 &&
1432 FileName
->Buffer
[0] == L
'\\') {
1433 DEBUG(DL_RES
, ( "Ext2AllocateMcb: Root Mcb is to be created !\n"));
1436 if ( FileName
->Length
== 2 &&
1437 FileName
->Buffer
[0] == L
'.') {
1441 if ( FileName
->Length
== 4 &&
1442 FileName
->Buffer
[0] == L
'.' &&
1443 FileName
->Buffer
[1] == L
'.' ) {
1448 if (( FileName
->Length
>= 4 && FileName
->Buffer
[0] == L
'.') &&
1449 ((FileName
->Length
== 4 && FileName
->Buffer
[1] != L
'.') ||
1450 FileName
->Length
>= 6 )) {
1451 SetFlag(Mcb
->FileAttr
, FILE_ATTRIBUTE_HIDDEN
);
1454 if (!Ext2BuildName(&Mcb
->ShortName
, FileName
, NULL
)) {
1457 if (!Ext2BuildName(&Mcb
->FullName
, FileName
, Parent
)) {
1462 /* initialize Mcb Extents, it will raise an expcetion if failed */
1464 FsRtlInitializeLargeMcb(&(Mcb
->Extents
), NonPagedPool
);
1465 FsRtlInitializeLargeMcb(&(Mcb
->MetaExts
), NonPagedPool
);
1466 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
1467 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1471 if (!NT_SUCCESS(Status
)) {
1475 INC_MEM_COUNT(PS_MCB
, Mcb
, sizeof(EXT2_MCB
));
1476 DEBUG(DL_INF
, ( "Ext2AllocateMcb: Mcb %wZ created.\n", &Mcb
->FullName
));
1484 if (Mcb
->ShortName
.Buffer
) {
1485 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->ShortName
.Buffer
,
1486 Mcb
->ShortName
.MaximumLength
);
1487 Ext2FreePool(Mcb
->ShortName
.Buffer
, EXT2_FNAME_MAGIC
);
1490 if (Mcb
->FullName
.Buffer
) {
1491 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->FullName
.Buffer
,
1492 Mcb
->FullName
.MaximumLength
);
1493 Ext2FreePool(Mcb
->FullName
.Buffer
, EXT2_FNAME_MAGIC
);
1496 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2McbLookasideList
), Mcb
);
1503 Ext2FreeMcb (IN PEXT2_VCB Vcb
, IN PEXT2_MCB Mcb
)
1506 PEXT2_MCB Parent
= Mcb
->Parent
;
1508 ASSERT(Mcb
!= NULL
);
1510 ASSERT((Mcb
->Identifier
.Type
== EXT2MCB
) &&
1511 (Mcb
->Identifier
.Size
== sizeof(EXT2_MCB
)));
1513 if ((Mcb
->Identifier
.Type
!= EXT2MCB
) ||
1514 (Mcb
->Identifier
.Size
!= sizeof(EXT2_MCB
))) {
1518 DEBUG(DL_INF
, ( "Ext2FreeMcb: Mcb %wZ will be freed.\n", &Mcb
->FullName
));
1520 if (IsMcbSymLink(Mcb
) && Mcb
->Target
) {
1521 Ext2DerefMcb(Mcb
->Target
);
1524 if (FsRtlNumberOfRunsInLargeMcb(&Mcb
->Extents
)) {
1525 DEBUG(DL_EXT
, ("List data extents for: %wZ\n", &Mcb
->FullName
));
1526 Ext2ListExtents(&Mcb
->Extents
);
1528 FsRtlUninitializeLargeMcb(&(Mcb
->Extents
));
1529 if (FsRtlNumberOfRunsInLargeMcb(&Mcb
->MetaExts
)) {
1530 DEBUG(DL_EXT
, ("List meta extents for: %wZ\n", &Mcb
->FullName
));
1531 Ext2ListExtents(&Mcb
->MetaExts
);
1533 FsRtlUninitializeLargeMcb(&(Mcb
->MetaExts
));
1534 ClearLongFlag(Mcb
->Flags
, MCB_ZONE_INITED
);
1536 if (Mcb
->ShortName
.Buffer
) {
1537 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->ShortName
.Buffer
,
1538 Mcb
->ShortName
.MaximumLength
);
1539 Ext2FreePool(Mcb
->ShortName
.Buffer
, EXT2_FNAME_MAGIC
);
1542 if (Mcb
->FullName
.Buffer
) {
1543 DEC_MEM_COUNT(PS_MCB_NAME
, Mcb
->FullName
.Buffer
,
1544 Mcb
->FullName
.MaximumLength
);
1545 Ext2FreePool(Mcb
->FullName
.Buffer
, EXT2_FNAME_MAGIC
);
1550 Ext2FreeEntry(Mcb
->de
);
1553 Mcb
->Identifier
.Type
= 0;
1554 Mcb
->Identifier
.Size
= 0;
1556 ExFreeToNPagedLookasideList(&(Ext2Global
->Ext2McbLookasideList
), Mcb
);
1557 DEC_MEM_COUNT(PS_MCB
, Mcb
, sizeof(EXT2_MCB
));
1565 PUNICODE_STRING FileName
1568 BOOLEAN LockAcquired
= FALSE
;
1569 PEXT2_MCB Mcb
= NULL
;
1572 ExAcquireResourceSharedLite(&Vcb
->McbLock
, TRUE
);
1573 LockAcquired
= TRUE
;
1574 Mcb
= Ext2SearchMcbWithoutLock(Parent
, FileName
);
1577 ExReleaseResourceLite(&Vcb
->McbLock
);
1586 Ext2SearchMcbWithoutLock(
1588 PUNICODE_STRING FileName
1591 PEXT2_MCB TmpMcb
= NULL
;
1593 DEBUG(DL_RES
, ("Ext2SearchMcb: %wZ\n", FileName
));
1597 Ext2ReferMcb(Parent
);
1599 if (Ext2IsDot(FileName
)) {
1601 Ext2ReferMcb(Parent
);
1605 if (Ext2IsDotDot(FileName
)) {
1606 if (IsMcbRoot(Parent
)) {
1609 TmpMcb
= Parent
->Parent
;
1612 Ext2ReferMcb(TmpMcb
);
1617 if (IsMcbSymLink(Parent
)) {
1618 if (Parent
->Target
) {
1619 TmpMcb
= Parent
->Target
->Child
;
1620 ASSERT(!IsMcbSymLink(Parent
->Target
));
1626 TmpMcb
= Parent
->Child
;
1631 if (!RtlCompareUnicodeString(
1632 &(TmpMcb
->ShortName
),
1634 Ext2ReferMcb(TmpMcb
);
1638 TmpMcb
= TmpMcb
->Next
;
1643 Ext2DerefMcb(Parent
);
1656 BOOLEAN LockAcquired
= FALSE
;
1657 PEXT2_MCB Mcb
= NULL
;
1661 ExAcquireResourceExclusiveLite(
1664 LockAcquired
= TRUE
;
1666 /* use it's target if it's a symlink */
1667 if (IsMcbSymLink(Parent
)) {
1668 Parent
= Parent
->Target
;
1669 ASSERT(!IsMcbSymLink(Parent
));
1672 Mcb
= Parent
->Child
;
1681 /* already attached in the list */
1682 DEBUG(DL_ERR
, ( "Ext2InsertMcb: Child Mcb is alreay attached.\n"));
1683 if (!IsFlagOn(Mcb
->Flags
, MCB_ENTRY_TREE
)) {
1684 SetLongFlag(Child
->Flags
, MCB_ENTRY_TREE
);
1685 DEBUG(DL_ERR
, ( "Ext2InsertMcb: Child Mcb's flag isn't set.\n"));
1692 /* insert this Mcb into the head */
1693 Child
->Next
= Parent
->Child
;
1694 Parent
->Child
= Child
;
1695 Child
->Parent
= Parent
;
1696 Child
->de
->d_parent
= Parent
->de
;
1697 Ext2ReferMcb(Parent
);
1698 SetLongFlag(Child
->Flags
, MCB_ENTRY_TREE
);
1704 ExReleaseResourceLite(&Vcb
->McbLock
);
1715 PEXT2_MCB TmpMcb
= NULL
;
1716 BOOLEAN LockAcquired
= FALSE
;
1717 BOOLEAN bLinked
= FALSE
;
1721 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
1722 LockAcquired
= TRUE
;
1726 if (Mcb
->Parent
->Child
== Mcb
) {
1727 Mcb
->Parent
->Child
= Mcb
->Next
;
1730 TmpMcb
= Mcb
->Parent
->Child
;
1732 while (TmpMcb
&& TmpMcb
->Next
!= Mcb
) {
1733 TmpMcb
= TmpMcb
->Next
;
1737 TmpMcb
->Next
= Mcb
->Next
;
1740 /* we got errors: link broken */
1745 if (IsFlagOn(Mcb
->Flags
, MCB_ENTRY_TREE
)) {
1746 DEBUG(DL_RES
, ("Mcb %p %wZ removed from Mcb %p %wZ\n", Mcb
,
1747 &Mcb
->FullName
, Mcb
->Parent
, &Mcb
->Parent
->FullName
));
1748 Ext2DerefMcb(Mcb
->Parent
);
1749 ClearLongFlag(Mcb
->Flags
, MCB_ENTRY_TREE
);
1754 if (IsFlagOn(Mcb
->Flags
, MCB_ENTRY_TREE
)) {
1755 ClearLongFlag(Mcb
->Flags
, MCB_ENTRY_TREE
);
1760 Mcb
->de
->d_parent
= NULL
;
1766 ExReleaseResourceLite(&Vcb
->McbLock
);
1774 Ext2CleanupAllMcbs(PEXT2_VCB Vcb
)
1776 BOOLEAN LockAcquired
= FALSE
;
1777 PEXT2_MCB Mcb
= NULL
;
1781 ExAcquireResourceExclusiveLite(
1784 LockAcquired
= TRUE
;
1786 while ((Mcb
= Ext2FirstUnusedMcb(Vcb
, TRUE
, Vcb
->NumOfMcb
)) != 0) {
1788 PEXT2_MCB Next
= Mcb
->Next
;
1789 if (IsMcbSymLink(Mcb
)) {
1792 Ext2FreeMcb(Vcb
, Mcb
);
1796 Ext2FreeMcb(Vcb
, Vcb
->McbTree
);
1797 Vcb
->McbTree
= NULL
;
1802 ExReleaseResourceLite(&Vcb
->McbLock
);
1808 Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext
, PEXT2_VCB Vcb
, LONGLONG Block
)
1810 PEXT2_GROUP_DESC gd
;
1811 struct buffer_head
*gb
= NULL
;
1812 struct buffer_head
*bh
= NULL
;
1813 ULONG group
, dwBlk
, Length
;
1815 BOOLEAN bModified
= FALSE
;
1817 group
= (ULONG
)(Block
- EXT2_FIRST_DATA_BLOCK
) / BLOCKS_PER_GROUP
;
1818 dwBlk
= (ULONG
)(Block
- EXT2_FIRST_DATA_BLOCK
) % BLOCKS_PER_GROUP
;
1820 gd
= ext4_get_group_desc(&Vcb
->sb
, group
, &gb
);
1824 bh
= sb_getblk(&Vcb
->sb
, ext4_block_bitmap(&Vcb
->sb
, gd
));
1826 if (group
== Vcb
->sbi
.s_groups_count
- 1) {
1827 Length
= (ULONG
)(TOTAL_BLOCKS
% BLOCKS_PER_GROUP
);
1829 /* s_blocks_count is integer multiple of s_blocks_per_group */
1831 Length
= BLOCKS_PER_GROUP
;
1833 Length
= BLOCKS_PER_GROUP
;
1836 if (dwBlk
>= Length
) {
1842 RtlInitializeBitMap(&bitmap
, (PULONG
)bh
->b_data
, Length
);
1844 if (RtlCheckBit(&bitmap
, dwBlk
) == 0) {
1846 RtlSetBits(&bitmap
, dwBlk
, 1);
1848 mark_buffer_dirty(bh
);
1854 return (!bModified
);
1858 Ext2CheckBitmapConsistency(PEXT2_IRP_CONTEXT IrpContext
, PEXT2_VCB Vcb
)
1860 ULONG i
, j
, InodeBlocks
;
1862 for (i
= 0; i
< Vcb
->sbi
.s_groups_count
; i
++) {
1864 PEXT2_GROUP_DESC gd
;
1865 struct buffer_head
*bh
= NULL
;
1867 gd
= ext4_get_group_desc(&Vcb
->sb
, i
, &bh
);
1870 Ext2CheckSetBlock(IrpContext
, Vcb
, ext4_block_bitmap(&Vcb
->sb
, gd
));
1871 Ext2CheckSetBlock(IrpContext
, Vcb
, ext4_inode_bitmap(&Vcb
->sb
, gd
));
1874 if (i
== Vcb
->sbi
.s_groups_count
- 1) {
1875 InodeBlocks
= ((INODES_COUNT
% INODES_PER_GROUP
) *
1876 Vcb
->InodeSize
+ Vcb
->BlockSize
- 1) /
1879 InodeBlocks
= (INODES_PER_GROUP
* Vcb
->InodeSize
+
1880 Vcb
->BlockSize
- 1) / (Vcb
->BlockSize
);
1883 for (j
= 0; j
< InodeBlocks
; j
++ )
1884 Ext2CheckSetBlock(IrpContext
, Vcb
, ext4_inode_table(&Vcb
->sb
, gd
) + j
);
1892 /* Ext2Global->Resource should be already acquired */
1894 Ext2InsertVcb(PEXT2_VCB Vcb
)
1896 InsertTailList(&(Ext2Global
->VcbList
), &Vcb
->Next
);
1900 /* Ext2Global->Resource should be already acquired */
1902 Ext2RemoveVcb(PEXT2_VCB Vcb
)
1904 RemoveEntryList(&Vcb
->Next
);
1905 InitializeListHead(&Vcb
->Next
);
1909 Ext2QueryVolumeParams(IN PEXT2_VCB Vcb
, IN PUNICODE_STRING Params
)
1912 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1914 UNICODE_STRING UniName
;
1915 PUSHORT UniBuffer
= NULL
;
1923 RtlZeroMemory(Params
, sizeof(UNICODE_STRING
));
1925 /* constructing volume UUID name */
1926 memset(UUID
, 0, sizeof(USHORT
) * 50);
1927 for (i
=0; i
< 16; i
++) {
1929 swprintf((wchar_t *)&UUID
[len
], L
"{%2.2X",Vcb
->SuperBlock
->s_uuid
[i
]);
1931 } else if (i
== 15) {
1932 swprintf((wchar_t *)&UUID
[len
], L
"-%2.2X}", Vcb
->SuperBlock
->s_uuid
[i
]);
1935 swprintf((wchar_t *)&UUID
[len
], L
"-%2.2X", Vcb
->SuperBlock
->s_uuid
[i
]);
1940 /* allocating memory for UniBuffer */
1941 UniBuffer
= Ext2AllocatePool(PagedPool
, 1024, EXT2_PARAM_MAGIC
);
1942 if (NULL
== UniBuffer
) {
1943 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1946 RtlZeroMemory(UniBuffer
, 1024);
1948 /* querying volume parameter string */
1949 RtlZeroMemory(&QueryTable
[0], sizeof(RTL_QUERY_REGISTRY_TABLE
) * 2);
1950 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1951 QueryTable
[0].Name
= UUID
;
1952 QueryTable
[0].EntryContext
= &(UniName
);
1953 UniName
.MaximumLength
= 1024;
1955 UniName
.Buffer
= UniBuffer
;
1957 Status
= RtlQueryRegistryValues(
1958 RTL_REGISTRY_ABSOLUTE
,
1959 Ext2Global
->RegistryPath
.Buffer
,
1965 if (!NT_SUCCESS(Status
)) {
1971 if (NT_SUCCESS(Status
)) {
1975 Ext2FreePool(UniBuffer
, EXT2_PARAM_MAGIC
);
1983 Ext2ParseRegistryVolumeParams(
1984 IN PUNICODE_STRING Params
,
1985 OUT PEXT2_VOLUME_PROPERTY2 Property
1988 WCHAR Codepage
[CODEPAGE_MAXLEN
];
1989 WCHAR Prefix
[HIDINGPAT_LEN
];
1990 WCHAR Suffix
[HIDINGPAT_LEN
];
1991 USHORT MountPoint
[4];
1994 BOOLEAN bWriteSupport
= FALSE
,
1995 bCheckBitmap
= FALSE
,
1997 bMountPoint
= FALSE
;
1999 PWCHAR Name
; /* parameters name */
2000 PBOOLEAN bExist
; /* is it contained in params */
2001 USHORT Length
; /* parameter value length */
2002 PWCHAR uValue
; /* value buffer in unicode */
2003 PCHAR aValue
; /* value buffer in ansi */
2004 } ParamPattern
[] = {
2005 /* writing support */
2006 {READING_ONLY
, &Property
->bReadonly
, 0, NULL
, NULL
},
2007 {WRITING_SUPPORT
, &bWriteSupport
, 0, NULL
, NULL
},
2008 {EXT3_FORCEWRITING
, &Property
->bExt3Writable
, 0, NULL
, NULL
},
2010 /* need check bitmap */
2011 {CHECKING_BITMAP
, &bCheckBitmap
, 0, NULL
, NULL
},
2013 {CODEPAGE_NAME
, &bCodeName
, CODEPAGE_MAXLEN
,
2014 &Codepage
[0], Property
->Codepage
},
2015 /* filter prefix and suffix */
2016 {HIDING_PREFIX
, &Property
->bHidingPrefix
, HIDINGPAT_LEN
,
2017 &Prefix
[0], Property
->sHidingPrefix
},
2018 {HIDING_SUFFIX
, &Property
->bHidingSuffix
, HIDINGPAT_LEN
,
2019 &Suffix
[0], Property
->sHidingSuffix
},
2020 {MOUNT_POINT
, &bMountPoint
, 4,
2021 &MountPoint
[0], &DrvLetter
[0]},
2024 {NULL
, NULL
, 0, NULL
}
2029 RtlZeroMemory(Codepage
, CODEPAGE_MAXLEN
);
2030 RtlZeroMemory(Prefix
, HIDINGPAT_LEN
);
2031 RtlZeroMemory(Suffix
, HIDINGPAT_LEN
);
2032 RtlZeroMemory(MountPoint
, sizeof(USHORT
) * 4);
2033 RtlZeroMemory(DrvLetter
, sizeof(CHAR
) * 4);
2035 RtlZeroMemory(Property
, sizeof(EXT2_VOLUME_PROPERTY2
));
2036 Property
->Magic
= EXT2_VOLUME_PROPERTY_MAGIC
;
2037 Property
->Command
= APP_CMD_SET_PROPERTY2
;
2039 for (i
=0; ParamPattern
[i
].Name
!= NULL
; i
++) {
2041 UNICODE_STRING Name1
=*Params
, Name2
;
2042 RtlInitUnicodeString(&Name2
, ParamPattern
[i
].Name
);
2043 *ParamPattern
[i
].bExist
= FALSE
;
2045 for (j
=0; j
* sizeof(WCHAR
) + Name2
.Length
<= Params
->Length
; j
++) {
2047 Name1
.MaximumLength
= Params
->Length
- j
* sizeof(WCHAR
);
2048 Name1
.Length
= Name2
.Length
;
2049 Name1
.Buffer
= &Params
->Buffer
[j
];
2051 if (!RtlCompareUnicodeString(&Name1
, &Name2
, TRUE
)) {
2052 if (j
* sizeof(WCHAR
) + Name2
.Length
== Params
->Length
||
2053 Name1
.Buffer
[Name2
.Length
/sizeof(WCHAR
)] == L
';' ||
2054 Name1
.Buffer
[Name2
.Length
/sizeof(WCHAR
)] == L
',' ) {
2055 *(ParamPattern
[i
].bExist
) = TRUE
;
2056 } else if ((j
* 2 + Name2
.Length
< Params
->Length
+ 2) ||
2057 (Name1
.Buffer
[Name2
.Length
/sizeof(WCHAR
)] == L
'=' )) {
2058 j
+= Name2
.Length
/sizeof(WCHAR
) + 1;
2060 while ( j
+ k
< Params
->Length
/2 &&
2061 k
< ParamPattern
[i
].Length
&&
2062 Params
->Buffer
[j
+k
] != L
';' &&
2063 Params
->Buffer
[j
+k
] != L
',' ) {
2065 ParamPattern
[i
].uValue
[k
] = Params
->Buffer
[j
+ k
];
2068 ParamPattern
[i
].uValue
[k
] = Params
->Buffer
[j
+ k
++];
2073 ANSI_STRING AnsiName
;
2074 AnsiName
.Length
= 0;
2075 AnsiName
.MaximumLength
=ParamPattern
[i
].Length
;
2076 AnsiName
.Buffer
= ParamPattern
[i
].aValue
;
2078 Name2
.Buffer
= ParamPattern
[i
].uValue
;
2079 Name2
.MaximumLength
= Name2
.Length
= k
* sizeof(WCHAR
);
2080 status
= RtlUnicodeStringToAnsiString(
2081 &AnsiName
, &Name2
, FALSE
);
2082 if (NT_SUCCESS(status
)) {
2083 *(ParamPattern
[i
].bExist
) = TRUE
;
2085 *ParamPattern
[i
].bExist
= FALSE
;
2095 Property
->DrvLetter
= DrvLetter
[0];
2096 Property
->DrvLetter
|= 0x80;
2101 Ext2PerformRegistryVolumeParams(IN PEXT2_VCB Vcb
)
2104 UNICODE_STRING VolumeParams
;
2106 Status
= Ext2QueryVolumeParams(Vcb
, &VolumeParams
);
2107 if (NT_SUCCESS(Status
)) {
2109 /* set Vcb settings from registery */
2110 EXT2_VOLUME_PROPERTY2 Property
;
2111 Ext2ParseRegistryVolumeParams(&VolumeParams
, &Property
);
2112 Ext2ProcessVolumeProperty(Vcb
, &Property
, sizeof(Property
));
2116 /* don't support auto mount */
2117 if (IsFlagOn(Ext2Global
->Flags
, EXT2_AUTO_MOUNT
)) {
2118 Status
= STATUS_SUCCESS
;
2120 Status
= STATUS_UNSUCCESSFUL
;
2124 /* set Vcb settings from Ext2Global */
2125 if (IsFlagOn(Ext2Global
->Flags
, EXT2_SUPPORT_WRITING
)) {
2126 if (Vcb
->IsExt3fs
) {
2127 if (IsFlagOn(Ext2Global
->Flags
, EXT3_FORCE_WRITING
)) {
2128 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2130 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2133 ClearLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2136 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2139 /* set the default codepage */
2140 Vcb
->Codepage
.PageTable
= Ext2Global
->Codepage
.PageTable
;
2141 memcpy(Vcb
->Codepage
.AnsiName
, Ext2Global
->Codepage
.AnsiName
, CODEPAGE_MAXLEN
);
2142 Vcb
->Codepage
.PageTable
= Ext2Global
->Codepage
.PageTable
;
2144 if ((Vcb
->bHidingPrefix
= Ext2Global
->bHidingPrefix
) != 0) {
2145 RtlCopyMemory( Vcb
->sHidingPrefix
,
2146 Ext2Global
->sHidingPrefix
,
2149 RtlZeroMemory( Vcb
->sHidingPrefix
,
2153 if ((Vcb
->bHidingSuffix
= Ext2Global
->bHidingSuffix
) != 0) {
2154 RtlCopyMemory( Vcb
->sHidingSuffix
,
2155 Ext2Global
->sHidingSuffix
,
2158 RtlZeroMemory( Vcb
->sHidingSuffix
,
2165 if (VolumeParams
.Buffer
) {
2166 Ext2FreePool(VolumeParams
.Buffer
, EXT2_PARAM_MAGIC
);
2173 Ext2InitializeLabel(
2175 IN PEXT2_SUPER_BLOCK Sb
2181 UNICODE_STRING Label
;
2184 Label
.MaximumLength
= 16 * sizeof(WCHAR
);
2186 Label
.Buffer
= Vcb
->Vpb
->VolumeLabel
;
2187 Vcb
->Vpb
->VolumeLabelLength
= 0;
2188 RtlZeroMemory(Label
.Buffer
, Label
.MaximumLength
);
2191 while ( (Length
> 0) &&
2192 ((Sb
->s_volume_name
[Length
-1] == 0x00) ||
2193 (Sb
->s_volume_name
[Length
- 1] == 0x20) )
2199 return STATUS_SUCCESS
;
2202 OemName
.Buffer
= Sb
->s_volume_name
;
2203 OemName
.MaximumLength
= 16;
2204 OemName
.Length
= Length
;
2206 status
= Ext2OEMToUnicode(Vcb
, &Label
, &OemName
);
2207 if (NT_SUCCESS(status
)) {
2208 Vcb
->Vpb
->VolumeLabelLength
= Label
.Length
;
2214 static __inline BOOLEAN
Ext2IsNullUuid (__u8
* uuid
)
2217 for (i
= 0; i
< 16; i
++) {
2226 #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
2229 Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext
,
2231 IN PEXT2_SUPER_BLOCK sb
,
2232 IN PDEVICE_OBJECT TargetDevice
,
2233 IN PDEVICE_OBJECT VolumeDevice
,
2236 NTSTATUS Status
= STATUS_UNRECOGNIZED_VOLUME
;
2240 UNICODE_STRING RootNode
;
2242 ULONG ChangeCount
= 0, features
;
2243 CC_FILE_SIZES FileSizes
;
2244 int i
, has_huge_files
;
2246 BOOLEAN VcbResourceInitialized
= FALSE
;
2247 BOOLEAN NotifySyncInitialized
= FALSE
;
2248 BOOLEAN ExtentsInitialized
= FALSE
;
2249 BOOLEAN InodeLookasideInitialized
= FALSE
;
2254 Status
= STATUS_DEVICE_NOT_READY
;
2258 /* checking in/compat features */
2259 if (IsFlagOn(sb
->s_feature_compat
, EXT3_FEATURE_COMPAT_HAS_JOURNAL
)) {
2260 Vcb
->IsExt3fs
= TRUE
;
2263 /* don't mount any volumes with external journal devices */
2264 if (IsFlagOn(sb
->s_feature_incompat
, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)) {
2265 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2269 /* check block size */
2270 Vcb
->BlockSize
= (EXT2_MIN_BLOCK_SIZE
<< sb
->s_log_block_size
);
2271 /* we cannot handle volume with block size bigger than 64k */
2272 if (Vcb
->BlockSize
> EXT2_MAX_USER_BLKSIZE
) {
2273 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2277 if (Vcb
->BlockSize
>= PAGE_SIZE
) {
2278 Vcb
->IoUnitBits
= PAGE_SHIFT
;
2279 Vcb
->IoUnitSize
= PAGE_SIZE
;
2281 Vcb
->IoUnitSize
= Vcb
->BlockSize
;
2282 Vcb
->IoUnitBits
= Ext2Log2(Vcb
->BlockSize
);
2285 /* initialize vcb header members ... */
2286 Vcb
->Header
.IsFastIoPossible
= FastIoIsNotPossible
;
2287 Vcb
->Header
.Resource
= &(Vcb
->MainResource
);
2288 Vcb
->Header
.PagingIoResource
= &(Vcb
->PagingIoResource
);
2289 Vcb
->OpenVolumeCount
= 0;
2290 Vcb
->OpenHandleCount
= 0;
2291 Vcb
->ReferenceCount
= 0;
2293 /* initialize eresources */
2294 ExInitializeResourceLite(&Vcb
->MainResource
);
2295 ExInitializeResourceLite(&Vcb
->PagingIoResource
);
2296 ExInitializeResourceLite(&Vcb
->MetaLock
);
2297 ExInitializeResourceLite(&Vcb
->McbLock
);
2298 #ifndef _WIN2K_TARGET_
2299 ExInitializeFastMutex(&Vcb
->Mutex
);
2300 FsRtlSetupAdvancedHeader(&Vcb
->Header
, &Vcb
->Mutex
);
2302 VcbResourceInitialized
= TRUE
;
2304 /* initialize Fcb list head */
2305 InitializeListHead(&Vcb
->FcbList
);
2306 KeInitializeSpinLock(&Vcb
->FcbLock
);
2308 /* initialize Mcb list head */
2309 InitializeListHead(&(Vcb
->McbList
));
2311 /* initialize directory notify list */
2312 InitializeListHead(&Vcb
->NotifyList
);
2313 FsRtlNotifyInitializeSync(&Vcb
->NotifySync
);
2314 NotifySyncInitialized
= TRUE
;
2316 /* superblock checking */
2317 Vcb
->SuperBlock
= sb
;
2319 /* initialize Vpb and Label */
2320 Vcb
->DeviceObject
= VolumeDevice
;
2321 Vcb
->TargetDeviceObject
= TargetDevice
;
2323 Vcb
->RealDevice
= Vpb
->RealDevice
;
2324 Vpb
->DeviceObject
= VolumeDevice
;
2326 /* set inode size */
2327 Vcb
->InodeSize
= (ULONG
)sb
->s_inode_size
;
2328 if (Vcb
->InodeSize
== 0) {
2329 Vcb
->InodeSize
= EXT2_GOOD_OLD_INODE_SIZE
;
2332 /* initialize inode lookaside list */
2333 ExInitializeNPagedLookasideList(&(Vcb
->InodeLookasideList
),
2334 NULL
, NULL
, 0, sizeof(EXT2_INODE
),
2337 InodeLookasideInitialized
= TRUE
;
2339 /* initialize label in Vpb */
2340 Status
= Ext2InitializeLabel(Vcb
, sb
);
2341 if (!NT_SUCCESS(Status
)) {
2345 /* check device characteristics flags */
2346 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
2347 SetLongFlag(Vcb
->Flags
, VCB_REMOVABLE_MEDIA
);
2350 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_FLOPPY_DISKETTE
)) {
2351 SetLongFlag(Vcb
->Flags
, VCB_FLOPPY_DISK
);
2354 if (IsFlagOn(Vpb
->RealDevice
->Characteristics
, FILE_READ_ONLY_DEVICE
)) {
2355 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2358 if (IsFlagOn(TargetDevice
->Characteristics
, FILE_READ_ONLY_DEVICE
)) {
2359 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2362 /* verify device is writable ? */
2363 if (Ext2IsMediaWriteProtected(IrpContext
, TargetDevice
)) {
2364 SetFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
2367 /* initialize UUID and serial number */
2368 if (Ext2IsNullUuid(sb
->s_uuid
)) {
2369 ExUuidCreate((UUID
*)sb
->s_uuid
);
2371 /* query parameters from registry */
2372 if (!NT_SUCCESS(Ext2PerformRegistryVolumeParams(Vcb
))) {
2373 /* don't mount this volume */
2374 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2379 Vpb
->SerialNumber
= ((ULONG
*)sb
->s_uuid
)[0] +
2380 ((ULONG
*)sb
->s_uuid
)[1] +
2381 ((ULONG
*)sb
->s_uuid
)[2] +
2382 ((ULONG
*)sb
->s_uuid
)[3];
2384 /* query partition size and disk geometry parameters */
2385 DiskSize
= Vcb
->DiskGeometry
.Cylinders
.QuadPart
*
2386 Vcb
->DiskGeometry
.TracksPerCylinder
*
2387 Vcb
->DiskGeometry
.SectorsPerTrack
*
2388 Vcb
->DiskGeometry
.BytesPerSector
;
2390 IoctlSize
= sizeof(PARTITION_INFORMATION
);
2391 Status
= Ext2DiskIoControl(
2393 IOCTL_DISK_GET_PARTITION_INFO
,
2396 &Vcb
->PartitionInformation
,
2398 if (NT_SUCCESS(Status
)) {
2399 PartSize
= Vcb
->PartitionInformation
.PartitionLength
.QuadPart
;
2401 Vcb
->PartitionInformation
.StartingOffset
.QuadPart
= 0;
2402 Vcb
->PartitionInformation
.PartitionLength
.QuadPart
= DiskSize
;
2403 PartSize
= DiskSize
;
2404 Status
= STATUS_SUCCESS
;
2406 Vcb
->Header
.AllocationSize
.QuadPart
=
2407 Vcb
->Header
.FileSize
.QuadPart
= PartSize
;
2409 Vcb
->Header
.ValidDataLength
.QuadPart
=
2410 Vcb
->Header
.FileSize
.QuadPart
;
2413 IoctlSize
= sizeof(ULONG
);
2414 Status
= Ext2DiskIoControl(
2416 IOCTL_DISK_CHECK_VERIFY
,
2422 if (!NT_SUCCESS(Status
)) {
2425 Vcb
->ChangeCount
= ChangeCount
;
2427 /* create the stream object for ext2 volume */
2428 Vcb
->Volume
= IoCreateStreamFileObject(NULL
, Vcb
->Vpb
->RealDevice
);
2430 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2434 /* initialize streaming object file */
2435 Vcb
->Volume
->SectionObjectPointer
= &(Vcb
->SectionObject
);
2436 Vcb
->Volume
->ReadAccess
= TRUE
;
2437 Vcb
->Volume
->WriteAccess
= TRUE
;
2438 Vcb
->Volume
->DeleteAccess
= TRUE
;
2439 Vcb
->Volume
->FsContext
= (PVOID
) Vcb
;
2440 Vcb
->Volume
->FsContext2
= NULL
;
2441 Vcb
->Volume
->Vpb
= Vcb
->Vpb
;
2443 FileSizes
.AllocationSize
.QuadPart
=
2444 FileSizes
.FileSize
.QuadPart
=
2445 FileSizes
.ValidDataLength
.QuadPart
=
2446 Vcb
->Header
.AllocationSize
.QuadPart
;
2448 CcInitializeCacheMap( Vcb
->Volume
,
2451 &(Ext2Global
->CacheManagerNoOpCallbacks
),
2454 /* initialize disk block LargetMcb and entry Mcb,
2455 it will raise an expcetion if failed */
2457 FsRtlInitializeLargeMcb(&(Vcb
->Extents
), PagedPool
);
2458 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
2459 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2462 if (!NT_SUCCESS(Status
)) {
2465 ExtentsInitialized
= TRUE
;
2467 /* set block device */
2468 Vcb
->bd
.bd_dev
= Vcb
->RealDevice
;
2469 Vcb
->bd
.bd_geo
= Vcb
->DiskGeometry
;
2470 Vcb
->bd
.bd_part
= Vcb
->PartitionInformation
;
2471 Vcb
->bd
.bd_volume
= Vcb
->Volume
;
2472 Vcb
->bd
.bd_priv
= (void *) Vcb
;
2473 memset(&Vcb
->bd
.bd_bh_root
, 0, sizeof(struct rb_root
));
2474 spin_lock_init(&Vcb
->bd
.bd_bh_lock
);
2475 Vcb
->bd
.bd_bh_cache
= kmem_cache_create("bd_bh_buffer",
2476 Vcb
->BlockSize
, 0, 0, NULL
);
2477 if (!Vcb
->bd
.bd_bh_cache
) {
2478 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2482 Vcb
->SectorBits
= Ext2Log2(SECTOR_SIZE
);
2483 Vcb
->sb
.s_magic
= sb
->s_magic
;
2484 Vcb
->sb
.s_bdev
= &Vcb
->bd
;
2485 Vcb
->sb
.s_blocksize
= BLOCK_SIZE
;
2486 Vcb
->sb
.s_blocksize_bits
= BLOCK_BITS
;
2487 Vcb
->sb
.s_priv
= (void *) Vcb
;
2488 Vcb
->sb
.s_fs_info
= &Vcb
->sbi
;
2491 Vcb
->sbi
.s_blocks_per_group
= sb
->s_blocks_per_group
;
2492 Vcb
->sbi
.s_first_ino
= sb
->s_first_ino
;
2493 Vcb
->sbi
.s_desc_size
= sb
->s_desc_size
;
2495 if (EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, EXT4_FEATURE_INCOMPAT_64BIT
)) {
2496 if (Vcb
->sbi
.s_desc_size
< EXT4_MIN_DESC_SIZE_64BIT
||
2497 Vcb
->sbi
.s_desc_size
> EXT4_MAX_DESC_SIZE
||
2498 !is_power_of_2(Vcb
->sbi
.s_desc_size
)) {
2499 DEBUG(DL_ERR
, ("EXT4-fs: unsupported descriptor size %lu\n", Vcb
->sbi
.s_desc_size
));
2500 Status
= STATUS_DISK_CORRUPT_ERROR
;
2504 Vcb
->sbi
.s_desc_size
= EXT4_MIN_DESC_SIZE
;
2507 Vcb
->sbi
.s_blocks_per_group
= sb
->s_blocks_per_group
;
2508 Vcb
->sbi
.s_inodes_per_group
= sb
->s_inodes_per_group
;
2509 if (EXT3_INODES_PER_GROUP(&Vcb
->sb
) == 0) {
2510 Status
= STATUS_DISK_CORRUPT_ERROR
;
2513 Vcb
->sbi
.s_inodes_per_block
= BLOCK_SIZE
/ Vcb
->InodeSize
;
2514 if (Vcb
->sbi
.s_inodes_per_block
== 0) {
2515 Status
= STATUS_DISK_CORRUPT_ERROR
;
2518 Vcb
->sbi
.s_itb_per_group
= Vcb
->sbi
.s_inodes_per_group
/
2519 Vcb
->sbi
.s_inodes_per_block
;
2522 Vcb
->sbi
.s_desc_per_block
= BLOCK_SIZE
/ GROUP_DESC_SIZE
;
2523 Vcb
->sbi
.s_desc_per_block_bits
= ilog2(Vcb
->sbi
.s_desc_per_block
);
2525 for (i
=0; i
< 4; i
++) {
2526 Vcb
->sbi
.s_hash_seed
[i
] = sb
->s_hash_seed
[i
];
2528 Vcb
->sbi
.s_def_hash_version
= sb
->s_def_hash_version
;
2530 if (le32_to_cpu(sb
->s_rev_level
) == EXT3_GOOD_OLD_REV
&&
2531 (EXT3_HAS_COMPAT_FEATURE(&Vcb
->sb
, ~0U) ||
2532 EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, ~0U) ||
2533 EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, ~0U))) {
2535 "EXT3-fs warning: feature flags set on rev 0 fs, "
2536 "running e2fsck is recommended\n");
2540 * Check feature flags regardless of the revision level, since we
2541 * previously didn't change the revision level when setting the flags,
2542 * so there is a chance incompat flags are set on a rev 0 filesystem.
2544 features
= EXT3_HAS_INCOMPAT_FEATURE(&Vcb
->sb
, ~EXT4_FEATURE_INCOMPAT_SUPP
);
2545 if (features
& EXT4_FEATURE_INCOMPAT_DIRDATA
) {
2546 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2547 ClearFlag(features
, EXT4_FEATURE_INCOMPAT_DIRDATA
);
2550 printk(KERN_ERR
"EXT3-fs: %s: couldn't mount because of "
2551 "unsupported optional features (%x).\n",
2552 Vcb
->sb
.s_id
, le32_to_cpu(features
));
2553 Status
= STATUS_UNRECOGNIZED_VOLUME
;
2557 features
= EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, ~EXT4_FEATURE_RO_COMPAT_SUPP
);
2559 printk(KERN_ERR
"EXT3-fs: %s: unsupported optional features in this volume: (%x).\n",
2560 Vcb
->sb
.s_id
, le32_to_cpu(features
));
2561 if (CanIWrite(Vcb
)) {
2563 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2567 has_huge_files
= EXT3_HAS_RO_COMPAT_FEATURE(&Vcb
->sb
, EXT4_FEATURE_RO_COMPAT_HUGE_FILE
);
2569 Vcb
->sb
.s_maxbytes
= ext3_max_size(BLOCK_BITS
, has_huge_files
);
2570 Vcb
->max_bitmap_bytes
= ext3_max_bitmap_size(BLOCK_BITS
,
2572 Vcb
->max_bytes
= ext3_max_size(BLOCK_BITS
, has_huge_files
);
2574 /* calculate maximum file bocks ... */
2576 ULONG dwData
[EXT2_BLOCK_TYPES
] = {EXT2_NDIR_BLOCKS
, 1, 1, 1};
2579 ASSERT(BLOCK_BITS
== Ext2Log2(BLOCK_SIZE
));
2581 Vcb
->sbi
.s_groups_count
= (ULONG
)(ext3_blocks_count(sb
) - sb
->s_first_data_block
+
2582 sb
->s_blocks_per_group
- 1) / sb
->s_blocks_per_group
;
2584 Vcb
->max_data_blocks
= 0;
2585 for (i
= 0; i
< EXT2_BLOCK_TYPES
; i
++) {
2586 if (BLOCK_BITS
>= 12 && i
== (EXT2_BLOCK_TYPES
- 1)) {
2587 dwData
[i
] = 0x40000000;
2589 dwData
[i
] = dwData
[i
] << ((BLOCK_BITS
- 2) * i
);
2591 Vcb
->max_blocks_per_layer
[i
] = dwData
[i
];
2592 Vcb
->max_data_blocks
+= Vcb
->max_blocks_per_layer
[i
];
2596 Vcb
->sbi
.s_gdb_count
= (Vcb
->sbi
.s_groups_count
+ Vcb
->sbi
.s_desc_per_block
- 1) /
2597 Vcb
->sbi
.s_desc_per_block
;
2598 /* load all gorup desc */
2599 if (!Ext2LoadGroup(Vcb
)) {
2600 Status
= STATUS_UNSUCCESSFUL
;
2604 /* recovery journal since it's ext3 */
2605 if (Vcb
->IsExt3fs
) {
2606 Ext2RecoverJournal(IrpContext
, Vcb
);
2607 if (IsFlagOn(Vcb
->Flags
, VCB_JOURNAL_RECOVER
)) {
2608 SetLongFlag(Vcb
->Flags
, VCB_READ_ONLY
);
2612 /* Now allocating the mcb for root ... */
2615 RootNode
.Buffer
= Buffer
;
2616 RootNode
.MaximumLength
= RootNode
.Length
= 2;
2617 Vcb
->McbTree
= Ext2AllocateMcb(
2618 Vcb
, &RootNode
, NULL
,
2619 FILE_ATTRIBUTE_DIRECTORY
2621 if (!Vcb
->McbTree
) {
2623 Status
= STATUS_UNSUCCESSFUL
;
2627 Vcb
->sb
.s_root
= Ext2BuildEntry(Vcb
, NULL
, &RootNode
);
2628 if (!Vcb
->sb
.s_root
) {
2630 Status
= STATUS_UNSUCCESSFUL
;
2633 Vcb
->sb
.s_root
->d_sb
= &Vcb
->sb
;
2634 Vcb
->sb
.s_root
->d_inode
= &Vcb
->McbTree
->Inode
;
2635 Vcb
->McbTree
->de
= Vcb
->sb
.s_root
;
2637 /* load root inode */
2638 Vcb
->McbTree
->Inode
.i_ino
= EXT2_ROOT_INO
;
2639 Vcb
->McbTree
->Inode
.i_sb
= &Vcb
->sb
;
2640 if (!Ext2LoadInode(Vcb
, &Vcb
->McbTree
->Inode
)) {
2642 Status
= STATUS_CANT_WAIT
;
2646 /* initializeroot node */
2647 Vcb
->McbTree
->CreationTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_ctime
);
2648 Vcb
->McbTree
->LastAccessTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_atime
);
2649 Vcb
->McbTree
->LastWriteTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_mtime
);
2650 Vcb
->McbTree
->ChangeTime
= Ext2NtTime(Vcb
->McbTree
->Inode
.i_mtime
);
2652 /* check bitmap if user specifies it */
2653 if (IsFlagOn(Ext2Global
->Flags
, EXT2_CHECKING_BITMAP
)) {
2654 Ext2CheckBitmapConsistency(IrpContext
, Vcb
);
2657 /* get anything doen, then refer target device */
2658 ObReferenceObject(Vcb
->TargetDeviceObject
);
2659 SetLongFlag(Vcb
->Flags
, VCB_INITIALIZED
);
2663 if (!NT_SUCCESS(Status
)) {
2666 Ext2FreeMcb(Vcb
, Vcb
->McbTree
);
2669 if (InodeLookasideInitialized
) {
2670 ExDeleteNPagedLookasideList(&(Vcb
->InodeLookasideList
));
2673 if (ExtentsInitialized
) {
2675 if (Vcb
->bd
.bd_bh_cache
)
2676 kmem_cache_destroy(Vcb
->bd
.bd_bh_cache
);
2677 FsRtlUninitializeLargeMcb(&(Vcb
->Extents
));
2681 if (Vcb
->Volume
->PrivateCacheMap
) {
2682 Ext2SyncUninitializeCacheMap(Vcb
->Volume
);
2684 ObDereferenceObject(Vcb
->Volume
);
2687 if (NotifySyncInitialized
) {
2688 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
2691 if (VcbResourceInitialized
) {
2692 ExDeleteResourceLite(&Vcb
->McbLock
);
2693 ExDeleteResourceLite(&Vcb
->MetaLock
);
2694 ExDeleteResourceLite(&Vcb
->MainResource
);
2695 ExDeleteResourceLite(&Vcb
->PagingIoResource
);
2705 Ext2TearDownStream(IN PEXT2_VCB Vcb
)
2707 PFILE_OBJECT Stream
= Vcb
->Volume
;
2708 IO_STATUS_BLOCK IoStatus
;
2710 ASSERT(Vcb
!= NULL
);
2711 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2712 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2718 if (IsFlagOn(Stream
->Flags
, FO_FILE_MODIFIED
)) {
2719 CcFlushCache(&(Vcb
->SectionObject
), NULL
, 0, &IoStatus
);
2720 ClearFlag(Stream
->Flags
, FO_FILE_MODIFIED
);
2723 if (Stream
->PrivateCacheMap
) {
2724 Ext2SyncUninitializeCacheMap(Stream
);
2727 ObDereferenceObject(Stream
);
2732 Ext2DestroyVcb (IN PEXT2_VCB Vcb
)
2734 ASSERT(Vcb
!= NULL
);
2735 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2736 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2738 DEBUG(DL_FUN
, ("Ext2DestroyVcb ...\n"));
2741 Ext2TearDownStream(Vcb
);
2743 ASSERT(NULL
== Vcb
->Volume
);
2745 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
2746 Ext2ListExtents(&Vcb
->Extents
);
2747 FsRtlUninitializeLargeMcb(&(Vcb
->Extents
));
2749 Ext2CleanupAllMcbs(Vcb
);
2753 if (Vcb
->bd
.bd_bh_cache
)
2754 kmem_cache_destroy(Vcb
->bd
.bd_bh_cache
);
2756 if (Vcb
->SuperBlock
) {
2757 Ext2FreePool(Vcb
->SuperBlock
, EXT2_SB_MAGIC
);
2758 Vcb
->SuperBlock
= NULL
;
2761 if (IsFlagOn(Vcb
->Flags
, VCB_NEW_VPB
)) {
2762 ASSERT(Vcb
->Vpb2
!= NULL
);
2763 DEBUG(DL_DBG
, ("Ext2DestroyVcb: Vpb2 to be freed: %p\n", Vcb
->Vpb2
));
2764 ExFreePoolWithTag(Vcb
->Vpb2
, TAG_VPB
);
2765 DEC_MEM_COUNT(PS_VPB
, Vcb
->Vpb2
, sizeof(VPB
));
2769 ObDereferenceObject(Vcb
->TargetDeviceObject
);
2771 ExDeleteNPagedLookasideList(&(Vcb
->InodeLookasideList
));
2772 ExDeleteResourceLite(&Vcb
->McbLock
);
2773 ExDeleteResourceLite(&Vcb
->MetaLock
);
2774 ExDeleteResourceLite(&Vcb
->PagingIoResource
);
2775 ExDeleteResourceLite(&Vcb
->MainResource
);
2777 DEBUG(DL_DBG
, ("Ext2DestroyVcb: DevObject=%p Vcb=%p\n", Vcb
->DeviceObject
, Vcb
));
2778 IoDeleteDevice(Vcb
->DeviceObject
);
2779 DEC_MEM_COUNT(PS_VCB
, Vcb
->DeviceObject
, sizeof(EXT2_VCB
));
2783 /* uninitialize cache map */
2786 Ext2SyncUninitializeCacheMap (
2787 IN PFILE_OBJECT FileObject
2790 CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent
;
2791 NTSTATUS WaitStatus
;
2792 LARGE_INTEGER Ext2LargeZero
= {0,0};
2795 KeInitializeEvent( &UninitializeCompleteEvent
.Event
,
2796 SynchronizationEvent
,
2799 CcUninitializeCacheMap( FileObject
,
2801 &UninitializeCompleteEvent
);
2803 WaitStatus
= KeWaitForSingleObject( &UninitializeCompleteEvent
.Event
,
2809 ASSERT (NT_SUCCESS(WaitStatus
));
2812 /* Link Mcb to tail of Vcb->McbList queue */
2815 Ext2LinkTailMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2817 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2821 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2823 if (IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2824 DEBUG(DL_RES
, ( "Ext2LinkTailMcb: %wZ already linked.\n",
2827 InsertTailList(&Vcb
->McbList
, &Mcb
->Link
);
2828 SetLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2829 Ext2ReferXcb(&Vcb
->NumOfMcb
);
2832 ExReleaseResourceLite(&Vcb
->McbLock
);
2835 /* Link Mcb to head of Vcb->McbList queue */
2838 Ext2LinkHeadMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2840 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2844 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2846 if (!IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2847 InsertHeadList(&Vcb
->McbList
, &Mcb
->Link
);
2848 SetLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2849 Ext2ReferXcb(&Vcb
->NumOfMcb
);
2851 DEBUG(DL_RES
, ( "Ext2LinkHeadMcb: %wZ already linked.\n",
2854 ExReleaseResourceLite(&Vcb
->McbLock
);
2857 /* Unlink Mcb from Vcb->McbList queue */
2860 Ext2UnlinkMcb(PEXT2_VCB Vcb
, PEXT2_MCB Mcb
)
2862 if (Mcb
->Inode
.i_ino
== EXT2_ROOT_INO
) {
2866 ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, TRUE
);
2868 if (IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
)) {
2869 RemoveEntryList(&(Mcb
->Link
));
2870 ClearLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2871 Ext2DerefXcb(&Vcb
->NumOfMcb
);
2873 DEBUG(DL_RES
, ( "Ext2UnlinkMcb: %wZ already unlinked.\n",
2876 ExReleaseResourceLite(&Vcb
->McbLock
);
2879 /* get the first Mcb record in Vcb->McbList */
2882 Ext2FirstUnusedMcb(PEXT2_VCB Vcb
, BOOLEAN Wait
, ULONG Number
)
2884 PEXT2_MCB Head
= NULL
;
2885 PEXT2_MCB Tail
= NULL
;
2886 PEXT2_MCB Mcb
= NULL
;
2887 PLIST_ENTRY List
= NULL
;
2890 if (!ExAcquireResourceExclusiveLite(&Vcb
->McbLock
, Wait
)) {
2896 if (!IsListEmpty(&Vcb
->McbList
)) {
2898 while (i
++ < Vcb
->NumOfMcb
) {
2900 List
= RemoveHeadList(&Vcb
->McbList
);
2901 Mcb
= CONTAINING_RECORD(List
, EXT2_MCB
, Link
);
2902 ASSERT(IsFlagOn(Mcb
->Flags
, MCB_VCB_LINK
));
2904 if (Mcb
->Fcb
== NULL
&& !IsMcbRoot(Mcb
) &&
2905 Mcb
->Refercount
== 0 &&
2906 (Mcb
->Child
== NULL
|| IsMcbSymLink(Mcb
))) {
2908 Ext2RemoveMcb(Vcb
, Mcb
);
2909 ClearLongFlag(Mcb
->Flags
, MCB_VCB_LINK
);
2910 Ext2DerefXcb(&Vcb
->NumOfMcb
);
2912 /* attach all Mcb into a chain*/
2914 ASSERT(Tail
!= NULL
);
2924 InsertTailList(&Vcb
->McbList
, &Mcb
->Link
);
2930 ExReleaseResourceLite(&Vcb
->McbLock
);
2936 /* Reaper thread to release unused Mcb blocks */
2942 BOOLEAN GlobalAcquired
= FALSE
;
2944 BOOLEAN DidNothing
= TRUE
;
2945 BOOLEAN LastState
= TRUE
;
2948 PLIST_ENTRY List
= NULL
;
2949 LARGE_INTEGER Timeout
;
2951 PEXT2_VCB Vcb
= NULL
;
2952 PEXT2_MCB Mcb
= NULL
;
2958 /* wake up DirverEntry */
2959 KeSetEvent(&Ext2Global
->Reaper
.Engine
, 0, FALSE
);
2961 /* now process looping */
2966 /* calculate how long we need wait */
2967 if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 128)) {
2968 Timeout
.QuadPart
= (LONGLONG
)-1000*1000; /* 0.1 second */
2969 NumOfMcbs
= Ext2Global
->MaxDepth
* 4;
2971 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 32)) {
2972 Timeout
.QuadPart
= (LONGLONG
)-1000*1000*5; /* 0.5 second */
2973 NumOfMcbs
= Ext2Global
->MaxDepth
* 2;
2975 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 8)) {
2976 Timeout
.QuadPart
= (LONGLONG
)-1000*1000*10; /* 1 second */
2977 NumOfMcbs
= Ext2Global
->MaxDepth
;
2978 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (((ULONG
)Ext2Global
->MaxDepth
) * 2)) {
2979 Timeout
.QuadPart
= (LONGLONG
)-2*1000*1000*10; /* 2 second */
2980 NumOfMcbs
= Ext2Global
->MaxDepth
/ 4;
2981 } else if (Ext2Global
->PerfStat
.Current
.Mcb
> (ULONG
)Ext2Global
->MaxDepth
) {
2982 Timeout
.QuadPart
= (LONGLONG
)-4*1000*1000*10; /* 4 seconds */
2983 NumOfMcbs
= Ext2Global
->MaxDepth
/ 8;
2984 } else if (DidNothing
) {
2985 Timeout
.QuadPart
= (LONGLONG
)-8*1000*1000*10; /* 8 seconds */
2987 Timeout
.QuadPart
*= 2;
2989 NumOfMcbs
= Ext2Global
->MaxDepth
/ 16;
2991 Timeout
.QuadPart
= (LONGLONG
)-5*1000*1000*10; /* 5 seconds */
2993 Timeout
.QuadPart
*= 2;
2995 NumOfMcbs
= Ext2Global
->MaxDepth
/ 32;
3001 LastState
= DidNothing
;
3003 /* wait until it is waken or it times out */
3004 KeWaitForSingleObject(
3005 &(Ext2Global
->Reaper
.Wait
),
3014 /* acquire global exclusive lock */
3015 if (!ExAcquireResourceSharedLite(&Ext2Global
->Resource
, WaitLock
)) {
3018 GlobalAcquired
= TRUE
;
3020 /* search all Vcb to get unused resources freed to system */
3021 for (List
= Ext2Global
->VcbList
.Flink
;
3022 List
!= &(Ext2Global
->VcbList
);
3023 List
= List
->Flink
) {
3025 Vcb
= CONTAINING_RECORD(List
, EXT2_VCB
, Next
);
3027 Mcb
= Ext2FirstUnusedMcb(Vcb
, WaitLock
, NumOfMcbs
);
3029 PEXT2_MCB Next
= Mcb
->Next
;
3030 DEBUG(DL_RES
, ( "Ext2ReaperThread: releasing Mcb (%p): %wZ"
3031 " Total: %xh\n", Mcb
, &Mcb
->FullName
,
3032 Ext2Global
->PerfStat
.Current
.Mcb
));
3033 Ext2FreeMcb(Vcb
, Mcb
);
3035 LastState
= DidNothing
= FALSE
;
3039 if (GlobalAcquired
) {
3040 ExReleaseResourceLite(&Ext2Global
->Resource
);
3041 GlobalAcquired
= FALSE
;
3047 if (GlobalAcquired
) {
3048 ExReleaseResourceLite(&Ext2Global
->Resource
);
3052 PsTerminateSystemThread(STATUS_SUCCESS
);
3057 Ext2StartReaperThread()
3059 NTSTATUS status
= STATUS_SUCCESS
;
3060 OBJECT_ATTRIBUTES oa
;
3063 /* initialize wait event */
3065 &Ext2Global
->Reaper
.Wait
,
3066 SynchronizationEvent
, FALSE
3070 InitializeObjectAttributes(
3073 OBJ_CASE_INSENSITIVE
|
3079 /* start a new system thread */
3080 status
= PsCreateSystemThread(
3090 if (NT_SUCCESS(status
)) {