€•ѺŒsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ)/translations/zh_CN/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ)/translations/zh_TW/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ)/translations/it_IT/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ)/translations/ja_JP/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ)/translations/ko_KR/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ)/translations/pt_BR/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ)/translations/sp_SP/driver-api/nvdimm/btt”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒBTT - Block Translation Table”h]”hŒBTT - Block Translation Table”…”�”}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³ŒC/var/lib/git/docbuild/linux/Documentation/driver-api/nvdimm/btt.rst”h´Kubh¶)�”}”(hhh]”(h»)�”}”(hŒ1. Introduction”h]”hŒ1. Introduction”…”�”}”(hhÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhhËh²hh³hÊh´KubhŒ paragraph”“”)�”}”(hX¹Persistent memory based storage is able to perform IO at byte (or more accurately, cache line) granularity. However, we often want to expose such storage as traditional block devices. The block drivers for persistent memory will do exactly this. However, they do not provide any atomicity guarantees. Traditional SSDs typically provide protection against torn sectors in hardware, using stored energy in capacitors to complete in-flight block writes, or perhaps in firmware. We don't have this luxury with persistent memory - if a write is in progress, and we experience a power failure, the block will contain a mix of old and new data. Applications may not be prepared to handle such a scenario.”h]”hX»Persistent memory based storage is able to perform IO at byte (or more accurately, cache line) granularity. However, we often want to expose such storage as traditional block devices. The block drivers for persistent memory will do exactly this. However, they do not provide any atomicity guarantees. Traditional SSDs typically provide protection against torn sectors in hardware, using stored energy in capacitors to complete in-flight block writes, or perhaps in firmware. We don’t have this luxury with persistent memory - if a write is in progress, and we experience a power failure, the block will contain a mix of old and new data. Applications may not be prepared to handle such a scenario.”…”�”}”(hhÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K hhËh²hubhÝ)�”}”(hXîThe Block Translation Table (BTT) provides atomic sector update semantics for persistent memory devices, so that applications that rely on sector writes not being torn can continue to do so. The BTT manifests itself as a stacked block device, and reserves a portion of the underlying storage for its metadata. At the heart of it, is an indirection table that re-maps all the blocks on the volume. It can be thought of as an extremely simple file system that only provides atomic sector updates.”h]”hXîThe Block Translation Table (BTT) provides atomic sector update semantics for persistent memory devices, so that applications that rely on sector writes not being torn can continue to do so. The BTT manifests itself as a stacked block device, and reserves a portion of the underlying storage for its metadata. At the heart of it, is an indirection table that re-maps all the blocks on the volume. It can be thought of as an extremely simple file system that only provides atomic sector updates.”…”�”}”(hhìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KhhËh²hubeh}”(h]”Œ introduction”ah ]”h"]”Œ1. introduction”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)�”}”(hhh]”(h»)�”}”(hŒ2. Static Layout”h]”hŒ2. Static Layout”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjh²hh³hÊh´KubhÝ)�”}”(hŒ¬The underlying storage on which a BTT can be laid out is not limited in any way. The BTT, however, splits the available space into chunks of up to 512 GiB, called "Arenas".”h]”hŒ°The underlying storage on which a BTT can be laid out is not limited in any way. The BTT, however, splits the available space into chunks of up to 512 GiB, called “Arenasâ€�.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Khjh²hubhÝ)�”}”(hŒÝEach arena follows the same layout for its metadata, and all references in an arena are internal to it (with the exception of one field that points to the next arena). The following depicts the "On-disk" metadata layout::”h]”hŒàEach arena follows the same layout for its metadata, and all references in an arena are internal to it (with the exception of one field that points to the next arena). The following depicts the “On-diskâ€� metadata layout:”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K#hjh²hubhŒ literal_block”“”)�”}”(hX= Backing Store +-------> Arena +---------------+ | +------------------+ | | | | Arena info block | | Arena 0 +---+ | 4K | | 512G | +------------------+ | | | | +---------------+ | | | | | | | Arena 1 | | Data Blocks | | 512G | | | | | | | +---------------+ | | | . | | | | . | | | | . | | | | | | | | | | | +---------------+ +------------------+ | | | BTT Map | | | | | +------------------+ | | | BTT Flog | | | +------------------+ | Info block copy | | 4K | +------------------+”h]”hX= Backing Store +-------> Arena +---------------+ | +------------------+ | | | | Arena info block | | Arena 0 +---+ | 4K | | 512G | +------------------+ | | | | +---------------+ | | | | | | | Arena 1 | | Data Blocks | | 512G | | | | | | | +---------------+ | | | . | | | | . | | | | . | | | | | | | | | | | +---------------+ +------------------+ | | | BTT Map | | | | | +------------------+ | | | BTT Flog | | | +------------------+ | Info block copy | | 4K | +------------------+”…”�”}”hj1sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1j/h³hÊh´K(hjh²hubeh}”(h]”Œ static-layout”ah ]”h"]”Œ2. static layout”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)�”}”(hhh]”(h»)�”}”(hŒ3. Theory of Operation”h]”hŒ3. Theory of Operation”…”�”}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjIh²hh³hÊh´KIubh¶)�”}”(hhh]”(h»)�”}”(hŒa. The BTT Map”h]”hŒa. The BTT Map”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjZh²hh³hÊh´KMubhÝ)�”}”(hŒÑThe map is a simple lookup/indirection table that maps an LBA to an internal block. Each map entry is 32 bits. The two most significant bits are special flags, and the remaining form the internal block number.”h]”hŒÑThe map is a simple lookup/indirection table that maps an LBA to an internal block. Each map entry is 32 bits. The two most significant bits are special flags, and the remaining form the internal block number.”…”�”}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KOhjZh²hubhŒtable”“”)�”}”(hhh]”hŒtgroup”“”)�”}”(hhh]”(hŒcolspec”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jƒhj€ubj„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K=uh1jƒhj€ubhŒthead”“”)�”}”(hhh]”hŒrow”“”)�”}”(hhh]”(hŒentry”“”)�”}”(hhh]”hÝ)�”}”(hŒBit”h]”hŒBit”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KThj¥ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ Description”h]”hŒ Description”…”�”}”(hj¿h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KThj¼ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj›ubah}”(h]”h ]”h"]”h$]”h&]”uh1j™hj€ubhŒtbody”“”)�”}”(hhh]”(jŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ31 - 30”h]”hŒ31 - 30”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KVhjçubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjäubj¤)�”}”(hhh]”(hÝ)�”}”(hŒ1Error and Zero flags - Used in the following way:”h]”hŒ1Error and Zero flags - Used in the following way:”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KVhjþubhŒ block_quote”“”)�”}”(hX‰== == ==================================================== 31 30 Description == == ==================================================== 0 0 Initial state. Reads return zeroes; Premap = Postmap 0 1 Zero state: Reads return zeroes 1 0 Error state: Reads fail; Writes clear 'E' bit 1 1 Normal Block – has valid postmap == == ==================================================== ”h]”jz)�”}”(hhh]”j)�”}”(hhh]”(j„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jƒhjubj„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jƒhjubj„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K4uh1jƒhjubjš)�”}”(hhh]”jŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ31”h]”hŒ31”…”�”}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KYhj?ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj<ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ30”h]”hŒ30”…”�”}”(hjYh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KYhjVubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj<ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ Description”h]”hŒ Description”…”�”}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KYhjmubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj<ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj9ubah}”(h]”h ]”h"]”h$]”h&]”uh1j™hjubjà)�”}”(hhh]”(jŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ0”h]”hŒ0”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K[hj–ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj“ubj¤)�”}”(hhh]”hÝ)�”}”(hj›h]”hŒ0”…”�”}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K[hj­ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj“ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ4Initial state. Reads return zeroes; Premap = Postmap”h]”hŒ4Initial state. Reads return zeroes; Premap = Postmap”…”�”}”(hjÆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K[hjÃubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj“ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj�ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hj›h]”hŒ0”…”�”}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K\hjãubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjàubj¤)�”}”(hhh]”hÝ)�”}”(hŒ1”h]”hŒ1”…”�”}”(hjüh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K\hjùubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjàubj¤)�”}”(hhh]”hÝ)�”}”(hŒZero state: Reads return zeroes”h]”hŒZero state: Reads return zeroes”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K\hjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjàubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj�ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hjþh]”hŒ1”…”�”}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K]hj0ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj-ubj¤)�”}”(hhh]”hÝ)�”}”(hj›h]”hŒ0”…”�”}”(hjIh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K]hjFubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj-ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ-Error state: Reads fail; Writes clear 'E' bit”h]”hŒ1Error state: Reads fail; Writes clear ‘E’ bit”…”�”}”(hj_h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K]hj\ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj-ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj�ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hjþh]”hŒ1”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K^hj|ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjyubj¤)�”}”(hhh]”hÝ)�”}”(hjþh]”hŒ1”…”�”}”(hj•h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K^hj’ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjyubj¤)�”}”(hhh]”hÝ)�”}”(hŒ"Normal Block – has valid postmap”h]”hŒ"Normal Block – has valid postmap”…”�”}”(hj«h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K^hj¨ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjyubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj�ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jßhjubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1j~hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jyhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÊh´KXhjþubeh}”(h]”h ]”h"]”h$]”h&]”uh1j£hjäubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjáubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ29 - 0”h]”hŒ29 - 0”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kahjíubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjêubj¤)�”}”(hhh]”hÝ)�”}”(hŒ%Mappings to internal 'postmap' blocks”h]”hŒ)Mappings to internal ‘postmap’ blocks”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kahjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjêubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjáubeh}”(h]”h ]”h"]”h$]”h&]”uh1jßhj€ubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1j~hj{ubah}”(h]”h ]”h"]”h$]”h&]”uh1jyhjZh²hh³hÊh´NubhÝ)�”}”(hŒ7Some of the terminology that will be subsequently used:”h]”hŒ7Some of the terminology that will be subsequently used:”…”�”}”(hj4h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KehjZh²hubjz)�”}”(hhh]”j)�”}”(hhh]”(j„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K uh1jƒhjEubj„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K@uh1jƒhjEubjà)�”}”(hhh]”(jŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ External LBA”h]”hŒ External LBA”…”�”}”(hjeh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Khhjbubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj_ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ$LBA as made visible to upper layers.”h]”hŒ$LBA as made visible to upper layers.”…”�”}”(hj|h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Khhjyubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj_ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj\ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒABA”h]”hŒABA”…”�”}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kihj™ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj–ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ9Arena Block Address - Block offset/number within an arena”h]”hŒ9Arena Block Address - Block offset/number within an arena”…”�”}”(hj³h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kihj°ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj–ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj\ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ Premap ABA”h]”hŒ Premap ABA”…”�”}”(hjÓh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KjhjÐubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjÍubj¤)�”}”(hhh]”hÝ)�”}”(hŒYThe block offset into an arena, which was decided upon by range checking the External LBA”h]”hŒYThe block offset into an arena, which was decided upon by range checking the External LBA”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kjhjçubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjÍubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj\ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒ Postmap ABA”h]”hŒ Postmap ABA”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Klhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjubj¤)�”}”(hhh]”hÝ)�”}”(hŒRThe block number in the "Data Blocks" area obtained after indirection from the map”h]”hŒVThe block number in the “Data Blocksâ€� area obtained after indirection from the map”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Klhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj\ubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒnfree”h]”hŒnfree”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Knhj>ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj;ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ†The number of free blocks that are maintained at any given time. This is the number of concurrent writes that can happen to the arena.”h]”hŒ†The number of free blocks that are maintained at any given time. This is the number of concurrent writes that can happen to the arena.”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KnhjUubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj;ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhj\ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jßhjEubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1j~hjBubah}”(h]”h ]”h"]”h$]”h&]”uh1jyhjZh²hh³hÊh´NubhÝ)�”}”(hX~For example, after adding a BTT, we surface a disk of 1024G. We get a read for the external LBA at 768G. This falls into the second arena, and of the 512G worth of blocks that this arena contributes, this block is at 256G. Thus, the premap ABA is 256G. We now refer to the map, and find out the mapping for block 'X' (256G) points to block 'Y', say '64'. Thus the postmap ABA is 64.”h]”hXŠFor example, after adding a BTT, we surface a disk of 1024G. We get a read for the external LBA at 768G. This falls into the second arena, and of the 512G worth of blocks that this arena contributes, this block is at 256G. Thus, the premap ABA is 256G. We now refer to the map, and find out the mapping for block ‘X’ (256G) points to block ‘Y’, say ‘64’. Thus the postmap ABA is 64.”…”�”}”(hj…h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KthjZh²hubeh}”(h]”Œ a-the-btt-map”ah ]”h"]”Œa. the btt map”ah$]”h&]”uh1hµhjIh²hh³hÊh´KMubh¶)�”}”(hhh]”(h»)�”}”(hŒb. The BTT Flog”h]”hŒb. The BTT Flog”…”�”}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj›h²hh³hÊh´K|ubhÝ)�”}”(hX6The BTT provides sector atomicity by making every write an "allocating write", i.e. Every write goes to a "free" block. A running list of free blocks is maintained in the form of the BTT flog. 'Flog' is a combination of the words "free list" and "log". The flog contains 'nfree' entries, and an entry contains:”h]”hXNThe BTT provides sector atomicity by making every write an “allocating writeâ€�, i.e. Every write goes to a “freeâ€� block. A running list of free blocks is maintained in the form of the BTT flog. ‘Flog’ is a combination of the words “free listâ€� and “logâ€�. The flog contains ‘nfree’ entries, and an entry contains:”…”�”}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K~hj›h²hubjz)�”}”(hhh]”j)�”}”(hhh]”(j„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jƒhj½ubj„)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”KEuh1jƒhj½ubjà)�”}”(hhh]”(jŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒlba”h]”hŒlba”…”�”}”(hjÝh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K„hjÚubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj×ubj¤)�”}”(hhh]”hÝ)�”}”(hŒ'The premap ABA that is being written to”h]”hŒ'The premap ABA that is being written to”…”�”}”(hjôh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K„hjñubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj×ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒold_map”h]”hŒold_map”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K…hjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjubj¤)�”}”(hhh]”hÝ)�”}”(hŒNThe old postmap ABA - after 'this' write completes, this will be a free block.”h]”hŒRThe old postmap ABA - after ‘this’ write completes, this will be a free block.”…”�”}”(hj+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K…hj(ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒnew_map”h]”hŒnew_map”…”�”}”(hjKh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K‡hjHubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjEubj¤)�”}”(hhh]”hÝ)�”}”(hŒ…The new postmap ABA. The map will up updated to reflect this lba->postmap_aba mapping, but we log it here in case we have to recover.”h]”hŒ…The new postmap ABA. The map will up updated to reflect this lba->postmap_aba mapping, but we log it here in case we have to recover.”…”�”}”(hjbh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K‡hj_ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjEubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒseq”h]”hŒseq”…”�”}”(hj‚h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KŠhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj|ubj¤)�”}”(hhh]”hÝ)�”}”(hŒÀSequence number to mark which of the 2 sections of this flog entry is valid/newest. It cycles between 01->10->11->01 (binary) under normal operation, with 00 indicating an uninitialized state.”h]”hŒÀSequence number to mark which of the 2 sections of this flog entry is valid/newest. It cycles between 01->10->11->01 (binary) under normal operation, with 00 indicating an uninitialized state.”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KŠhj–ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj|ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒlba'”h]”hŒlba’”…”�”}”(hj¹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hj¶ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj³ubj¤)�”}”(hhh]”hÝ)�”}”(hŒalternate lba entry”h]”hŒalternate lba entry”…”�”}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hjÍubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj³ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒold_map'”h]”hŒ old_map’”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KŽhjíubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjêubj¤)�”}”(hhh]”hÝ)�”}”(hŒalternate old postmap entry”h]”hŒalternate old postmap entry”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KŽhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjêubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒnew_map'”h]”hŒ new_map’”…”�”}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hj$ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj!ubj¤)�”}”(hhh]”hÝ)�”}”(hŒalternate new postmap entry”h]”hŒalternate new postmap entry”…”�”}”(hj>h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hj;ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hj!ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubjŸ)�”}”(hhh]”(j¤)�”}”(hhh]”hÝ)�”}”(hŒseq'”h]”hŒseq’”…”�”}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hj[ubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjXubj¤)�”}”(hhh]”hÝ)�”}”(hŒalternate sequence number.”h]”hŒalternate sequence number.”…”�”}”(hjuh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hjrubah}”(h]”h ]”h"]”h$]”h&]”uh1j£hjXubeh}”(h]”h ]”h"]”h$]”h&]”uh1jžhjÔubeh}”(h]”h ]”h"]”h$]”h&]”uh1jßhj½ubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1j~hjºubah}”(h]”h ]”h"]”h$]”h&]”uh1jyhj›h²hh³hÊh´NubhÝ)�”}”(hX^Each of the above fields is 32-bit, making one entry 32 bytes. Entries are also padded to 64 bytes to avoid cache line sharing or aliasing. Flog updates are done such that for any entry being written, it: a. overwrites the 'old' section in the entry based on sequence numbers b. writes the 'new' section such that the sequence number is written last.”h]”hXfEach of the above fields is 32-bit, making one entry 32 bytes. Entries are also padded to 64 bytes to avoid cache line sharing or aliasing. Flog updates are done such that for any entry being written, it: a. overwrites the ‘old’ section in the entry based on sequence numbers b. writes the ‘new’ section such that the sequence number is written last.”…”�”}”(hj¢h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K“hj›h²hubeh}”(h]”Œb-the-btt-flog”ah ]”h"]”Œb. the btt flog”ah$]”h&]”uh1hµhjIh²hh³hÊh´K|ubh¶)�”}”(hhh]”(h»)�”}”(hŒc. The concept of lanes”h]”hŒc. The concept of lanes”…”�”}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj¸h²hh³hÊh´K›ubhÝ)�”}”(hŒ�While 'nfree' describes the number of concurrent IOs an arena can process concurrently, 'nlanes' is the number of IOs the BTT device as a whole can process::”h]”hŒ¤While ‘nfree’ describes the number of concurrent IOs an arena can process concurrently, ‘nlanes’ is the number of IOs the BTT device as a whole can process:”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K�hj¸h²hubj0)�”}”(hŒnlanes = min(nfree, num_cpus)”h]”hŒnlanes = min(nfree, num_cpus)”…”�”}”hj×sbah}”(h]”h ]”h"]”h$]”h&]”j?j@uh1j/h³hÊh´K¡hj¸h²hubhÝ)�”}”(hŒ¹A lane number is obtained at the start of any IO, and is used for indexing into all the on-disk and in-memory data structures for the duration of the IO. Lanes are protected by mutexes.”h]”hŒ¹A lane number is obtained at the start of any IO, and is used for indexing into all the on-disk and in-memory data structures for the duration of the IO. Lanes are protected by mutexes.”…”�”}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K£hj¸h²hubeh}”(h]”Œc-the-concept-of-lanes”ah ]”h"]”Œc. the concept of lanes”ah$]”h&]”uh1hµhjIh²hh³hÊh´K›ubh¶)�”}”(hhh]”(h»)�”}”(hŒ6d. In-memory data structure: Read Tracking Table (RTT)”h]”hŒ6d. In-memory data structure: Read Tracking Table (RTT)”…”�”}”(hjþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjûh²hh³hÊh´K©ubhÝ)�”}”(hXüConsider a case where we have two threads, one doing reads and the other, writes. We can hit a condition where the writer thread grabs a free block to do a new IO, but the (slow) reader thread is still reading from it. In other words, the reader consulted a map entry, and started reading the corresponding block. A writer started writing to the same external LBA, and finished the write updating the map for that external LBA to point to its new postmap ABA. At this point the internal, postmap block that the reader is (still) reading has been inserted into the list of free blocks. If another write comes in for the same LBA, it can grab this free block, and start writing to it, causing the reader to read incorrect data. To prevent this, we introduce the RTT.”h]”hXüConsider a case where we have two threads, one doing reads and the other, writes. We can hit a condition where the writer thread grabs a free block to do a new IO, but the (slow) reader thread is still reading from it. In other words, the reader consulted a map entry, and started reading the corresponding block. A writer started writing to the same external LBA, and finished the write updating the map for that external LBA to point to its new postmap ABA. At this point the internal, postmap block that the reader is (still) reading has been inserted into the list of free blocks. If another write comes in for the same LBA, it can grab this free block, and start writing to it, causing the reader to read incorrect data. To prevent this, we introduce the RTT.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K«hjûh²hubhÝ)�”}”(hX~The RTT is a simple, per arena table with 'nfree' entries. Every reader inserts into rtt[lane_number], the postmap ABA it is reading, and clears it after the read is complete. Every writer thread, after grabbing a free block, checks the RTT for its presence. If the postmap free block is in the RTT, it waits till the reader clears the RTT entry, and only then starts writing to it.”h]”hX‚The RTT is a simple, per arena table with ‘nfree’ entries. Every reader inserts into rtt[lane_number], the postmap ABA it is reading, and clears it after the read is complete. Every writer thread, after grabbing a free block, checks the RTT for its presence. If the postmap free block is in the RTT, it waits till the reader clears the RTT entry, and only then starts writing to it.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K¶hjûh²hubeh}”(h]”Œ2d-in-memory-data-structure-read-tracking-table-rtt”ah ]”h"]”Œ6d. in-memory data structure: read tracking table (rtt)”ah$]”h&]”uh1hµhjIh²hh³hÊh´K©ubh¶)�”}”(hhh]”(h»)�”}”(hŒ&e. In-memory data structure: map locks”h]”hŒ&e. In-memory data structure: map locks”…”�”}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj0h²hh³hÊh´K¾ubhÝ)�”}”(hŒ~Consider a case where two writer threads are writing to the same LBA. There can be a race in the following sequence of steps::”h]”hŒ}Consider a case where two writer threads are writing to the same LBA. There can be a race in the following sequence of steps:”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KÀhj0h²hubj0)�”}”(hŒ:free[lane] = map[premap_aba] map[premap_aba] = postmap_aba”h]”hŒ:free[lane] = map[premap_aba] map[premap_aba] = postmap_aba”…”�”}”hjOsbah}”(h]”h ]”h"]”h$]”h&]”j?j@uh1j/h³hÊh´KÃhj0h²hubhÝ)�”}”(hŒÛBoth threads can update their respective free[lane] with the same old, freed postmap_aba. This has made the layout inconsistent by losing a free entry, and at the same time, duplicating another free entry for two lanes.”h]”hŒÛBoth threads can update their respective free[lane] with the same old, freed postmap_aba. This has made the layout inconsistent by losing a free entry, and at the same time, duplicating another free entry for two lanes.”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KÆhj0h²hubhÝ)�”}”(hŒûTo solve this, we could have a single map lock (per arena) that has to be taken before performing the above sequence, but we feel that could be too contentious. Instead we use an array of (nfree) map_locks that is indexed by (premap_aba modulo nfree).”h]”hŒûTo solve this, we could have a single map lock (per arena) that has to be taken before performing the above sequence, but we feel that could be too contentious. Instead we use an array of (nfree) map_locks that is indexed by (premap_aba modulo nfree).”…”�”}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KÊhj0h²hubeh}”(h]”Œ$e-in-memory-data-structure-map-locks”ah ]”h"]”Œ&e. in-memory data structure: map locks”ah$]”h&]”uh1hµhjIh²hh³hÊh´K¾ubh¶)�”}”(hhh]”(h»)�”}”(hŒf. Reconstruction from the Flog”h]”hŒf. Reconstruction from the Flog”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj�h²hh³hÊh´KÑubhÝ)�”}”(hXOn startup, we analyze the BTT flog to create our list of free blocks. We walk through all the entries, and for each lane, of the set of two possible 'sections', we always look at the most recent one only (based on the sequence number). The reconstruction rules/steps are simple:”h]”hXOn startup, we analyze the BTT flog to create our list of free blocks. We walk through all the entries, and for each lane, of the set of two possible ‘sections’, we always look at the most recent one only (based on the sequence number). The reconstruction rules/steps are simple:”…”�”}”(hj’h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KÓhj�h²hubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hŒRead map[log_entry.lba].”h]”hÝ)�”}”(hj©h]”hŒRead map[log_entry.lba].”…”�”}”(hj«h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KØhj§ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj¢h²hh³hÊh´Nubj¦)�”}”(hŒCIf log_entry.new matches the map entry, then log_entry.old is free.”h]”hÝ)�”}”(hjÀh]”hŒCIf log_entry.new matches the map entry, then log_entry.old is free.”…”�”}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KÙhj¾ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj¢h²hh³hÊh´Nubj¦)�”}”(hŒ‹If log_entry.new does not match the map entry, then log_entry.new is free. (This case can only be caused by power-fails/unsafe shutdowns) ”h]”hÝ)�”}”(hŒ‰If log_entry.new does not match the map entry, then log_entry.new is free. (This case can only be caused by power-fails/unsafe shutdowns)”h]”hŒ‰If log_entry.new does not match the map entry, then log_entry.new is free. (This case can only be caused by power-fails/unsafe shutdowns)”…”�”}”(hjÙh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KÚhjÕubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj¢h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j h³hÊh´KØhj�h²hubeh}”(h]”Œf-reconstruction-from-the-flog”ah ]”h"]”Œf. reconstruction from the flog”ah$]”h&]”uh1hµhjIh²hh³hÊh´KÑubh¶)�”}”(hhh]”(h»)�”}”(hŒ%g. Summarizing - Read and Write flows”h]”hŒ%g. Summarizing - Read and Write flows”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjýh²hh³hÊh´KßubhÝ)�”}”(hŒRead:”h]”hŒRead:”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Káhjýh²hubhŒenumerated_list”“”)�”}”(hhh]”(j¦)�”}”(hŒ2Convert external LBA to arena number + pre-map ABA”h]”hÝ)�”}”(hj# h]”hŒ2Convert external LBA to arena number + pre-map ABA”…”�”}”(hj% h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kãhj! ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒGet a lane (and take lane_lock)”h]”hÝ)�”}”(hj: h]”hŒGet a lane (and take lane_lock)”…”�”}”(hj< h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kähj8 ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒ.Read map to get the entry for this pre-map ABA”h]”hÝ)�”}”(hjQ h]”hŒ.Read map to get the entry for this pre-map ABA”…”�”}”(hjS h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KåhjO ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒ!Enter post-map ABA into RTT[lane]”h]”hÝ)�”}”(hjh h]”hŒ!Enter post-map ABA into RTT[lane]”…”�”}”(hjj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kæhjf ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒAIf TRIM flag set in map, return zeroes, and end IO (go to step 8)”h]”hÝ)�”}”(hj h]”hŒAIf TRIM flag set in map, return zeroes, and end IO (go to step 8)”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kçhj} ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒ8If ERROR flag set in map, end IO with EIO (go to step 8)”h]”hÝ)�”}”(hj– h]”hŒ8If ERROR flag set in map, end IO with EIO (go to step 8)”…”�”}”(hj˜ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kèhj” ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒRead data from this block”h]”hÝ)�”}”(hj­ h]”hŒRead data from this block”…”�”}”(hj¯ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kéhj« ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒ(Remove post-map ABA entry from RTT[lane]”h]”hÝ)�”}”(hjÄ h]”hŒ(Remove post-map ABA entry from RTT[lane]”…”�”}”(hjÆ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kêhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒRelease lane (and lane_lock) ”h]”hÝ)�”}”(hŒRelease lane (and lane_lock)”h]”hŒRelease lane (and lane_lock)”…”�”}”(hjÝ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KëhjÙ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œarabic”Œprefix”hŒsuffix”Œ.”uh1j hjýh²hh³hÊh´KãubhÝ)�”}”(hŒWrite:”h]”hŒWrite:”…”�”}”(hjü h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kíhjýh²hubj )�”}”(hhh]”(j¦)�”}”(hŒ2Convert external LBA to Arena number + pre-map ABA”h]”hÝ)�”}”(hj h]”hŒ2Convert external LBA to Arena number + pre-map ABA”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kïhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒGet a lane (and take lane_lock)”h]”hÝ)�”}”(hj& h]”hŒGet a lane (and take lane_lock)”…”�”}”(hj( h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kðhj$ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒhUse lane to index into in-memory free list and obtain a new block, next flog index, next sequence number”h]”hÝ)�”}”(hŒhUse lane to index into in-memory free list and obtain a new block, next flog index, next sequence number”h]”hŒhUse lane to index into in-memory free list and obtain a new block, next flog index, next sequence number”…”�”}”(hj? h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kñhj; ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒGScan the RTT to check if free block is present, and spin/wait if it is.”h]”hÝ)�”}”(hjU h]”hŒGScan the RTT to check if free block is present, and spin/wait if it is.”…”�”}”(hjW h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KóhjS ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒWrite data to this free block”h]”hÝ)�”}”(hjl h]”hŒWrite data to this free block”…”�”}”(hjn h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kôhjj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒDRead map to get the existing post-map ABA entry for this pre-map ABA”h]”hÝ)�”}”(hjƒ h]”hŒDRead map to get the existing post-map ABA entry for this pre-map ABA”…”�”}”(hj… h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kõhj� ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒLWrite flog entry: [premap_aba / old postmap_aba / new postmap_aba / seq_num]”h]”hÝ)�”}”(hjš h]”hŒLWrite flog entry: [premap_aba / old postmap_aba / new postmap_aba / seq_num]”…”�”}”(hjœ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Köhj˜ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒ Write new post-map ABA into map.”h]”hÝ)�”}”(hj± h]”hŒ Write new post-map ABA into map.”…”�”}”(hj³ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´K÷hj¯ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒ+Write old post-map entry into the free list”h]”hÝ)�”}”(hjÈ h]”hŒ+Write old post-map entry into the free list”…”�”}”(hjÊ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KøhjÆ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒACalculate next sequence number and write into the free list entry”h]”hÝ)�”}”(hjß h]”hŒACalculate next sequence number and write into the free list entry”…”�”}”(hjá h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´KùhjÝ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubj¦)�”}”(hŒRelease lane (and lane_lock) ”h]”hÝ)�”}”(hŒRelease lane (and lane_lock)”h]”hŒRelease lane (and lane_lock)”…”�”}”(hjø h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Kúhjô ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hj h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j÷ jø jù hjú jû uh1j hjýh²hh³hÊh´Kïubeh}”(h]”Œ"g-summarizing-read-and-write-flows”ah ]”h"]”Œ%g. summarizing - read and write flows”ah$]”h&]”uh1hµhjIh²hh³hÊh´Kßubeh}”(h]”Œtheory-of-operation”ah ]”h"]”Œ3. theory of operation”ah$]”h&]”uh1hµhh·h²hh³hÊh´KIubh¶)�”}”(hhh]”(h»)�”}”(hŒ4. Error Handling”h]”hŒ4. Error Handling”…”�”}”(hj% h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj" h²hh³hÊh´KþubhÝ)�”}”(hŒ¨An arena would be in an error state if any of the metadata is corrupted irrecoverably, either due to a bug or a media error. The following conditions indicate an error:”h]”hŒ¨An arena would be in an error state if any of the metadata is corrupted irrecoverably, either due to a bug or a media error. The following conditions indicate an error:”…”�”}”(hj3 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhj" h²hubj¡)�”}”(hhh]”(j¦)�”}”(hŒLInfo block checksum does not match (and recovering from the copy also fails)”h]”hÝ)�”}”(hjF h]”hŒLInfo block checksum does not match (and recovering from the copy also fails)”…”�”}”(hjH h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´MhjD ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hjA h²hh³hÊh´Nubj¦)�”}”(hŒ†All internal available blocks are not uniquely and entirely addressed by the sum of mapped blocks and free blocks (from the BTT flog).”h]”hÝ)�”}”(hŒ†All internal available blocks are not uniquely and entirely addressed by the sum of mapped blocks and free blocks (from the BTT flog).”h]”hŒ†All internal available blocks are not uniquely and entirely addressed by the sum of mapped blocks and free blocks (from the BTT flog).”…”�”}”(hj_ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhj[ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hjA h²hh³hÊh´Nubj¦)�”}”(hŒORebuilding free list from the flog reveals missing/duplicate/impossible entries”h]”hÝ)�”}”(hŒORebuilding free list from the flog reveals missing/duplicate/impossible entries”h]”hŒORebuilding free list from the flog reveals missing/duplicate/impossible entries”…”�”}”(hjw h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhjs ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hjA h²hh³hÊh´Nubj¦)�”}”(hŒA map entry is out of bounds ”h]”hÝ)�”}”(hŒA map entry is out of bounds”h]”hŒA map entry is out of bounds”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´M hj‹ ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¥hjA h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jójôuh1j h³hÊh´Mhj" h²hubhÝ)�”}”(hŒyIf any of these error conditions are encountered, the arena is put into a read only state using a flag in the info block.”h]”hŒyIf any of these error conditions are encountered, the arena is put into a read only state using a flag in the info block.”…”�”}”(hj© h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´M hj" h²hubeh}”(h]”Œerror-handling”ah ]”h"]”Œ4. error handling”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kþubh¶)�”}”(hhh]”(h»)�”}”(hŒ5. Usage”h]”hŒ5. Usage”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj¿ h²hh³hÊh´MubhÝ)�”}”(hŒ²The BTT can be set up on any disk (namespace) exposed by the libnvdimm subsystem (pmem, or blk mode). The easiest way to set up such a namespace is using the 'ndctl' utility [1]:”h]”hŒ¶The BTT can be set up on any disk (namespace) exposed by the libnvdimm subsystem (pmem, or blk mode). The easiest way to set up such a namespace is using the ‘ndctl’ utility [1]:”…”�”}”(hjÐ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhj¿ h²hubhÝ)�”}”(hŒMFor example, the ndctl command line to setup a btt with a 4k sector size is::”h]”hŒLFor example, the ndctl command line to setup a btt with a 4k sector size is:”…”�”}”(hjÞ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhj¿ h²hubj0)�”}”(hŒ9ndctl create-namespace -f -e namespace0.0 -m sector -l 4k”h]”hŒ9ndctl create-namespace -f -e namespace0.0 -m sector -l 4k”…”�”}”hjì sbah}”(h]”h ]”h"]”h$]”h&]”j?j@uh1j/h³hÊh´Mhj¿ h²hubhÝ)�”}”(hŒ3See ndctl create-namespace --help for more options.”h]”hŒ3See ndctl create-namespace --help for more options.”…”�”}”(hjú h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhj¿ h²hubhÝ)�”}”(hŒ"[1]: https://github.com/pmem/ndctl”h]”(hŒ[1]: ”…”�”}”(hj h²hh³Nh´NubhŒ reference”“”)�”}”(hŒhttps://github.com/pmem/ndctl”h]”hŒhttps://github.com/pmem/ndctl”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”j uh1j hj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÜh³hÊh´Mhj¿ h²hubeh}”(h]”Œusage”ah ]”h"]”Œ5. usage”ah$]”h&]”uh1hµhh·h²hh³hÊh´Mubeh}”(h]”Œbtt-block-translation-table”ah ]”h"]”Œbtt - block translation table”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”j£Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jY Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j4 j1 hÿhüjFjCj j j˜j•jµj²jøjõj-j*j~j{júj÷j j j¼ j¹ j, j) uŒ nametypes”}”(j4 ‰hÿ‰jF‰j ‰j˜‰jµ‰jø‰j-‰j~‰jú‰j ‰j¼ ‰j, ‰uh}”(j1 h·hühËjCjj jIj•jZj²j›jõj¸j*jûj{j0j÷j�j jýj¹ j" j) j¿ uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.