Source code of Windows XP (NT5)
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.

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