ReactOS 0.4.16-dev-297-gc569aee
close.c File Reference
#include "cdprocs.h"
Include dependency graph for close.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (CDFS_BUG_CHECK_CLOSE)
 

Functions

 _Requires_lock_held_ (_Global_critical_region_)
 
VOID NTAPI CdCloseWorker (_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
 
VOID CdQueueClose (_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ ULONG UserReference, _In_ BOOLEAN DelayedClose)
 
PIRP_CONTEXT CdRemoveClose (_In_opt_ PVCB Vcb)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (CDFS_BUG_CHECK_CLOSE)

Definition at line 51 of file close.c.

Function Documentation

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 57 of file close.c.

124{
125 PIRP_CONTEXT IrpContext;
126 IRP_CONTEXT StackIrpContext;
127
128 THREAD_CONTEXT ThreadContext = {0};
129
130 PFCB Fcb;
131 ULONG UserReference;
132
133 ULONG VcbHoldCount = 0;
134 PVCB CurrentVcb = NULL;
135
136 BOOLEAN PotentialVcbTeardown = FALSE;
137
138 PAGED_CODE();
139
141
142 //
143 // Continue processing until there are no more closes to process.
144 //
145
146 while ((IrpContext = CdRemoveClose( Vcb )) != NULL) {
147
148 //
149 // If we don't have an IrpContext then use the one on the stack.
150 // Initialize it for this request.
151 //
152
153 if (SafeNodeType( IrpContext ) != CDFS_NTC_IRP_CONTEXT ) {
154
155 //
156 // Update the local values from the IrpContextLite.
157 //
158
159 Fcb = ((PIRP_CONTEXT_LITE) IrpContext)->Fcb;
160 UserReference = ((PIRP_CONTEXT_LITE) IrpContext)->UserReference;
161
162 //
163 // Update the stack irp context with the values from the
164 // IrpContextLite.
165 //
166
167 CdInitializeStackIrpContext( &StackIrpContext,
168 (PIRP_CONTEXT_LITE) IrpContext );
169
170 //
171 // Free the IrpContextLite.
172 //
173
174 CdFreeIrpContextLite( *(PVOID*)&IrpContext ); /* ReactOS Change: GCC "error: invalid lvalue in unary '&'" */
175
176 //
177 // Remember we have the IrpContext from the stack.
178 //
179
180 IrpContext = &StackIrpContext;
181
182 //
183 // Otherwise cleanup the existing IrpContext.
184 //
185
186 } else {
187
188 //
189 // Remember the Fcb and user reference count.
190 //
191
192 Fcb = (PFCB) IrpContext->Irp;
193 IrpContext->Irp = NULL;
194
195 UserReference = (ULONG) IrpContext->ExceptionStatus;
196 IrpContext->ExceptionStatus = STATUS_SUCCESS;
197 }
198
200
201 //
202 // We have an IrpContext. Now we need to set the top level thread
203 // context.
204 //
205
206 SetFlag( IrpContext->Flags, IRP_CONTEXT_FSP_FLAGS );
207
208 //
209 // If we were given a Vcb then there is a request on top of this.
210 //
211
212 if (ARGUMENT_PRESENT( Vcb )) {
213
214 ClearFlag( IrpContext->Flags,
216 }
217
218 CdSetThreadContext( IrpContext, &ThreadContext );
219
220 //
221 // If we have hit the maximum number of requests to process without
222 // releasing the Vcb then release the Vcb now. If we are holding
223 // a different Vcb to this one then release the previous Vcb.
224 //
225 // In either case acquire the current Vcb.
226 //
227 // We use the MinDelayedCloseCount from the CdData since it is
228 // a convenient value based on the system size. Only thing we are trying
229 // to do here is prevent this routine starving other threads which
230 // may need this Vcb exclusively.
231 //
232 // Note that the check for potential teardown below is unsafe. We'll
233 // repeat later within the cddata lock.
234 //
235
236 PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) &&
239 (Fcb->Vcb->VcbCleanup == 0);
240
241 if (PotentialVcbTeardown ||
242 (VcbHoldCount > CdData.MinDelayedCloseCount) ||
243 (Fcb->Vcb != CurrentVcb)) {
244
245 if (CurrentVcb != NULL) {
246
247 CdReleaseVcb( IrpContext, CurrentVcb );
248 }
249
250 if (PotentialVcbTeardown) {
251
252 CdAcquireCdData( IrpContext );
253
254 //
255 // Repeat the checks with global lock held. The volume could have
256 // been remounted while we didn't hold the lock.
257 //
258
259 PotentialVcbTeardown = !ARGUMENT_PRESENT( Vcb ) &&
262 (Fcb->Vcb->VcbCleanup == 0);
263
264 if (!PotentialVcbTeardown) {
265
266 CdReleaseCdData( IrpContext);
267 }
268 }
269
270 CurrentVcb = Fcb->Vcb;
271
272 _Analysis_assume_( CurrentVcb != NULL );
273
274 CdAcquireVcbShared( IrpContext, CurrentVcb, FALSE );
275
276 VcbHoldCount = 0;
277
278 } else {
279
280 VcbHoldCount += 1;
281 }
282
283 //
284 // Call our worker routine to perform the close operation.
285 //
286
287 CdCommonClosePrivate( IrpContext, CurrentVcb, Fcb, UserReference, FALSE );
288
289 //
290 // If the reference count on this Vcb is below our residual reference
291 // then check if we should dismount the volume.
292 //
293
294 if (PotentialVcbTeardown) {
295
296 CdReleaseVcb( IrpContext, CurrentVcb );
297 CdCheckForDismount( IrpContext, CurrentVcb, FALSE );
298
299 CurrentVcb = NULL;
300
301 CdReleaseCdData( IrpContext );
302 PotentialVcbTeardown = FALSE;
303 }
304
305 //
306 // Complete the current request to cleanup the IrpContext.
307 //
308
309 CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
310 }
311
312 //
313 // Release any Vcb we may still hold.
314 //
315
316 if (CurrentVcb != NULL) {
317
318 CdReleaseVcb( IrpContext, CurrentVcb );
319
320 }
321
322#ifdef _MSC_VER
323#pragma prefast(suppress:26165, "Esp:1153")
324#endif
326}
#define PAGED_CODE()
unsigned char BOOLEAN
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
VOID CdSetThreadContext(_Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext)
Definition: cddata.c:981
VOID CdInitializeStackIrpContext(_Out_ PIRP_CONTEXT IrpContext, _In_ PIRP_CONTEXT_LITE IrpContextLite)
Definition: strucsup.c:1839
#define CdAcquireCdData(IC)
Definition: cdprocs.h:973
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:985
#define CdFreeIrpContextLite(ICL)
Definition: cdprocs.h:1252
#define CdReleaseCdData(IC)
Definition: cdprocs.h:976
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:982
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define IRP_CONTEXT_FSP_FLAGS
Definition: cdstruc.h:1261
#define IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS
Definition: cdstruc.h:1218
FCB * PFCB
Definition: cdstruc.h:1040
IRP_CONTEXT_LITE * PIRP_CONTEXT_LITE
Definition: cdstruc.h:1308
@ VcbMounted
Definition: cdstruc.h:492
@ VcbMountInProgress
Definition: cdstruc.h:491
#define IRP_CONTEXT_FLAG_TOP_LEVEL
Definition: cdstruc.h:1217
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
PIRP_CONTEXT CdRemoveClose(_In_opt_ PVCB Vcb)
Definition: close.c:877
#define CDFS_NTC_IRP_CONTEXT
Definition: nodetype.h:34
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define _Analysis_assume_
Definition: no_sal2.h:388
#define ARGUMENT_PRESENT(ArgumentPointer)
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_SUCCESS
Definition: shellext.h:65
PIRP Irp
Definition: usbstor.h:99
ULONG MinDelayedCloseCount
Definition: cdstruc.h:389
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
struct _FCB::@729::@732 Fcb
Definition: cdstruc.h:498
VCB_CONDITION VcbCondition
Definition: cdstruc.h:541
ULONG VcbCleanup
Definition: cdstruc.h:551
uint32_t ULONG
Definition: typedefs.h:59

◆ CdCloseWorker()

VOID NTAPI CdCloseWorker ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_opt_ PVOID  Context 
)

Definition at line 657 of file close.c.

679{
680 PAGED_CODE();
681
684
686}
VOID CdFspClose(_In_opt_ PVCB Vcb)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

Referenced by CdQueueClose().

◆ CdQueueClose()

VOID CdQueueClose ( _In_ PIRP_CONTEXT  IrpContext,
_In_ PFCB  Fcb,
_In_ ULONG  UserReference,
_In_ BOOLEAN  DelayedClose 
)

Definition at line 690 of file close.c.

724{
725 PIRP_CONTEXT_LITE IrpContextLite = NULL;
726 BOOLEAN StartWorker = FALSE;
727
728 PAGED_CODE();
729
730 ASSERT_IRP_CONTEXT( IrpContext );
731 ASSERT_FCB( Fcb );
732
733 //
734 // Start with the delayed queue request. We can move this to the async
735 // queue if there is an allocation failure.
736 //
737
738 if (DelayedClose) {
739
740 //
741 // Try to allocate non-paged pool for the IRP_CONTEXT_LITE.
742 //
743
744 IrpContextLite = CdCreateIrpContextLite( IrpContext );
745 }
746
747 //
748 // We want to clear the top level context in this thread if
749 // necessary. Call our cleanup routine to do the work.
750 //
751
752 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
753 CdCleanupIrpContext( IrpContext, TRUE );
754
755 //
756 // Synchronize with the CdData lock.
757 //
758
759 CdLockCdData();
760
761 //
762 // If we have an IrpContext then put the request on the delayed close queue.
763 //
764
765 if (IrpContextLite != NULL) {
766
767 //
768 // Initialize the IrpContextLite.
769 //
770
771 IrpContextLite->NodeTypeCode = CDFS_NTC_IRP_CONTEXT_LITE;
772 IrpContextLite->NodeByteSize = sizeof( IRP_CONTEXT_LITE );
773 IrpContextLite->Fcb = Fcb;
774 IrpContextLite->UserReference = UserReference;
775 IrpContextLite->RealDevice = IrpContext->RealDevice;
776
777 //
778 // Add this to the delayed close list and increment
779 // the count.
780 //
781
783 &IrpContextLite->DelayedCloseLinks );
784
786
787 //
788 // If we are above our threshold then start the delayed
789 // close operation.
790 //
791
793
795
796 if (!CdData.FspCloseActive) {
797
799 StartWorker = TRUE;
800 }
801 }
802
803 //
804 // Unlock the CdData.
805 //
806
808
809 //
810 // Cleanup the IrpContext.
811 //
812
813 CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
814
815 //
816 // Otherwise drop into the async case below.
817 //
818
819 } else {
820
821 //
822 // Store the information about the file object into the IrpContext.
823 //
824
825 IrpContext->Irp = (PIRP) Fcb;
826 IrpContext->ExceptionStatus = (NTSTATUS) UserReference;
827
828 //
829 // Add this to the async close list and increment the count.
830 //
831
833 &IrpContext->WorkQueueItem.List );
834
836
837 //
838 // Remember to start the Fsp close thread if not currently started.
839 //
840
841 if (!CdData.FspCloseActive) {
842
844
845 StartWorker = TRUE;
846 }
847
848 //
849 // Unlock the CdData.
850 //
851
853 }
854
855 //
856 // Start the FspClose thread if we need to.
857 //
858
859 if (StartWorker) {
860
862 }
863
864 //
865 // Return to our caller.
866 //
867
868 return;
869}
struct _IRP * PIRP
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:248
#define ASSERT_FCB(F)
Definition: cddata.h:243
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
#define CdCreateIrpContextLite(IC)
Definition: cdprocs.h:1249
#define CdUnlockCdData()
Definition: cdprocs.h:1019
#define CdLockCdData()
Definition: cdprocs.h:1015
struct _IRP_CONTEXT_LITE IRP_CONTEXT_LITE
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1214
#define TRUE
Definition: types.h:120
#define NTSTATUS
Definition: precomp.h:21
VOID NTAPI CdCloseWorker(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
Definition: close.c:657
#define CDFS_NTC_IRP_CONTEXT_LITE
Definition: nodetype.h:35
#define InsertTailList(ListHead, Entry)
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
BOOLEAN ReduceDelayedClose
Definition: cdstruc.h:379
ULONG DelayedCloseCount
Definition: cdstruc.h:387
LIST_ENTRY AsyncCloseQueue
Definition: cdstruc.h:376
ULONG MaxDelayedCloseCount
Definition: cdstruc.h:388
PIO_WORKITEM CloseItem
Definition: cdstruc.h:416
BOOLEAN FspCloseActive
Definition: cdstruc.h:378
LIST_ENTRY DelayedCloseQueue
Definition: cdstruc.h:386
ULONG AsyncCloseCount
Definition: cdstruc.h:377
LIST_ENTRY DelayedCloseLinks
Definition: cdstruc.h:1293
PDEVICE_OBJECT RealDevice
Definition: cdstruc.h:1305
ULONG UserReference
Definition: cdstruc.h:1299
NODE_BYTE_SIZE NodeByteSize
Definition: cdstruc.h:1281
@ CriticalWorkQueue
Definition: extypes.h:189

◆ CdRemoveClose()

PIRP_CONTEXT CdRemoveClose ( _In_opt_ PVCB  Vcb)

Definition at line 877 of file close.c.

901{
902 PIRP_CONTEXT IrpContext = NULL;
903 PIRP_CONTEXT NextIrpContext;
904 PIRP_CONTEXT_LITE NextIrpContextLite;
905
907
908 PAGED_CODE();
909
911
912 //
913 // Lock the CdData to perform the scan.
914 //
915
916 CdLockCdData();
917
918 //
919 // First check the list of async closes.
920 //
921
923
924 while (Entry != &CdData.AsyncCloseQueue) {
925
926 //
927 // Extract the IrpContext.
928 //
929
930 NextIrpContext = CONTAINING_RECORD( Entry,
932 WorkQueueItem.List );
933
934 //
935 // If no Vcb was specified or this Vcb is for our volume
936 // then perform the close.
937 //
938
939 if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContext->Vcb == Vcb)) {
940
943
944 IrpContext = NextIrpContext;
945 break;
946 }
947
948 //
949 // Move to the next entry.
950 //
951
952 Entry = Entry->Flink;
953 }
954
955 //
956 // If we didn't find anything look through the delayed close
957 // queue.
958 //
959 // We will only check the delayed close queue if we were given
960 // a Vcb or the delayed close operation is active.
961 //
962
963 if ((IrpContext == NULL) &&
964 (ARGUMENT_PRESENT( Vcb ) ||
967
969
970 while (Entry != &CdData.DelayedCloseQueue) {
971
972 //
973 // Extract the IrpContext.
974 //
975
976 NextIrpContextLite = CONTAINING_RECORD( Entry,
978 DelayedCloseLinks );
979
980 //
981 // If no Vcb was specified or this Vcb is for our volume
982 // then perform the close.
983 //
984
985 if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContextLite->Fcb->Vcb == Vcb)) {
986
989
990 IrpContext = (PIRP_CONTEXT) NextIrpContextLite;
991 break;
992 }
993
994 //
995 // Move to the next entry.
996 //
997
998 Entry = Entry->Flink;
999 }
1000 }
1001
1002 //
1003 // If the Vcb wasn't specified and we couldn't find an entry
1004 // then turn off the Fsp thread.
1005 //
1006
1007 if (!ARGUMENT_PRESENT( Vcb ) && (IrpContext == NULL)) {
1008
1011 }
1012
1013 //
1014 // Unlock the CdData.
1015 //
1016
1018
1019 return IrpContext;
1020}
#define ASSERT_OPTIONAL_VCB(V)
Definition: cddata.h:242
IRP_CONTEXT * PIRP_CONTEXT
Definition: cdstruc.h:1211
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
base of all file and directory entries
Definition: entries.h:83
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260