TCMU拷贝优化

TCM(Target Core Module)是LIO(Linux IO Target)的别称,是内核态的iSCSI target。TCMU(TCM in Userspace)是LIO的用户态实现,允许用户程序方便地对接各种用户态后端实现。基于TCMU框架和LIO loopback(tcm_loop)模块,可以方便地实现用户态iSCSI target。本文介绍Alibaba Cloud Linux 3中针对TCMU在拷贝上的优化。

使用限制

  • 操作系统:Alibaba Cloud Linux 3

  • 内核版本:5.10.134-14及以上版本

TCMU现有流程在读写操作中均存在二次拷贝的问题,这在高吞吐场景下对性能造成了显著的影响。Alibaba Cloud Linux 3针对TCMU实现了两种类型的优化。

  • bypass data area:提供ioctl接口使得用户态控制TCMU直接在用户态数据buffer与内核sgl页之间拷贝数据。

  • zero copy:提供ioctl接口使得用户态控制TCMU将内核的sg页映射到用户态,从而方便tcmu-runner直接访问。

适用场景

tcmu-runner可根据自己当前的场景来选择采用哪种优化。

bypass data area

适用于backstore管理自己的数据buffer场景。

  1. DMA_FROM_DEVICE类命令如readinquiry等,需要先将数据从用户态buffer拷贝到data area,再从data area拷贝到sgl页。开启bypass data area后数据将直接从用户态buffer拷贝到sgl页。

  2. DMA_TO_DEVICE类命令如writewritesame等,需要先将数据从sgl页拷贝到data area,再从data area拷贝到用户态buffer。开启bypass data area后数据将直接从sgl页拷贝到用户态buffer

zero copy

适用于backstore不管理自己的数据buffer,读写都直接使用TCMU的data area场景。开启该优化需要注意:

  • 当IO命令大小在256 KB及以上时才会相对于拷贝有比较明显的性能提升,因此需要根据业务IO模型来评估是否需要开启。

  • 如果IO命令在tcmu-runner hang住时导致命令超时,内存映射被解除,后续再访问将触发SIGBUS,因此需要评估该场景的影响。

  • 只有当IO命令大小是4 KB对齐,且每个sg页偏移也是4 KB对齐时才会走zero copy流程。

    说明

    4 KB对齐:起始偏移和长度都是4 KB倍数。

设备配置接口

针对读写命令类型,bypass data areazero copy分别提供不同的配置。当两者都开启时,将优先走zero copy优化路径,即仅当无法满足走zero copy路径时才会走bypass data area优化路径。

bypass data area

  • read_bypass_data_area:针对读命令类型(DMA_FROM_DEVICE),默认为false;设置为true将开启该优化。

  • write_bypass_data_area:针对写命令类型(DMA_TO_DEVICE),默认为false;设置为true将开启该优化。

查询配置属性

不同设备的配置属性路径不同,本文以在user_0/testblk为例。

sudo cat /sys/kernel/config/target/core/user_0/testblk/attrib/read_bypass_data_area
sudo cat /sys/kernel/config/target/core/user_0/testblk/attrib/write_bypass_data_area

修改配置属性

sudo bash -c "echo 1 > /sys/kernel/config/target/core/user_0/testblk/attrib/read_bypass_data_area"
sudo bash -c "echo 1 > /sys/kernel/config/target/core/user_0/testblk/attrib/write_bypass_data_area"

zero copy

  • read_zc_size:针对读命令类型(DMA_FROM_DEVICE),默认为0 KB;当设置为非零值时,如果命令的数据长度大于该值且满足对齐要求,将开启该优化。

  • write_zc_size:针对写命令类型(DMA_TO_DEVICE),默认为0 KB;当设置为非零值时,如果命令的数据长度大于该值且满足对齐要求,将开启该优化。

查询配置属性

不同设备的配置属性路径不同,本文以在user_0/testblk为例。

sudo cat /sys/kernel/config/target/core/user_0/testblk/attrib/read_zc_size
sudo cat /sys/kernel/config/target/core/user_0/testblk/attrib/write_zc_size

修改配置属性

sudo bash -c "echo 256 > /sys/kernel/config/target/core/user_0/testblk/attrib/read_zc_size"
sudo bash -c "echo 256 > /sys/kernel/config/target/core/user_0/testblk/attrib/write_zc_size"

用户编程接口

参考接口文件/usr/include/linux/target_core_user.h中的定义。

struct tcmu_data_xfer {
  __u16 cmd_id;
  __u16 __pad1;
  __u32 iov_cnt;
  struct iovec __user *iovec;
};

struct tcmu_cmd_zerocopy {
  struct iovec __user *iov;
  __u32 iov_cnt;
  __u16 cmd_id;
};

#define TCMU_IOCTL_CMD_COPY_TO_SGL    _IOW('T', 0xe0, struct tcmu_data_xfer)
#define TCMU_IOCTL_CMD_COPY_FROM_SGL  _IOR('T', 0xe1, struct tcmu_data_xfer)
#define TCMU_IOCTL_CMD_ZEROCOPY       _IOW('T', 0xe2, struct tcmu_cmd_zerocopy)