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_region。对多个区域的写入通过 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”参数,以及所有同步版本中的 *error 参数,是一个位集(而不是简单的错误值)。在对多个区域进行写 I/O 的情况下,此位集允许 dm-io 指示每个单独区域的成功或失败。

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

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