ReactOS 0.4.15-dev-7788-g1ad9096
cachesup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1990-2000 Microsoft Corporation
4
5Module Name:
6
7 Cache.c
8
9Abstract:
10
11 This module implements the cache management routines for the Cdfs
12 FSD and FSP, by calling the Common Cache Manager.
13
14
15--*/
16
17#include "cdprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (CDFS_BUG_CHECK_CACHESUP)
24
25//
26// Local debug trace level
27//
28
29#ifdef ALLOC_PRAGMA
30#pragma alloc_text(PAGE, CdCompleteMdl)
31#pragma alloc_text(PAGE, CdCreateInternalStream)
32#pragma alloc_text(PAGE, CdDeleteInternalStream)
33#pragma alloc_text(PAGE, CdPurgeVolume)
34#endif
35
36
37VOID
39 _In_ PIRP_CONTEXT IrpContext,
43 )
44
45/*++
46
47Routine Description:
48
49 This function creates an internal stream file for interaction
50 with the cache manager. The Fcb here can be for either a
51 directory stream or for a path table stream.
52
53Arguments:
54
55 Vcb - Vcb for this volume.
56
57 Fcb - Points to the Fcb for this file. It is either an Index or
58 Path Table Fcb.
59
60Return Value:
61
62 None.
63
64--*/
65
66{
67 PFILE_OBJECT StreamFile = NULL;
68 BOOLEAN DecrementReference = FALSE;
69
70 BOOLEAN CleanupDirContext = FALSE;
71 BOOLEAN UpdateFcbSizes = FALSE;
72
73 DIRENT Dirent = {0};
75
76 PAGED_CODE();
77
78 ASSERT_IRP_CONTEXT( IrpContext );
79 ASSERT_FCB( Fcb );
80
81 //
82 // We may only have the Fcb shared. Lock the Fcb and do a
83 // safe test to see if we need to really create the file object.
84 //
85
86 CdLockFcb( IrpContext, Fcb );
87
88 if (Fcb->FileObject != NULL) {
89
90 CdUnlockFcb( IrpContext, Fcb );
91 return;
92 }
93
94 //
95 // Use a try-finally to facilitate cleanup.
96 //
97
98 _SEH2_TRY {
99
100 //
101 // Create the internal stream. The Vpb should be pointing at our volume
102 // device object at this point.
103 //
104
105 StreamFile = IoCreateStreamFileObjectLite( NULL, Vcb->Vpb->RealDevice );
106
107 if (StreamFile == NULL) {
108
110 }
111
112 //
113 // Initialize the fields of the file object.
114 //
115
116 StreamFile->ReadAccess = TRUE;
117 StreamFile->WriteAccess = FALSE;
118 StreamFile->DeleteAccess = FALSE;
119
120 StreamFile->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject;
121
122 //
123 // Set the file object type and increment the Vcb counts.
124 //
125
126 CdSetFileObject( IrpContext,
127 StreamFile,
129 Fcb,
130 NULL );
131
132 //
133 // We'll give stream file objects a name to aid IO profiling etc. We
134 // NULL this in CdDeleteInternalStream before OB deletes the file object,
135 // and before CdRemovePrefix is called (which frees Fcb names).
136 //
137
138 StreamFile->FileName = *Name;
139
140 //
141 // We will reference the current Fcb twice to keep it from going
142 // away in the error path. Otherwise if we dereference it
143 // below in the finally clause a close could cause the Fcb to
144 // be deallocated.
145 //
146
147 CdLockVcb( IrpContext, Vcb );
148 CdIncrementReferenceCounts( IrpContext, Fcb, 2, 0 );
149 CdUnlockVcb( IrpContext, Vcb );
150 DecrementReference = TRUE;
151
152 //
153 // Initialize the cache map for the file.
154 //
155
156 CcInitializeCacheMap( StreamFile,
157 (PCC_FILE_SIZES)&Fcb->AllocationSize,
158 TRUE,
160 Fcb );
161
162 //
163 // Go ahead and store the stream file into the Fcb.
164 //
165
166 Fcb->FileObject = StreamFile;
167 StreamFile = NULL;
168
169 //
170 // If this is the first file object for a directory then we need to
171 // read the self entry for this directory and update the sizes
172 // in the Fcb. We know that the Fcb has been initialized so
173 // that we have a least one sector available to read.
174 //
175
177
178 ULONG NewDataLength;
179
180 //
181 // Initialize the search structures.
182 //
183
184 CdInitializeDirContext( IrpContext, &DirContext );
185 CdInitializeDirent( IrpContext, &Dirent );
186 CleanupDirContext = TRUE;
187
188 //
189 // Read the dirent from disk and transfer the data to the
190 // in-memory dirent.
191 //
192
193 CdLookupDirent( IrpContext,
194 Fcb,
195 Fcb->StreamOffset,
196 &DirContext );
197
198 CdUpdateDirentFromRawDirent( IrpContext, Fcb, &DirContext, &Dirent );
199
200 //
201 // Verify that this really for the self entry. We do this by
202 // updating the name in the dirent and then checking that it matches
203 // one of the hard coded names.
204 //
205
206 CdUpdateDirentName( IrpContext, &Dirent, FALSE );
207
208 if (Dirent.CdFileName.FileName.Buffer != CdUnicodeSelfArray) {
209
211 }
212
213 //
214 // If the data sizes are different then update the header
215 // and Mcb for this Fcb.
216 //
217
218 NewDataLength = BlockAlign( Vcb, Dirent.DataLength + Fcb->StreamOffset );
219
220 if (NewDataLength == 0) {
221
223 }
224
225 if (NewDataLength != Fcb->FileSize.QuadPart) {
226
227 Fcb->AllocationSize.QuadPart =
228 Fcb->FileSize.QuadPart =
229 Fcb->ValidDataLength.QuadPart = NewDataLength;
230
231 CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize );
232
233 CdTruncateAllocation( IrpContext, Fcb, 0 );
234 CdAddInitialAllocation( IrpContext,
235 Fcb,
236 Dirent.StartingOffset,
237 NewDataLength );
238
239 UpdateFcbSizes = TRUE;
240 }
241
242 //
243 // Check for the existence flag and transform to hidden.
244 //
245
246 if (FlagOn( Dirent.DirentFlags, CD_ATTRIBUTE_HIDDEN )) {
247
249 }
250
251 //
252 // Convert the time to NT time.
253 //
254
255 CdConvertCdTimeToNtTime( IrpContext,
256 Dirent.CdTime,
258
259 //
260 // Update the Fcb flags to indicate we have read the
261 // self entry.
262 //
263
265
266 //
267 // If we updated the sizes then we want to purge the file. Go
268 // ahead and unpin and then purge the first page.
269 //
270
271 CdCleanupDirContext( IrpContext, &DirContext );
272 CdCleanupDirent( IrpContext, &Dirent );
273 CleanupDirContext = FALSE;
274
275 if (UpdateFcbSizes) {
276
278 NULL,
279 0,
280 FALSE );
281 }
282 }
283
284 } _SEH2_FINALLY {
285
286 //
287 // Cleanup any dirent structures we may have used.
288 //
289
290 if (CleanupDirContext) {
291
292 CdCleanupDirContext( IrpContext, &DirContext );
293 CdCleanupDirent( IrpContext, &Dirent );
294 }
295
296 //
297 // If we raised then we need to dereference the file object.
298 //
299
300 if (StreamFile != NULL) {
301
302 //
303 // Null the name pointer, since the stream file object never actually
304 // 'owns' the names, we just point it to existing ones.
305 //
306
307 StreamFile->FileName.Buffer = NULL;
308 StreamFile->FileName.MaximumLength = StreamFile->FileName.Length = 0;
309
310 ObDereferenceObject( StreamFile );
312 }
313
314 //
315 // Dereference and unlock the Fcb.
316 //
317
318 if (DecrementReference) {
319
320 CdLockVcb( IrpContext, Vcb );
321 CdDecrementReferenceCounts( IrpContext, Fcb, 1, 0 );
322 CdUnlockVcb( IrpContext, Vcb );
323 }
324
325 CdUnlockFcb( IrpContext, Fcb );
326 } _SEH2_END;
327
328 return;
329}
330
331
332VOID
334 _In_ PIRP_CONTEXT IrpContext,
336 )
337
338/*++
339
340Routine Description:
341
342 This function creates an internal stream file for interaction
343 with the cache manager. The Fcb here can be for either a
344 directory stream or for a path table stream.
345
346Arguments:
347
348 Fcb - Points to the Fcb for this file. It is either an Index or
349 Path Table Fcb.
350
351Return Value:
352
353 None.
354
355--*/
356
357{
359
360 PAGED_CODE();
361
362 UNREFERENCED_PARAMETER( IrpContext );
363
364 ASSERT_IRP_CONTEXT( IrpContext );
365 ASSERT_FCB( Fcb );
366
367 //
368 // Lock the Fcb.
369 //
370
371 CdLockFcb( IrpContext, Fcb );
372
373 //
374 // Capture the file object.
375 //
376
379
380 //
381 // It is now safe to unlock the Fcb.
382 //
383
384 CdUnlockFcb( IrpContext, Fcb );
385
386 //
387 // Dereference the file object if present.
388 //
389
390 if (FileObject != NULL) {
391
392 if (FileObject->PrivateCacheMap != NULL) {
393
395 }
396
397 //
398 // Null the name pointer, since the stream file object never actually
399 // 'owns' the names, we just point it to existing ones.
400 //
401
402 FileObject->FileName.Buffer = NULL;
403 FileObject->FileName.MaximumLength = FileObject->FileName.Length = 0;
404
406 }
407}
408
409
412 _In_ PIRP_CONTEXT IrpContext,
414 )
415
416/*++
417
418Routine Description:
419
420 This routine performs the function of completing Mdl reads.
421 It should be called only from CdFsdRead.
422
423Arguments:
424
425 Irp - Supplies the originating Irp.
426
427Return Value:
428
429 NTSTATUS - Will always be STATUS_SUCCESS.
430
431--*/
432
433{
435
436 PAGED_CODE();
437
438 //
439 // Do completion processing.
440 //
441
443
444 CcMdlReadComplete( FileObject, Irp->MdlAddress );
445
446 //
447 // Mdl is now deallocated.
448 //
449
450 Irp->MdlAddress = NULL;
451
452 //
453 // Complete the request and exit right away.
454 //
455
456 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
457
458 return STATUS_SUCCESS;
459}
460
461
462
463_Requires_lock_held_(_Global_critical_region_)
465CdPurgeVolume (
466 _In_ PIRP_CONTEXT IrpContext,
467 _In_ PVCB Vcb,
469 )
470
471/*++
472
473Routine Description:
474
475 This routine is called to purge the volume. The purpose is to make all the stale file
476 objects in the system go away in order to lock the volume.
477
478 The Vcb is already acquired exclusively. We will lock out all file operations by
479 acquiring the global file resource. Then we will walk through all of the Fcb's and
480 perform the purge.
481
482Arguments:
483
484 Vcb - Vcb for the volume to purge.
485
486 DismountUnderway - Indicates that we are trying to delete all of the objects.
487 We will purge the Path Table and VolumeDasd and dereference all
488 internal streams.
489
490Return Value:
491
492 NTSTATUS - The first failure of the purge operation.
493
494--*/
495
496{
498
499 PVOID RestartKey = NULL;
500 PFCB ThisFcb = NULL;
501 PFCB NextFcb;
502
503 BOOLEAN RemovedFcb;
504
505 PAGED_CODE();
506
508
509 //
510 // Force any remaining Fcb's in the delayed close queue to be closed.
511 //
512
513 CdFspClose( Vcb );
514
515 //
516 // Acquire the global file resource.
517 //
518
519 CdAcquireAllFiles( IrpContext, Vcb );
520
521 //
522 // Loop through each Fcb in the Fcb Table and perform the flush.
523 //
524
525 while (TRUE) {
526
527 //
528 // Lock the Vcb to lookup the next Fcb.
529 //
530
531 CdLockVcb( IrpContext, Vcb );
532 NextFcb = CdGetNextFcb( IrpContext, Vcb, &RestartKey );
533
534 //
535 // Reference the NextFcb if present.
536 //
537
538 if (NextFcb != NULL) {
539
540 NextFcb->FcbReference += 1;
541 }
542
543 //
544 // If the last Fcb is present then decrement reference count and call teardown
545 // to see if it should be removed.
546 //
547
548 if (ThisFcb != NULL) {
549
550 ThisFcb->FcbReference -= 1;
551
552 CdUnlockVcb( IrpContext, Vcb );
553
554 CdTeardownStructures( IrpContext, ThisFcb, &RemovedFcb );
555
556 } else {
557
558 CdUnlockVcb( IrpContext, Vcb );
559 }
560
561 //
562 // Break out of the loop if no more Fcb's.
563 //
564
565 if (NextFcb == NULL) {
566
567 break;
568 }
569
570 //
571 // Move to the next Fcb.
572 //
573
574 ThisFcb = NextFcb;
575
576 //
577 // If there is a image section then see if that can be closed.
578 //
579
581
582 MmFlushImageSection( &ThisFcb->FcbNonpaged->SegmentObject, MmFlushForWrite );
583 }
584
585 //
586 // If there is a data section then purge this. If there is an image
587 // section then we won't be able to. Remember this if it is our first
588 // error.
589 //
590
591 if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
593 NULL,
594 0,
595 FALSE ) &&
596 (Status == STATUS_SUCCESS)) {
597
599 }
600
601 //
602 // Dereference the internal stream if dismounting.
603 //
604
605 if (DismountUnderway &&
606 (SafeNodeType( ThisFcb ) != CDFS_NTC_FCB_DATA) &&
607 (ThisFcb->FileObject != NULL)) {
608
609 CdDeleteInternalStream( IrpContext, ThisFcb );
610 }
611 }
612
613 //
614 // Now look at the path table and volume Dasd Fcb's.
615 //
616
617 if (DismountUnderway) {
618
619 if (Vcb->PathTableFcb != NULL) {
620
621 ThisFcb = Vcb->PathTableFcb;
622 InterlockedIncrement( (LONG*)&Vcb->PathTableFcb->FcbReference );
623
624 if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
626 NULL,
627 0,
628 FALSE ) &&
629 (Status == STATUS_SUCCESS)) {
630
632 }
633
634 CdDeleteInternalStream( IrpContext, ThisFcb );
635
637
638 CdTeardownStructures( IrpContext, ThisFcb, &RemovedFcb );
639 }
640
641 if (Vcb->VolumeDasdFcb != NULL) {
642
643 ThisFcb = Vcb->VolumeDasdFcb;
645
646 if ((ThisFcb->FcbNonpaged->SegmentObject.DataSectionObject != NULL) &&
648 NULL,
649 0,
650 FALSE ) &&
651 (Status == STATUS_SUCCESS)) {
652
654 }
655
657
658 CdTeardownStructures( IrpContext, ThisFcb, &RemovedFcb );
659 }
660 }
661
662 //
663 // Release all of the files.
664 //
665
666 CdReleaseAllFiles( IrpContext, Vcb );
667
668 return Status;
669}
670
671
#define PAGED_CODE()
unsigned char BOOLEAN
struct NameRec_ * Name
Definition: cdprocs.h:460
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcMdlReadComplete(IN PFILE_OBJECT FileObject, IN PMDL MdlChain)
Definition: mdlsup.c:75
#define CD_ATTRIBUTE_HIDDEN
Definition: cd.h:353
#define CdConvertCdTimeToNtTime(IC, CD, NT)
Definition: cd.h:394
WCHAR CdUnicodeSelfArray[]
Definition: cddata.c:49
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
CD_DATA CdData
Definition: cddata.c:42
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:248
#define ASSERT_EXCLUSIVE_VCB(V)
Definition: cddata.h:258
#define ASSERT_FCB(F)
Definition: cddata.h:243
VOID CdTruncateAllocation(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ LONGLONG StartingFileOffset)
Definition: allocsup.c:575
VOID CdAddInitialAllocation(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ ULONG StartingBlock, _In_ LONGLONG DataLength)
Definition: allocsup.c:484
VOID CdCreateInternalStream(_In_ PIRP_CONTEXT IrpContext, _In_ PVCB Vcb, _Inout_ PFCB Fcb, _In_ PUNICODE_STRING Name)
Definition: cachesup.c:38
VOID CdDeleteInternalStream(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb)
Definition: cachesup.c:333
NTSTATUS CdCompleteMdl(_In_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: cachesup.c:411
#define CdInitializeDirent(IC, D)
Definition: cdprocs.h:536
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1044
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:427
VOID CdFspClose(_In_opt_ PVCB Vcb)
#define BlockAlign(V, L)
Definition: cdprocs.h:1638
@ StreamFileOpen
Definition: cdprocs.h:574
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1023
VOID CdUpdateDirentName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PDIRENT Dirent, _In_ ULONG IgnoreCase)
Definition: dirsup.c:534
_In_ PVCB _In_ BOOLEAN DismountUnderway
Definition: cdprocs.h:237
#define CdCleanupDirContext(IC, DC)
Definition: cdprocs.h:548
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1028
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define CdReleaseAllFiles(IC, V)
Definition: cdprocs.h:991
VOID CdLookupDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ ULONG DirentOffset, _Out_ PDIRENT_ENUM_CONTEXT DirContext)
Definition: dirsup.c:125
#define CdCleanupDirent(IC, D)
Definition: cdprocs.h:542
#define CdInitializeDirContext(IC, DC)
Definition: cdprocs.h:539
#define CdDecrementReferenceCounts(IC, F, C, UC)
Definition: cdprocs.h:1325
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:425
PFCB CdGetNextFcb(_In_ PIRP_CONTEXT IrpContext, _In_ PVCB Vcb, _In_ PVOID *RestartKey)
Definition: strucsup.c:2155
#define CdAcquireAllFiles(IC, V)
Definition: cdprocs.h:988
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1060
#define CdIncrementReferenceCounts(IC, F, C, UC)
Definition: cdprocs.h:1317
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define FCB_STATE_INITIALIZED
Definition: cdstruc.h:1042
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
#define CDFS_NTC_FCB_DATA
Definition: nodetype.h:31
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
Status
Definition: gdiplustypes.h:25
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
PFILE_OBJECT NTAPI IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL)
Definition: file.c:3199
#define STATUS_UNABLE_TO_DELETE_SECTION
Definition: ntstatus.h:264
long LONG
Definition: pedump.c:60
#define Vcb
Definition: cdprocs.h:1415
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
#define STATUS_SUCCESS
Definition: shellext.h:65
CACHE_MANAGER_CALLBACKS CacheManagerCallbacks
Definition: cdstruc.h:409
SECTION_OBJECT_POINTERS SegmentObject
Definition: cdstruc.h:873
Definition: cdstruc.h:902
LONGLONG CreationTime
Definition: cdstruc.h:1030
ULONG FcbState
Definition: cdstruc.h:971
ULONG FileAttributes
Definition: cdstruc.h:977
__volatile LONG FcbReference
Definition: cdstruc.h:964
PFILE_OBJECT FileObject
Definition: ntfs.h:520
PFCB_NONPAGED FcbNonpaged
Definition: cdstruc.h:1003
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
Definition: cdstruc.h:498
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203