nvdimm.rst 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. ===============================
  2. LIBNVDIMM: Non-Volatile Devices
  3. ===============================
  4. libnvdimm - kernel / libndctl - userspace helper library
  5. [email protected]
  6. Version 13
  7. .. contents:
  8. Glossary
  9. Overview
  10. Supporting Documents
  11. Git Trees
  12. LIBNVDIMM PMEM
  13. PMEM-REGIONs, Atomic Sectors, and DAX
  14. Example NVDIMM Platform
  15. LIBNVDIMM Kernel Device Model and LIBNDCTL Userspace API
  16. LIBNDCTL: Context
  17. libndctl: instantiate a new library context example
  18. LIBNVDIMM/LIBNDCTL: Bus
  19. libnvdimm: control class device in /sys/class
  20. libnvdimm: bus
  21. libndctl: bus enumeration example
  22. LIBNVDIMM/LIBNDCTL: DIMM (NMEM)
  23. libnvdimm: DIMM (NMEM)
  24. libndctl: DIMM enumeration example
  25. LIBNVDIMM/LIBNDCTL: Region
  26. libnvdimm: region
  27. libndctl: region enumeration example
  28. Why Not Encode the Region Type into the Region Name?
  29. How Do I Determine the Major Type of a Region?
  30. LIBNVDIMM/LIBNDCTL: Namespace
  31. libnvdimm: namespace
  32. libndctl: namespace enumeration example
  33. libndctl: namespace creation example
  34. Why the Term "namespace"?
  35. LIBNVDIMM/LIBNDCTL: Block Translation Table "btt"
  36. libnvdimm: btt layout
  37. libndctl: btt creation example
  38. Summary LIBNDCTL Diagram
  39. Glossary
  40. ========
  41. PMEM:
  42. A system-physical-address range where writes are persistent. A
  43. block device composed of PMEM is capable of DAX. A PMEM address range
  44. may span an interleave of several DIMMs.
  45. DPA:
  46. DIMM Physical Address, is a DIMM-relative offset. With one DIMM in
  47. the system there would be a 1:1 system-physical-address:DPA association.
  48. Once more DIMMs are added a memory controller interleave must be
  49. decoded to determine the DPA associated with a given
  50. system-physical-address.
  51. DAX:
  52. File system extensions to bypass the page cache and block layer to
  53. mmap persistent memory, from a PMEM block device, directly into a
  54. process address space.
  55. DSM:
  56. Device Specific Method: ACPI method to control specific
  57. device - in this case the firmware.
  58. DCR:
  59. NVDIMM Control Region Structure defined in ACPI 6 Section 5.2.25.5.
  60. It defines a vendor-id, device-id, and interface format for a given DIMM.
  61. BTT:
  62. Block Translation Table: Persistent memory is byte addressable.
  63. Existing software may have an expectation that the power-fail-atomicity
  64. of writes is at least one sector, 512 bytes. The BTT is an indirection
  65. table with atomic update semantics to front a PMEM block device
  66. driver and present arbitrary atomic sector sizes.
  67. LABEL:
  68. Metadata stored on a DIMM device that partitions and identifies
  69. (persistently names) capacity allocated to different PMEM namespaces. It
  70. also indicates whether an address abstraction like a BTT is applied to
  71. the namepsace. Note that traditional partition tables, GPT/MBR, are
  72. layered on top of a PMEM namespace, or an address abstraction like BTT
  73. if present, but partition support is deprecated going forward.
  74. Overview
  75. ========
  76. The LIBNVDIMM subsystem provides support for PMEM described by platform
  77. firmware or a device driver. On ACPI based systems the platform firmware
  78. conveys persistent memory resource via the ACPI NFIT "NVDIMM Firmware
  79. Interface Table" in ACPI 6. While the LIBNVDIMM subsystem implementation
  80. is generic and supports pre-NFIT platforms, it was guided by the
  81. superset of capabilities need to support this ACPI 6 definition for
  82. NVDIMM resources. The original implementation supported the
  83. block-window-aperture capability described in the NFIT, but that support
  84. has since been abandoned and never shipped in a product.
  85. Supporting Documents
  86. --------------------
  87. ACPI 6:
  88. https://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
  89. NVDIMM Namespace:
  90. https://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
  91. DSM Interface Example:
  92. https://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
  93. Driver Writer's Guide:
  94. https://pmem.io/documents/NVDIMM_Driver_Writers_Guide.pdf
  95. Git Trees
  96. ---------
  97. LIBNVDIMM:
  98. https://git.kernel.org/cgit/linux/kernel/git/nvdimm/nvdimm.git
  99. LIBNDCTL:
  100. https://github.com/pmem/ndctl.git
  101. LIBNVDIMM PMEM
  102. ==============
  103. Prior to the arrival of the NFIT, non-volatile memory was described to a
  104. system in various ad-hoc ways. Usually only the bare minimum was
  105. provided, namely, a single system-physical-address range where writes
  106. are expected to be durable after a system power loss. Now, the NFIT
  107. specification standardizes not only the description of PMEM, but also
  108. platform message-passing entry points for control and configuration.
  109. PMEM (nd_pmem.ko): Drives a system-physical-address range. This range is
  110. contiguous in system memory and may be interleaved (hardware memory controller
  111. striped) across multiple DIMMs. When interleaved the platform may optionally
  112. provide details of which DIMMs are participating in the interleave.
  113. It is worth noting that when the labeling capability is detected (a EFI
  114. namespace label index block is found), then no block device is created
  115. by default as userspace needs to do at least one allocation of DPA to
  116. the PMEM range. In contrast ND_NAMESPACE_IO ranges, once registered,
  117. can be immediately attached to nd_pmem. This latter mode is called
  118. label-less or "legacy".
  119. PMEM-REGIONs, Atomic Sectors, and DAX
  120. -------------------------------------
  121. For the cases where an application or filesystem still needs atomic sector
  122. update guarantees it can register a BTT on a PMEM device or partition. See
  123. LIBNVDIMM/NDCTL: Block Translation Table "btt"
  124. Example NVDIMM Platform
  125. =======================
  126. For the remainder of this document the following diagram will be
  127. referenced for any example sysfs layouts::
  128. (a) (b) DIMM
  129. +-------------------+--------+--------+--------+
  130. +------+ | pm0.0 | free | pm1.0 | free | 0
  131. | imc0 +--+- - - region0- - - +--------+ +--------+
  132. +--+---+ | pm0.0 | free | pm1.0 | free | 1
  133. | +-------------------+--------v v--------+
  134. +--+---+ | |
  135. | cpu0 | region1
  136. +--+---+ | |
  137. | +----------------------------^ ^--------+
  138. +--+---+ | free | pm1.0 | free | 2
  139. | imc1 +--+----------------------------| +--------+
  140. +------+ | free | pm1.0 | free | 3
  141. +----------------------------+--------+--------+
  142. In this platform we have four DIMMs and two memory controllers in one
  143. socket. Each PMEM interleave set is identified by a region device with
  144. a dynamically assigned id.
  145. 1. The first portion of DIMM0 and DIMM1 are interleaved as REGION0. A
  146. single PMEM namespace is created in the REGION0-SPA-range that spans most
  147. of DIMM0 and DIMM1 with a user-specified name of "pm0.0". Some of that
  148. interleaved system-physical-address range is left free for
  149. another PMEM namespace to be defined.
  150. 2. In the last portion of DIMM0 and DIMM1 we have an interleaved
  151. system-physical-address range, REGION1, that spans those two DIMMs as
  152. well as DIMM2 and DIMM3. Some of REGION1 is allocated to a PMEM namespace
  153. named "pm1.0".
  154. This bus is provided by the kernel under the device
  155. /sys/devices/platform/nfit_test.0 when the nfit_test.ko module from
  156. tools/testing/nvdimm is loaded. This module is a unit test for
  157. LIBNVDIMM and the acpi_nfit.ko driver.
  158. LIBNVDIMM Kernel Device Model and LIBNDCTL Userspace API
  159. ========================================================
  160. What follows is a description of the LIBNVDIMM sysfs layout and a
  161. corresponding object hierarchy diagram as viewed through the LIBNDCTL
  162. API. The example sysfs paths and diagrams are relative to the Example
  163. NVDIMM Platform which is also the LIBNVDIMM bus used in the LIBNDCTL unit
  164. test.
  165. LIBNDCTL: Context
  166. -----------------
  167. Every API call in the LIBNDCTL library requires a context that holds the
  168. logging parameters and other library instance state. The library is
  169. based on the libabc template:
  170. https://git.kernel.org/cgit/linux/kernel/git/kay/libabc.git
  171. LIBNDCTL: instantiate a new library context example
  172. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  173. ::
  174. struct ndctl_ctx *ctx;
  175. if (ndctl_new(&ctx) == 0)
  176. return ctx;
  177. else
  178. return NULL;
  179. LIBNVDIMM/LIBNDCTL: Bus
  180. -----------------------
  181. A bus has a 1:1 relationship with an NFIT. The current expectation for
  182. ACPI based systems is that there is only ever one platform-global NFIT.
  183. That said, it is trivial to register multiple NFITs, the specification
  184. does not preclude it. The infrastructure supports multiple busses and
  185. we use this capability to test multiple NFIT configurations in the unit
  186. test.
  187. LIBNVDIMM: control class device in /sys/class
  188. ---------------------------------------------
  189. This character device accepts DSM messages to be passed to DIMM
  190. identified by its NFIT handle::
  191. /sys/class/nd/ndctl0
  192. |-- dev
  193. |-- device -> ../../../ndbus0
  194. |-- subsystem -> ../../../../../../../class/nd
  195. LIBNVDIMM: bus
  196. --------------
  197. ::
  198. struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
  199. struct nvdimm_bus_descriptor *nfit_desc);
  200. ::
  201. /sys/devices/platform/nfit_test.0/ndbus0
  202. |-- commands
  203. |-- nd
  204. |-- nfit
  205. |-- nmem0
  206. |-- nmem1
  207. |-- nmem2
  208. |-- nmem3
  209. |-- power
  210. |-- provider
  211. |-- region0
  212. |-- region1
  213. |-- region2
  214. |-- region3
  215. |-- region4
  216. |-- region5
  217. |-- uevent
  218. `-- wait_probe
  219. LIBNDCTL: bus enumeration example
  220. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  221. Find the bus handle that describes the bus from Example NVDIMM Platform::
  222. static struct ndctl_bus *get_bus_by_provider(struct ndctl_ctx *ctx,
  223. const char *provider)
  224. {
  225. struct ndctl_bus *bus;
  226. ndctl_bus_foreach(ctx, bus)
  227. if (strcmp(provider, ndctl_bus_get_provider(bus)) == 0)
  228. return bus;
  229. return NULL;
  230. }
  231. bus = get_bus_by_provider(ctx, "nfit_test.0");
  232. LIBNVDIMM/LIBNDCTL: DIMM (NMEM)
  233. -------------------------------
  234. The DIMM device provides a character device for sending commands to
  235. hardware, and it is a container for LABELs. If the DIMM is defined by
  236. NFIT then an optional 'nfit' attribute sub-directory is available to add
  237. NFIT-specifics.
  238. Note that the kernel device name for "DIMMs" is "nmemX". The NFIT
  239. describes these devices via "Memory Device to System Physical Address
  240. Range Mapping Structure", and there is no requirement that they actually
  241. be physical DIMMs, so we use a more generic name.
  242. LIBNVDIMM: DIMM (NMEM)
  243. ^^^^^^^^^^^^^^^^^^^^^^
  244. ::
  245. struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
  246. const struct attribute_group **groups, unsigned long flags,
  247. unsigned long *dsm_mask);
  248. ::
  249. /sys/devices/platform/nfit_test.0/ndbus0
  250. |-- nmem0
  251. | |-- available_slots
  252. | |-- commands
  253. | |-- dev
  254. | |-- devtype
  255. | |-- driver -> ../../../../../bus/nd/drivers/nvdimm
  256. | |-- modalias
  257. | |-- nfit
  258. | | |-- device
  259. | | |-- format
  260. | | |-- handle
  261. | | |-- phys_id
  262. | | |-- rev_id
  263. | | |-- serial
  264. | | `-- vendor
  265. | |-- state
  266. | |-- subsystem -> ../../../../../bus/nd
  267. | `-- uevent
  268. |-- nmem1
  269. [..]
  270. LIBNDCTL: DIMM enumeration example
  271. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  272. Note, in this example we are assuming NFIT-defined DIMMs which are
  273. identified by an "nfit_handle" a 32-bit value where:
  274. - Bit 3:0 DIMM number within the memory channel
  275. - Bit 7:4 memory channel number
  276. - Bit 11:8 memory controller ID
  277. - Bit 15:12 socket ID (within scope of a Node controller if node
  278. controller is present)
  279. - Bit 27:16 Node Controller ID
  280. - Bit 31:28 Reserved
  281. ::
  282. static struct ndctl_dimm *get_dimm_by_handle(struct ndctl_bus *bus,
  283. unsigned int handle)
  284. {
  285. struct ndctl_dimm *dimm;
  286. ndctl_dimm_foreach(bus, dimm)
  287. if (ndctl_dimm_get_handle(dimm) == handle)
  288. return dimm;
  289. return NULL;
  290. }
  291. #define DIMM_HANDLE(n, s, i, c, d) \
  292. (((n & 0xfff) << 16) | ((s & 0xf) << 12) | ((i & 0xf) << 8) \
  293. | ((c & 0xf) << 4) | (d & 0xf))
  294. dimm = get_dimm_by_handle(bus, DIMM_HANDLE(0, 0, 0, 0, 0));
  295. LIBNVDIMM/LIBNDCTL: Region
  296. --------------------------
  297. A generic REGION device is registered for each PMEM interleave-set /
  298. range. Per the example there are 2 PMEM regions on the "nfit_test.0"
  299. bus. The primary role of regions are to be a container of "mappings". A
  300. mapping is a tuple of <DIMM, DPA-start-offset, length>.
  301. LIBNVDIMM provides a built-in driver for REGION devices. This driver
  302. is responsible for all parsing LABELs, if present, and then emitting NAMESPACE
  303. devices for the nd_pmem driver to consume.
  304. In addition to the generic attributes of "mapping"s, "interleave_ways"
  305. and "size" the REGION device also exports some convenience attributes.
  306. "nstype" indicates the integer type of namespace-device this region
  307. emits, "devtype" duplicates the DEVTYPE variable stored by udev at the
  308. 'add' event, "modalias" duplicates the MODALIAS variable stored by udev
  309. at the 'add' event, and finally, the optional "spa_index" is provided in
  310. the case where the region is defined by a SPA.
  311. LIBNVDIMM: region::
  312. struct nd_region *nvdimm_pmem_region_create(struct nvdimm_bus *nvdimm_bus,
  313. struct nd_region_desc *ndr_desc);
  314. ::
  315. /sys/devices/platform/nfit_test.0/ndbus0
  316. |-- region0
  317. | |-- available_size
  318. | |-- btt0
  319. | |-- btt_seed
  320. | |-- devtype
  321. | |-- driver -> ../../../../../bus/nd/drivers/nd_region
  322. | |-- init_namespaces
  323. | |-- mapping0
  324. | |-- mapping1
  325. | |-- mappings
  326. | |-- modalias
  327. | |-- namespace0.0
  328. | |-- namespace_seed
  329. | |-- numa_node
  330. | |-- nfit
  331. | | `-- spa_index
  332. | |-- nstype
  333. | |-- set_cookie
  334. | |-- size
  335. | |-- subsystem -> ../../../../../bus/nd
  336. | `-- uevent
  337. |-- region1
  338. [..]
  339. LIBNDCTL: region enumeration example
  340. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  341. Sample region retrieval routines based on NFIT-unique data like
  342. "spa_index" (interleave set id).
  343. ::
  344. static struct ndctl_region *get_pmem_region_by_spa_index(struct ndctl_bus *bus,
  345. unsigned int spa_index)
  346. {
  347. struct ndctl_region *region;
  348. ndctl_region_foreach(bus, region) {
  349. if (ndctl_region_get_type(region) != ND_DEVICE_REGION_PMEM)
  350. continue;
  351. if (ndctl_region_get_spa_index(region) == spa_index)
  352. return region;
  353. }
  354. return NULL;
  355. }
  356. LIBNVDIMM/LIBNDCTL: Namespace
  357. -----------------------------
  358. A REGION, after resolving DPA aliasing and LABEL specified boundaries, surfaces
  359. one or more "namespace" devices. The arrival of a "namespace" device currently
  360. triggers the nd_pmem driver to load and register a disk/block device.
  361. LIBNVDIMM: namespace
  362. ^^^^^^^^^^^^^^^^^^^^
  363. Here is a sample layout from the 2 major types of NAMESPACE where namespace0.0
  364. represents DIMM-info-backed PMEM (note that it has a 'uuid' attribute), and
  365. namespace1.0 represents an anonymous PMEM namespace (note that has no 'uuid'
  366. attribute due to not support a LABEL)
  367. ::
  368. /sys/devices/platform/nfit_test.0/ndbus0/region0/namespace0.0
  369. |-- alt_name
  370. |-- devtype
  371. |-- dpa_extents
  372. |-- force_raw
  373. |-- modalias
  374. |-- numa_node
  375. |-- resource
  376. |-- size
  377. |-- subsystem -> ../../../../../../bus/nd
  378. |-- type
  379. |-- uevent
  380. `-- uuid
  381. /sys/devices/platform/nfit_test.1/ndbus1/region1/namespace1.0
  382. |-- block
  383. | `-- pmem0
  384. |-- devtype
  385. |-- driver -> ../../../../../../bus/nd/drivers/pmem
  386. |-- force_raw
  387. |-- modalias
  388. |-- numa_node
  389. |-- resource
  390. |-- size
  391. |-- subsystem -> ../../../../../../bus/nd
  392. |-- type
  393. `-- uevent
  394. LIBNDCTL: namespace enumeration example
  395. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  396. Namespaces are indexed relative to their parent region, example below.
  397. These indexes are mostly static from boot to boot, but subsystem makes
  398. no guarantees in this regard. For a static namespace identifier use its
  399. 'uuid' attribute.
  400. ::
  401. static struct ndctl_namespace
  402. *get_namespace_by_id(struct ndctl_region *region, unsigned int id)
  403. {
  404. struct ndctl_namespace *ndns;
  405. ndctl_namespace_foreach(region, ndns)
  406. if (ndctl_namespace_get_id(ndns) == id)
  407. return ndns;
  408. return NULL;
  409. }
  410. LIBNDCTL: namespace creation example
  411. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  412. Idle namespaces are automatically created by the kernel if a given
  413. region has enough available capacity to create a new namespace.
  414. Namespace instantiation involves finding an idle namespace and
  415. configuring it. For the most part the setting of namespace attributes
  416. can occur in any order, the only constraint is that 'uuid' must be set
  417. before 'size'. This enables the kernel to track DPA allocations
  418. internally with a static identifier::
  419. static int configure_namespace(struct ndctl_region *region,
  420. struct ndctl_namespace *ndns,
  421. struct namespace_parameters *parameters)
  422. {
  423. char devname[50];
  424. snprintf(devname, sizeof(devname), "namespace%d.%d",
  425. ndctl_region_get_id(region), paramaters->id);
  426. ndctl_namespace_set_alt_name(ndns, devname);
  427. /* 'uuid' must be set prior to setting size! */
  428. ndctl_namespace_set_uuid(ndns, paramaters->uuid);
  429. ndctl_namespace_set_size(ndns, paramaters->size);
  430. /* unlike pmem namespaces, blk namespaces have a sector size */
  431. if (parameters->lbasize)
  432. ndctl_namespace_set_sector_size(ndns, parameters->lbasize);
  433. ndctl_namespace_enable(ndns);
  434. }
  435. Why the Term "namespace"?
  436. ^^^^^^^^^^^^^^^^^^^^^^^^^
  437. 1. Why not "volume" for instance? "volume" ran the risk of confusing
  438. ND (libnvdimm subsystem) to a volume manager like device-mapper.
  439. 2. The term originated to describe the sub-devices that can be created
  440. within a NVME controller (see the nvme specification:
  441. https://www.nvmexpress.org/specifications/), and NFIT namespaces are
  442. meant to parallel the capabilities and configurability of
  443. NVME-namespaces.
  444. LIBNVDIMM/LIBNDCTL: Block Translation Table "btt"
  445. -------------------------------------------------
  446. A BTT (design document: https://pmem.io/2014/09/23/btt.html) is a
  447. personality driver for a namespace that fronts entire namespace as an
  448. 'address abstraction'.
  449. LIBNVDIMM: btt layout
  450. ^^^^^^^^^^^^^^^^^^^^^
  451. Every region will start out with at least one BTT device which is the
  452. seed device. To activate it set the "namespace", "uuid", and
  453. "sector_size" attributes and then bind the device to the nd_pmem or
  454. nd_blk driver depending on the region type::
  455. /sys/devices/platform/nfit_test.1/ndbus0/region0/btt0/
  456. |-- namespace
  457. |-- delete
  458. |-- devtype
  459. |-- modalias
  460. |-- numa_node
  461. |-- sector_size
  462. |-- subsystem -> ../../../../../bus/nd
  463. |-- uevent
  464. `-- uuid
  465. LIBNDCTL: btt creation example
  466. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  467. Similar to namespaces an idle BTT device is automatically created per
  468. region. Each time this "seed" btt device is configured and enabled a new
  469. seed is created. Creating a BTT configuration involves two steps of
  470. finding and idle BTT and assigning it to consume a namespace.
  471. ::
  472. static struct ndctl_btt *get_idle_btt(struct ndctl_region *region)
  473. {
  474. struct ndctl_btt *btt;
  475. ndctl_btt_foreach(region, btt)
  476. if (!ndctl_btt_is_enabled(btt)
  477. && !ndctl_btt_is_configured(btt))
  478. return btt;
  479. return NULL;
  480. }
  481. static int configure_btt(struct ndctl_region *region,
  482. struct btt_parameters *parameters)
  483. {
  484. btt = get_idle_btt(region);
  485. ndctl_btt_set_uuid(btt, parameters->uuid);
  486. ndctl_btt_set_sector_size(btt, parameters->sector_size);
  487. ndctl_btt_set_namespace(btt, parameters->ndns);
  488. /* turn off raw mode device */
  489. ndctl_namespace_disable(parameters->ndns);
  490. /* turn on btt access */
  491. ndctl_btt_enable(btt);
  492. }
  493. Once instantiated a new inactive btt seed device will appear underneath
  494. the region.
  495. Once a "namespace" is removed from a BTT that instance of the BTT device
  496. will be deleted or otherwise reset to default values. This deletion is
  497. only at the device model level. In order to destroy a BTT the "info
  498. block" needs to be destroyed. Note, that to destroy a BTT the media
  499. needs to be written in raw mode. By default, the kernel will autodetect
  500. the presence of a BTT and disable raw mode. This autodetect behavior
  501. can be suppressed by enabling raw mode for the namespace via the
  502. ndctl_namespace_set_raw_mode() API.
  503. Summary LIBNDCTL Diagram
  504. ------------------------
  505. For the given example above, here is the view of the objects as seen by the
  506. LIBNDCTL API::
  507. +---+
  508. |CTX|
  509. +-+-+
  510. |
  511. +-------+ |
  512. | DIMM0 <-+ | +---------+ +--------------+ +---------------+
  513. +-------+ | | +-> REGION0 +---> NAMESPACE0.0 +--> PMEM8 "pm0.0" |
  514. | DIMM1 <-+ +-v--+ | +---------+ +--------------+ +---------------+
  515. +-------+ +-+BUS0+-| +---------+ +--------------+ +----------------------+
  516. | DIMM2 <-+ +----+ +-> REGION1 +---> NAMESPACE1.0 +--> PMEM6 "pm1.0" | BTT1 |
  517. +-------+ | | +---------+ +--------------+ +---------------+------+
  518. | DIMM3 <-+
  519. +-------+