并发I / O-缓冲损坏,阻止设备驱动程序

时间:2018-08-24 13:42:31

标签: c linux linux-kernel

我正在开发块分层设备驱动程序。因此,我拦截了 WRITE 请求并加密了数据,并在end_bio()例程中解密了数据(在处理和 READ 请求期间)。 因此,所有功能都可以在单个流中正常运行。但是,如果试图同时从两个或多个进程执行I / O,我将缓冲内容损坏。我没有用于缓冲区的本地存储。

我是否需要将BIO合并到驱动程序中?

Linux I / O子系统对一些并发I / O请求是否有一些要求?

是否有一些与堆栈使用或编译相关的技巧?

这是在4.15内核下。

当时我使用下一个限制条件来运行磁盘扇区:

    /*
     * A portion of the bio_copy_data() ...
     */
    for (vcnt = 0, src_iter = src->bi_iter; ; vcnt++)
        {
        if ( !src_iter.bi_size)
            {
            if ( !(src = src->bi_next) )
                break;

            src_iter = src->bi_iter;
            }

        src_bv = bio_iter_iovec(src, src_iter);

        src_p = bv_page = kmap_atomic(src_bv.bv_page);
        src_p += src_bv.bv_offset;

        nlbn    = src_bv.bv_len512;
        for ( ; nlbn--; lbn++ , src_p += 512 )
                {
                {
                /* Simulate a processing of data in the I/O buffer */
               char *srcp = src_p, *dstp = src_p;
               int  count = DUDRV$K_SECTORSZ;

               while ( count--)
                {
                *(dstp++) = ~ (*(srcp++));
                }

                }
                }
        kunmap_atomic(bv_page);
        **bio_advance_iter**(src, &src_iter, src_bv.bv_len);
        }

这是正确的吗?还是我需要使用诸如** bio_for_each_segment(bvl,bio,iter)**之类的东西?

2 个答案:

答案 0 :(得分:1)

您是否考虑过将vmap与全局同步一起使用?

使用kmap_atomic有一些限制:

  

由于映射仅限于发出该映射的CPU,因此它   表现良好,但必须执行发布任务   CPU,直到完成为止,以免其他任务替换其映射。

     

kmap_atomic()也可以被中断上下文使用,因为它不是   进入睡眠状态,直到调用kunmap_atomic()之后,呼叫者才可能进入睡眠状态。

参考:https://www.kernel.org/doc/Documentation/vm/highmem.txt

答案 1 :(得分:1)

问题的根源是Block I / O方法的“功能”。特别是(请参见Linex网站reference上的说明)

** Biovecs 可以在多个BIOS之间共享-bvec iter可以代表    现有生物载体的任意范围,中途开始和结束    通过生物媒介。这就是有效分割任意对象的原因    BIOS。请注意,这意味着我们使用bi_size来确定何时    到达了bio的末尾,而不是bi_vcnt-并且bio_iovec()宏需要    构建生物载体时要考虑bi_size。*

因此,在我的情况下,这是导致磁盘扇区溢出的缓冲区的原因。

在将BIO发送到支持的设备驱动程序之前,先在 .bi_opf 中设置 REQ_NOMERGE_FLAGS

第二个原因是备份设备驱动程序返回了不实际的 .bi_iter 。因此,我们需要保存它(在向后端提交BIO请求之前),然后将其恢复到我们的“ bio_endio()”例程中。