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.

557 lines
13 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. FilObSup.c
  5. Abstract:
  6. This module implements the Rx File object support routines.
  7. Author:
  8. Gary Kimura [GaryKi] 30-Aug-1990
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // The Bug check file id for this module
  15. //
  16. #define BugCheckFileId (RDBSS_BUG_CHECK_FILOBSUP)
  17. //
  18. // The debug trace level
  19. //
  20. #define Dbg (DEBUG_TRACE_FILOBSUP)
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, RxForceCacheMiss)
  23. //#pragma alloc_text(PAGE, RxPurgeReferencedFileObjects)
  24. #pragma alloc_text(PAGE, RxSetFileObject)
  25. //#pragma alloc_text(PAGE, RxDecodeFileObject)
  26. #endif
  27. VOID
  28. RxSetFileObject (
  29. IN PFILE_OBJECT FileObject OPTIONAL,
  30. IN TYPE_OF_OPEN TypeOfOpen,
  31. IN PVOID VcbOrFcbOrDcb,
  32. IN PFOBX Fobx OPTIONAL
  33. )
  34. /*++
  35. Routine Description:
  36. This routine sets the file system pointers within the file object
  37. Arguments:
  38. FileObject - Supplies a pointer to the file object being modified, and
  39. can optionally be null.
  40. TypeOfOpen - Supplies the type of open denoted by the file object.
  41. This is only used by this procedure for sanity checking.
  42. //joejoe i disabled this because i'm not using the same open types
  43. VcbOrFcbOrDcb - Supplies a pointer to either a vcb, fcb, or dcb
  44. Fobx - Optionally supplies a pointer to a ccb
  45. Return Value:
  46. None.
  47. --*/
  48. {
  49. RxDbgTrace(+1, Dbg, ("RxSetFileObject, FileObject = %08lx\n", FileObject ));
  50. ASSERT((Fobx == NULL) || (NodeType(Fobx) == RDBSS_NTC_FOBX));
  51. /*
  52. ASSERT(((TypeOfOpen == UnopenedFileObject))
  53. ||
  54. ((TypeOfOpen == UserFileOpen) &&
  55. (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_FCB) &&
  56. (Fobx != NULL))
  57. ||
  58. ((TypeOfOpen == EaFile) &&
  59. (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_FCB) &&
  60. (Fobx == NULL))
  61. ||
  62. ((TypeOfOpen == UserDirectoryOpen) &&
  63. ((NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_DCB) || (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_ROOT_DCB)) &&
  64. (Fobx != NULL))
  65. ||
  66. ((TypeOfOpen == UserVolumeOpen) &&
  67. (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_VCB) &&
  68. (Fobx != NULL))
  69. ||
  70. ((TypeOfOpen == VirtualVolumeFile) &&
  71. (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_VCB) &&
  72. (Fobx == NULL))
  73. ||
  74. ((TypeOfOpen == DirectoryFile) &&
  75. ((NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_DCB) || (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_ROOT_DCB)) &&
  76. (Fobx == NULL)));
  77. */
  78. //
  79. // If we were given an Fcb, Dcb, or Vcb, we have some processing to do.
  80. //
  81. ASSERT((Fobx == NULL) || (NodeType(Fobx) == RDBSS_NTC_FOBX));
  82. if ( VcbOrFcbOrDcb != NULL ) {
  83. //
  84. // Set the Vpb field in the file object, and if we were given an
  85. // Fcb or Dcb move the field over to point to the nonpaged Fcb/Dcb
  86. //
  87. if (NodeType(VcbOrFcbOrDcb) == RDBSS_NTC_VCB) {
  88. NOTHING; //FileObject->Vpb = ((PVCB)VcbOrFcbOrDcb)->Vpb;
  89. } else {
  90. //joejoe we don't do vpbs
  91. //FileObject->Vpb = ((PFCB)VcbOrFcbOrDcb)->Vcb->Vpb;
  92. //
  93. // If this is a temporary file, note it in the FcbState
  94. //
  95. if (FlagOn(((PFCB)VcbOrFcbOrDcb)->FcbState, FCB_STATE_TEMPORARY)) {
  96. SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
  97. }
  98. }
  99. }
  100. ASSERT((Fobx == NULL) || (NodeType(Fobx) == RDBSS_NTC_FOBX));
  101. //
  102. // Now set the fscontext fields of the file object
  103. //
  104. if (ARGUMENT_PRESENT( FileObject )) {
  105. FileObject->FsContext = VcbOrFcbOrDcb;
  106. FileObject->FsContext2 = Fobx;
  107. }
  108. ASSERT((Fobx == NULL) || (NodeType(Fobx) == RDBSS_NTC_FOBX));
  109. //
  110. // And return to our caller
  111. //
  112. RxDbgTrace(-1, Dbg, ("RxSetFileObject -> VOID\n", 0));
  113. return;
  114. }
  115. #if 0
  116. TYPE_OF_OPEN
  117. RxDecodeFileObject (
  118. IN PFILE_OBJECT FileObject,
  119. OUT PVCB *Vcb,
  120. OUT PFCB *FcbOrDcb,
  121. OUT PFOBX *Fobx
  122. )
  123. /*++
  124. Routine Description:
  125. This procedure takes a pointer to a file object, that has already been
  126. opened by the Rx file system and figures out what really is opened.
  127. Arguments:
  128. FileObject - Supplies the file object pointer being interrogated
  129. Vcb - Receives a pointer to the Vcb for the file object.
  130. FcbOrDcb - Receives a pointer to the Fcb/Dcb for the file object, if
  131. one exists.
  132. Fobx - Receives a pointer to the Fobx for the file object, if one exists.
  133. Return Value:
  134. TYPE_OF_OPEN - returns the type of file denoted by the input file object.
  135. UserFileOpen - The FO represents a user's opened data file.
  136. Fobx, FcbOrDcb, and Vcb are set. FcbOrDcb points to an Fcb.
  137. UserDirectoryOpen - The FO represents a user's opened directory.
  138. Fobx, FcbOrDcb, and Vcb are set. FcbOrDcb points to a Dcb/RootDcb
  139. UserVolumeOpen - The FO represents a user's opened volume.
  140. Fobx and Vcb are set. FcbOrDcb is null.
  141. VirtualVolumeFile - The FO represents the special virtual volume file.
  142. Vcb is set, and Fobx and FcbOrDcb are null.
  143. DirectoryFile - The FO represents a special directory file.
  144. Vcb and FcbOrDcb are set. Fobx is null. FcbOrDcb points to a
  145. Dcb/RootDcb.
  146. EaFile - The FO represents an Ea Io stream file.
  147. FcbOrDcb, and Vcb are set. FcbOrDcb points to an Fcb, and Fobx is
  148. null.
  149. --*/
  150. {
  151. TYPE_OF_OPEN TypeOfOpen;
  152. PVOID FsContext;
  153. PVOID FsContext2;
  154. RxDbgTrace(+1, Dbg, ("RxDecodeFileObject, FileObject = %08lx\n", FileObject));
  155. //
  156. // Reference the fs context fields of the file object, and zero out
  157. // the out pointer parameters.
  158. //
  159. FsContext = FileObject->FsContext;
  160. FsContext2 = FileObject->FsContext2;
  161. //
  162. // Special case the situation where FsContext is null
  163. //
  164. if (FsContext == NULL) {
  165. *Fobx = NULL;
  166. *FcbOrDcb = NULL;
  167. *Vcb = NULL;
  168. TypeOfOpen = UnopenedFileObject;
  169. } else {
  170. //
  171. // Now we can case on the node type code of the fscontext pointer
  172. // and set the appropriate out pointers
  173. //
  174. switch (NodeType(FsContext)) {
  175. case RDBSS_NTC_VCB:
  176. *Fobx = FsContext2;
  177. *FcbOrDcb = NULL;
  178. *Vcb = FsContext;
  179. TypeOfOpen = ( *Fobx == NULL ? VirtualVolumeFile : UserVolumeOpen );
  180. break;
  181. case RDBSS_NTC_ROOT_DCB:
  182. case RDBSS_NTC_DCB:
  183. *Fobx = FsContext2;
  184. *FcbOrDcb = FsContext;
  185. *Vcb = (*FcbOrDcb)->Vcb;
  186. TypeOfOpen = ( *Fobx == NULL ? DirectoryFile : UserDirectoryOpen );
  187. RxDbgTrace(0, Dbg, ("Referencing directory: %wZ\n", &(*FcbOrDcb)->FullFileName));
  188. break;
  189. case RDBSS_NTC_FCB:
  190. *Fobx = FsContext2;
  191. *FcbOrDcb = FsContext;
  192. *Vcb = (*FcbOrDcb)->Vcb;
  193. TypeOfOpen = ( *Fobx == NULL ? EaFile : UserFileOpen );
  194. RxDbgTrace(0, Dbg, ("Referencing file: %wZ\n", &(*FcbOrDcb)->FullFileName));
  195. break;
  196. default:
  197. RxBugCheck( NodeType(FsContext), 0, 0 );
  198. }
  199. }
  200. //
  201. // and return to our caller
  202. //
  203. RxDbgTrace(-1, Dbg, ("RxDecodeFileObject -> %08lx\n", TypeOfOpen));
  204. return TypeOfOpen;
  205. }
  206. VOID
  207. RxPurgeReferencedFileObjects (
  208. IN PRX_CONTEXT RxContext,
  209. IN PFCB Fcb,
  210. IN BOOLEAN FlushFirst
  211. )
  212. /*++
  213. Routine Description:
  214. This routine non-recursively walks from the given FcbOrDcb and trys
  215. to force Cc or Mm to close any sections it may be holding on to.
  216. Arguments:
  217. Fcb - Supplies a pointer to either an fcb or a dcb
  218. FlushFirst - If given as TRUE, then the files are flushed before they
  219. are purged.
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. PFCB OriginalFcb = Fcb;
  225. PFCB NextFcb;
  226. RxDbgTrace(+1, Dbg, ("RxPurgeReferencedFileObjects, Fcb = %08lx\n", Fcb ));
  227. ASSERT(FALSE); //this shouldn't happen in the rdr.....it may play with volume opens
  228. ASSERT( FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT) );
  229. //close //
  230. //close // First, if we have a delayed close, force it closed.
  231. //close //
  232. //close
  233. //close RxFspClose(Fcb->Vcb);
  234. //
  235. // Walk the directory tree forcing sections closed.
  236. //
  237. // Note that it very important to get the next node to visit before
  238. // acting on the current node. This is because acting on a node may
  239. // make it, and an arbitrary number of direct ancestors, vanish.
  240. // Since we never visit ancestors in our enumeration scheme, we can
  241. // safely continue the enumeration even when the tree is vanishing
  242. // beneath us. This is way cool.
  243. //
  244. while ( Fcb != NULL ) {
  245. NextFcb = RxGetNextFcb(RxContext, Fcb, OriginalFcb);
  246. //
  247. // Check for the EA file fcb
  248. //
  249. if ( !FlagOn(Fcb->DirentRxFlags, RDBSS_DIRENT_ATTR_VOLUME_ID) ) {
  250. RxForceCacheMiss( RxContext, Fcb, FlushFirst );
  251. }
  252. Fcb = NextFcb;
  253. }
  254. RxDbgTrace(-1, Dbg, ("RxPurgeReferencedFileObjects (VOID)\n", 0 ));
  255. return;
  256. }
  257. #endif
  258. VOID
  259. RxForceCacheMiss (
  260. IN PRX_CONTEXT RxContext,
  261. IN PFCB Fcb,
  262. IN BOOLEAN FlushFirst
  263. )
  264. /*++
  265. Routine Description:
  266. The following routine asks either Cc or Mm to get rid of any cached
  267. pages on a file. Note that this will fail if a user has mapped a file.
  268. If there is a shared cache map, purge the cache section. Otherwise
  269. we have to go and ask Mm to blow away the section.
  270. NOTE: This caller MUST own the Vcb exclusive.
  271. Arguments:
  272. Fcb - Supplies a pointer to an fcb
  273. FlushFirst - If given as TRUE, then the files are flushed before they
  274. are purged.
  275. Return Value:
  276. None.
  277. --*/
  278. {
  279. PVCB Vcb;
  280. BOOLEAN ChildrenAcquired = FALSE;
  281. //
  282. // If we can't wait, bail.
  283. //
  284. ASSERT( RxVcbAcquiredExclusive( RxContext, Fcb->Vcb ) ||
  285. FlagOn( Fcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );
  286. if (!FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT)) {
  287. RxRaiseStatus( RxContext, RxStatus(CANT_WAIT) );
  288. }
  289. (VOID)RxAcquireExclusiveFcb( RxContext, Fcb );
  290. //
  291. // If we are purging a directory file object, we must acquire all the
  292. // FCBs exclusive so that the parent directory is not being pinned.
  293. //
  294. if ((NodeType(Fcb) != RDBSS_NTC_FCB) &&
  295. !IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) {
  296. PLIST_ENTRY Links;
  297. PFCB TempFcb;
  298. ChildrenAcquired = TRUE;
  299. for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
  300. Links != &Fcb->Specific.Dcb.ParentDcbQueue;
  301. Links = Links->Flink) {
  302. TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
  303. (VOID)RxAcquireExclusiveFcb( RxContext, TempFcb );
  304. }
  305. }
  306. //
  307. // We use this flag to indicate to a close beneath us that
  308. // the Fcb resource should be freed before deleting the Fcb.
  309. //
  310. Vcb = Fcb->Vcb;
  311. SetFlag( Fcb->FcbState, FCB_STATE_FORCE_MISS_IN_PROGRESS );
  312. ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );
  313. try {
  314. BOOLEAN DataSectionExists;
  315. BOOLEAN ImageSectionExists;
  316. PSECTION_OBJECT_POINTERS Section;
  317. if ( FlushFirst ) {
  318. (VOID)RxFlushFile( RxContext, Fcb );
  319. }
  320. //
  321. // The Flush may have made the Fcb go away
  322. //
  323. if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB)) {
  324. Section = &Fcb->NonPaged->SectionObjectPointers;
  325. DataSectionExists = (BOOLEAN)(Section->DataSectionObject != NULL);
  326. ImageSectionExists = (BOOLEAN)(Section->ImageSectionObject != NULL);
  327. //
  328. // Note, it is critical to do the Image section first as the
  329. // purge of the data section may cause the image section to go
  330. // away, but the opposite is not true.
  331. //
  332. if (ImageSectionExists) {
  333. (VOID)MmFlushImageSection( Section, MmFlushForWrite );
  334. }
  335. if (DataSectionExists) {
  336. CcPurgeCacheSection( Section, NULL, 0, FALSE );
  337. }
  338. }
  339. } finally {
  340. //
  341. // If we purging a directory file object, release all the Fcb
  342. // resources that we acquired above. The Dcb cannot have vanished
  343. // if there were Fcbs underneath it, and the Fcbs couldn't have gone
  344. // away since I own the Vcb.
  345. //
  346. if (ChildrenAcquired) {
  347. PLIST_ENTRY Links;
  348. PFCB TempFcb;
  349. for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
  350. Links != &Fcb->Specific.Dcb.ParentDcbQueue;
  351. Links = Links->Flink) {
  352. TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
  353. RxReleaseFcb( RxContext, TempFcb );
  354. }
  355. }
  356. //
  357. // Since we have the Vcb exclusive we know that if any closes
  358. // come in it is because the CcPurgeCacheSection caused the
  359. // Fcb to go away. Also in close, the Fcb was released
  360. // before being freed.
  361. //
  362. if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB) ) {
  363. ClearFlag( Fcb->FcbState, FCB_STATE_FORCE_MISS_IN_PROGRESS );
  364. RxReleaseFcb( (RXCONTEXT), Fcb );
  365. }
  366. }
  367. }
  368.