btt.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. =============================
  2. BTT - Block Translation Table
  3. =============================
  4. 1. Introduction
  5. ===============
  6. Persistent memory based storage is able to perform IO at byte (or more
  7. accurately, cache line) granularity. However, we often want to expose such
  8. storage as traditional block devices. The block drivers for persistent memory
  9. will do exactly this. However, they do not provide any atomicity guarantees.
  10. Traditional SSDs typically provide protection against torn sectors in hardware,
  11. using stored energy in capacitors to complete in-flight block writes, or perhaps
  12. in firmware. We don't have this luxury with persistent memory - if a write is in
  13. progress, and we experience a power failure, the block will contain a mix of old
  14. and new data. Applications may not be prepared to handle such a scenario.
  15. The Block Translation Table (BTT) provides atomic sector update semantics for
  16. persistent memory devices, so that applications that rely on sector writes not
  17. being torn can continue to do so. The BTT manifests itself as a stacked block
  18. device, and reserves a portion of the underlying storage for its metadata. At
  19. the heart of it, is an indirection table that re-maps all the blocks on the
  20. volume. It can be thought of as an extremely simple file system that only
  21. provides atomic sector updates.
  22. 2. Static Layout
  23. ================
  24. The underlying storage on which a BTT can be laid out is not limited in any way.
  25. The BTT, however, splits the available space into chunks of up to 512 GiB,
  26. called "Arenas".
  27. Each arena follows the same layout for its metadata, and all references in an
  28. arena are internal to it (with the exception of one field that points to the
  29. next arena). The following depicts the "On-disk" metadata layout::
  30. Backing Store +-------> Arena
  31. +---------------+ | +------------------+
  32. | | | | Arena info block |
  33. | Arena 0 +---+ | 4K |
  34. | 512G | +------------------+
  35. | | | |
  36. +---------------+ | |
  37. | | | |
  38. | Arena 1 | | Data Blocks |
  39. | 512G | | |
  40. | | | |
  41. +---------------+ | |
  42. | . | | |
  43. | . | | |
  44. | . | | |
  45. | | | |
  46. | | | |
  47. +---------------+ +------------------+
  48. | |
  49. | BTT Map |
  50. | |
  51. | |
  52. +------------------+
  53. | |
  54. | BTT Flog |
  55. | |
  56. +------------------+
  57. | Info block copy |
  58. | 4K |
  59. +------------------+
  60. 3. Theory of Operation
  61. ======================
  62. a. The BTT Map
  63. --------------
  64. The map is a simple lookup/indirection table that maps an LBA to an internal
  65. block. Each map entry is 32 bits. The two most significant bits are special
  66. flags, and the remaining form the internal block number.
  67. ======== =============================================================
  68. Bit Description
  69. ======== =============================================================
  70. 31 - 30 Error and Zero flags - Used in the following way::
  71. == == ====================================================
  72. 31 30 Description
  73. == == ====================================================
  74. 0 0 Initial state. Reads return zeroes; Premap = Postmap
  75. 0 1 Zero state: Reads return zeroes
  76. 1 0 Error state: Reads fail; Writes clear 'E' bit
  77. 1 1 Normal Block – has valid postmap
  78. == == ====================================================
  79. 29 - 0 Mappings to internal 'postmap' blocks
  80. ======== =============================================================
  81. Some of the terminology that will be subsequently used:
  82. ============ ================================================================
  83. External LBA LBA as made visible to upper layers.
  84. ABA Arena Block Address - Block offset/number within an arena
  85. Premap ABA The block offset into an arena, which was decided upon by range
  86. checking the External LBA
  87. Postmap ABA The block number in the "Data Blocks" area obtained after
  88. indirection from the map
  89. nfree The number of free blocks that are maintained at any given time.
  90. This is the number of concurrent writes that can happen to the
  91. arena.
  92. ============ ================================================================
  93. For example, after adding a BTT, we surface a disk of 1024G. We get a read for
  94. the external LBA at 768G. This falls into the second arena, and of the 512G
  95. worth of blocks that this arena contributes, this block is at 256G. Thus, the
  96. premap ABA is 256G. We now refer to the map, and find out the mapping for block
  97. 'X' (256G) points to block 'Y', say '64'. Thus the postmap ABA is 64.
  98. b. The BTT Flog
  99. ---------------
  100. The BTT provides sector atomicity by making every write an "allocating write",
  101. i.e. Every write goes to a "free" block. A running list of free blocks is
  102. maintained in the form of the BTT flog. 'Flog' is a combination of the words
  103. "free list" and "log". The flog contains 'nfree' entries, and an entry contains:
  104. ======== =====================================================================
  105. lba The premap ABA that is being written to
  106. old_map The old postmap ABA - after 'this' write completes, this will be a
  107. free block.
  108. new_map The new postmap ABA. The map will up updated to reflect this
  109. lba->postmap_aba mapping, but we log it here in case we have to
  110. recover.
  111. seq Sequence number to mark which of the 2 sections of this flog entry is
  112. valid/newest. It cycles between 01->10->11->01 (binary) under normal
  113. operation, with 00 indicating an uninitialized state.
  114. lba' alternate lba entry
  115. old_map' alternate old postmap entry
  116. new_map' alternate new postmap entry
  117. seq' alternate sequence number.
  118. ======== =====================================================================
  119. Each of the above fields is 32-bit, making one entry 32 bytes. Entries are also
  120. padded to 64 bytes to avoid cache line sharing or aliasing. Flog updates are
  121. done such that for any entry being written, it:
  122. a. overwrites the 'old' section in the entry based on sequence numbers
  123. b. writes the 'new' section such that the sequence number is written last.
  124. c. The concept of lanes
  125. -----------------------
  126. While 'nfree' describes the number of concurrent IOs an arena can process
  127. concurrently, 'nlanes' is the number of IOs the BTT device as a whole can
  128. process::
  129. nlanes = min(nfree, num_cpus)
  130. A lane number is obtained at the start of any IO, and is used for indexing into
  131. all the on-disk and in-memory data structures for the duration of the IO. If
  132. there are more CPUs than the max number of available lanes, than lanes are
  133. protected by spinlocks.
  134. d. In-memory data structure: Read Tracking Table (RTT)
  135. ------------------------------------------------------
  136. Consider a case where we have two threads, one doing reads and the other,
  137. writes. We can hit a condition where the writer thread grabs a free block to do
  138. a new IO, but the (slow) reader thread is still reading from it. In other words,
  139. the reader consulted a map entry, and started reading the corresponding block. A
  140. writer started writing to the same external LBA, and finished the write updating
  141. the map for that external LBA to point to its new postmap ABA. At this point the
  142. internal, postmap block that the reader is (still) reading has been inserted
  143. into the list of free blocks. If another write comes in for the same LBA, it can
  144. grab this free block, and start writing to it, causing the reader to read
  145. incorrect data. To prevent this, we introduce the RTT.
  146. The RTT is a simple, per arena table with 'nfree' entries. Every reader inserts
  147. into rtt[lane_number], the postmap ABA it is reading, and clears it after the
  148. read is complete. Every writer thread, after grabbing a free block, checks the
  149. RTT for its presence. If the postmap free block is in the RTT, it waits till the
  150. reader clears the RTT entry, and only then starts writing to it.
  151. e. In-memory data structure: map locks
  152. --------------------------------------
  153. Consider a case where two writer threads are writing to the same LBA. There can
  154. be a race in the following sequence of steps::
  155. free[lane] = map[premap_aba]
  156. map[premap_aba] = postmap_aba
  157. Both threads can update their respective free[lane] with the same old, freed
  158. postmap_aba. This has made the layout inconsistent by losing a free entry, and
  159. at the same time, duplicating another free entry for two lanes.
  160. To solve this, we could have a single map lock (per arena) that has to be taken
  161. before performing the above sequence, but we feel that could be too contentious.
  162. Instead we use an array of (nfree) map_locks that is indexed by
  163. (premap_aba modulo nfree).
  164. f. Reconstruction from the Flog
  165. -------------------------------
  166. On startup, we analyze the BTT flog to create our list of free blocks. We walk
  167. through all the entries, and for each lane, of the set of two possible
  168. 'sections', we always look at the most recent one only (based on the sequence
  169. number). The reconstruction rules/steps are simple:
  170. - Read map[log_entry.lba].
  171. - If log_entry.new matches the map entry, then log_entry.old is free.
  172. - If log_entry.new does not match the map entry, then log_entry.new is free.
  173. (This case can only be caused by power-fails/unsafe shutdowns)
  174. g. Summarizing - Read and Write flows
  175. -------------------------------------
  176. Read:
  177. 1. Convert external LBA to arena number + pre-map ABA
  178. 2. Get a lane (and take lane_lock)
  179. 3. Read map to get the entry for this pre-map ABA
  180. 4. Enter post-map ABA into RTT[lane]
  181. 5. If TRIM flag set in map, return zeroes, and end IO (go to step 8)
  182. 6. If ERROR flag set in map, end IO with EIO (go to step 8)
  183. 7. Read data from this block
  184. 8. Remove post-map ABA entry from RTT[lane]
  185. 9. Release lane (and lane_lock)
  186. Write:
  187. 1. Convert external LBA to Arena number + pre-map ABA
  188. 2. Get a lane (and take lane_lock)
  189. 3. Use lane to index into in-memory free list and obtain a new block, next flog
  190. index, next sequence number
  191. 4. Scan the RTT to check if free block is present, and spin/wait if it is.
  192. 5. Write data to this free block
  193. 6. Read map to get the existing post-map ABA entry for this pre-map ABA
  194. 7. Write flog entry: [premap_aba / old postmap_aba / new postmap_aba / seq_num]
  195. 8. Write new post-map ABA into map.
  196. 9. Write old post-map entry into the free list
  197. 10. Calculate next sequence number and write into the free list entry
  198. 11. Release lane (and lane_lock)
  199. 4. Error Handling
  200. =================
  201. An arena would be in an error state if any of the metadata is corrupted
  202. irrecoverably, either due to a bug or a media error. The following conditions
  203. indicate an error:
  204. - Info block checksum does not match (and recovering from the copy also fails)
  205. - All internal available blocks are not uniquely and entirely addressed by the
  206. sum of mapped blocks and free blocks (from the BTT flog).
  207. - Rebuilding free list from the flog reveals missing/duplicate/impossible
  208. entries
  209. - A map entry is out of bounds
  210. If any of these error conditions are encountered, the arena is put into a read
  211. only state using a flag in the info block.
  212. 5. Usage
  213. ========
  214. The BTT can be set up on any disk (namespace) exposed by the libnvdimm subsystem
  215. (pmem, or blk mode). The easiest way to set up such a namespace is using the
  216. 'ndctl' utility [1]:
  217. For example, the ndctl command line to setup a btt with a 4k sector size is::
  218. ndctl create-namespace -f -e namespace0.0 -m sector -l 4k
  219. See ndctl create-namespace --help for more options.
  220. [1]: https://github.com/pmem/ndctl