Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

997 lines
28 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ResrcSup.c
  5. Abstract:
  6. This module implements the Rx Resource acquisition routines
  7. Author:
  8. Joe Linn [JoeLi] 22-Mar-1995
  9. Revision History:
  10. Balan Sethu Raman [SethuR] 7-June-95
  11. Modified return value of resource acquistion routines to RXSTATUS to incorporate
  12. aborts of cancelled requests.
  13. Balan Sethu Raman [SethuR] 8-Nov-95
  14. Unified FCB resource acquistion routines and incorporated the two step process
  15. for handling change buffering state requests in progress.
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. //
  20. // no special bug check id for this module
  21. //
  22. #define BugCheckFileId (0)
  23. //
  24. // The local debug trace level
  25. //
  26. #define Dbg (DEBUG_TRACE_RESRCSUP)
  27. #ifdef RDBSS_TRACKER
  28. #define TRACKER_Doit(XXX__) XXX__
  29. #define TRACKER_ONLY_DECL(XXX__) XXX__
  30. VOID RxTrackerUpdateHistory (
  31. PRX_CONTEXT RxContext,
  32. IN OUT PMRX_FCB MrxFcb,
  33. IN ULONG Operation,
  34. IN ULONG LineNumber,
  35. IN PSZ FileName,
  36. IN ULONG SerialNumber
  37. )
  38. {
  39. PFCB Fcb = (PFCB)MrxFcb;
  40. ULONG i;
  41. RX_FCBTRACKER_CASES TrackerType;
  42. //
  43. // boy this is some great code!
  44. //
  45. if (RxContext == NULL) {
  46. TrackerType = (RX_FCBTRACKER_CASE_NULLCONTEXT);
  47. } else if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT) {
  48. TrackerType = (RX_FCBTRACKER_CASE_CBS_CONTEXT);
  49. } else if (RxContext == CHANGE_BUFFERING_STATE_CONTEXT_WAIT) {
  50. TrackerType = (RX_FCBTRACKER_CASE_CBS_WAIT_CONTEXT);
  51. } else {
  52. ASSERT( NodeType( RxContext ) == RDBSS_NTC_RX_CONTEXT );
  53. TrackerType = (RX_FCBTRACKER_CASE_NORMAL);
  54. }
  55. if (Fcb != NULL) {
  56. ASSERT( NodeTypeIsFcb( Fcb ) );
  57. if (Operation == 'aaaa') {
  58. Fcb->FcbAcquires[TrackerType] += 1;
  59. } else {
  60. Fcb->FcbReleases[TrackerType] += 1;
  61. }
  62. }
  63. if (TrackerType != RX_FCBTRACKER_CASE_NORMAL) {
  64. return;
  65. }
  66. if (Operation == 'aaaa') {
  67. InterlockedIncrement( &RxContext->AcquireReleaseFcbTrackerX );
  68. } else {
  69. InterlockedDecrement( &RxContext->AcquireReleaseFcbTrackerX );
  70. }
  71. i = InterlockedIncrement( &RxContext->TrackerHistoryPointer ) - 1;
  72. if (i < RDBSS_TRACKER_HISTORY_SIZE) {
  73. RxContext->TrackerHistory[i].AcquireRelease = Operation;
  74. RxContext->TrackerHistory[i].LineNumber = (USHORT)LineNumber;
  75. RxContext->TrackerHistory[i].FileName = FileName;
  76. RxContext->TrackerHistory[i].SavedTrackerValue = (USHORT)(RxContext->AcquireReleaseFcbTrackerX);
  77. RxContext->TrackerHistory[i].Flags = (ULONG)(RxContext->Flags);
  78. }
  79. ASSERT( RxContext->AcquireReleaseFcbTrackerX >= 0 );
  80. }
  81. #else
  82. #define TRACKER_Doit(XXX__)
  83. #define TRACKER_ONLY_DECL(XXX__)
  84. #endif
  85. #ifdef ALLOC_PRAGMA
  86. #pragma alloc_text(PAGE, RxAcquireExclusiveFcbResourceInMRx)
  87. #pragma alloc_text(PAGE, RxAcquireSharedFcbResourceInMRx)
  88. #pragma alloc_text(PAGE, RxReleaseFcbResourceInMRx)
  89. #pragma alloc_text(PAGE, __RxAcquireFcb)
  90. #pragma alloc_text(PAGE, RxAcquireFcbForLazyWrite)
  91. #pragma alloc_text(PAGE, RxAcquireFcbForReadAhead)
  92. #pragma alloc_text(PAGE, RxNoOpAcquire)
  93. #pragma alloc_text(PAGE, RxNoOpRelease)
  94. #pragma alloc_text(PAGE, RxReleaseFcbFromLazyWrite)
  95. #pragma alloc_text(PAGE, RxReleaseFcbFromReadAhead)
  96. #pragma alloc_text(PAGE, RxVerifyOperationIsLegal)
  97. #pragma alloc_text(PAGE, RxAcquireFileForNtCreateSection)
  98. #pragma alloc_text(PAGE, RxReleaseFileForNtCreateSection)
  99. #endif
  100. NTSTATUS
  101. RxAcquireExclusiveFcbResourceInMRx (
  102. PMRX_FCB Fcb
  103. )
  104. {
  105. return RxAcquireExclusiveFcb( NULL, (PFCB)Fcb );
  106. }
  107. NTSTATUS
  108. RxAcquireSharedFcbResourceInMRx (
  109. PMRX_FCB Fcb
  110. )
  111. {
  112. return RxAcquireSharedFcb( NULL, (PFCB)Fcb );
  113. }
  114. VOID
  115. RxReleaseFcbResourceInMRx (
  116. PMRX_FCB Fcb
  117. )
  118. {
  119. RxReleaseFcb( NULL, Fcb );
  120. }
  121. NTSTATUS
  122. __RxAcquireFcb(
  123. IN OUT PFCB Fcb,
  124. IN PRX_CONTEXT RxContext OPTIONAL,
  125. IN ULONG Mode
  126. #ifdef RDBSS_TRACKER
  127. ,ULONG LineNumber,
  128. PSZ FileName,
  129. ULONG SerialNumber
  130. #endif
  131. )
  132. /*++
  133. Routine Description:
  134. This routine acquires the Fcb in the specified mode and ensures that the desired
  135. operation is legal. If it is not legal the resource is released and the
  136. appropriate error code is returned.
  137. Arguments:
  138. Fcb - the FCB
  139. RxContext - supplies the context of the operation for special treatement
  140. particularly of async, noncached writes. if NULL, you don't do
  141. the special treatment.
  142. Mode - the mode in which the FCB is to be acquired.
  143. Return Value:
  144. STATUS_SUCCESS -- the Fcb was acquired
  145. STATUS_LOCK_NOT_GRANTED -- the resource was not acquired
  146. STATUS_CANCELLED -- the associated RxContext was cancelled.
  147. Notes:
  148. There are three kinds of resource acquistion patterns folded into this routine.
  149. These are all dependent upon the context passed in.
  150. 1) When the context parameter is NULL the resource acquistion routines wait for the
  151. the FCB resource to be free, i.e., this routine does not return control till the
  152. resource has been accquired.
  153. 2) When the context is CHANGE_BUFFERING_STATE_CONTEXT the resource acquistion routines
  154. do not wait for the resource to become free. The control is returned if the resource is not
  155. available immmediately.
  156. 2) When the context is CHANGE_BUFFERING_STATE_CONTEXT_WAIT the resource acquistion routines
  157. wait for the resource to become free but bypass the wait for the buffering state change
  158. 3) When the context parameter represents a valid context the behaviour is dictated
  159. by the flags associated with the context. If the context was cancelled while
  160. waiting the control is returned immediately with the appropriate erroc code
  161. (STATUS_CANCELLED). If not the waiting behaviour is dictated by the wait flag in
  162. the context.
  163. --*/
  164. {
  165. NTSTATUS Status = STATUS_SUCCESS;
  166. BOOLEAN ResourceAcquired;
  167. BOOLEAN UncachedAsyncWrite;
  168. BOOLEAN Wait;
  169. BOOLEAN ValidContext = FALSE;
  170. BOOLEAN RecursiveAcquire;
  171. BOOLEAN ChangeBufferingStateContext;
  172. PAGED_CODE();
  173. ChangeBufferingStateContext = (RxContext == CHANGE_BUFFERING_STATE_CONTEXT) ||
  174. (RxContext == CHANGE_BUFFERING_STATE_CONTEXT_WAIT);
  175. RecursiveAcquire = RxIsFcbAcquiredExclusive( Fcb ) || (RxIsFcbAcquiredShared( Fcb ) > 0);
  176. if (!RecursiveAcquire && !ChangeBufferingStateContext) {
  177. //
  178. // Ensure that no change buffering requests are currently being processed
  179. //
  180. if (FlagOn( Fcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING )) {
  181. BOOLEAN WaitForChangeBufferingStateProcessing;
  182. //
  183. // A buffering change state request is pending which gets priority
  184. // over all other FCB resource acquistion requests. Hold this request
  185. // till the buffering state change request has been completed.
  186. //
  187. RxAcquireSerializationMutex();
  188. WaitForChangeBufferingStateProcessing = BooleanFlagOn( Fcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING );
  189. RxReleaseSerializationMutex();
  190. if (WaitForChangeBufferingStateProcessing) {
  191. RxLog(( "_RxAcquireFcb CBS wait %lx\n", Fcb ));
  192. RxWmiLog( LOG,
  193. RxAcquireFcb_1,
  194. LOGPTR( Fcb ) );
  195. ASSERT( Fcb->pBufferingStateChangeCompletedEvent != NULL );
  196. KeWaitForSingleObject( Fcb->pBufferingStateChangeCompletedEvent,
  197. Executive,
  198. KernelMode,
  199. FALSE,
  200. (PLARGE_INTEGER)NULL );
  201. RxLog(( "_RxAcquireFcb CBS wait over %lx\n", Fcb ));
  202. RxWmiLog( LOG,
  203. RxAcquireFcb_2,
  204. LOGPTR( Fcb ) );
  205. }
  206. }
  207. }
  208. //
  209. // Set up the parameters for acquiring the resource.
  210. //
  211. if (ChangeBufferingStateContext) {
  212. //
  213. // An acquisition operation initiated for changing the buffering state will
  214. // not wait.
  215. //
  216. Wait = (RxContext == CHANGE_BUFFERING_STATE_CONTEXT_WAIT);
  217. UncachedAsyncWrite = FALSE;
  218. } else if (RxContext == NULL) {
  219. Wait = TRUE;
  220. UncachedAsyncWrite = FALSE;
  221. } else {
  222. ValidContext = TRUE;
  223. Wait = BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT );
  224. UncachedAsyncWrite = (RxContext->MajorFunction == IRP_MJ_WRITE) &&
  225. FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION ) &&
  226. (FlagOn( RxContext->CurrentIrp->Flags, IRP_NOCACHE ) ||
  227. !RxWriteCachingAllowed( Fcb, ((PFOBX)(RxContext->pFobx))->SrvOpen ));
  228. if (FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED )) {
  229. Status = STATUS_CANCELLED;
  230. } else {
  231. Status = STATUS_SUCCESS;
  232. }
  233. }
  234. if (Status == STATUS_SUCCESS) {
  235. do {
  236. Status = STATUS_LOCK_NOT_GRANTED;
  237. switch (Mode) {
  238. case FCB_MODE_EXCLUSIVE:
  239. ResourceAcquired = ExAcquireResourceExclusiveLite( Fcb->Header.Resource, Wait );
  240. break;
  241. case FCB_MODE_SHARED:
  242. ResourceAcquired = ExAcquireResourceSharedLite( Fcb->Header.Resource, Wait );
  243. break;
  244. case FCB_MODE_SHARED_WAIT_FOR_EXCLUSIVE:
  245. ResourceAcquired = ExAcquireSharedWaitForExclusive( Fcb->Header.Resource, Wait );
  246. break;
  247. case FCB_MODE_SHARED_STARVE_EXCLUSIVE:
  248. ResourceAcquired = ExAcquireSharedStarveExclusive( Fcb->Header.Resource, Wait );
  249. break;
  250. default:
  251. ASSERTMSG( "Valid Mode for acquiring FCB resource", FALSE );
  252. ResourceAcquired = FALSE;
  253. break;
  254. }
  255. if (ResourceAcquired) {
  256. Status = STATUS_SUCCESS;
  257. //
  258. // If the resource was acquired and it is an async. uncached write operation
  259. // if the number of outstanding writes operations are greater than zero and there
  260. // are outstanding waiters,
  261. //
  262. ASSERT_CORRECT_FCB_STRUCTURE( Fcb );
  263. if ((Fcb->NonPaged->OutstandingAsyncWrites != 0) &&
  264. (!UncachedAsyncWrite ||
  265. (Fcb->Header.Resource->NumberOfSharedWaiters != 0) ||
  266. (Fcb->Header.Resource->NumberOfExclusiveWaiters != 0))) {
  267. KeWaitForSingleObject( Fcb->NonPaged->OutstandingAsyncEvent,
  268. Executive,
  269. KernelMode,
  270. FALSE,
  271. (PLARGE_INTEGER)NULL );
  272. ASSERT_CORRECT_FCB_STRUCTURE(Fcb);
  273. RxReleaseFcb( NULL, Fcb ); // this is not a contextful release;
  274. #ifdef RDBSS_TRACKER
  275. //
  276. // in fact, this doesn't count as a release at all; dec the count
  277. //
  278. Fcb->FcbReleases[RX_FCBTRACKER_CASE_NULLCONTEXT] -= 1;
  279. #endif
  280. ResourceAcquired = FALSE;
  281. if (ValidContext) {
  282. ASSERT(( NodeType( RxContext ) == RDBSS_NTC_RX_CONTEXT) );
  283. //
  284. // if the context is still valid, i.e., it has not been cancelled
  285. //
  286. if (FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED)) {
  287. Status = STATUS_CANCELLED;
  288. } else {
  289. Status = STATUS_SUCCESS;
  290. }
  291. }
  292. }
  293. }
  294. } while (!ResourceAcquired && (Status == STATUS_SUCCESS));
  295. if (ResourceAcquired &&
  296. ValidContext &&
  297. !FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK )) {
  298. try {
  299. RxVerifyOperationIsLegal( RxContext );
  300. } finally {
  301. if ( AbnormalTermination() ) {
  302. ExReleaseResourceLite( Fcb->Header.Resource );
  303. Status = STATUS_LOCK_NOT_GRANTED;
  304. }
  305. }
  306. }
  307. }
  308. #ifdef RDBSS_TRACKER
  309. if (Status == STATUS_SUCCESS) {
  310. RxTrackerUpdateHistory( RxContext, (PMRX_FCB)Fcb, 'aaaa', LineNumber, FileName, SerialNumber );
  311. }
  312. #endif
  313. return Status;
  314. }
  315. VOID
  316. __RxReleaseFcb(
  317. IN PRX_CONTEXT RxContext,
  318. IN OUT PMRX_FCB MrxFcb
  319. #ifdef RDBSS_TRACKER
  320. ,IN ULONG LineNumber,
  321. IN PSZ FileName,
  322. IN ULONG SerialNumber
  323. #endif
  324. )
  325. {
  326. PFCB Fcb = (PFCB)MrxFcb;
  327. BOOLEAN ChangeBufferingStateRequestsPending;
  328. BOOLEAN ResourceExclusivelyOwned;
  329. RxAcquireSerializationMutex();
  330. ChangeBufferingStateRequestsPending = BooleanFlagOn( Fcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING );
  331. ResourceExclusivelyOwned = RxIsResourceOwnershipStateExclusive( Fcb->Header.Resource );
  332. if (!ChangeBufferingStateRequestsPending) {
  333. RxTrackerUpdateHistory( RxContext, MrxFcb, 'rrrr', LineNumber, FileName, SerialNumber );
  334. ExReleaseResourceLite( Fcb->Header.Resource );
  335. } else if (!ResourceExclusivelyOwned) {
  336. RxTrackerUpdateHistory( RxContext, MrxFcb, 'rrr0', LineNumber, FileName, SerialNumber );
  337. ExReleaseResourceLite( Fcb->Header.Resource );
  338. }
  339. RxReleaseSerializationMutex();
  340. if (ChangeBufferingStateRequestsPending) {
  341. if (ResourceExclusivelyOwned) {
  342. ASSERT( RxIsFcbAcquiredExclusive( Fcb ) );
  343. //
  344. // If there are any buffering state change requests process them.
  345. //
  346. RxProcessFcbChangeBufferingStateRequest( Fcb );
  347. RxTrackerUpdateHistory( RxContext, MrxFcb, 'rrr1', LineNumber, FileName, SerialNumber );
  348. ExReleaseResourceLite( Fcb->Header.Resource );
  349. }
  350. }
  351. }
  352. VOID
  353. __RxReleaseFcbForThread(
  354. IN PRX_CONTEXT RxContext,
  355. IN OUT PMRX_FCB MrxFcb,
  356. IN ERESOURCE_THREAD ResourceThreadId
  357. #ifdef RDBSS_TRACKER
  358. ,IN ULONG LineNumber,
  359. IN PSZ FileName,
  360. IN ULONG SerialNumber
  361. #endif
  362. )
  363. {
  364. PFCB Fcb = (PFCB)MrxFcb;
  365. BOOLEAN BufferingInTransistion;
  366. BOOLEAN ExclusivelyOwned;
  367. RxAcquireSerializationMutex();
  368. BufferingInTransistion = BooleanFlagOn( Fcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING );
  369. RxReleaseSerializationMutex();
  370. ExclusivelyOwned = RxIsResourceOwnershipStateExclusive( Fcb->Header.Resource );
  371. if (!BufferingInTransistion) {
  372. RxTrackerUpdateHistory( RxContext, MrxFcb, 'rrtt', LineNumber, FileName, SerialNumber );
  373. } else if (!ExclusivelyOwned) {
  374. RxTrackerUpdateHistory( RxContext, MrxFcb, 'rrt0', LineNumber, FileName, SerialNumber );
  375. } else {
  376. //
  377. // If there are any buffering state change requests process them.
  378. //
  379. RxTrackerUpdateHistory( RxContext,MrxFcb, 'rrt1', LineNumber, FileName, SerialNumber );
  380. RxProcessFcbChangeBufferingStateRequest( Fcb );
  381. }
  382. ExReleaseResourceForThreadLite( Fcb->Header.Resource, ResourceThreadId );
  383. }
  384. BOOLEAN
  385. RxAcquireFcbForLazyWrite (
  386. IN PVOID Fcb,
  387. IN BOOLEAN Wait
  388. )
  389. /*++
  390. Routine Description:
  391. The address of this routine is specified when creating a CacheMap for
  392. a file. It is subsequently called by the Lazy Writer prior to its
  393. performing lazy writes to the file.
  394. Arguments:
  395. Fcb - The Fcb which was specified as a context parameter for this
  396. routine.
  397. Wait - TRUE if the caller is willing to block.
  398. Return Value:
  399. FALSE - if Wait was specified as FALSE and blocking would have
  400. been required. The Fcb is not acquired.
  401. TRUE - if the Fcb has been acquired
  402. --*/
  403. {
  404. PFCB ThisFcb = (PFCB)Fcb;
  405. BOOLEAN AcquiredFile;
  406. //
  407. // We assume the Lazy Writer only acquires this Fcb once.
  408. // Therefore, it should be guaranteed that this flag is currently
  409. // clear and then we will set this flag, to insure
  410. // that the Lazy Writer will never try to advance Valid Data, and
  411. // also not deadlock by trying to get the Fcb exclusive.
  412. //
  413. PAGED_CODE();
  414. ASSERT_CORRECT_FCB_STRUCTURE( ThisFcb );
  415. AcquiredFile = RxAcquirePagingIoResourceShared( NULL, ThisFcb, Wait );
  416. if (AcquiredFile) {
  417. //
  418. // This is a kludge because Cc is really the top level. When it
  419. // enters the file system, we will think it is a resursive call
  420. // and complete the request with hard errors or verify. It will
  421. // then have to deal with them, somehow....
  422. //
  423. ASSERT( RxIsThisTheTopLevelIrp( NULL ) );
  424. AcquiredFile = RxTryToBecomeTheTopLevelIrp( NULL,
  425. (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP,
  426. ((PFCB)Fcb)->RxDeviceObject,
  427. TRUE ); // force
  428. if (!AcquiredFile) {
  429. RxReleasePagingIoResource( NULL, ThisFcb );
  430. }
  431. }
  432. return AcquiredFile;
  433. }
  434. VOID
  435. RxReleaseFcbFromLazyWrite (
  436. IN PVOID Fcb
  437. )
  438. /*++
  439. Routine Description:
  440. The address of this routine is specified when creating a CacheMap for
  441. a file. It is subsequently called by the Lazy Writer after its
  442. performing lazy writes to the file.
  443. Arguments:
  444. Fcb - The Fcb which was specified as a context parameter for this
  445. routine.
  446. Return Value:
  447. None
  448. --*/
  449. {
  450. PFCB ThisFcb = (PFCB)Fcb;
  451. PAGED_CODE();
  452. ASSERT_CORRECT_FCB_STRUCTURE( ThisFcb );
  453. //
  454. // Clear the kludge at this point.
  455. //
  456. //
  457. // NTBUG #61902 this is a paged pool leak if the test fails....in fastfat, they assert
  458. // that the condition is true.
  459. //
  460. if(RxGetTopIrpIfRdbssIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) {
  461. RxUnwindTopLevelIrp( NULL );
  462. }
  463. RxReleasePagingIoResource( NULL, ThisFcb );
  464. return;
  465. }
  466. BOOLEAN
  467. RxAcquireFcbForReadAhead (
  468. IN PVOID Fcb,
  469. IN BOOLEAN Wait
  470. )
  471. /*++
  472. Routine Description:
  473. The address of this routine is specified when creating a CacheMap for
  474. a file. It is subsequently called by the Lazy Writer prior to its
  475. performing read ahead to the file.
  476. Arguments:
  477. Fcb - The Fcb which was specified as a context parameter for this
  478. routine.
  479. Wait - TRUE if the caller is willing to block.
  480. Return Value:
  481. FALSE - if Wait was specified as FALSE and blocking would have
  482. been required. The Fcb is not acquired.
  483. TRUE - if the Fcb has been acquired
  484. --*/
  485. {
  486. PFCB ThisFcb = (PFCB)Fcb;
  487. BOOLEAN AcquiredFile;
  488. PAGED_CODE();
  489. ASSERT_CORRECT_FCB_STRUCTURE( ThisFcb );
  490. //
  491. // We acquire the normal file resource shared here to synchronize
  492. // correctly with purges.
  493. //
  494. if (!ExAcquireResourceSharedLite( ThisFcb->Header.Resource, Wait )) {
  495. return FALSE;
  496. }
  497. //
  498. // This is a kludge because Cc is really the top level. We it
  499. // enters the file system, we will think it is a resursive call
  500. // and complete the request with hard errors or verify. It will
  501. // have to deal with them, somehow....
  502. //
  503. ASSERT( RxIsThisTheTopLevelIrp( NULL ) );
  504. AcquiredFile = RxTryToBecomeTheTopLevelIrp( NULL,
  505. (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP,
  506. ((PFCB)Fcb)->RxDeviceObject,
  507. TRUE ); // force
  508. if (!AcquiredFile) {
  509. ExReleaseResourceLite( ThisFcb->Header.Resource );
  510. }
  511. return AcquiredFile;
  512. }
  513. VOID
  514. RxReleaseFcbFromReadAhead (
  515. IN PVOID Fcb
  516. )
  517. /*++
  518. Routine Description:
  519. The address of this routine is specified when creating a CacheMap for
  520. a file. It is subsequently called by the Lazy Writer after its
  521. read ahead.
  522. Arguments:
  523. Fcb - The Fcb which was specified as a context parameter for this
  524. routine.
  525. Return Value:
  526. None
  527. --*/
  528. {
  529. PFCB ThisFcb = (PFCB)Fcb;
  530. PAGED_CODE();
  531. ASSERT_CORRECT_FCB_STRUCTURE( ThisFcb );
  532. //
  533. // Clear the kludge at this point.
  534. //
  535. ASSERT( RxGetTopIrpIfRdbssIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP );
  536. RxUnwindTopLevelIrp( NULL );
  537. ExReleaseResourceLite( ThisFcb->Header.Resource );
  538. return;
  539. }
  540. VOID
  541. RxVerifyOperationIsLegal (
  542. IN PRX_CONTEXT RxContext
  543. )
  544. /*++
  545. Routine Description:
  546. This routine determines is the requested operation should be allowed to
  547. continue. It either returns to the user if the request is Okay, or
  548. raises an appropriate status.
  549. Arguments:
  550. Irp - Supplies the Irp to check
  551. Return Value:
  552. None.
  553. --*/
  554. {
  555. PIRP Irp = RxContext->CurrentIrp;
  556. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  557. PFILE_OBJECT FileObject = IrpSp->FileObject;
  558. PFOBX Fobx = (PFOBX)RxContext->pFobx;
  559. #if DBG
  560. ULONG SaveExceptionFlag; //to save the state of breakpoint-on-exception for this context
  561. #endif
  562. PAGED_CODE();
  563. //
  564. // If the Irp is not present, then we got here via close. If there isn't a fileobject
  565. // we also can't continue
  566. //
  567. if ((Irp == NULL) || (FileObject == NULL)) {
  568. return;
  569. }
  570. RxSaveAndSetExceptionNoBreakpointFlag( RxContext, SaveExceptionFlag );
  571. if (Fobx) {
  572. PSRV_OPEN SrvOpen = (PSRV_OPEN)Fobx->SrvOpen;
  573. //
  574. // If we are trying to do any other operation than close on a file
  575. // object that has been renamed, raise RxStatus(FILE_RENAMED).
  576. //
  577. if ((SrvOpen != NULL) &&
  578. (RxContext->MajorFunction != IRP_MJ_CLEANUP) &&
  579. (RxContext->MajorFunction != IRP_MJ_CLOSE) &&
  580. (FlagOn( SrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED ))) {
  581. RxRaiseStatus( RxContext, STATUS_FILE_RENAMED );
  582. }
  583. //
  584. // If we are trying to do any other operation than close on a file
  585. // object that has been deleted, raise RxStatus(FILE_DELETED).
  586. //
  587. if ((SrvOpen != NULL) &&
  588. (RxContext->MajorFunction != IRP_MJ_CLEANUP) &&
  589. (RxContext->MajorFunction != IRP_MJ_CLOSE) &&
  590. (FlagOn( SrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED ))) {
  591. RxRaiseStatus( RxContext, STATUS_FILE_DELETED );
  592. }
  593. }
  594. //
  595. // If we are doing a create, and there is a related file object, and
  596. // it it is marked for delete, raise RxStatus(DELETE_PENDING).
  597. //
  598. if (RxContext->MajorFunction == IRP_MJ_CREATE) {
  599. PFILE_OBJECT RelatedFileObject;
  600. RelatedFileObject = FileObject->RelatedFileObject;
  601. if ((RelatedFileObject != NULL) &&
  602. FlagOn( ((PFCB)RelatedFileObject->FsContext)->FcbState, FCB_STATE_DELETE_ON_CLOSE ) ) {
  603. RxRaiseStatus( RxContext, STATUS_DELETE_PENDING );
  604. }
  605. }
  606. //
  607. // If the file object has already been cleaned up, and
  608. //
  609. // A) This request is a paging io read or write, or
  610. // B) This request is a close operation, or
  611. // C) This request is a set or query info call (for Lou)
  612. // D) This is an MDL complete
  613. //
  614. // let it pass, otherwise return RxStatus(FILE_CLOSED).
  615. //
  616. if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) {
  617. if ((FlagOn( Irp->Flags, IRP_PAGING_IO )) ||
  618. (IrpSp->MajorFunction == IRP_MJ_CLEANUP) ||
  619. (IrpSp->MajorFunction == IRP_MJ_CLOSE) ||
  620. (IrpSp->MajorFunction == IRP_MJ_SET_INFORMATION) ||
  621. (IrpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION) ||
  622. (((IrpSp->MajorFunction == IRP_MJ_READ) ||
  623. (IrpSp->MajorFunction == IRP_MJ_WRITE)) &&
  624. FlagOn( IrpSp->MinorFunction, IRP_MN_COMPLETE ))) {
  625. NOTHING;
  626. } else {
  627. RxRaiseStatus( RxContext, STATUS_FILE_CLOSED );
  628. }
  629. }
  630. RxRestoreExceptionNoBreakpointFlag( RxContext, SaveExceptionFlag );
  631. return;
  632. }
  633. VOID
  634. RxAcquireFileForNtCreateSection (
  635. IN PFILE_OBJECT FileObject
  636. )
  637. {
  638. NTSTATUS Status;
  639. PFCB Fcb = (PFCB)FileObject->FsContext;
  640. PAGED_CODE();
  641. Status = RxAcquireExclusiveFcb( NULL, Fcb );
  642. #if DBG
  643. if (Status != STATUS_SUCCESS) {
  644. RxBugCheck( (ULONG_PTR)Fcb, 0, 0 );
  645. }
  646. #endif
  647. //
  648. // Inform lwio rdr of this call after we get the lock.
  649. // It would be nice if we could fail the create section
  650. // call the same way filter drivers can.
  651. //
  652. if (FlagOn( Fcb->FcbState, FCB_STATE_LWIO_ENABLED )) {
  653. PFAST_IO_DISPATCH FastIoDispatch = Fcb->MRxFastIoDispatch;
  654. if (FastIoDispatch &&
  655. FastIoDispatch->AcquireFileForNtCreateSection) {
  656. FastIoDispatch->AcquireFileForNtCreateSection( FileObject );
  657. }
  658. }
  659. }
  660. VOID
  661. RxReleaseFileForNtCreateSection (
  662. IN PFILE_OBJECT FileObject
  663. )
  664. {
  665. PMRX_FCB Fcb = (PMRX_FCB)FileObject->FsContext;
  666. PAGED_CODE();
  667. //
  668. // Inform lwio rdr of this call before we drop the lock
  669. //
  670. if (FlagOn( Fcb->FcbState, FCB_STATE_LWIO_ENABLED )) {
  671. PFAST_IO_DISPATCH FastIoDispatch = ((PFCB)Fcb)->MRxFastIoDispatch;
  672. if (FastIoDispatch &&
  673. FastIoDispatch->AcquireFileForNtCreateSection) {
  674. FastIoDispatch->AcquireFileForNtCreateSection( FileObject );
  675. }
  676. }
  677. RxReleaseFcb( NULL, Fcb );
  678. }
  679. NTSTATUS
  680. RxAcquireForCcFlush (
  681. IN PFILE_OBJECT FileObject,
  682. IN PDEVICE_OBJECT DeviceObject
  683. )
  684. {
  685. return STATUS_INVALID_DEVICE_REQUEST;
  686. }
  687. NTSTATUS
  688. RxReleaseForCcFlush (
  689. IN PFILE_OBJECT FileObject,
  690. IN PDEVICE_OBJECT DeviceObject
  691. )
  692. {
  693. return STATUS_INVALID_DEVICE_REQUEST;
  694. }
  695. VOID
  696. RxTrackPagingIoResource (
  697. PVOID Instance,
  698. ULONG Type,
  699. ULONG Line,
  700. PCHAR File)
  701. {
  702. PFCB Fcb = (PFCB)Instance;
  703. switch(Type) {
  704. case 1:
  705. case 2:
  706. Fcb->PagingIoResourceFile = File;
  707. Fcb->PagingIoResourceLine = Line;
  708. break;
  709. case 3:
  710. Fcb->PagingIoResourceFile = NULL;
  711. Fcb->PagingIoResourceLine = 0;
  712. break;
  713. }
  714. }