ReactOS  0.4.13-dev-482-ge57f103
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 
199  _Analysis_assume_(Fcb != NULL && Fcb->Vcb != NULL);
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 ) &&
237  (Fcb->Vcb->VcbCondition != VcbMounted) &&
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 ) &&
260  (Fcb->Vcb->VcbCondition != VcbMounted) &&
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 }
VOID CdSetThreadContext(_Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext)
Definition: cddata.c:981
#define FsRtlEnterFileSystem
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:987
PIRP Irp
Definition: usbstor.h:294
#define FsRtlExitFileSystem
Definition: cdstruc.h:908
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
#define IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS
Definition: cdstruc.h:1224
Definition: cdstruc.h:504
VOID CdInitializeStackIrpContext(_Out_ PIRP_CONTEXT IrpContext, _In_ PIRP_CONTEXT_LITE IrpContextLite)
Definition: strucsup.c:1839
#define PAGED_CODE()
Definition: video.h:57
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define IRP_CONTEXT_FSP_FLAGS
Definition: cdstruc.h:1267
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
PIRP_CONTEXT CdRemoveClose(_In_opt_ PVCB Vcb)
Definition: close.c:877
CD_DATA CdData
Definition: cddata.c:42
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:990
FCB * PFCB
Definition: cdstruc.h:1046
#define ARGUMENT_PRESENT(ArgumentPointer)
#define Vcb
Definition: cdprocs.h:1425
#define CdFreeIrpContextLite(ICL)
Definition: cdprocs.h:1257
#define CdAcquireCdData(IC)
Definition: cdprocs.h:978
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
struct _FCB::@691::@694 Fcb
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
VCB_CONDITION VcbCondition
Definition: cdstruc.h:547
#define IRP_CONTEXT_FLAG_TOP_LEVEL
Definition: cdstruc.h:1223
#define CdReleaseCdData(IC)
Definition: cdprocs.h:981
#define CDFS_NTC_IRP_CONTEXT
Definition: nodetype.h:34
unsigned int ULONG
Definition: retypes.h:1
IRP_CONTEXT_LITE * PIRP_CONTEXT_LITE
Definition: cdstruc.h:1314
PVCB Vcb
Definition: cdstruc.h:939
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2777
ULONG MinDelayedCloseCount
Definition: cdstruc.h:395
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
ULONG VcbCleanup
Definition: cdstruc.h:557

◆ 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 
685  CdFspClose (NULL);
686 }
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define PAGED_CODE()
Definition: video.h:57
VOID CdFspClose(_In_opt_ PVCB Vcb)
smooth NULL
Definition: ftsmooth.c:416
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560

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 
807  CdUnlockCdData();
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 
835  CdData.AsyncCloseCount += 1;
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 
852  CdUnlockCdData();
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 }
ULONG MaxDelayedCloseCount
Definition: cdstruc.h:394
#define TRUE
Definition: types.h:120
NODE_BYTE_SIZE NodeByteSize
Definition: cdstruc.h:1287
LIST_ENTRY AsyncCloseQueue
Definition: cdstruc.h:382
ULONG UserReference
Definition: cdstruc.h:1305
ULONG AsyncCloseCount
Definition: cdstruc.h:383
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1220
PDEVICE_OBJECT RealDevice
Definition: cdstruc.h:1311
#define InsertTailList(ListHead, Entry)
#define ASSERT_FCB(F)
Definition: cddata.h:243
#define PAGED_CODE()
Definition: video.h:57
PIO_WORKITEM CloseItem
Definition: cdstruc.h:422
VOID NTAPI CdCloseWorker(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
Definition: close.c:657
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:249
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
struct _IRP_CONTEXT_LITE IRP_CONTEXT_LITE
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
CD_DATA CdData
Definition: cddata.c:42
LIST_ENTRY DelayedCloseLinks
Definition: cdstruc.h:1299
#define CdLockCdData()
Definition: cdprocs.h:1020
#define NTSTATUS
Definition: precomp.h:20
#define CDFS_NTC_IRP_CONTEXT_LITE
Definition: nodetype.h:35
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
ULONG DelayedCloseCount
Definition: cdstruc.h:393
LIST_ENTRY DelayedCloseQueue
Definition: cdstruc.h:392
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
#define CdCreateIrpContextLite(IC)
Definition: cdprocs.h:1254
BOOLEAN FspCloseActive
Definition: cdstruc.h:384
BOOLEAN ReduceDelayedClose
Definition: cdstruc.h:385
PVOID PIRP
Definition: usb.h:38
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define CdUnlockCdData()
Definition: cdprocs.h:1024

◆ 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,
931  IRP_CONTEXT,
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 
942  CdData.AsyncCloseCount -= 1;
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 
1017  CdUnlockCdData();
1018 
1019  return IrpContext;
1020 }
LIST_ENTRY AsyncCloseQueue
Definition: cdstruc.h:382
struct _Entry Entry
Definition: kefuncs.h:640
IRP_CONTEXT * PIRP_CONTEXT
Definition: cdstruc.h:1217
ULONG AsyncCloseCount
Definition: cdstruc.h:383
#define PAGED_CODE()
Definition: video.h:57
#define ASSERT_OPTIONAL_VCB(V)
Definition: cddata.h:242
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
CD_DATA CdData
Definition: cddata.c:42
#define ARGUMENT_PRESENT(ArgumentPointer)
#define Vcb
Definition: cdprocs.h:1425
#define CdLockCdData()
Definition: cdprocs.h:1020
Definition: typedefs.h:117
ULONG DelayedCloseCount
Definition: cdstruc.h:393
LIST_ENTRY DelayedCloseQueue
Definition: cdstruc.h:392
BOOLEAN FspCloseActive
Definition: cdstruc.h:384
BOOLEAN ReduceDelayedClose
Definition: cdstruc.h:385
PVCB Vcb
Definition: cdstruc.h:939
ULONG MinDelayedCloseCount
Definition: cdstruc.h:395
base of all file and directory entries
Definition: entries.h:82
#define CdUnlockCdData()
Definition: cdprocs.h:1024