dev_dax

当我们生成了nd_dax设备后,nvdimm驱动的任务就基本结束了。或者应该说,nvdimm驱动最后的任务是创建一个dev_dax设备,由这个设备接过最后的枪。

构造dev_dax的过程

从nd_dax构造dev_dax的过程在dax_pmem_probe中完成。

dax_pmem_probe()
  nvdimm_setup_pfn(nd_pfn, &pgmap);
    nd_pfn_init(nd_pfn);
    __nvdimm_setup_pfn(nd_pfn, pgmap);
  dax_region = alloc_dax_region(dev, region_id, &res,
    le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP);
  dev_dax = __devm_create_dev_dax(dax_region, id, &pgmap, subsys);
    dax_dev = alloc_dax(dev_dax, NULL, NULL);
      dax_dev = dax_dev_get(devt);
        ...
        alloc_inode(super_block)
    dev_dax->dax_dev = dax_dev;

上面的流程就是从nd_dax/nd_pfn设备构造到dev_dax的过程。大致可以分成三个步骤:

  • nvdimm_setup_pfn() 对nd_pfn中的成员做了设置,比如对齐和计算page struct的空间

  • alloc_dax_region() 这是构造dev_dax所需的信息

  • 函数__devm_create_dev_dax用来创建dax_dev,也就是dax文件系统。值得注意的是这个数据结构是通过super_block创建inode时候创建的。

dev_dax是个庞大的结构体,就让我们来看一看吧。

dev_dax, dax_dev, dax_region

着重讲几点:

  • 最终的目标是生成dev_dax设备,该设备对应一个字符类型的文件/dev/dax0.0

  • /dev/dax0.0的fops是dax_fops,所以后面的mmap就靠它了

  • dev_dax生成的信息在dax_region中

  • dax_region中res就是对齐过后,去掉元数据的部分;

怎么样,这下是不是够爽?

dev_dax的驱动device_dax_driver

既然有了dev_dax,那么这个设备是如何开始它的工作的呢?再来回顾一下dev_dax结构体中新创建的设备。

这部分已经超出了nvdimm驱动的范畴,但是为了把故事讲完,我们还是要看一下生成的这个设备是如何被使用到的。

因为这个设备是在dax_bus_type总线上的,所以它的驱动也应该是在同一个总线上的了。这个默认的驱动就是device_dax_driver.

探测

这个驱动的探测函数dev_dax_probe主要做了两件事情:

  • devm_memremap_pages(dev, &dev->pgmap)

  • cdev_init(cdev, &dax_fops);

Last updated

Was this helpful?