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.

680 lines
14 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. // Init the waiters list
  106. //
  107. InitializeListHead( &Lfcb->WaiterList );
  108. //
  109. // Initialize the pseudo Lsn for the restart Lbcb's
  110. //
  111. Lfcb->LfsRestartBias = 1;
  112. Lfcb->Sync->UserCount = 0;
  113. //
  114. // Set the io state to no io ongoing
  115. //
  116. Lfcb->Sync->LfsIoState = LfsNoIoInProgress;
  117. //
  118. // Initialize the spare list mutex
  119. //
  120. ExInitializeFastMutex( &(Lfcb->Sync->Mutex) );
  121. Lfcb->FileSize = FileSize;
  122. } finally {
  123. DebugUnwind( LfsAllocateFileControlBlock );
  124. if (AbnormalTermination() && (Lfcb != NULL)) {
  125. LfsDeallocateLfcb( Lfcb, TRUE );
  126. Lfcb = NULL;
  127. }
  128. DebugTrace( -1, Dbg, "LfsAllocateLfcb: Exit -> %08lx\n", Lfcb );
  129. }
  130. return Lfcb;
  131. }
  132. VOID
  133. LfsDeallocateLfcb (
  134. IN PLFCB Lfcb,
  135. IN BOOLEAN CompleteTeardown
  136. )
  137. /*++
  138. Routine Description:
  139. This routine releases the resources associated with a log file control
  140. block.
  141. Arguments:
  142. Lfcb - Supplies a pointer to the log file control block.
  143. CompleteTeardown - Indicates if we are to completely remove this Lfcb.
  144. Return Value:
  145. None
  146. --*/
  147. {
  148. PLBCB NextLbcb;
  149. PLEB NextLeb;
  150. PAGED_CODE();
  151. DebugTrace( +1, Dbg, "LfsDeallocateLfcb: Entered\n", 0 );
  152. DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb );
  153. //
  154. // Check that there are no buffer blocks.
  155. //
  156. ASSERT( IsListEmpty( &Lfcb->LbcbActive ));
  157. ASSERT( IsListEmpty( &Lfcb->LbcbWorkque ));
  158. //
  159. // Check that we have no clients.
  160. //
  161. ASSERT( IsListEmpty( &Lfcb->LchLinks ));
  162. //
  163. // If there is a restart area we deallocate it.
  164. //
  165. if (Lfcb->RestartArea != NULL) {
  166. LfsDeallocateRestartArea( Lfcb->RestartArea );
  167. }
  168. //
  169. // If there are any of the tail Lbcb's, deallocate them now.
  170. //
  171. if (Lfcb->ActiveTail != NULL) {
  172. LfsDeallocateLbcb( Lfcb, Lfcb->ActiveTail );
  173. Lfcb->ActiveTail = NULL;
  174. }
  175. if (Lfcb->PrevTail != NULL) {
  176. LfsDeallocateLbcb( Lfcb, Lfcb->PrevTail );
  177. Lfcb->PrevTail = NULL;
  178. }
  179. //
  180. // Only do the following if we are to remove the Lfcb completely.
  181. //
  182. if (CompleteTeardown) {
  183. //
  184. // If there is a resource structure we deallocate it.
  185. //
  186. if (Lfcb->Sync != NULL) {
  187. #ifdef BENL_DBG
  188. KdPrint(( "LFS: lfcb teardown: 0x%x 0x%x\n", Lfcb, Lfcb->Sync ));
  189. #endif
  190. ExDeleteResourceLite( &Lfcb->Sync->Resource );
  191. ExFreePool( Lfcb->Sync );
  192. }
  193. }
  194. //
  195. // Deallocate all of the spare Lbcb's.
  196. //
  197. while (!IsListEmpty( &Lfcb->SpareLbcbList )) {
  198. NextLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
  199. RemoveHeadList( &Lfcb->SpareLbcbList );
  200. ExFreePool( NextLbcb );
  201. }
  202. //
  203. // Deallocate all of the spare Leb's.
  204. //
  205. while (!IsListEmpty( &Lfcb->SpareLebList )) {
  206. NextLeb = (PLEB) Lfcb->SpareLebList.Flink;
  207. RemoveHeadList( &Lfcb->SpareLebList );
  208. ExFreePool( NextLeb );
  209. }
  210. //
  211. // Cleanup the log head mdls and buffer
  212. //
  213. if (Lfcb->LogHeadBuffer) {
  214. LfsFreePool( Lfcb->LogHeadBuffer );
  215. }
  216. if (Lfcb->LogHeadPartialMdl) {
  217. IoFreeMdl( Lfcb->LogHeadPartialMdl );
  218. }
  219. if (Lfcb->LogHeadMdl) {
  220. IoFreeMdl( Lfcb->LogHeadMdl );
  221. }
  222. if (Lfcb->ErrorLogPacket) {
  223. IoFreeErrorLogEntry( Lfcb->ErrorLogPacket );
  224. Lfcb->ErrorLogPacket = NULL;
  225. }
  226. //
  227. // Discard the Lfcb structure.
  228. //
  229. ExFreePool( Lfcb );
  230. DebugTrace( -1, Dbg, "LfsDeallocateLfcb: Exit\n", 0 );
  231. return;
  232. }
  233. VOID
  234. LfsAllocateLbcb (
  235. IN PLFCB Lfcb,
  236. OUT PLBCB *Lbcb
  237. )
  238. /*++
  239. Routine Description:
  240. This routine will allocate the next Lbcb. If the pool allocation fails
  241. we will look at the private queue of Lbcb's.
  242. Arguments:
  243. Lfcb - Supplies a pointer to the log file control block.
  244. Lbcb - Address to store the allocated Lbcb.
  245. Return Value:
  246. None
  247. --*/
  248. {
  249. PLBCB NewLbcb = NULL;
  250. PAGED_CODE();
  251. //
  252. // If there are enough entries on the look-aside list then get one from
  253. // there.
  254. //
  255. if (Lfcb->SpareLbcbCount > LFCB_RESERVE_LBCB_COUNT) {
  256. NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
  257. Lfcb->SpareLbcbCount -= 1;
  258. RemoveHeadList( &Lfcb->SpareLbcbList );
  259. //
  260. // Otherwise try to allocate from pool.
  261. //
  262. } else {
  263. NewLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' );
  264. }
  265. //
  266. // If we didn't get one then look at the look-aside list.
  267. //
  268. if (NewLbcb == NULL) {
  269. if (Lfcb->SpareLbcbCount != 0) {
  270. NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink;
  271. Lfcb->SpareLbcbCount -= 1;
  272. RemoveHeadList( &Lfcb->SpareLbcbList );
  273. } else {
  274. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  275. }
  276. }
  277. //
  278. // Initialize the structure.
  279. //
  280. RtlZeroMemory( NewLbcb, sizeof( LBCB ));
  281. NewLbcb->NodeTypeCode = LFS_NTC_LBCB;
  282. NewLbcb->NodeByteSize = sizeof( LBCB );
  283. //
  284. // Return it to the user.
  285. //
  286. *Lbcb = NewLbcb;
  287. return;
  288. }
  289. VOID
  290. LfsDeallocateLbcb (
  291. IN PLFCB Lfcb,
  292. IN PLBCB Lbcb
  293. )
  294. /*++
  295. Routine Description:
  296. This routine will deallocate the Lbcb. If we need one for the look-aside
  297. list we will put it there.
  298. Arguments:
  299. Lfcb - Supplies a pointer to the log file control block.
  300. Lbcb - This is the Lbcb to deallocate.
  301. Return Value:
  302. None
  303. --*/
  304. {
  305. PAGED_CODE();
  306. //
  307. // Deallocate any restart area attached to this Lbcb.
  308. //
  309. if (FlagOn( Lbcb->LbcbFlags, LBCB_RESTART_LBCB ) &&
  310. (Lbcb->PageHeader != NULL)) {
  311. LfsDeallocateRestartArea( Lbcb->PageHeader );
  312. }
  313. //
  314. // Put this in the Lbcb queue if it is short.
  315. //
  316. if (Lfcb->SpareLbcbCount < LFCB_MAX_LBCB_COUNT) {
  317. InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) Lbcb );
  318. Lfcb->SpareLbcbCount += 1;
  319. //
  320. // Otherwise just free the pool block.
  321. //
  322. } else {
  323. ExFreePool( Lbcb );
  324. }
  325. return;
  326. }
  327. VOID
  328. LfsAllocateLeb (
  329. IN PLFCB Lfcb,
  330. OUT PLEB *NewLeb
  331. )
  332. /*++
  333. Routine Description:
  334. This routine will allocate an Leb. If the pool fails we will fall back
  335. on our spare list. A failure then will result in an exception
  336. Arguments:
  337. Lfcb - Supplies a pointer to the log file control block.
  338. Leb - This will contain the new Leb
  339. Return Value:
  340. None
  341. --*/
  342. {
  343. ExAcquireFastMutexUnsafe( &(Lfcb->Sync->Mutex) );
  344. try {
  345. *NewLeb = NULL;
  346. if (Lfcb->SpareLebCount < LFCB_RESERVE_LEB_COUNT) {
  347. (*NewLeb) = ExAllocatePoolWithTag( PagedPool, sizeof( LEB ), ' sfL' );
  348. }
  349. if ((*NewLeb) == NULL) {
  350. if (Lfcb->SpareLebCount > 0) {
  351. *NewLeb = (PLEB) Lfcb->SpareLebList.Flink;
  352. Lfcb->SpareLebCount -= 1;
  353. RemoveHeadList( &Lfcb->SpareLebList );
  354. } else {
  355. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  356. }
  357. }
  358. RtlZeroMemory( (*NewLeb), sizeof( LEB ) );
  359. (*NewLeb)->NodeTypeCode = LFS_NTC_LEB;
  360. (*NewLeb)->NodeByteSize = sizeof( LEB );
  361. } finally {
  362. ExReleaseFastMutexUnsafe( &(Lfcb->Sync->Mutex) );
  363. }
  364. }
  365. VOID
  366. LfsDeallocateLeb (
  367. IN PLFCB Lfcb,
  368. IN PLEB Leb
  369. )
  370. /*++
  371. Routine Description:
  372. This routine will deallocate an Leb. We'll cache the old Leb if there
  373. aren't too many already on the spare list
  374. Arguments:
  375. Lfcb - Supplies a pointer to the log file control block.
  376. Leb - This will contain the Leb to release
  377. Return Value:
  378. None
  379. --*/
  380. {
  381. if (Leb->RecordHeaderBcb != NULL) {
  382. CcUnpinData( Leb->RecordHeaderBcb );
  383. }
  384. if ((Leb->CurrentLogRecord != NULL) && Leb->AuxilaryBuffer) {
  385. LfsFreeSpanningBuffer( Leb->CurrentLogRecord );
  386. }
  387. ExAcquireFastMutexUnsafe( &(Lfcb->Sync->Mutex) );
  388. try {
  389. if (Lfcb->SpareLebCount < LFCB_MAX_LEB_COUNT) {
  390. InsertHeadList( &Lfcb->SpareLebList, (PLIST_ENTRY) Leb );
  391. Lfcb->SpareLebCount += 1;
  392. } else {
  393. ExFreePool( Leb );
  394. }
  395. } finally {
  396. ExReleaseFastMutexUnsafe( &(Lfcb->Sync->Mutex) );
  397. }
  398. }
  399. VOID
  400. LfsReadPage (
  401. IN PLFCB Lfcb,
  402. IN PLARGE_INTEGER Offset,
  403. OUT PMDL *Mdl,
  404. OUT PVOID *Buffer
  405. )
  406. /*++
  407. Routine Description:
  408. Directly pages in a page off the disk - the cache manager interfaces (LfsPinOrMapPage)
  409. may come from the cache. This wil raise if memory can't be allocated and used for
  410. verification purposes
  411. Arguments:
  412. Lfcb - Supplies a pointer to the log file control block.
  413. Offset - offset of page to pagein from the logfile
  414. Mdl - On success the mdl that describes the mdl - it must be deallocated via
  415. IoFreeMdl
  416. Buffer - On output an allocated buffer that holds the data from the page - it
  417. must be freed using ExFreePool
  418. Return Value:
  419. None
  420. --*/
  421. {
  422. IO_STATUS_BLOCK Iosb;
  423. KEVENT Event;
  424. NTSTATUS Status;
  425. PAGED_CODE();
  426. KeInitializeEvent( &Event, NotificationEvent, FALSE );
  427. //
  428. // Allocate buffer / mdl and page in the restart page from disk
  429. //
  430. *Buffer = LfsAllocatePool( NonPagedPool, (ULONG)Lfcb->LogPageSize );
  431. *Mdl = IoAllocateMdl( *Buffer,
  432. (ULONG)Lfcb->LogPageSize,
  433. FALSE,
  434. FALSE,
  435. NULL );
  436. if (*Mdl == NULL) {
  437. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  438. }
  439. MmBuildMdlForNonPagedPool( *Mdl );
  440. //
  441. // We own the LFCB sync exclusively and there is only a main resource for the logfile
  442. // so we don't need to preacquire any resources before doing the page read
  443. //
  444. Status = IoPageRead( Lfcb->FileObject, *Mdl, Offset, &Event, &Iosb );
  445. if (Status == STATUS_PENDING) {
  446. KeWaitForSingleObject( &Event,
  447. WrPageIn,
  448. KernelMode,
  449. FALSE,
  450. (PLARGE_INTEGER)NULL);
  451. }
  452. }