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.

720 lines
19 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. NtfsLog.h
  5. Abstract:
  6. This module defines the Ntfs-specific log file structures.
  7. Author:
  8. Tom Miller [TomM] 21-Jul-1991
  9. Revision History:
  10. --*/
  11. #ifndef _NTFSLOG_
  12. #define _NTFSLOG_
  13. #pragma pack(4)
  14. //
  15. // The following type defines the Ntfs log operations.
  16. //
  17. // The comment specifies the record type which follows the record.
  18. // These record types are defined either here or in ntfs.h.
  19. //
  20. typedef enum _NTFS_LOG_OPERATION {
  21. Noop = 0x00, //
  22. CompensationLogRecord = 0x01, //
  23. InitializeFileRecordSegment = 0x02, // FILE_RECORD_SEGMENT_HEADER
  24. DeallocateFileRecordSegment = 0x03, //
  25. WriteEndOfFileRecordSegment = 0x04, // ATTRIBUTE_RECORD_HEADER
  26. CreateAttribute = 0x05, // ATTRIBUTE_RECORD_HEADER
  27. DeleteAttribute = 0x06, //
  28. UpdateResidentValue = 0x07, // (value)
  29. UpdateNonresidentValue = 0x08, // (value)
  30. UpdateMappingPairs = 0x09, // (value = mapping pairs bytes)
  31. DeleteDirtyClusters = 0x0A, // array of LCN_RANGE
  32. SetNewAttributeSizes = 0x0B, // NEW_ATTRIBUTE_SIZES
  33. AddIndexEntryRoot = 0x0C, // INDEX_ENTRY
  34. DeleteIndexEntryRoot = 0x0D, // INDEX_ENTRY
  35. AddIndexEntryAllocation = 0x0E, // INDEX_ENTRY
  36. DeleteIndexEntryAllocation = 0x0F, // INDEX_ENTRY
  37. WriteEndOfIndexBuffer = 0x10, // INDEX_ENTRY
  38. SetIndexEntryVcnRoot = 0x11, // VCN
  39. SetIndexEntryVcnAllocation = 0x12, // VCN
  40. UpdateFileNameRoot = 0x13, // DUPLICATED_INFORMATION
  41. UpdateFileNameAllocation = 0x14, // DUPLICATED_INFORMATION
  42. SetBitsInNonresidentBitMap = 0x15, // BITMAP_RANGE
  43. ClearBitsInNonresidentBitMap = 0x16, // BITMAP_RANGE
  44. HotFix = 0x17, //
  45. EndTopLevelAction = 0x18, //
  46. PrepareTransaction = 0x19, //
  47. CommitTransaction = 0x1A, //
  48. ForgetTransaction = 0x1B, //
  49. OpenNonresidentAttribute = 0x1C, // OPEN_ATTRIBUTE_ENTRY+ATTRIBUTE_NAME_ENTRY
  50. OpenAttributeTableDump = 0x1D, // OPEN_ATTRIBUTE_ENTRY array
  51. AttributeNamesDump = 0x1E, // (all attribute names)
  52. DirtyPageTableDump = 0x1F, // DIRTY_PAGE_ENTRY array
  53. TransactionTableDump = 0x20 // TRANSACTION_ENTRY array
  54. } NTFS_LOG_OPERATION, *PNTFS_LOG_OPERATION;
  55. char *NtfsLogOperationStrings[] = {
  56. "Noop"
  57. "CompensationLogRecord" ,
  58. "InitializeFileRecordSegment",
  59. "DeallocateFileRecordSegment",
  60. "WriteEndOfFileRecordSegment",
  61. "CreateAttribute",
  62. "DeleteAttribute",
  63. "UpdateResidentValue",
  64. "UpdateNonresidentValue",
  65. "UpdateMappingPairs",
  66. "DeleteDirtyClusters",
  67. "SetNewAttributeSize",
  68. "AddIndexEntryRoot",
  69. "DeleteIndexEntryRoot",
  70. "AddIndexEntryAllocation",
  71. "DeleteIndexEntryAllocation",
  72. "WriteEndOfIndexBuffer",
  73. "SetIndexEntryVcnRoot",
  74. "SetIndexEntryVcnAllocation",
  75. "UpdateFileNameRoot",
  76. "UpdateFileNameAllocation",
  77. "SetBitsInNonresidentBitMap",
  78. "ClearBitsInNonresidentBitMap" ,
  79. "HotFix",
  80. "EndTopLevelAction",
  81. "PrepareTransaction",
  82. "CommitTransaction",
  83. "ForgetTransaction",
  84. "OpenNonresidentAttribute",
  85. "OpenAttributeTableDump",
  86. "AttributeNamesDump",
  87. "DirtyPageTableDump",
  88. "TransactionTableDump"
  89. };
  90. //
  91. // The Ntfs log record header precedes every log record written to
  92. // disk by Ntfs.
  93. //
  94. //
  95. // Log record header.
  96. //
  97. typedef struct _NTFS_LOG_RECORD_HEADER {
  98. //
  99. // Log Operations (LOG_xxx codes)
  100. //
  101. USHORT RedoOperation;
  102. USHORT UndoOperation;
  103. //
  104. // Offset to Redo record, and its length
  105. //
  106. USHORT RedoOffset;
  107. USHORT RedoLength;
  108. //
  109. // Offset to Undo record, and its length. Note, for some Redo/Undo
  110. // combinations, the expected records may be the same, and thus
  111. // these two values will be identical to the above values.
  112. //
  113. USHORT UndoOffset;
  114. USHORT UndoLength;
  115. //
  116. // Open attribute table index to which this update applies. Index 0 is
  117. // always reserved for the MFT itself. The value of this field
  118. // essentially distinguishes two cases for this update, which will be
  119. // referred to as MFT update and nonresident attribute update.
  120. //
  121. // MFT updates are for initialization and deletion of file record
  122. // segments and updates to resident attributes.
  123. //
  124. // Nonresident attribute updates are used to update attributes which
  125. // have been allocated externally to the MFT.
  126. //
  127. USHORT TargetAttribute;
  128. //
  129. // Number of Lcns in use at end of header.
  130. //
  131. USHORT LcnsToFollow;
  132. //
  133. // Byte offset and Vcn for which this update is to be applied. If the
  134. // TargetAttribute is the MFT, then the Vcn will always be the exact
  135. // Vcn of the start of the file record segment being modified, even
  136. // if the modification happens to be in a subsequent cluster of the
  137. // same file record. The byte offset in this case is the offset to
  138. // the attribute being changed. For the Mft, AttributeOffset may be used
  139. // to represent the offset from the start of the attribute record
  140. // at which an update is to be applied.
  141. //
  142. // If the update is to some other (nonresident) attribute, then
  143. // TargetVcn and RecordOffset may be used to calculate the reference
  144. // point for the update.
  145. //
  146. // As a bottom line, the exact use of these fields is up to the
  147. // writer of this particular log operation, and the associated
  148. // restart routines for this attribute.
  149. //
  150. USHORT RecordOffset;
  151. USHORT AttributeOffset;
  152. USHORT Reserved[2];
  153. LONGLONG TargetVcn;
  154. //
  155. // Run information. This is a variable-length array of LcnsToFollow
  156. // entries, only the first of which is declared. Note that the writer
  157. // always writes log records according to the physical page size on his
  158. // machine, however whenever the log file is being read, no assumption
  159. // is made about page size. This is to facilitate moving disks between
  160. // systems with different page sizes.
  161. //
  162. LONGLONG LcnsForPage[1];
  163. //
  164. // Immediately following the last run is a log-operation-specific record
  165. // whose length may be calculated by subtracting the length of this header
  166. // from the length of the entire record returned by LFS. These records
  167. // are defined below.
  168. //
  169. } NTFS_LOG_RECORD_HEADER, *PNTFS_LOG_RECORD_HEADER;
  170. //
  171. // RESTART AREA STRUCTURES
  172. //
  173. // The following structures are present in the Restart Area.
  174. //
  175. //
  176. // Generic Restart Table
  177. //
  178. // This is a generic table definition for the purpose of describing one
  179. // of the three table structures used at Restart: the Open Attribute Table,
  180. // the Dirty Pages Table, and the Transaction Table. This simple structure
  181. // allows for common initialization and free list management. Allocation
  182. // and Deallocation and lookup by index are extremely fast, while lookup
  183. // by value (only performed in the Dirty Pages Table during Restart) is
  184. // a little slower. I.e., all accesses to these tables during normal
  185. // operation are extremely fast.
  186. //
  187. // If fast access to a table entry by value becomes an issue, then the
  188. // table may be supplemented by an external Generic Table - it is probably
  189. // not a good idea to make the Generic Table be part of the structure
  190. // written to the Log File.
  191. //
  192. // Entries in a Restart Table should start with:
  193. //
  194. // ULONG AllocatedOrNextFree;
  195. //
  196. // An allocated entry will have the pattern RESTART_ENTRY_ALLOCATED
  197. // in this field.
  198. //
  199. #define RESTART_ENTRY_ALLOCATED (0xFFFFFFFF)
  200. typedef struct _RESTART_TABLE {
  201. //
  202. // Entry size, in bytes
  203. //
  204. USHORT EntrySize;
  205. //
  206. // Total number of entries in table
  207. //
  208. USHORT NumberEntries;
  209. //
  210. // Number entries that are allocated
  211. //
  212. USHORT NumberAllocated;
  213. //
  214. // Reserved for alignment
  215. //
  216. USHORT Reserved[3];
  217. //
  218. // Free goal - Offset after which entries should be freed to end of
  219. // list, as opposed to front. At each checkpoint, the table may be
  220. // truncated if there are enough free entries at the end of the list.
  221. // Expressed as an offset from the start of this structure.
  222. //
  223. ULONG FreeGoal;
  224. //
  225. // First Free entry (head of list) and Last Free entry (used to deallocate
  226. // beyond Free Goal). Expressed as an offset from the start of this
  227. // structure.
  228. //
  229. ULONG FirstFree;
  230. ULONG LastFree;
  231. //
  232. // The table itself starts here.
  233. //
  234. } RESTART_TABLE, *PRESTART_TABLE;
  235. //
  236. // Macro to get a pointer to an entry in a Restart Table, from the Table
  237. // pointer and entry index.
  238. //
  239. #define GetRestartEntryFromIndex(TBL,INDX) ( \
  240. (PVOID)((PCHAR)(TBL)->Table + (INDX)) \
  241. )
  242. //
  243. // Macro to get an index for an entry in a Restart Table, from the Table
  244. // pointer and entry pointer.
  245. //
  246. #define GetIndexFromRestartEntry(TBL,ENTRY) ( \
  247. (ULONG)((PCHAR)(ENTRY) - (PCHAR)(TBL)->Table) \
  248. )
  249. //
  250. // Macro to see if an entry in a Restart Table is allocated.
  251. //
  252. #define IsRestartTableEntryAllocated(PTR) ( \
  253. (BOOLEAN)(*(PULONG)(PTR) == RESTART_ENTRY_ALLOCATED) \
  254. )
  255. //
  256. // Macro to retrieve the size of a Restart Table in bytes.
  257. //
  258. #define SizeOfRestartTable(TBL) ( \
  259. (ULONG)(((TBL)->Table->NumberEntries * \
  260. (TBL)->Table->EntrySize) + \
  261. sizeof(RESTART_TABLE)) \
  262. )
  263. //
  264. // Macro to see if Restart Table is empty. It is empty if the
  265. // number allocated is zero.
  266. //
  267. #define IsRestartTableEmpty(TBL) (!(TBL)->Table->NumberAllocated)
  268. //
  269. // Macro to see if an index is within the currently allocated size
  270. // for that table.
  271. //
  272. #define IsRestartIndexWithinTable(TBL,INDX) ( \
  273. (BOOLEAN)((INDX) < SizeOfRestartTable(TBL)) \
  274. )
  275. //
  276. // Macros to acquire and release a Restart Table.
  277. //
  278. #define NtfsAcquireExclusiveRestartTable(TBL,WAIT) { \
  279. ExAcquireResourceExclusiveLite( &(TBL)->Resource,(WAIT)); \
  280. }
  281. #define NtfsAcquireSharedRestartTable(TBL,WAIT) { \
  282. ExAcquireResourceSharedLite( &(TBL)->Resource,(WAIT)); \
  283. }
  284. #define NtfsReleaseRestartTable(TBL) { \
  285. ExReleaseResourceLite(&(TBL)->Resource); \
  286. }
  287. //
  288. // Define some tuning parameters to keep the restart tables a
  289. // reasonable size.
  290. //
  291. #define INITIAL_NUMBER_TRANSACTIONS (5)
  292. #define HIGHWATER_TRANSACTION_COUNT (10)
  293. #define INITIAL_NUMBER_ATTRIBUTES (8)
  294. #define HIGHWATER_ATTRIBUTE_COUNT (16)
  295. //
  296. // Attribute Name Entry. This is a simple structure used to store
  297. // all of the attribute names for the Open Attribute Table during
  298. // checkpoint processing. The Attribute Names record written to the log
  299. // is a series of Attribute Name Entries terminated by an entry with
  300. // Index == NameLength == 0. The end of the table may be tested for by
  301. // looking for either of these fields to be 0, as 0 is otherwise invalid
  302. // for both.
  303. //
  304. // Note that the size of this structure is equal to the overhead for storing
  305. // an attribute name in the table, including the UNICODE_NULL.
  306. //
  307. typedef struct _ATTRIBUTE_NAME_ENTRY {
  308. //
  309. // Index for Attibute with this name in the Open Attribute Table.
  310. //
  311. USHORT Index;
  312. //
  313. // Length of attribute name to follow in bytes, including a terminating
  314. // UNICODE_NULL.
  315. //
  316. USHORT NameLength;
  317. //
  318. // Start of attribute name
  319. //
  320. WCHAR Name[1];
  321. } ATTRIBUTE_NAME_ENTRY, *PATTRIBUTE_NAME_ENTRY;
  322. //
  323. // Open Attribute Table
  324. //
  325. // One entry exists in the Open Attribute Table for each nonresident
  326. // attribute of each file that is open with modify access.
  327. //
  328. // This table is initialized at Restart to the maximum of
  329. // DEFAULT_ATTRIBUTE_TABLE_SIZE or the size of the table in the log file.
  330. // It is maintained in the running system.
  331. //
  332. typedef struct _OPEN_ATTRIBUTE_ENTRY {
  333. //
  334. // Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
  335. // Otherwise, it is a free link.
  336. //
  337. ULONG AllocatedOrNextFree;
  338. //
  339. // The following overlay either contains an optional pointer to an
  340. // Attribute Name Entry from the Analysis Phase of Restart, or a
  341. // pointer to an Scb once attributes have been open and in the normal
  342. // running system.
  343. //
  344. // Specifically, after the Analysis Phase of Restart:
  345. //
  346. // AttributeName == NULL if there is no attribute name, or the
  347. // attribute name was captured in the Attribute
  348. // Names Dump in the last successful checkpoint.
  349. // AttributeName != NULL if an OpenNonresidentAttribute log record
  350. // was encountered, and an Attribute Name Entry
  351. // was allocated at that time (and must be
  352. // deallocated when no longer needed).
  353. //
  354. // Once the Nonresident Attributes have been opened during Restart,
  355. // and in the running system, this is an Scb pointer.
  356. //
  357. union {
  358. PWSTR AttributeName;
  359. PVOID Scb;
  360. } Overlay;
  361. //
  362. // File Reference of file containing attribute.
  363. //
  364. FILE_REFERENCE FileReference;
  365. //
  366. // Lsn of OpenNonresidentAttribute log record, to distinguish reuses
  367. // of this open file record. Log records referring to this Open
  368. // Attribute Entry Index, but with Lsns older than this field, can
  369. // only occur when the attribute was subsequently deleted - these
  370. // log records can be ignored.
  371. //
  372. LSN LsnOfOpenRecord;
  373. //
  374. // Flag to say if dirty pages seen for this attribute during dirty
  375. // page scan.
  376. //
  377. BOOLEAN DirtyPagesSeen;
  378. //
  379. // Reserved for alignment
  380. //
  381. UCHAR Reserved[3];
  382. //
  383. // The following two fields identify the actual attribute
  384. // with respect to its file. We identify the attribute by
  385. // its type code and name. When the Restart Area is written,
  386. // all of the names for all of the open attributes are temporarily
  387. // copied to the end of the Restart Area.
  388. //
  389. ATTRIBUTE_TYPE_CODE AttributeTypeCode;
  390. UNICODE_STRING AttributeName;
  391. //
  392. // This field is only relevant to indices, i.e., if AttributeTypeCode
  393. // above is $INDEX_ALLOCATION.
  394. //
  395. ULONG BytesPerIndexBuffer;
  396. } OPEN_ATTRIBUTE_ENTRY, *POPEN_ATTRIBUTE_ENTRY;
  397. #define SIZEOF_OPEN_ATTRIBUTE_ENTRY ( \
  398. FIELD_OFFSET( OPEN_ATTRIBUTE_ENTRY, BytesPerIndexBuffer ) + 4 \
  399. )
  400. //
  401. // Dirty Pages Table
  402. //
  403. // One entry exists in the Dirty Pages Table for each page which is
  404. // dirty at the time the Restart Area is written.
  405. //
  406. // This table is initialized at Restart to the maximum of
  407. // DEFAULT_DIRTY_PAGES_TABLE_SIZE or the size of the table in the log file.
  408. // It is *not* maintained in the running system.
  409. //
  410. typedef struct _DIRTY_PAGE_ENTRY {
  411. //
  412. // Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
  413. // Otherwise, it is a free link.
  414. //
  415. ULONG AllocatedOrNextFree;
  416. //
  417. // Target attribute index. This is the index into the Open Attribute
  418. // Table to which this dirty page entry applies.
  419. //
  420. ULONG TargetAttribute;
  421. //
  422. // Length of transfer, in case this is the end of file, and we cannot
  423. // write an entire page.
  424. //
  425. ULONG LengthOfTransfer;
  426. //
  427. // Number of Lcns in the array at end of this structure. See comment
  428. // with this array.
  429. //
  430. ULONG LcnsToFollow;
  431. //
  432. // Reserved for alignment
  433. //
  434. ULONG Reserved;
  435. //
  436. // Vcn of dirty page.
  437. //
  438. VCN Vcn;
  439. //
  440. // OldestLsn for log record for which the update has not yet been
  441. // written through to disk.
  442. //
  443. LSN OldestLsn;
  444. //
  445. // Run information. This is a variable-length array of LcnsToFollow
  446. // entries, only the first of which is declared. Note that the writer
  447. // always writes pages according to the physical page size on his
  448. // machine, however whenever the log file is being read, no assumption
  449. // is made about page size. This is to facilitate moving disks between
  450. // systems with different page sizes.
  451. //
  452. LCN LcnsForPage[1];
  453. } DIRTY_PAGE_ENTRY, *PDIRTY_PAGE_ENTRY;
  454. //
  455. // Transaction Table
  456. //
  457. // One transaction entry exists for each existing transaction at the time
  458. // the Restart Area is written.
  459. //
  460. // Currently only local transactions are supported, and the transaction
  461. // ID is simply used to index into this table.
  462. //
  463. // This table is initialized at Restart to the maximum of
  464. // DEFAULT_TRANSACTION_TABLE_SIZE or the size of the table in the log file.
  465. // It is maintained in the running system.
  466. //
  467. typedef struct _TRANSACTION_ENTRY {
  468. //
  469. // Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
  470. // Otherwise, it is a free link.
  471. //
  472. ULONG AllocatedOrNextFree;
  473. //
  474. // Transaction State
  475. //
  476. UCHAR TransactionState;
  477. //
  478. // Reserved for proper alignment
  479. //
  480. UCHAR Reserved[3];
  481. //
  482. // First Lsn for transaction. This tells us how far back in the log
  483. // we may have to read to abort the transaction.
  484. //
  485. LSN FirstLsn;
  486. //
  487. // PreviousLsn written for the transaction and UndoNextLsn (next record
  488. // which should be undone in the event of a rollback.
  489. //
  490. LSN PreviousLsn;
  491. LSN UndoNextLsn;
  492. //
  493. // Number of of undo log records pending abort, and total undo size.
  494. //
  495. ULONG UndoRecords;
  496. LONG UndoBytes;
  497. } TRANSACTION_ENTRY, *PTRANSACTION_ENTRY;
  498. //
  499. // Restart record
  500. //
  501. // The Restart record used by NTFS is small, and it only describes where
  502. // the above information has been written to the log. The above records
  503. // may be considered logically part of NTFS's restart area.
  504. //
  505. typedef struct _RESTART_AREA {
  506. //
  507. // Version numbers of NTFS Restart Implementation
  508. //
  509. ULONG MajorVersion;
  510. ULONG MinorVersion;
  511. //
  512. // Lsn of Start of Checkpoint. This is the Lsn at which the Analysis
  513. // Phase of Restart must begin.
  514. //
  515. LSN StartOfCheckpoint;
  516. //
  517. // Lsns at which the four tables above plus the attribute names reside.
  518. //
  519. LSN OpenAttributeTableLsn;
  520. LSN AttributeNamesLsn;
  521. LSN DirtyPageTableLsn;
  522. LSN TransactionTableLsn;
  523. //
  524. // Lengths of the above structures in bytes.
  525. //
  526. ULONG OpenAttributeTableLength;
  527. ULONG AttributeNamesLength;
  528. ULONG DirtyPageTableLength;
  529. ULONG TransactionTableLength;
  530. } RESTART_AREA, *PRESTART_AREA;
  531. //
  532. // RECORD STRUCTURES USED BY LOG RECORDS
  533. //
  534. //
  535. // Set new attribute sizes
  536. //
  537. typedef struct _NEW_ATTRIBUTE_SIZES {
  538. LONGLONG AllocationSize;
  539. LONGLONG ValidDataLength;
  540. LONGLONG FileSize;
  541. } NEW_ATTRIBUTE_SIZES, *PNEW_ATTRIBUTE_SIZES;
  542. //
  543. // Describe a bitmap range
  544. //
  545. typedef struct _BITMAP_RANGE {
  546. ULONG BitMapOffset;
  547. ULONG NumberOfBits;
  548. } BITMAP_RANGE, *PBITMAP_RANGE;
  549. //
  550. // Describe a range of Lcns
  551. //
  552. typedef struct _LCN_RANGE {
  553. LCN StartLcn;
  554. LONGLONG Count;
  555. } LCN_RANGE, *PLCN_RANGE;
  556. #pragma pack()
  557. #endif // _NTFSLOG_