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.

674 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. StrucSup.c
  5. Abstract:
  6. This module provides support routines for creation and deletion
  7. of Lfs structures.
  8. Author:
  9. Brian Andrew [BrianAn] 20-June-1991
  10. Revision History:
  11. --*/
  12. #include "lfsprocs.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_STRUC_SUP)
  17. #undef MODULE_POOL_TAG
  18. #define MODULE_POOL_TAG ('SsfL')
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, LfsAllocateLbcb)
  21. #pragma alloc_text(PAGE, LfsAllocateLfcb)
  22. #pragma alloc_text(PAGE, LfsDeallocateLbcb)
  23. #pragma alloc_text(PAGE, LfsDeallocateLfcb)
  24. #pragma alloc_text(PAGE, LfsAllocateLeb)
  25. #pragma alloc_text(PAGE, LfsDeallocateLeb)
  26. #pragma alloc_text(PAGE, LfsReadPage)
  27. #endif
  28. PLFCB
  29. LfsAllocateLfcb (
  30. IN ULONG LogPageSize,
  31. IN LONGLONG FileSize
  32. )
  33. /*++
  34. Routine Description:
  35. This routine allocates and initializes a log file control block.
  36. Arguments:
  37. LogPageSize - lfs log file page size
  38. FileSize - Initial file size
  39. Return Value:
  40. PLFCB - A pointer to the log file control block just
  41. allocated and initialized.
  42. --*/
  43. {
  44. PLFCB Lfcb = NULL;
  45. ULONG Count;
  46. PLBCB NextLbcb;
  47. PLEB NextLeb;
  48. PAGED_CODE();
  49. DebugTrace( +1, Dbg, "LfsAllocateLfcb: Entered\n", 0 );
  50. //
  51. // Use a try-finally to facilitate cleanup.
  52. //
  53. try {
  54. //
  55. // Allocate and zero the structure for the Lfcb.
  56. //
  57. ASSERT( LogPageSize <= PAGE_SIZE );
  58. Lfcb = LfsAllocatePool( PagedPool, sizeof( LFCB ) + sizeof( PLBCB ) * (PAGE_SIZE / LogPageSize) );
  59. //
  60. // Zero out the structure initially.
  61. //
  62. RtlZeroMemory( Lfcb, sizeof( LFCB ) + sizeof( PLBCB ) * (PAGE_SIZE / LogPageSize));
  63. //
  64. // Initialize the log file control block.
  65. //
  66. Lfcb->NodeTypeCode = LFS_NTC_LFCB;
  67. Lfcb->NodeByteSize = sizeof( LFCB );
  68. //
  69. // Initialize the client links.
  70. //
  71. InitializeListHead( &Lfcb->LchLinks );
  72. //
  73. // Initialize the Lbcb links.
  74. //
  75. InitializeListHead( &Lfcb->LbcbWorkque );
  76. InitializeListHead( &Lfcb->LbcbActive );
  77. //
  78. // Initialize and allocate the spare Lbcb queue.
  79. //
  80. InitializeListHead( &Lfcb->SpareLbcbList );
  81. for (Count = 0; Count < LFCB_RESERVE_LBCB_COUNT; Count++) {
  82. NextLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' );
  83. if (NextLbcb != NULL) {
  84. InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) NextLbcb );
  85. Lfcb->SpareLbcbCount += 1;
  86. }
  87. }
  88. //
  89. // Initialize and allocate the spare Leb queue.
  90. //
  91. InitializeListHead( &Lfcb->SpareLebList );
  92. for (Count = 0; Count < LFCB_RESERVE_LEB_COUNT; Count++) {
  93. NextLeb = ExAllocatePoolWithTag( PagedPool, sizeof( LEB ), ' sfL' );
  94. if (NextLeb != NULL) {
  95. InsertHeadList( &Lfcb->SpareLebList, (PLIST_ENTRY) NextLeb );
  96. Lfcb->SpareLebCount += 1;
  97. }
  98. }
  99. //
  100. // Allocate the Lfcb synchronization event.
  101. //
  102. Lfcb->Sync = LfsAllocatePool( NonPagedPool, sizeof( LFCB_SYNC ));
  103. ExInitializeResourceLite( &Lfcb->Sync->Resource );
  104. //
  105. // Initialize the pseudo Lsn for the restart Lbcb's
  106. //
  107. Lfcb->NextRestartLsn = LfsLi1;
  108. //
  109. // Initialize the event to the signalled state.
  110. //
  111. KeInitializeEvent( &Lfcb->Sync->Event, NotificationEvent, TRUE );
  112. Lfcb->Sync->UserCount = 0;
  113. //
  114. // Initialize the spare list mutex
  115. //
  116. ExInitializeFastMutex( &(Lfcb->Sync->SpareListMutex) );
  117. Lfcb->FileSize = FileSize;
  118. } finally {
  119. DebugUnwind( LfsAllocateFileControlBlock );
  120. if (AbnormalTermination() && (Lfcb != NULL)) {
  121. LfsDeallocateLfcb( Lfcb, TRUE );
  122. Lfcb = NULL;
  123. }
  124. DebugTrace( -1, Dbg, "LfsAllocateLfcb: Exit -> %08lx\n", Lfcb );
  125. }
  126. return Lfcb;
  127. }
  128. VOID
  129. LfsDeallocateLfcb (
  130. IN PLFCB Lfcb,
  131. IN BOOLEAN CompleteTeardown
  132. )
  133. /*++
  134. Routine Description:
  135. This routine releases the resources associated with a log file control
  136. block.
  137. Arguments:
  138. Lfcb - Supplies a pointer to the log file control block.
  139. CompleteTeardown - Indicates if we are to completely remove this Lfcb.
  140. Return Value:
  141. None
  142. --*/
  143. {
  144. PLBCB NextLbcb;
  145. PLEB NextLeb;
  146. PAGED_CODE();
  147. DebugTrace( +1, Dbg, "LfsDeallocateLfcb: Entered\n", 0 );
  148. DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb );
  149. //
  150. // Check that there are no buffer blocks.
  151. //
  152. ASSERT( IsListEmpty( &Lfcb->LbcbActive ));
  153. ASSERT( IsListEmpty( &Lfcb->LbcbWorkque ));
  154. //
  155. // Check that we have no clients.
  156. //
  157. ASSERT( IsListEmpty( &Lfcb->LchLinks ));
  158. //
  159. // If there is a restart area we deallocate it.
  160. //
  161. if (Lfcb->RestartArea != NULL) {
  162. LfsDeallocateRestartArea( Lfcb->RestartArea );
  163. }
  164. //
  165. // If there are any of the tail Lbcb's, deallocate them now.
  166. //
  167. if (Lfcb->ActiveTail != NULL) {
  168. LfsDeallocateLbcb( Lfcb, Lfcb->ActiveTail );
  169. Lfcb->ActiveTail = NULL;
  170. }
  171. if (Lfcb->PrevTail != NULL) {
  172. LfsDeallocateLbcb( Lfcb, Lfcb->PrevTail );
  173. Lfcb->PrevTail = NULL;
  174. }
  175. //
  176. // Only do the following if we are to remove the Lfcb completely.
  177. //
  178. if (CompleteTeardown) {
  179. //
  180. // If there is a resource structure we deallocate it.
  181. //
  182. if (Lfcb->Sync != NULL) {
  183. #ifdef BENL_DBG
  184. KdPrint(( "LFS: lfcb teardown: 0x%x 0x%x\n", Lfcb, Lfcb->Sync ));
  185. #endif
  186. ExDeleteResourceLite( &Lfcb->Sync->Resource );
  187. ExFreePool( Lfcb->Sync );
  188. }
  189. }
  190. //
  191. // Deallocate all of the spare Lbcb's.
  192. //
  193. while (!IsListEmpty( &Lfcb->SpareLbcbList )) {
  194. NextLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
  195. RemoveHeadList( &Lfcb->SpareLbcbList );
  196. ExFreePool( NextLbcb );
  197. }
  198. //
  199. // Deallocate all of the spare Leb's.
  200. //
  201. while (!IsListEmpty( &Lfcb->SpareLebList )) {
  202. NextLeb = (PLEB) Lfcb->SpareLebList.Flink;
  203. RemoveHeadList( &Lfcb->SpareLebList );
  204. ExFreePool( NextLeb );
  205. }
  206. //
  207. // Cleanup the log head mdls and buffer
  208. //
  209. if (Lfcb->LogHeadBuffer) {
  210. LfsFreePool( Lfcb->LogHeadBuffer );
  211. }
  212. if (Lfcb->LogHeadPartialMdl) {
  213. IoFreeMdl( Lfcb->LogHeadPartialMdl );
  214. }
  215. if (Lfcb->LogHeadMdl) {
  216. IoFreeMdl( Lfcb->LogHeadMdl );
  217. }
  218. if (Lfcb->ErrorLogPacket) {
  219. IoFreeErrorLogEntry( Lfcb->ErrorLogPacket );
  220. Lfcb->ErrorLogPacket = NULL;
  221. }
  222. //
  223. // Discard the Lfcb structure.
  224. //
  225. ExFreePool( Lfcb );
  226. DebugTrace( -1, Dbg, "LfsDeallocateLfcb: Exit\n", 0 );
  227. return;
  228. }
  229. VOID
  230. LfsAllocateLbcb (
  231. IN PLFCB Lfcb,
  232. OUT PLBCB *Lbcb
  233. )
  234. /*++
  235. Routine Description:
  236. This routine will allocate the next Lbcb. If the pool allocation fails
  237. we will look at the private queue of Lbcb's.
  238. Arguments:
  239. Lfcb - Supplies a pointer to the log file control block.
  240. Lbcb - Address to store the allocated Lbcb.
  241. Return Value:
  242. None
  243. --*/
  244. {
  245. PLBCB NewLbcb = NULL;
  246. PAGED_CODE();
  247. //
  248. // If there are enough entries on the look-aside list then get one from
  249. // there.
  250. //
  251. if (Lfcb->SpareLbcbCount > LFCB_RESERVE_LBCB_COUNT) {
  252. NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
  253. Lfcb->SpareLbcbCount -= 1;
  254. RemoveHeadList( &Lfcb->SpareLbcbList );
  255. //
  256. // Otherwise try to allocate from pool.
  257. //
  258. } else {
  259. NewLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' );
  260. }
  261. //
  262. // If we didn't get one then look at the look-aside list.
  263. //
  264. if (NewLbcb == NULL) {
  265. if (Lfcb->SpareLbcbCount != 0) {
  266. NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
  267. Lfcb->SpareLbcbCount -= 1;
  268. RemoveHeadList( &Lfcb->SpareLbcbList );
  269. } else {
  270. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  271. }
  272. }
  273. //
  274. // Initialize the structure.
  275. //
  276. RtlZeroMemory( NewLbcb, sizeof( LBCB ));
  277. NewLbcb->NodeTypeCode = LFS_NTC_LBCB;
  278. NewLbcb->NodeByteSize = sizeof( LBCB );
  279. //
  280. // Return it to the user.
  281. //
  282. *Lbcb = NewLbcb;
  283. return;
  284. }
  285. VOID
  286. LfsDeallocateLbcb (
  287. IN PLFCB Lfcb,
  288. IN PLBCB Lbcb
  289. )
  290. /*++
  291. Routine Description:
  292. This routine will deallocate the Lbcb. If we need one for the look-aside
  293. list we will put it there.
  294. Arguments:
  295. Lfcb - Supplies a pointer to the log file control block.
  296. Lbcb - This is the Lbcb to deallocate.
  297. Return Value:
  298. None
  299. --*/
  300. {
  301. PAGED_CODE();
  302. //
  303. // Deallocate any restart area attached to this Lbcb.
  304. //
  305. if (FlagOn( Lbcb->LbcbFlags, LBCB_RESTART_LBCB ) &&
  306. (Lbcb->PageHeader != NULL)) {
  307. LfsDeallocateRestartArea( Lbcb->PageHeader );
  308. }
  309. //
  310. // Put this in the Lbcb queue if it is short.
  311. //
  312. if (Lfcb->SpareLbcbCount < LFCB_MAX_LBCB_COUNT) {
  313. InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) Lbcb );
  314. Lfcb->SpareLbcbCount += 1;
  315. //
  316. // Otherwise just free the pool block.
  317. //
  318. } else {
  319. ExFreePool( Lbcb );
  320. }
  321. return;
  322. }
  323. VOID
  324. LfsAllocateLeb (
  325. IN PLFCB Lfcb,
  326. OUT PLEB *NewLeb
  327. )
  328. /*++
  329. Routine Description:
  330. This routine will allocate an Leb. If the pool fails we will fall back
  331. on our spare list. A failure then will result in an exception
  332. Arguments:
  333. Lfcb - Supplies a pointer to the log file control block.
  334. Leb - This will contain the new Leb
  335. Return Value:
  336. None
  337. --*/
  338. {
  339. ExAcquireFastMutex( &(Lfcb->Sync->SpareListMutex) );
  340. try {
  341. *NewLeb = NULL;
  342. if (Lfcb->SpareLebCount < LFCB_RESERVE_LEB_COUNT) {
  343. (*NewLeb) = ExAllocatePoolWithTag( PagedPool, sizeof( LEB ), ' sfL' );
  344. }
  345. if ((*NewLeb) == NULL) {
  346. if (Lfcb->SpareLebCount > 0) {
  347. *NewLeb = (PLEB) Lfcb->SpareLebList.Flink;
  348. Lfcb->SpareLebCount -= 1;
  349. RemoveHeadList( &Lfcb->SpareLebList );
  350. } else {
  351. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  352. }
  353. }
  354. RtlZeroMemory( (*NewLeb), sizeof( LEB ) );
  355. (*NewLeb)->NodeTypeCode = LFS_NTC_LEB;
  356. (*NewLeb)->NodeByteSize = sizeof( LEB );
  357. } finally {
  358. ExReleaseFastMutex( &(Lfcb->Sync->SpareListMutex) );
  359. }
  360. }
  361. VOID
  362. LfsDeallocateLeb (
  363. IN PLFCB Lfcb,
  364. IN PLEB Leb
  365. )
  366. /*++
  367. Routine Description:
  368. This routine will deallocate an Leb. We'll cache the old Leb if there
  369. aren't too many already on the spare list
  370. Arguments:
  371. Lfcb - Supplies a pointer to the log file control block.
  372. Leb - This will contain the Leb to release
  373. Return Value:
  374. None
  375. --*/
  376. {
  377. if (Leb->RecordHeaderBcb != NULL) {
  378. CcUnpinData( Leb->RecordHeaderBcb );
  379. }
  380. if ((Leb->CurrentLogRecord != NULL) && Leb->AuxilaryBuffer) {
  381. LfsFreeSpanningBuffer( Leb->CurrentLogRecord );
  382. }
  383. ExAcquireFastMutex( &(Lfcb->Sync->SpareListMutex) );
  384. try {
  385. if (Lfcb->SpareLebCount < LFCB_MAX_LEB_COUNT) {
  386. InsertHeadList( &Lfcb->SpareLebList, (PLIST_ENTRY) Leb );
  387. Lfcb->SpareLebCount += 1;
  388. } else {
  389. ExFreePool( Leb );
  390. }
  391. } finally {
  392. ExReleaseFastMutex( &(Lfcb->Sync->SpareListMutex) );
  393. }
  394. }
  395. VOID
  396. LfsReadPage (
  397. IN PLFCB Lfcb,
  398. IN PLARGE_INTEGER Offset,
  399. OUT PMDL *Mdl,
  400. OUT PVOID *Buffer
  401. )
  402. /*++
  403. Routine Description:
  404. Directly pages in a page off the disk - the cache manager interfaces (LfsPinOrMapPage)
  405. may come from the cache. This wil raise if memory can't be allocated and used for
  406. verification purposes
  407. Arguments:
  408. Lfcb - Supplies a pointer to the log file control block.
  409. Offset - offset of page to pagein from the logfile
  410. Mdl - On success the mdl that describes the mdl - it must be deallocated via
  411. IoFreeMdl
  412. Buffer - On output an allocated buffer that holds the data from the page - it
  413. must be freed using ExFreePool
  414. Return Value:
  415. None
  416. --*/
  417. {
  418. IO_STATUS_BLOCK Iosb;
  419. KEVENT Event;
  420. NTSTATUS Status;
  421. PAGED_CODE();
  422. KeInitializeEvent( &Event, NotificationEvent, FALSE );
  423. //
  424. // Allocate buffer / mdl and page in the restart page from disk
  425. //
  426. *Buffer = LfsAllocatePool( NonPagedPool, (ULONG)Lfcb->LogPageSize );
  427. *Mdl = IoAllocateMdl( *Buffer,
  428. (ULONG)Lfcb->LogPageSize,
  429. FALSE,
  430. FALSE,
  431. NULL );
  432. if (*Mdl == NULL) {
  433. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  434. }
  435. MmBuildMdlForNonPagedPool( *Mdl );
  436. //
  437. // We own the LFCB sync exclusively and there is only a main resource for the logfile
  438. // so we don't need to preacquire any resources before doing the page read
  439. //
  440. Status = IoPageRead( Lfcb->FileObject, *Mdl, Offset, &Event, &Iosb );
  441. if (Status == STATUS_PENDING) {
  442. KeWaitForSingleObject( &Event,
  443. WrPageIn,
  444. KernelMode,
  445. FALSE,
  446. (PLARGE_INTEGER)NULL);
  447. }
  448. }