dm-io

Dm-io 提供同步和异步 I/O 服务。有三种类型的 I/O 服务可用,每种类型都有同步和异步版本。

用户必须设置一个 io_region 结构来描述所需的 I/O 位置。每个 io_region 指示一个块设备以及区域的起始扇区和大小

struct io_region {
   struct block_device *bdev;
   sector_t sector;
   sector_t count;
};

Dm-io 可以从一个 io_region 读取或写入一个或多个 io_regions。通过 io_region 结构的数组指定写入多个区域。

第一种 I/O 服务类型将内存页列表作为 I/O 的数据缓冲区,以及到第一页的偏移量

struct page_list {
   struct page_list *next;
   struct page *page;
};

int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
               struct page_list *pl, unsigned int offset,
               unsigned long *error_bits);
int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
                struct page_list *pl, unsigned int offset,
                io_notify_fn fn, void *context);

第二种 I/O 服务类型将 bio 向量数组作为 I/O 的数据缓冲区。如果调用者有预先组装好的 bio,但希望将 bio 的不同部分定向到不同的设备,则此服务会很方便

int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
                    int rw, struct bio_vec *bvec,
                    unsigned long *error_bits);
int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
                     int rw, struct bio_vec *bvec,
                     io_notify_fn fn, void *context);

第三种 I/O 服务类型将指向 vmalloc'd 内存缓冲区的指针作为 I/O 的数据缓冲区。如果调用者需要对一个大区域进行 I/O,但又不想分配大量单独的内存页,则此服务会很方便

int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
                  void *data, unsigned long *error_bits);
int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
                   void *data, io_notify_fn fn, void *context);

异步 I/O 服务的调用者必须包含完成回调例程的名称和一个指向 I/O 上下文数据的指针

typedef void (*io_notify_fn)(unsigned long error, void *context);

此回调中的“错误”参数,以及所有同步版本中的 *error 参数,是一个位集(而不是简单的错误值)。在写入 I/O 到多个区域的情况下,此位集允许 dm-io 指示每个区域的成功或失败。

在使用任何 dm-io 服务之前,用户应调用 dm_io_get() 并指定他们希望同时执行 I/O 的页数。Dm-io 将尝试调整其 mempool 的大小,以确保始终有足够的页面可用,以避免在执行 I/O 时不必要的等待。

当用户完成使用 dm-io 服务时,他们应调用 dm_io_put() 并指定在 dm_io_get() 调用中给出的相同页数。