Linux回写存储设备cache机制-FUA,FLUSH

2022-08-27  本文已影响0人  1哥

1 背景

很多存储设备,特别是消费级市场,都自带板载cache. 意思是在data 实际写入非易失性的存储介质前就存储设备就发送 IO completion 信号给OS。这样的好处是能更快的响应host 的 IO,但为了确保数据落盘,就需要OS 发送额外的命令(如fsync, sync 或umount ) 以确保数据的完整。此外,系统有多个request 保序的需求。
Linux block layer 提供了两种机制让filesystem 控制存储设备的cache行为: (Force cache flush)Flush , FUA(Force unit access) Flag。

2 原理

2.1 Explicit cache flushes(FLUSH)

REQ_PREFLUSH:文件系统可以将该flag 和 r/w flag 要一起放入bio, 可确保在已有的write cache 刷入非易失性存储介质后才开始当前的IO 。此外,REQ_PREFLUSH flag 可以用于一个empty 的bio, 用于flush 已有的cache. 推荐blkdev_issue_flush() 用于纯cache flush.

2.2 Forced Unit Access(FUA)

REQ_FUA:文件系统可以将该flag 和 r/w flag 要一起放入bio, 可确保在数据写入非易失性存储介质后,才发送IO completion 信号。

2.3 Linux 中REQ_{PREFLUSH | FUA}

根据请求的属性和硬件的能力,REQ_{PREFLUSH | FUA} request 分解成由三个可选的步骤:PREFLUSH, DATA,和 POSTFLUSH
i. 若 request没有数据,只需要REQ_PREFLUSH 才起作用,表示只是一个flush request.
ii. 如果有数据,REQ_PREFLUSH 表示device cache 必须在data 处理前FLUSH 进device. REQ_FUA 表示一旦request 完成,数据必须写入Non-Volatile 介质中。
iii. 若device 没有writecache, PREFLUSH 和FUA 没什么区别。请求要么立即完成,要么
vi. 若device 有writecache, 并支持FUA,REQ_PREFLUSH 转化成PREFLUSH,REQ_FUA 直接和数据一起传给device.
v. 若device 有writecache, 但不支持FUA,REQ_PREFLUSH 转化成PREFLUSH, REQ_FUA 则转换成POSTFLUSH。

static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq)
{
    unsigned int policy = 0;

    if (blk_rq_sectors(rq))
        policy |= REQ_FSEQ_DATA;

    if (fflags & (1UL << QUEUE_FLAG_WC)) {
        if (rq->cmd_flags & REQ_PREFLUSH)
            policy |= REQ_FSEQ_PREFLUSH;
        if (!(fflags & (1UL << QUEUE_FLAG_FUA)) &&
            (rq->cmd_flags & REQ_FUA))
            policy |= REQ_FSEQ_POSTFLUSH;
    }
    return policy;
}

3 实现

3.1 文件系统实现

文件系统可使用REQ_PREFLUSH and REQ_FUA flag , 不需要关心存储设备是否需要显性cache flush 以及 FUA如何实现。 REQ_PREFLUSH 和 REQ_FUA flag 可用在一个单个bio 中。

3.2 block driver 实现细节

3.2.1 make_request_fn based block driver 实现细节

这种driver 能看到REQ_PREFLUSH 和 REQ_FUA flag. 对于不支持write cache的device:
可以忽略非空的bio 的 REQ_PREFLUSH and REQ_FUA flag了;处理没有数据的REQ_PREFLUSH requests ,可以什么都不做。
对于支持write cache 的device:driver需要实现这些flag 的支持。

3.2.2 request_fn based block driver 实现细节

对于不支持write cache的设备,没有driver 支持,block layer 处理empty REQ_PREFLUSH request,剥离REQ_PREFLUSH 和 REQ_FUA。
对于支持write cache 的设备,driver 通过”blk_queue_write_cache(sdkp->disk->queue, true, false); “通知block layer 支持flush writecache. block layer 将一个带payload 的REQ_PREFLUSH request 自动转化成:一个empty REQ_OP_FLUSH request ,紧跟着一个write .
对于支持FUA的devices, driver 通过“blk_queue_write_cache(sdkp->disk->queue, true, true);” 告知block layer . driver 必须在prep_fn/request_fn中处理REQ_FUA. 若不支持FUA flag,block layer 转化FUA flag成一个write request 和 一个empty REQ_OP_FLUSH。

上一篇下一篇

猜你喜欢

热点阅读