Create the AHCI branch for Aman's work
[reactos.git] / drivers / filesystems / reiserfs / src / memory.c
1 /*
2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
4 * FILE: memory.c
5 * PURPOSE:
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
7 * HOMEPAGE:
8 * UPDATE HISTORY:
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "rfsd.h"
14
15 /* GLOBALS ***************************************************************/
16
17 extern PRFSD_GLOBAL RfsdGlobal;
18
19 /* DEFINITIONS *************************************************************/
20
21 #ifdef ALLOC_PRAGMA
22 #pragma alloc_text(PAGE, RfsdAllocateIrpContext)
23 #pragma alloc_text(PAGE, RfsdFreeIrpContext)
24 #pragma alloc_text(PAGE, RfsdAllocateFcb)
25 #pragma alloc_text(PAGE, RfsdFreeFcb)
26 #pragma alloc_text(PAGE, RfsdAllocateMcb)
27 #pragma alloc_text(PAGE, RfsdSearchMcbTree)
28 #pragma alloc_text(PAGE, RfsdSearchMcb)
29 #pragma alloc_text(PAGE, RfsdGetFullFileName)
30 #pragma alloc_text(PAGE, RfsdRefreshMcb)
31 #pragma alloc_text(PAGE, RfsdAddMcbNode)
32 #pragma alloc_text(PAGE, RfsdDeleteMcbNode)
33 #pragma alloc_text(PAGE, RfsdFreeMcbTree)
34 #if !RFSD_READ_ONLY
35 #pragma alloc_text(PAGE, RfsdCheckBitmapConsistency)
36 #pragma alloc_text(PAGE, RfsdCheckSetBlock)
37 #endif // !RFSD_READ_ONLY
38 #pragma alloc_text(PAGE, RfsdInitializeVcb)
39 #pragma alloc_text(PAGE, RfsdFreeCcb)
40 #pragma alloc_text(PAGE, RfsdAllocateCcb)
41 #pragma alloc_text(PAGE, RfsdFreeVcb)
42 #pragma alloc_text(PAGE, RfsdCreateFcbFromMcb)
43 #pragma alloc_text(PAGE, RfsdSyncUninitializeCacheMap)
44 #endif
45
46 __drv_mustHoldCriticalRegion
47 PRFSD_IRP_CONTEXT
48 RfsdAllocateIrpContext (IN PDEVICE_OBJECT DeviceObject,
49 IN PIRP Irp )
50 {
51 PIO_STACK_LOCATION IoStackLocation;
52 PRFSD_IRP_CONTEXT IrpContext;
53
54 PAGED_CODE();
55
56 ASSERT(DeviceObject != NULL);
57 ASSERT(Irp != NULL);
58
59 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
60
61 ExAcquireResourceExclusiveLite(
62 &RfsdGlobal->LAResource,
63 TRUE );
64
65 IrpContext = (PRFSD_IRP_CONTEXT) (
66 ExAllocateFromNPagedLookasideList(
67 &(RfsdGlobal->RfsdIrpContextLookasideList)));
68
69 ExReleaseResourceForThreadLite(
70 &RfsdGlobal->LAResource,
71 ExGetCurrentResourceThread() );
72
73 if (IrpContext == NULL) {
74
75 IrpContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(RFSD_IRP_CONTEXT), RFSD_POOL_TAG);
76
77 //
78 // Zero out the irp context and indicate that it is from pool and
79 // not region allocated
80 //
81
82 RtlZeroMemory(IrpContext, sizeof(RFSD_IRP_CONTEXT));
83
84 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL);
85
86 } else {
87
88 //
89 // Zero out the irp context and indicate that it is from zone and
90 // not pool allocated
91 //
92
93 RtlZeroMemory(IrpContext, sizeof(RFSD_IRP_CONTEXT) );
94 }
95
96 if (!IrpContext) {
97 return NULL;
98 }
99
100 IrpContext->Identifier.Type = RFSDICX;
101 IrpContext->Identifier.Size = sizeof(RFSD_IRP_CONTEXT);
102
103 IrpContext->Irp = Irp;
104
105 IrpContext->MajorFunction = IoStackLocation->MajorFunction;
106 IrpContext->MinorFunction = IoStackLocation->MinorFunction;
107
108 IrpContext->DeviceObject = DeviceObject;
109
110 IrpContext->FileObject = IoStackLocation->FileObject;
111
112 if (IrpContext->FileObject != NULL) {
113 IrpContext->RealDevice = IrpContext->FileObject->DeviceObject;
114 } else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {
115 if (IoStackLocation->Parameters.MountVolume.Vpb) {
116 IrpContext->RealDevice =
117 IoStackLocation->Parameters.MountVolume.Vpb->RealDevice;
118 }
119 }
120
121 if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
122 IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
123 IrpContext->MajorFunction == IRP_MJ_SHUTDOWN) {
124 IrpContext->IsSynchronous = TRUE;
125 } else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP ||
126 IrpContext->MajorFunction == IRP_MJ_CLOSE) {
127 IrpContext->IsSynchronous = FALSE;
128 }
129 #if (_WIN32_WINNT >= 0x0500)
130 else if (IrpContext->MajorFunction == IRP_MJ_PNP) {
131 if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {
132 IrpContext->IsSynchronous = TRUE;
133 } else {
134 IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
135 }
136 }
137 #endif //(_WIN32_WINNT >= 0x0500)
138 else {
139 IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
140 }
141
142 #if 0
143 //
144 // Temporary workaround for a bug in close that makes it reference a
145 // fileobject when it is no longer valid.
146 //
147 if (IrpContext->MajorFunction == IRP_MJ_CLOSE) {
148 IrpContext->IsSynchronous = TRUE;
149 }
150 #endif
151
152 IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
153
154 IrpContext->ExceptionInProgress = FALSE;
155
156 return IrpContext;
157 }
158
159 NTSTATUS
160 RfsdCompleteIrpContext (
161 IN PRFSD_IRP_CONTEXT IrpContext,
162 IN NTSTATUS Status )
163 {
164 PIRP Irp = NULL;
165 BOOLEAN bPrint;
166
167 Irp = IrpContext->Irp;
168
169 if (Irp != NULL) {
170
171 if (NT_ERROR(Status)) {
172 Irp->IoStatus.Information = 0;
173 }
174
175 Irp->IoStatus.Status = Status;
176 bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
177
178 RfsdCompleteRequest(
179 Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)?
180 IO_DISK_INCREMENT : IO_NO_INCREMENT) );
181
182 IrpContext->Irp = NULL;
183 }
184
185 RfsdFreeIrpContext(IrpContext);
186
187 return Status;
188 }
189
190 __drv_mustHoldCriticalRegion
191 VOID
192 RfsdFreeIrpContext (IN PRFSD_IRP_CONTEXT IrpContext)
193 {
194 PAGED_CODE();
195
196 ASSERT(IrpContext != NULL);
197
198 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
199 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
200
201 RfsdUnpinRepinnedBcbs(IrpContext);
202
203 // Return the Irp context record to the region or to pool depending on
204 // its flag
205
206 if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL)) {
207
208 IrpContext->Identifier.Type = 0;
209 IrpContext->Identifier.Size = 0;
210
211 ExFreePool( IrpContext );
212
213 } else {
214
215 IrpContext->Identifier.Type = 0;
216 IrpContext->Identifier.Size = 0;
217
218 ExAcquireResourceExclusiveLite(
219 &RfsdGlobal->LAResource,
220 TRUE );
221
222 ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdIrpContextLookasideList), IrpContext);
223
224 ExReleaseResourceForThreadLite(
225 &RfsdGlobal->LAResource,
226 ExGetCurrentResourceThread() );
227
228 }
229 }
230
231 VOID
232 RfsdRepinBcb (
233 IN PRFSD_IRP_CONTEXT IrpContext,
234 IN PBCB Bcb
235 )
236 {
237 PRFSD_REPINNED_BCBS Repinned;
238
239 Repinned = &IrpContext->Repinned;
240
241 return;
242
243 #if 0
244
245 ULONG i;
246
247 while (Repinned) {
248
249 for (i = 0; i < RFSD_REPINNED_BCBS_ARRAY_SIZE; i += 1) {
250 if (Repinned->Bcb[i] == Bcb) {
251 return;
252 }
253 }
254
255 Repinned = Repinned->Next;
256 }
257
258 while (TRUE) {
259
260 for (i = 0; i < RFSD_REPINNED_BCBS_ARRAY_SIZE; i += 1) {
261 if (Repinned->Bcb[i] == Bcb) {
262 return;
263 }
264
265 if (Repinned->Bcb[i] == NULL) {
266 Repinned->Bcb[i] = Bcb;
267 CcRepinBcb( Bcb );
268
269 return;
270 }
271 }
272
273 if (Repinned->Next == NULL) {
274 Repinned->Next = ExAllocatePoolWithTag(PagedPool, sizeof(RFSD_REPINNED_BCBS), RFSD_POOL_TAG);
275 RtlZeroMemory( Repinned->Next, sizeof(RFSD_REPINNED_BCBS) );
276 }
277
278 Repinned = Repinned->Next;
279 }
280
281 #endif
282
283 }
284
285 VOID
286 RfsdUnpinRepinnedBcbs (
287 IN PRFSD_IRP_CONTEXT IrpContext
288 )
289 {
290 IO_STATUS_BLOCK RaiseIosb;
291 PRFSD_REPINNED_BCBS Repinned;
292 BOOLEAN WriteThroughToDisk;
293 PFILE_OBJECT FileObject = NULL;
294 BOOLEAN ForceVerify = FALSE;
295 ULONG i;
296
297 Repinned = &IrpContext->Repinned;
298 RaiseIosb.Status = STATUS_SUCCESS;
299
300 WriteThroughToDisk = (BOOLEAN) (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
301 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY));
302
303 while (Repinned != NULL) {
304 for (i = 0; i < RFSD_REPINNED_BCBS_ARRAY_SIZE; i += 1) {
305 if (Repinned->Bcb[i] != NULL) {
306 IO_STATUS_BLOCK Iosb;
307
308 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
309
310 if ( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) ) {
311 FileObject = CcGetFileObjectFromBcb( Repinned->Bcb[i] );
312 }
313
314 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
315
316 CcUnpinRepinnedBcb( Repinned->Bcb[i],
317 WriteThroughToDisk,
318 &Iosb );
319
320 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
321
322 if ( !NT_SUCCESS(Iosb.Status) ) {
323 if (RaiseIosb.Status == STATUS_SUCCESS) {
324 RaiseIosb = Iosb;
325 }
326
327 if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) &&
328 (IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
329 (IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
330 (IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION)) {
331
332 CcPurgeCacheSection( FileObject->SectionObjectPointer,
333 NULL,
334 0,
335 FALSE );
336
337 ForceVerify = TRUE;
338 }
339 }
340
341 Repinned->Bcb[i] = NULL;
342
343 } else {
344
345 break;
346 }
347 }
348
349 if (Repinned != &IrpContext->Repinned)
350 {
351 PRFSD_REPINNED_BCBS Saved;
352
353 Saved = Repinned->Next;
354 ExFreePool( Repinned );
355 Repinned = Saved;
356
357 } else {
358
359 Repinned = Repinned->Next;
360 IrpContext->Repinned.Next = NULL;
361 }
362 }
363
364 if (!NT_SUCCESS(RaiseIosb.Status)) {
365
366 DbgBreak();
367
368 if (ForceVerify && FileObject) {
369 SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
370 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
371 FileObject->DeviceObject );
372 }
373
374 IrpContext->Irp->IoStatus = RaiseIosb;
375 RfsdNormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status );
376 }
377
378 return;
379 }
380
381 __drv_mustHoldCriticalRegion
382 PRFSD_FCB
383 RfsdAllocateFcb (IN PRFSD_VCB Vcb,
384 IN PRFSD_MCB RfsdMcb,
385 IN PRFSD_INODE Inode )
386 {
387 PRFSD_FCB Fcb;
388
389 PAGED_CODE();
390
391 ExAcquireResourceExclusiveLite(
392 &RfsdGlobal->LAResource,
393 TRUE );
394
395 Fcb = (PRFSD_FCB) ExAllocateFromNPagedLookasideList(
396 &(RfsdGlobal->RfsdFcbLookasideList));
397
398 ExReleaseResourceForThreadLite(
399 &RfsdGlobal->LAResource,
400 ExGetCurrentResourceThread() );
401
402 if (Fcb == NULL) {
403 Fcb = (PRFSD_FCB) ExAllocatePoolWithTag(NonPagedPool, sizeof(RFSD_FCB), RFSD_POOL_TAG);
404
405 RtlZeroMemory(Fcb, sizeof(RFSD_FCB));
406
407 SetFlag(Fcb->Flags, FCB_FROM_POOL);
408 } else {
409 RtlZeroMemory(Fcb, sizeof(RFSD_FCB));
410 }
411
412 if (!Fcb) {
413 return NULL;
414 }
415
416 Fcb->Identifier.Type = RFSDFCB;
417 Fcb->Identifier.Size = sizeof(RFSD_FCB);
418
419 FsRtlInitializeFileLock (
420 &Fcb->FileLockAnchor,
421 NULL,
422 NULL );
423
424 Fcb->OpenHandleCount = 0;
425 Fcb->ReferenceCount = 0;
426
427 Fcb->Vcb = Vcb;
428
429 #if DBG
430
431 Fcb->AnsiFileName.MaximumLength = (USHORT)
432 RfsdUnicodeToOEMSize(&(RfsdMcb->ShortName)) + 1;
433
434 Fcb->AnsiFileName.Buffer = (PUCHAR)
435 ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, RFSD_POOL_TAG);
436
437 if (!Fcb->AnsiFileName.Buffer) {
438 goto errorout;
439 }
440
441 RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);
442
443 RfsdUnicodeToOEM( &(Fcb->AnsiFileName),
444 &(RfsdMcb->ShortName));
445
446 #endif
447
448 RfsdMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
449
450 if (S_ISDIR(Inode->i_mode)) {
451 SetFlag(RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
452 }
453
454 if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
455 RfsdIsReadOnly(Inode->i_mode)) {
456 SetFlag(RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
457 }
458
459 Fcb->Inode = Inode;
460
461 Fcb->RfsdMcb = RfsdMcb;
462 RfsdMcb->RfsdFcb = Fcb;
463
464 RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));
465
466 Fcb->Header.NodeTypeCode = (USHORT) RFSDFCB;
467 Fcb->Header.NodeByteSize = sizeof(RFSD_FCB);
468 Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
469 Fcb->Header.Resource = &(Fcb->MainResource);
470 Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);
471
472 // NOTE: In EXT2, the low part was stored in i_size (a 32-bit value); the high part would be stored in the acl field...
473 // However, on ReiserFS, the i_size is a 64-bit value.
474 Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size;
475
476
477 Fcb->Header.AllocationSize.QuadPart =
478 CEILING_ALIGNED(Fcb->Header.FileSize.QuadPart, (ULONGLONG)Vcb->BlockSize);
479
480 Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
481
482 Fcb->SectionObject.DataSectionObject = NULL;
483 Fcb->SectionObject.SharedCacheMap = NULL;
484 Fcb->SectionObject.ImageSectionObject = NULL;
485
486 ExInitializeResourceLite(&(Fcb->MainResource));
487 ExInitializeResourceLite(&(Fcb->PagingIoResource));
488
489 InsertTailList(&Vcb->FcbList, &Fcb->Next);
490
491 #if DBG
492
493 ExAcquireResourceExclusiveLite(
494 &RfsdGlobal->CountResource,
495 TRUE );
496
497 RfsdGlobal->FcbAllocated++;
498
499 ExReleaseResourceForThreadLite(
500 &RfsdGlobal->CountResource,
501 ExGetCurrentResourceThread() );
502 #endif
503
504 return Fcb;
505
506 #if DBG
507 errorout:
508 #endif
509
510 if (Fcb) {
511
512 #if DBG
513 if (Fcb->AnsiFileName.Buffer)
514 ExFreePool(Fcb->AnsiFileName.Buffer);
515 #endif
516
517 if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) {
518
519 ExFreePool( Fcb );
520
521 } else {
522
523 ExAcquireResourceExclusiveLite(
524 &RfsdGlobal->LAResource,
525 TRUE );
526
527 ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdFcbLookasideList), Fcb);
528
529 ExReleaseResourceForThreadLite(
530 &RfsdGlobal->LAResource,
531 ExGetCurrentResourceThread() );
532 }
533
534 }
535
536 return NULL;
537 }
538
539 __drv_mustHoldCriticalRegion
540 VOID
541 RfsdFreeFcb (IN PRFSD_FCB Fcb)
542 {
543 PRFSD_VCB Vcb;
544
545 PAGED_CODE();
546
547 ASSERT(Fcb != NULL);
548
549 ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
550 (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
551
552 Vcb = Fcb->Vcb;
553
554 FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
555
556 ExDeleteResourceLite(&Fcb->MainResource);
557
558 ExDeleteResourceLite(&Fcb->PagingIoResource);
559
560 Fcb->RfsdMcb->RfsdFcb = NULL;
561
562 if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
563 if (Fcb->RfsdMcb) {
564 RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
565 RfsdFreeMcb(Fcb->RfsdMcb);
566 }
567 }
568
569 if (Fcb->LongName.Buffer) {
570 ExFreePool(Fcb->LongName.Buffer);
571 Fcb->LongName.Buffer = NULL;
572 }
573
574 #if DBG
575 ExFreePool(Fcb->AnsiFileName.Buffer);
576 #endif
577
578 ExFreePool(Fcb->Inode);
579
580 Fcb->Header.NodeTypeCode = (SHORT)0xCCCC;
581 Fcb->Header.NodeByteSize = (SHORT)0xC0C0;
582
583 if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) {
584
585 ExFreePool( Fcb );
586
587 } else {
588
589 ExAcquireResourceExclusiveLite(
590 &RfsdGlobal->LAResource,
591 TRUE );
592
593 ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdFcbLookasideList), Fcb);
594
595 ExReleaseResourceForThreadLite(
596 &RfsdGlobal->LAResource,
597 ExGetCurrentResourceThread() );
598 }
599
600 #if DBG
601
602 ExAcquireResourceExclusiveLite(
603 &RfsdGlobal->CountResource,
604 TRUE );
605
606 RfsdGlobal->FcbAllocated--;
607
608 ExReleaseResourceForThreadLite(
609 &RfsdGlobal->CountResource,
610 ExGetCurrentResourceThread() );
611 #endif
612
613 }
614
615 __drv_mustHoldCriticalRegion
616 PRFSD_CCB
617 RfsdAllocateCcb (VOID)
618 {
619 PRFSD_CCB Ccb;
620
621 PAGED_CODE();
622
623 ExAcquireResourceExclusiveLite(
624 &RfsdGlobal->LAResource,
625 TRUE );
626
627 Ccb = (PRFSD_CCB) (ExAllocateFromNPagedLookasideList( &(RfsdGlobal->RfsdCcbLookasideList)));
628
629 ExReleaseResourceForThreadLite(
630 &RfsdGlobal->LAResource,
631 ExGetCurrentResourceThread() );
632
633 if (Ccb == NULL) {
634 Ccb = (PRFSD_CCB) ExAllocatePoolWithTag(NonPagedPool, sizeof(RFSD_CCB), RFSD_POOL_TAG);
635
636 RtlZeroMemory(Ccb, sizeof(RFSD_CCB));
637
638 SetFlag(Ccb->Flags, CCB_FROM_POOL);
639 } else {
640 RtlZeroMemory(Ccb, sizeof(RFSD_CCB));
641 }
642
643 if (!Ccb) {
644 return NULL;
645 }
646
647 Ccb->Identifier.Type = RFSDCCB;
648 Ccb->Identifier.Size = sizeof(RFSD_CCB);
649
650 Ccb->CurrentByteOffset = 0;
651
652 Ccb->DirectorySearchPattern.Length = 0;
653 Ccb->DirectorySearchPattern.MaximumLength = 0;
654 Ccb->DirectorySearchPattern.Buffer = 0;
655
656 return Ccb;
657 }
658
659 __drv_mustHoldCriticalRegion
660 VOID
661 RfsdFreeCcb (IN PRFSD_CCB Ccb)
662 {
663 PAGED_CODE();
664
665 ASSERT(Ccb != NULL);
666
667 ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
668 (Ccb->Identifier.Size == sizeof(RFSD_CCB)));
669
670 if (Ccb->DirectorySearchPattern.Buffer != NULL) {
671 ExFreePool(Ccb->DirectorySearchPattern.Buffer);
672 }
673
674 if (FlagOn(Ccb->Flags, CCB_FROM_POOL)) {
675
676 ExFreePool( Ccb );
677
678 } else {
679
680 ExAcquireResourceExclusiveLite(
681 &RfsdGlobal->LAResource,
682 TRUE );
683
684 ExFreeToNPagedLookasideList(&(RfsdGlobal->RfsdCcbLookasideList), Ccb);
685
686 ExReleaseResourceForThreadLite(
687 &RfsdGlobal->LAResource,
688 ExGetCurrentResourceThread() );
689 }
690 }
691
692 __drv_mustHoldCriticalRegion
693 PRFSD_MCB
694 RfsdAllocateMcb (PRFSD_VCB Vcb, PUNICODE_STRING FileName, ULONG FileAttr)
695 {
696 PRFSD_MCB Mcb = NULL;
697 PLIST_ENTRY List = NULL;
698 ULONG Extra = 0;
699
700 PAGED_CODE();
701
702 #define MCB_NUM_SHIFT 0x04
703
704 if (RfsdGlobal->McbAllocated > (RfsdGlobal->MaxDepth << MCB_NUM_SHIFT))
705 Extra = RfsdGlobal->McbAllocated -
706 (RfsdGlobal->MaxDepth << MCB_NUM_SHIFT) +
707 RfsdGlobal->MaxDepth;
708
709 RfsdPrint((DBG_INFO,
710 "RfsdAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n",
711 RfsdGlobal->McbAllocated,
712 RfsdGlobal->MaxDepth << MCB_NUM_SHIFT,
713 RfsdGlobal->FcbAllocated,
714 FileName->Buffer));
715
716 List = Vcb->McbList.Flink;
717
718 while ((List != &(Vcb->McbList)) && (Extra > 0)) {
719 Mcb = CONTAINING_RECORD(List, RFSD_MCB, Link);
720 List = List->Flink;
721
722 if ((!RFSD_IS_ROOT_KEY(Mcb->Key)) && (Mcb->Child == NULL) &&
723 (Mcb->RfsdFcb == NULL) && (!IsMcbUsed(Mcb))) {
724 RfsdPrint((DBG_INFO, "RfsdAllocateMcb: Mcb %S will be freed.\n",
725 Mcb->ShortName.Buffer));
726
727 if (RfsdDeleteMcbNode(Vcb, Vcb->McbTree, Mcb)) {
728 RfsdFreeMcb(Mcb);
729
730 Extra--;
731 }
732 }
733 }
734
735 ExAcquireResourceExclusiveLite(
736 &RfsdGlobal->LAResource,
737 TRUE );
738
739 Mcb = (PRFSD_MCB) (ExAllocateFromPagedLookasideList(
740 &(RfsdGlobal->RfsdMcbLookasideList)));
741
742 ExReleaseResourceForThreadLite(
743 &RfsdGlobal->LAResource,
744 ExGetCurrentResourceThread() );
745
746 if (Mcb == NULL) {
747 Mcb = (PRFSD_MCB) ExAllocatePoolWithTag(PagedPool, sizeof(RFSD_MCB), RFSD_POOL_TAG);
748
749 RtlZeroMemory(Mcb, sizeof(RFSD_MCB));
750
751 SetFlag(Mcb->Flags, MCB_FROM_POOL);
752 } else {
753 RtlZeroMemory(Mcb, sizeof(RFSD_MCB));
754 }
755
756 if (!Mcb) {
757 return NULL;
758 }
759
760 Mcb->Identifier.Type = RFSDMCB;
761 Mcb->Identifier.Size = sizeof(RFSD_MCB);
762
763 if (FileName && FileName->Length) {
764
765 Mcb->ShortName.Length = FileName->Length;
766 Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2;
767
768 Mcb->ShortName.Buffer = ExAllocatePoolWithTag(PagedPool, Mcb->ShortName.MaximumLength, RFSD_POOL_TAG);
769
770 if (!Mcb->ShortName.Buffer)
771 goto errorout;
772
773 RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength);
774 RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length);
775 }
776
777 Mcb->FileAttr = FileAttr;
778
779 ExAcquireResourceExclusiveLite(
780 &RfsdGlobal->CountResource,
781 TRUE );
782
783 RfsdGlobal->McbAllocated++;
784
785 ExReleaseResourceForThreadLite(
786 &RfsdGlobal->CountResource,
787 ExGetCurrentResourceThread() );
788
789 return Mcb;
790
791 errorout:
792
793 if (Mcb) {
794
795 if (Mcb->ShortName.Buffer)
796 ExFreePool(Mcb->ShortName.Buffer);
797
798 if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) {
799
800 ExFreePool( Mcb );
801
802 } else {
803
804 ExAcquireResourceExclusiveLite(
805 &RfsdGlobal->LAResource,
806 TRUE );
807
808 ExFreeToPagedLookasideList(&(RfsdGlobal->RfsdMcbLookasideList), Mcb);
809
810 ExReleaseResourceForThreadLite(
811 &RfsdGlobal->LAResource,
812 ExGetCurrentResourceThread() );
813 }
814 }
815
816 return NULL;
817 }
818
819 __drv_mustHoldCriticalRegion
820 VOID
821 RfsdFreeMcb (IN PRFSD_MCB Mcb)
822 {
823 #ifndef __REACTOS__
824 PRFSD_MCB Parent = Mcb->Parent;
825 #endif
826
827 ASSERT(Mcb != NULL);
828
829 ASSERT((Mcb->Identifier.Type == RFSDMCB) &&
830 (Mcb->Identifier.Size == sizeof(RFSD_MCB)));
831
832 RfsdPrint((DBG_INFO, "RfsdFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer));
833
834 if (Mcb->ShortName.Buffer)
835 ExFreePool(Mcb->ShortName.Buffer);
836
837 if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) {
838
839 ExFreePool( Mcb );
840
841 } else {
842
843 ExAcquireResourceExclusiveLite(
844 &RfsdGlobal->LAResource,
845 TRUE );
846
847 ExFreeToPagedLookasideList(&(RfsdGlobal->RfsdMcbLookasideList), Mcb);
848
849 ExReleaseResourceForThreadLite(
850 &RfsdGlobal->LAResource,
851 ExGetCurrentResourceThread() );
852 }
853
854 ExAcquireResourceExclusiveLite(
855 &RfsdGlobal->CountResource,
856 TRUE );
857
858 RfsdGlobal->McbAllocated--;
859
860 ExReleaseResourceForThreadLite(
861 &RfsdGlobal->CountResource,
862 ExGetCurrentResourceThread() );
863 }
864
865 __drv_mustHoldCriticalRegion
866 PRFSD_FCB
867 RfsdCreateFcbFromMcb(PRFSD_VCB Vcb, PRFSD_MCB Mcb)
868 {
869 PRFSD_FCB Fcb = NULL;
870 RFSD_INODE RfsdIno;
871
872 PAGED_CODE();
873
874 if (Mcb->RfsdFcb)
875 return Mcb->RfsdFcb;
876
877 if (RfsdLoadInode(Vcb, &(Mcb->Key), &RfsdIno)) {
878 PRFSD_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, sizeof(RFSD_INODE), RFSD_POOL_TAG);
879 if (!pTmpInode) {
880 goto errorout;
881 }
882
883 RtlCopyMemory(pTmpInode, &RfsdIno, sizeof(RFSD_INODE));
884 Fcb = RfsdAllocateFcb(Vcb, Mcb, pTmpInode);
885 if (!Fcb) {
886 ExFreePool(pTmpInode);
887 }
888 }
889
890 errorout:
891
892 return Fcb;
893 }
894
895 BOOLEAN
896 RfsdGetFullFileName(PRFSD_MCB Mcb, PUNICODE_STRING FileName)
897 {
898 USHORT Length = 0;
899 PRFSD_MCB TmpMcb = Mcb;
900 PUNICODE_STRING FileNames[256];
901 SHORT Count = 0 , i = 0, j = 0;
902
903 PAGED_CODE();
904
905 while(TmpMcb && Count < 256) {
906 if (RFSD_IS_ROOT_KEY(TmpMcb->Key))
907 break;
908
909 FileNames[Count++] = &TmpMcb->ShortName;
910 Length += (2 + TmpMcb->ShortName.Length);
911
912 TmpMcb = TmpMcb->Parent;
913 }
914
915 if (Count >= 256)
916 return FALSE;
917
918 if (Count ==0)
919 Length = 2;
920
921 FileName->Length = Length;
922 FileName->MaximumLength = Length + 2;
923 FileName->Buffer = ExAllocatePoolWithTag(PagedPool, Length + 2, RFSD_POOL_TAG);
924
925 if (!FileName->Buffer) {
926 return FALSE;
927 }
928
929 RtlZeroMemory(FileName->Buffer, FileName->MaximumLength);
930
931 if (Count == 0) {
932 FileName->Buffer[0] = L'\\';
933 return TRUE;
934 }
935
936 for (i = Count - 1; i >= 0 && j < (SHORT)(FileName->MaximumLength); i--) {
937 FileName->Buffer[j++] = L'\\';
938
939 RtlCopyMemory( &(FileName->Buffer[j]),
940 FileNames[i]->Buffer,
941 FileNames[i]->Length );
942
943 j += FileNames[i]->Length / 2;
944 }
945
946 return TRUE;
947 }
948
949 PRFSD_MCB
950 RfsdSearchMcbTree( PRFSD_VCB Vcb,
951 PRFSD_MCB RfsdMcb,
952 PRFSD_KEY_IN_MEMORY Key)
953 {
954 PRFSD_MCB Mcb = NULL;
955 PLIST_ENTRY List = NULL;
956 BOOLEAN bFind = FALSE;
957
958 PAGED_CODE();
959
960 List = Vcb->McbList.Flink;
961
962 while ((!bFind) && (List != &(Vcb->McbList))) {
963 Mcb = CONTAINING_RECORD(List, RFSD_MCB, Link);
964 List = List->Flink;
965
966 if (CompareShortKeys(&(Mcb->Key), Key) == RFSD_KEYS_MATCH) {
967 bFind = TRUE;
968 break;
969 }
970 }
971
972 if (bFind) {
973 ASSERT(Mcb != NULL);
974 RfsdRefreshMcb(Vcb, Mcb);
975 } else {
976 Mcb = NULL;
977 }
978
979 return Mcb;
980 }
981
982 /**
983 Returns NULL is the parent has no child, or if we search through the child's brothers and hit a NULL
984 Otherwise, returns the MCB of one of the the parent's children, which matches FileName.
985 */
986 PRFSD_MCB
987 RfsdSearchMcb( PRFSD_VCB Vcb,
988 PRFSD_MCB Parent,
989 PUNICODE_STRING FileName )
990 {
991 PRFSD_MCB TmpMcb = Parent->Child;
992
993 PAGED_CODE();
994
995 while (TmpMcb) {
996 if (!RtlCompareUnicodeString(
997 &(TmpMcb->ShortName),
998 FileName, TRUE ))
999 break;
1000
1001 TmpMcb = TmpMcb->Next;
1002 }
1003
1004 if (TmpMcb) {
1005 RfsdRefreshMcb(Vcb, TmpMcb);
1006 }
1007
1008 return TmpMcb;
1009 }
1010
1011 VOID
1012 RfsdRefreshMcb(PRFSD_VCB Vcb, PRFSD_MCB Mcb)
1013 {
1014 PAGED_CODE();
1015
1016 ASSERT (IsFlagOn(Mcb->Flags, MCB_IN_TREE));
1017
1018 RemoveEntryList(&(Mcb->Link));
1019 InsertTailList(&(Vcb->McbList), &(Mcb->Link));
1020 }
1021
1022 VOID
1023 RfsdAddMcbNode(PRFSD_VCB Vcb, PRFSD_MCB Parent, PRFSD_MCB Child)
1024 {
1025 PRFSD_MCB TmpMcb = Parent->Child;
1026
1027 PAGED_CODE();
1028
1029 if(IsFlagOn(Child->Flags, MCB_IN_TREE)) {
1030 DbgBreak();
1031 RfsdPrint((DBG_ERROR, "RfsdAddMcbNode: Child Mcb is alreay in the tree.\n"));
1032 return;
1033 }
1034
1035 if (TmpMcb) {
1036 ASSERT(TmpMcb->Parent == Parent);
1037
1038 while (TmpMcb->Next) {
1039 TmpMcb = TmpMcb->Next;
1040 ASSERT(TmpMcb->Parent == Parent);
1041 }
1042
1043 TmpMcb->Next = Child;
1044 Child->Parent = Parent;
1045 Child->Next = NULL;
1046 } else {
1047 Parent->Child = Child;
1048 Child->Parent = Parent;
1049 Child->Next = NULL;
1050 }
1051
1052 InsertTailList(&(Vcb->McbList), &(Child->Link));
1053 SetFlag(Child->Flags, MCB_IN_TREE);
1054 }
1055
1056 BOOLEAN
1057 RfsdDeleteMcbNode(PRFSD_VCB Vcb, PRFSD_MCB McbTree, PRFSD_MCB RfsdMcb)
1058 {
1059 PRFSD_MCB TmpMcb;
1060
1061 PAGED_CODE();
1062
1063 if(!IsFlagOn(RfsdMcb->Flags, MCB_IN_TREE)) {
1064 return TRUE;
1065 }
1066
1067 if (RfsdMcb->Parent) {
1068 if (RfsdMcb->Parent->Child == RfsdMcb) {
1069 RfsdMcb->Parent->Child = RfsdMcb->Next;
1070 } else {
1071 TmpMcb = RfsdMcb->Parent->Child;
1072
1073 while (TmpMcb && TmpMcb->Next != RfsdMcb)
1074 TmpMcb = TmpMcb->Next;
1075
1076 if (TmpMcb) {
1077 TmpMcb->Next = RfsdMcb->Next;
1078 } else {
1079 // error
1080 return FALSE;
1081 }
1082 }
1083 } else if (RfsdMcb->Child) {
1084 return FALSE;
1085 }
1086
1087 RemoveEntryList(&(RfsdMcb->Link));
1088 ClearFlag(RfsdMcb->Flags, MCB_IN_TREE);
1089
1090 return TRUE;
1091 }
1092
1093 __drv_mustHoldCriticalRegion
1094 VOID RfsdFreeMcbTree(PRFSD_MCB McbTree)
1095 {
1096 PAGED_CODE();
1097
1098 if (!McbTree)
1099 return;
1100
1101 if (McbTree->Child) {
1102 RfsdFreeMcbTree(McbTree->Child);
1103 }
1104
1105 if (McbTree->Next) {
1106
1107 PRFSD_MCB Current;
1108 PRFSD_MCB Next;
1109
1110 Current = McbTree->Next;
1111
1112 while (Current) {
1113
1114 Next = Current->Next;
1115
1116 if (Current->Child) {
1117 RfsdFreeMcbTree(Current->Child);
1118 }
1119
1120 RfsdFreeMcb(Current);
1121 Current = Next;
1122 }
1123 }
1124
1125 RfsdFreeMcb(McbTree);
1126 }
1127
1128 #if !RFSD_READ_ONLY
1129
1130 BOOLEAN
1131 RfsdCheckSetBlock(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb, ULONG Block)
1132 {
1133 ULONG Group, dwBlk, Length;
1134
1135 RTL_BITMAP BlockBitmap;
1136 PVOID BitmapCache;
1137 PBCB BitmapBcb;
1138
1139 LARGE_INTEGER Offset;
1140
1141 BOOLEAN bModified = FALSE;
1142
1143 PAGED_CODE();
1144 #if 0
1145 Group = (Block - RFSD_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
1146
1147 dwBlk = (Block - RFSD_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
1148
1149
1150 Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
1151 Offset.QuadPart = Offset.QuadPart * Vcb->GroupDesc[Group].bg_block_bitmap;
1152
1153 if (Group == Vcb->NumOfGroups - 1) {
1154 Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
1155
1156 /* s_blocks_count is integer multiple of s_blocks_per_group */
1157 if (Length == 0)
1158 Length = BLOCKS_PER_GROUP;
1159 } else {
1160 Length = BLOCKS_PER_GROUP;
1161 }
1162
1163 if (dwBlk >= Length)
1164 return FALSE;
1165
1166 if (!CcPinRead( Vcb->StreamObj,
1167 &Offset,
1168 Vcb->BlockSize,
1169 PIN_WAIT,
1170 &BitmapBcb,
1171 &BitmapCache ) ) {
1172
1173 RfsdPrint((DBG_ERROR, "RfsdDeleteBlock: PinReading error ...\n"));
1174 return FALSE;
1175 }
1176
1177 RtlInitializeBitMap( &BlockBitmap,
1178 BitmapCache,
1179 Length );
1180
1181 if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) {
1182 DbgBreak();
1183 RtlSetBits(&BlockBitmap, dwBlk, 1);
1184 bModified = TRUE;
1185 }
1186
1187 if (bModified) {
1188
1189 CcSetDirtyPinnedData(BitmapBcb, NULL );
1190
1191 RfsdRepinBcb(IrpContext, BitmapBcb);
1192
1193 RfsdAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
1194 }
1195
1196 {
1197 CcUnpinData(BitmapBcb);
1198 BitmapBcb = NULL;
1199 BitmapCache = NULL;
1200
1201 RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
1202 }
1203 #endif // 0
1204 return (!bModified);
1205 }
1206
1207 BOOLEAN
1208 RfsdCheckBitmapConsistency(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb)
1209 {
1210 ULONG i, j, InodeBlocks;
1211
1212 PAGED_CODE();
1213 #if 0
1214 for (i = 0; i < Vcb->NumOfGroups; i++) {
1215
1216 RfsdCheckSetBlock(IrpContext, Vcb, Vcb->GroupDesc[i].bg_block_bitmap);
1217 RfsdCheckSetBlock(IrpContext, Vcb, Vcb->GroupDesc[i].bg_inode_bitmap);
1218
1219
1220 if (i == Vcb->NumOfGroups - 1) {
1221 InodeBlocks = ((INODES_COUNT % INODES_PER_GROUP) *
1222 sizeof(RFSD_INODE) + Vcb->BlockSize - 1) /
1223 (Vcb->BlockSize);
1224 } else {
1225 InodeBlocks = (INODES_PER_GROUP * sizeof(RFSD_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize);
1226 }
1227
1228 for (j = 0; j < InodeBlocks; j++ )
1229 RfsdCheckSetBlock(IrpContext, Vcb, Vcb->GroupDesc[i].bg_inode_table + j);
1230 }
1231 #endif // 0
1232 return TRUE;
1233 }
1234
1235 #endif // !RFSD_READ_ONLY
1236
1237 VOID
1238 RfsdInsertVcb(PRFSD_VCB Vcb)
1239 {
1240 InsertTailList(&(RfsdGlobal->VcbList), &Vcb->Next);
1241 }
1242
1243 VOID
1244 RfsdRemoveVcb(PRFSD_VCB Vcb)
1245 {
1246 RemoveEntryList(&Vcb->Next);
1247 }
1248
1249 __drv_mustHoldCriticalRegion
1250 NTSTATUS
1251 RfsdInitializeVcb( IN PRFSD_IRP_CONTEXT IrpContext,
1252 IN PRFSD_VCB Vcb,
1253 IN PRFSD_SUPER_BLOCK RfsdSb,
1254 IN PDEVICE_OBJECT TargetDevice,
1255 IN PDEVICE_OBJECT VolumeDevice,
1256 IN PVPB Vpb )
1257 {
1258 BOOLEAN VcbResourceInitialized = FALSE;
1259 USHORT VolumeLabelLength;
1260 ULONG IoctlSize;
1261 BOOLEAN NotifySyncInitialized = FALSE;
1262 LONGLONG DiskSize;
1263 LONGLONG PartSize;
1264 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1265 UNICODE_STRING RootNode;
1266 USHORT Buffer[2];
1267 ULONG ChangeCount;
1268 char s_volume_name[16] = "ReiserFS\0"; /* volume name */ // FUTURE: pull in from v2 superblock, if available
1269 int templen;
1270
1271 PAGED_CODE();
1272
1273 _SEH2_TRY {
1274
1275 if (!Vpb) {
1276
1277 Status = STATUS_DEVICE_NOT_READY;
1278 _SEH2_LEAVE;
1279 }
1280
1281 RfsdPrint((DBG_ERROR, "RfsdInitializeVcb: Flink = %xh McbList = %xh\n",
1282 Vcb->McbList.Flink, &(Vcb->McbList.Flink)));
1283
1284 #if RFSD_READ_ONLY
1285 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1286 #endif //READ_ONLY
1287
1288 if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) {
1289 SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA);
1290 }
1291
1292 if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) {
1293 SetFlag(Vcb->Flags, VCB_FLOPPY_DISK);
1294 }
1295
1296 /*if (IsFlagOn(RfsdGlobal->Flags, RFSD_SUPPORT_WRITING)) {
1297 if ((IsFlagOn(RfsdSb->s_feature_incompat, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) ||
1298 IsFlagOn(RfsdSb->s_feature_incompat, EXT3_FEATURE_INCOMPAT_RECOVER) ||
1299 IsFlagOn(RfsdSb->s_feature_compat, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) ) {
1300 if(IsFlagOn(RfsdGlobal->Flags, EXT3_FORCE_WRITING)) {
1301 ClearFlag(Vcb->Flags, VCB_READ_ONLY);
1302 } else {
1303 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1304 }
1305 } else {
1306 ClearFlag(Vcb->Flags, VCB_READ_ONLY);
1307 }
1308 } else {
1309 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1310 }*/
1311 // RFSD will be read only.
1312 SetFlag(Vcb->Flags, VCB_READ_ONLY);
1313
1314 ExInitializeResourceLite(&Vcb->MainResource);
1315 ExInitializeResourceLite(&Vcb->PagingIoResource);
1316
1317 ExInitializeResourceLite(&Vcb->McbResource);
1318
1319 VcbResourceInitialized = TRUE;
1320
1321 Vcb->Vpb = Vpb;
1322
1323 Vcb->RealDevice = Vpb->RealDevice;
1324 Vpb->DeviceObject = VolumeDevice;
1325
1326 {
1327 UNICODE_STRING LabelName;
1328 OEM_STRING OemName;
1329
1330
1331
1332 LabelName.MaximumLength = 16 * 2;
1333 LabelName.Length = 0;
1334 LabelName.Buffer = Vcb->Vpb->VolumeLabel;
1335
1336 RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength);
1337
1338 VolumeLabelLength = 16;
1339
1340 while( (VolumeLabelLength > 0) &&
1341 ((s_volume_name[VolumeLabelLength-1] == '\0') ||
1342 (s_volume_name[VolumeLabelLength-1] == ' ')) ) {
1343 VolumeLabelLength--;
1344 }
1345
1346 OemName.Buffer = s_volume_name;
1347 OemName.MaximumLength = 16;
1348 OemName.Length = VolumeLabelLength;
1349
1350 templen = RtlOemStringToUnicodeSize(&OemName);
1351
1352 Status = RfsdOEMToUnicode( &LabelName,
1353 &OemName );
1354
1355 if (!NT_SUCCESS(Status)) {
1356 _SEH2_LEAVE;
1357 }
1358
1359 Vpb->VolumeLabelLength = LabelName.Length;
1360 }
1361
1362 #if DISABLED
1363 Vpb->SerialNumber = ((ULONG*)RfsdSb->s_uuid)[0] + ((ULONG*)RfsdSb->s_uuid)[1] +
1364 ((ULONG*)RfsdSb->s_uuid)[2] + ((ULONG*)RfsdSb->s_uuid)[3];
1365 #endif
1366
1367 Vcb->StreamObj = IoCreateStreamFileObject( NULL, Vcb->Vpb->RealDevice);
1368
1369 if (Vcb->StreamObj) {
1370
1371 Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject);
1372 Vcb->StreamObj->Vpb = Vcb->Vpb;
1373 Vcb->StreamObj->ReadAccess = TRUE;
1374 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
1375 {
1376 Vcb->StreamObj->WriteAccess = TRUE;
1377 Vcb->StreamObj->DeleteAccess = TRUE;
1378 }
1379 else
1380 {
1381 Vcb->StreamObj->WriteAccess = TRUE;
1382 Vcb->StreamObj->DeleteAccess = TRUE;
1383 }
1384 Vcb->StreamObj->FsContext = (PVOID) Vcb;
1385 Vcb->StreamObj->FsContext2 = NULL;
1386 Vcb->StreamObj->Vpb = Vcb->Vpb;
1387
1388 SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1389 } else {
1390 _SEH2_LEAVE;
1391 }
1392
1393 InitializeListHead(&Vcb->FcbList);
1394
1395 InitializeListHead(&Vcb->NotifyList);
1396
1397 FsRtlNotifyInitializeSync(&Vcb->NotifySync);
1398
1399 NotifySyncInitialized = TRUE;
1400
1401 Vcb->DeviceObject = VolumeDevice;
1402
1403 Vcb->TargetDeviceObject = TargetDevice;
1404
1405 Vcb->OpenFileHandleCount = 0;
1406
1407 Vcb->ReferenceCount = 0;
1408
1409 Vcb->SuperBlock = RfsdSb;
1410
1411 Vcb->Header.NodeTypeCode = (USHORT) RFSDVCB;
1412 Vcb->Header.NodeByteSize = sizeof(RFSD_VCB);
1413 Vcb->Header.IsFastIoPossible = FastIoIsNotPossible;
1414 Vcb->Header.Resource = &(Vcb->MainResource);
1415 Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource);
1416
1417 Vcb->Vpb->SerialNumber = 'MATT';
1418
1419 DiskSize =
1420 Vcb->DiskGeometry.Cylinders.QuadPart *
1421 Vcb->DiskGeometry.TracksPerCylinder *
1422 Vcb->DiskGeometry.SectorsPerTrack *
1423 Vcb->DiskGeometry.BytesPerSector;
1424
1425 IoctlSize = sizeof(PARTITION_INFORMATION);
1426
1427 Status = RfsdDiskIoControl(
1428 TargetDevice,
1429 IOCTL_DISK_GET_PARTITION_INFO,
1430 NULL,
1431 0,
1432 &Vcb->PartitionInformation,
1433 &IoctlSize );
1434
1435 PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart;
1436
1437 if (!NT_SUCCESS(Status)) {
1438 Vcb->PartitionInformation.StartingOffset.QuadPart = 0;
1439
1440 Vcb->PartitionInformation.PartitionLength.QuadPart =
1441 DiskSize;
1442
1443 PartSize = DiskSize;
1444
1445 Status = STATUS_SUCCESS;
1446 }
1447
1448 IoctlSize = sizeof(ULONG);
1449 Status = RfsdDiskIoControl(
1450 TargetDevice,
1451 IOCTL_DISK_CHECK_VERIFY,
1452 NULL,
1453 0,
1454 &ChangeCount,
1455 &IoctlSize );
1456
1457 if (!NT_SUCCESS(Status)) {
1458 _SEH2_LEAVE;
1459 }
1460
1461 Vcb->ChangeCount = ChangeCount;
1462
1463 Vcb->Header.AllocationSize.QuadPart =
1464 Vcb->Header.FileSize.QuadPart = PartSize;
1465
1466 Vcb->Header.ValidDataLength.QuadPart =
1467 (LONGLONG)(0x7fffffffffffffff);
1468 /*
1469 Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(rfsd_super_block->s_blocks_count - rfsd_super_block->s_free_blocks_count)
1470 * (RFSD_MIN_BLOCK << rfsd_super_block->s_log_block_size);
1471 Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
1472 Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart;
1473 */
1474 {
1475 CC_FILE_SIZES FileSizes;
1476
1477 FileSizes.AllocationSize.QuadPart =
1478 FileSizes.FileSize.QuadPart =
1479 Vcb->Header.AllocationSize.QuadPart;
1480
1481 FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff);
1482
1483 CcInitializeCacheMap( Vcb->StreamObj,
1484 &FileSizes,
1485 TRUE,
1486 &(RfsdGlobal->CacheManagerNoOpCallbacks),
1487 Vcb );
1488 }
1489 #if DISABLED // IN FFFS TOO
1490 if (!RfsdLoadGroup(Vcb)) {
1491 Status = STATUS_UNSUCCESSFUL;
1492 _SEH2_LEAVE;
1493 }
1494 #endif
1495
1496 FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool);
1497 InitializeListHead(&(Vcb->McbList));
1498
1499
1500 //
1501 // Now allocating the mcb for root ...
1502 //
1503
1504 Buffer[0] = L'\\';
1505 Buffer[1] = 0;
1506
1507 RootNode.Buffer = Buffer;
1508 RootNode.MaximumLength = RootNode.Length = 2;
1509
1510 Vcb->McbTree = RfsdAllocateMcb( Vcb, &RootNode,
1511 FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL);
1512
1513 if (!Vcb->McbTree) {
1514 _SEH2_LEAVE;
1515 }
1516
1517 // Set the root of the filesystem to the root directory's inode / stat data structure
1518 Vcb->McbTree->Key.k_dir_id = RFSD_ROOT_PARENT_ID;
1519 Vcb->McbTree->Key.k_objectid = RFSD_ROOT_OBJECT_ID;
1520 Vcb->McbTree->Key.k_offset = 0;
1521 Vcb->McbTree->Key.k_type = RFSD_KEY_TYPE_v1_STAT_DATA;
1522
1523 #ifdef DISABLED
1524 if (IsFlagOn(RfsdGlobal->Flags, RFSD_CHECKING_BITMAP)) {
1525 RfsdCheckBitmapConsistency(IrpContext, Vcb);
1526 }
1527
1528 {
1529 ULONG dwData[RFSD_BLOCK_TYPES] = {RFSD_NDIR_BLOCKS, 1, 1, 1};
1530 ULONG dwMeta[RFSD_BLOCK_TYPES] = {0, 0, 0, 0};
1531 ULONG i;
1532
1533 KdPrint(("Reminder: " __FUNCTION__ ", dwData, dwMeta??\n"));
1534
1535 for (i = 0; i < RFSD_BLOCK_TYPES; i++) {
1536 dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i);
1537
1538 if (i > 0) {
1539 dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2));
1540 }
1541
1542 Vcb->dwData[i] = dwData[i];
1543 Vcb->dwMeta[i] = dwMeta[i];
1544 }
1545 }
1546 #endif
1547
1548 SetFlag(Vcb->Flags, VCB_INITIALIZED);
1549
1550 } _SEH2_FINALLY {
1551
1552 if (!NT_SUCCESS(Status)) {
1553
1554 if (NotifySyncInitialized) {
1555 FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
1556 }
1557
1558 if (Vcb->GroupDesc) {
1559 ExFreePool(Vcb->GroupDesc);
1560 // CcUnpinData(Vcb->GroupDescBcb);
1561 Vcb->GroupDesc = NULL;
1562 }
1563
1564 if (Vcb->SuperBlock) {
1565 ExFreePool(Vcb->SuperBlock);
1566 Vcb->SuperBlock = NULL;
1567 }
1568
1569 if (VcbResourceInitialized) {
1570 ExDeleteResourceLite(&Vcb->MainResource);
1571 ExDeleteResourceLite(&Vcb->PagingIoResource);
1572 }
1573 }
1574 } _SEH2_END;
1575
1576 return Status;
1577 }
1578
1579 __drv_mustHoldCriticalRegion
1580 VOID
1581 RfsdFreeVcb (IN PRFSD_VCB Vcb )
1582 {
1583 PAGED_CODE();
1584
1585 ASSERT(Vcb != NULL);
1586
1587 ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
1588 (Vcb->Identifier.Size == sizeof(RFSD_VCB)));
1589
1590 FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
1591
1592 if (Vcb->StreamObj) {
1593 if (IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED)) {
1594 IO_STATUS_BLOCK IoStatus;
1595
1596 CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
1597 ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
1598 }
1599
1600 if (Vcb->StreamObj->PrivateCacheMap)
1601 RfsdSyncUninitializeCacheMap(Vcb->StreamObj);
1602
1603 ObDereferenceObject(Vcb->StreamObj);
1604 Vcb->StreamObj = NULL;
1605 }
1606
1607 #if DBG
1608 if (FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) != 0) {
1609 LONGLONG DirtyVba;
1610 LONGLONG DirtyLba;
1611 LONGLONG DirtyLength;
1612 int i;
1613
1614 for (i = 0; FsRtlGetNextLargeMcbEntry (&(Vcb->DirtyMcbs), i, &DirtyVba, &DirtyLba, &DirtyLength); i++)
1615 {
1616 RfsdPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
1617 RfsdPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
1618 RfsdPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
1619 }
1620
1621 DbgBreak();
1622 }
1623 #endif
1624
1625 FsRtlUninitializeLargeMcb(&(Vcb->DirtyMcbs));
1626
1627 RfsdFreeMcbTree(Vcb->McbTree);
1628
1629 if (Vcb->GroupDesc) {
1630 ExFreePool(Vcb->GroupDesc);
1631 // CcUnpinData(Vcb->GroupDescBcb);
1632 Vcb->GroupDesc = NULL;
1633 }
1634
1635 if (Vcb->SuperBlock) {
1636 ExFreePool(Vcb->SuperBlock);
1637 Vcb->SuperBlock = NULL;
1638 }
1639
1640 ExDeleteResourceLite(&Vcb->McbResource);
1641
1642 ExDeleteResourceLite(&Vcb->PagingIoResource);
1643
1644 ExDeleteResourceLite(&Vcb->MainResource);
1645
1646 IoDeleteDevice(Vcb->DeviceObject);
1647 }
1648
1649 VOID
1650 RfsdSyncUninitializeCacheMap (
1651 IN PFILE_OBJECT FileObject
1652 )
1653 {
1654 CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent;
1655 NTSTATUS WaitStatus;
1656 LARGE_INTEGER RfsdLargeZero = {0,0};
1657
1658 PAGED_CODE();
1659
1660 KeInitializeEvent( &UninitializeCompleteEvent.Event,
1661 SynchronizationEvent,
1662 FALSE);
1663
1664 CcUninitializeCacheMap( FileObject,
1665 &RfsdLargeZero,
1666 &UninitializeCompleteEvent );
1667
1668 WaitStatus = KeWaitForSingleObject( &UninitializeCompleteEvent.Event,
1669 Executive,
1670 KernelMode,
1671 FALSE,
1672 NULL);
1673
1674 ASSERT (NT_SUCCESS(WaitStatus));
1675 }