nd_namespace_X

在nd_region的驱动中我们看到其中一个重要的动作就是创建namespace。这个工作交给了nd_region_register_namespaces()函数处理。

构造nd_namespace的函数

先来看看构造namespace的函数流程。

nd_region_register_namespaces(struct nd_region *nd_region)
  init_active_labels(struct nd_region *nd_region)
  type = nd_region_to_nstype(nd_region);
  switch (type) {
  case ND_DEVICE_NAMESPACE_IO:
    devs = create_namespace_io(nd_region);
    break;
  case ND_DEVICE_NAMESPACE_PMEM:
  case ND_DEVICE_NAMESPACE_BLK:
    devs = create_namespaces(nd_region);
    break;
  default:
    break;
  }

大致看主要做了两件事:

  • 配置nd_regioin->mapping->labels

  • 根据nd_region的NS类型创建对应的namespace

其中labels数据类型看定义就是RFC4122中定义的label了。也算是找到了一个硬件和软件对应的关系。

而create_namespaces函数的工作则就是扫描nd_region->mapping->labels来构造的。具体做了什么,让我们来看看相关的数据结构。

nd_namespace_X

在上面的代码片段和nd_region的章节中我们都可以看出,namespace有三种类型

  • nd_namespace_blk

  • nd_namespace_io

  • nd_namespace_pmem

所以内核中用了三种类型分别表述。我们一个个来看。

nd_namespace_blk

下面是nd_namespace_blk这个数据结构的内容。

创建的时候根据nd_label的信息填写了uuid, alt_name以及dpa resource数组。

nd_namespace_io

下面是nd_namespace_io的数据结构。

这种namespace比较简单,创建的时候除了设置了type,就是把res设置成了nd_region中的空间。

nd_namespace_pmem

pmem最后整合了一个resource。我猜这个res表示的范围就是内存空间的物理地址了?

nd_pmem/blk_driver

以上三个namespace都会生成自己的设备,这样也就都有各自对应的驱动。

  • nd_blk_driver

  • nd_pmem_driver

很不好意思,nd_pmem_driver包揽了第二三种namespace的驱动,真实能者多劳的典范。

不过这两个驱动都有一个共同点,就是都调用了nvdimm_namespace_common_probe()做初始化。

这个函数其实也没做啥,主要做了两件事:

  • 检测空间大小是否合适

  • 设置了uuid

经过仔细研读和实验验证,结果发现了几个神奇的事儿。

  • nd_pmem_driver不仅仅是namespace的驱动,还是btt/pfn设备的驱动。

  • nd_region_probe()会也建立btt/pfn/dax设备。

  • nd_pmem_probe也会通过nd_btt/pfn/dax_probe建立对应的设备。

关于这个过程的具体细节可以看lkml中的这个讨论,或许可以让逻辑清楚一点。

总之当namespace被配置成这三种类型的某一种时,nd_pmem_probe会通过nd_btt/pfn/dax_probe去创建某一种类型的设备。并且有意思的是,这种情况下nd_pmem_probe会失败。这种高端的方法我还是头一次见。

接下来的事情就交给了各自的设备和驱动了。

Last updated

Was this helpful?