searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

nvme磁盘故障注入方法

2023-05-25 11:15:36
291
0

在存储系统中,磁盘的故障是很可能出现的问题。存储软件的设计需要对故障进行处理,提高系统的健壮性。然而磁盘的故障是不可控的,当我们想测试软件故障处理的分支时,不是很方便。用软件模拟的方法能覆盖的场景比较少,而且和实际故障的差距会比较大。因此,如果能让故障下沉到磁盘,尽可能的靠近磁盘,才能构造出尽可能真实的故障场景。本文针对nvme磁盘,在磁盘驱动这一层调研了几种可以注入磁盘故障的方法。

1. write uncorrectable

通过向nvme控制器发送write uncor命令,标记指定的LBA范围为invalid,当读到这个LBA范围时,ctrl会返回Unrecovered Read Error错误。可以用于模拟读的media error。如果要清除invalid状态,需要向这个LBA范围写入数据,覆盖调invalid标记。

不过,write uncor命令不是所有厂家的盘都支持。如果不支持,会返回invalid op code错误。查看是否支持的方法,可以看controller数据结构中的oncs->write_unc是否为1。

还有一个缺点是只能注入读故障。

2. write protect

通过设置namespace的属性,可以让namespace写保护,当这个namespace收到写请求时,会返回write error。

缺点是有的厂商的盘不支持这个属性,而且只能注入写故障。

3. 驱动层模拟故障

这是最通用的一种方法,可以构造出各种故障。spdk的代码中就实现了这一功能。下面详细介绍下它的接口。

/**
 * \brief Inject an error for the next request with a given opcode.
 *
 * \param ctrlr NVMe controller.
 * \param qpair I/O queue pair to add the error command,
 *              NULL for Admin queue pair.
 * \param opc Opcode for Admin or I/O commands.
 * \param do_not_submit True if matching requests should not be submitted
 *                      to the controller, but instead completed manually
 *                      after timeout_in_us has expired.  False if matching
 *                      requests should be submitted to the controller and
 *                      have their completion status modified after the
 *                      controller completes the request.
 * \param timeout_in_us Wait specified microseconds when do_not_submit is true.
 * \param err_count Number of matching requests to inject errors.
 * \param sct Status code type.
 * \param sc Status code.
 *
 * \return 0 if successfully enabled, ENOMEM if an error command
 *       structure cannot be allocated.
 *
 * The function can be called multiple times to inject errors for different
 * commands.  If the opcode matches an existing entry, the existing entry
 * will be updated with the values specified.
 */
int spdk_nvme_qpair_add_cmd_error_injection(struct spdk_nvme_ctrlr *ctrlr,
    struct spdk_nvme_qpair *qpair,
    uint8_t opc,
    bool do_not_submit,
    uint64_t timeout_in_us,
    uint32_t err_count,
    uint8_t sct, uint8_t sc);
 
ctrlr: nvme盘的控制器数据结构,每个盘有一个;
qpair: 注入故障的qpair,可以是io qpair,也可以是admin qpair。使用哪一种取决于希望在IO路径上还是在管理路径上产生故障;
opc: 操作类型,比如read,write等;
do_not_submit:如果是true,则这个opc的cmd不会提交到ctrl,而是在 timeout_in_us 到期后手动返回指定的sct,sc。如果是false,则这个opc的cmd会提交到ctrl,等ctrl返回cpl后,将sct和sc改成指定的sct,sc,回调的时候用改过的cpl。命令实际上是执行成功的;
timeout_in_us:do_not_submit=true时有效,等待timeout_in_us后再返回sct,sc。范围是(0-18446744073709551615)
err_count: 表示注入故障后,此后的多少个该opc的cmd会按照注入的故障来处理,每返回一个注入的故障,err_count减1。减为0的时候不再注入故障,但cmd也不会从 qpair->err_cmd_head 中摘除;
sct: 返回的状态码类型;
sc: 返回的状态码;
 
实现的原理是向指定qpair的err_cmd_head链表中添加一个错误的cmd,当下个该类型的cmd提交到该qpair的时候在 _nvme_qpair_submit_request 中遍历这个链表,处理这个cmd,强制修改cpl中的返回值,然后再调用回调,从而模拟故障。
使用此接口可以模拟出读写错误,IO hang住或超时的错误等,在开发测试中比较实用。
 
0条评论
0 / 1000
曹****飞
2文章数
0粉丝数
曹****飞
2 文章 | 0 粉丝
曹****飞
2文章数
0粉丝数
曹****飞
2 文章 | 0 粉丝
原创

nvme磁盘故障注入方法

2023-05-25 11:15:36
291
0

在存储系统中,磁盘的故障是很可能出现的问题。存储软件的设计需要对故障进行处理,提高系统的健壮性。然而磁盘的故障是不可控的,当我们想测试软件故障处理的分支时,不是很方便。用软件模拟的方法能覆盖的场景比较少,而且和实际故障的差距会比较大。因此,如果能让故障下沉到磁盘,尽可能的靠近磁盘,才能构造出尽可能真实的故障场景。本文针对nvme磁盘,在磁盘驱动这一层调研了几种可以注入磁盘故障的方法。

1. write uncorrectable

通过向nvme控制器发送write uncor命令,标记指定的LBA范围为invalid,当读到这个LBA范围时,ctrl会返回Unrecovered Read Error错误。可以用于模拟读的media error。如果要清除invalid状态,需要向这个LBA范围写入数据,覆盖调invalid标记。

不过,write uncor命令不是所有厂家的盘都支持。如果不支持,会返回invalid op code错误。查看是否支持的方法,可以看controller数据结构中的oncs->write_unc是否为1。

还有一个缺点是只能注入读故障。

2. write protect

通过设置namespace的属性,可以让namespace写保护,当这个namespace收到写请求时,会返回write error。

缺点是有的厂商的盘不支持这个属性,而且只能注入写故障。

3. 驱动层模拟故障

这是最通用的一种方法,可以构造出各种故障。spdk的代码中就实现了这一功能。下面详细介绍下它的接口。

/**
 * \brief Inject an error for the next request with a given opcode.
 *
 * \param ctrlr NVMe controller.
 * \param qpair I/O queue pair to add the error command,
 *              NULL for Admin queue pair.
 * \param opc Opcode for Admin or I/O commands.
 * \param do_not_submit True if matching requests should not be submitted
 *                      to the controller, but instead completed manually
 *                      after timeout_in_us has expired.  False if matching
 *                      requests should be submitted to the controller and
 *                      have their completion status modified after the
 *                      controller completes the request.
 * \param timeout_in_us Wait specified microseconds when do_not_submit is true.
 * \param err_count Number of matching requests to inject errors.
 * \param sct Status code type.
 * \param sc Status code.
 *
 * \return 0 if successfully enabled, ENOMEM if an error command
 *       structure cannot be allocated.
 *
 * The function can be called multiple times to inject errors for different
 * commands.  If the opcode matches an existing entry, the existing entry
 * will be updated with the values specified.
 */
int spdk_nvme_qpair_add_cmd_error_injection(struct spdk_nvme_ctrlr *ctrlr,
    struct spdk_nvme_qpair *qpair,
    uint8_t opc,
    bool do_not_submit,
    uint64_t timeout_in_us,
    uint32_t err_count,
    uint8_t sct, uint8_t sc);
 
ctrlr: nvme盘的控制器数据结构,每个盘有一个;
qpair: 注入故障的qpair,可以是io qpair,也可以是admin qpair。使用哪一种取决于希望在IO路径上还是在管理路径上产生故障;
opc: 操作类型,比如read,write等;
do_not_submit:如果是true,则这个opc的cmd不会提交到ctrl,而是在 timeout_in_us 到期后手动返回指定的sct,sc。如果是false,则这个opc的cmd会提交到ctrl,等ctrl返回cpl后,将sct和sc改成指定的sct,sc,回调的时候用改过的cpl。命令实际上是执行成功的;
timeout_in_us:do_not_submit=true时有效,等待timeout_in_us后再返回sct,sc。范围是(0-18446744073709551615)
err_count: 表示注入故障后,此后的多少个该opc的cmd会按照注入的故障来处理,每返回一个注入的故障,err_count减1。减为0的时候不再注入故障,但cmd也不会从 qpair->err_cmd_head 中摘除;
sct: 返回的状态码类型;
sc: 返回的状态码;
 
实现的原理是向指定qpair的err_cmd_head链表中添加一个错误的cmd,当下个该类型的cmd提交到该qpair的时候在 _nvme_qpair_submit_request 中遍历这个链表,处理这个cmd,强制修改cpl中的返回值,然后再调用回调,从而模拟故障。
使用此接口可以模拟出读写错误,IO hang住或超时的错误等,在开发测试中比较实用。
 
文章来自个人专栏
存储技术
2 文章 | 2 订阅
0条评论
0 / 1000
请输入你的评论
0
0