如何将数据缓冲区(bio_vec-s)从原始BIO克隆到新的bio_vec集?

时间:2018-01-11 13:47:27

标签: linux-device-driver

我需要克隆bi_io_vec中bio所携带的数据。我正在寻找正确的调用序列来执行:

  1. new bio_vec allocation
  2. 将原始bio_vec-s复制到新的
  3. 释放bio_vec-s区域

1 个答案:

答案 0 :(得分:0)

static int __dua_bvec_clone (
        struct bio  *src,
        IOB_ARGS    *iob_args
            )
{
int status;
unsigned nr_vecs = src->bi_vcnt;
struct bio *dst;
struct bvec_iter src_iter, dst_iter;
struct bio_vec  src_bv, dst_bv;
void *src_p, *dst_p;
unsigned bv_len;

    $TRACE("Start cloning ...");

    $SHOW_PTR(src);
    $SHOW_INT(src->bi_vcnt);

    /* Allocate a memory for a new 'bio' structure */
    if ( !(dst = bio_clone_bioset(src, GFP_KERNEL, src->bi_pool /*NULL*/)) )
        {
        printk(KERN_ERR  __MODULE__ ": bio_clone_bioset() -> NULL\n");

        return  -ENOMEM;
        }

    if ( status = bio_alloc_pages(dst , GFP_KERNEL))
        {
        printk(KERN_ERR  __MODULE__ ": bio_alloc_pages() -> %d\n", status);

        return  status;
        }

    /* Copy data from source bio_vec-s to a new bio_vec-s set */
    src_iter = src->bi_iter;
    dst_iter = dst->bi_iter;

    while( nr_vecs--)
        {
        src_bv = bio_iter_iovec(src, src_iter);
        dst_bv = bio_iter_iovec(dst, dst_iter);

        bv_len = min(src_bv.bv_len, dst_bv.bv_len);

        src_p = kmap_atomic(src_bv.bv_page);
        dst_p = kmap_atomic(dst_bv.bv_page);

        $SHOW_PTR(src_p);
        $SHOW_PTR(dst_p);

        memcpy(dst_p + dst_bv.bv_offset, src_p + src_bv.bv_offset, bv_len);

        kunmap_atomic(dst_p);
        kunmap_atomic(src_p);

        bio_advance_iter(src, &src_iter, bv_len);
        bio_advance_iter(dst, &dst_iter, bv_len);
        }



    iob_args->bi_io_vec = src->bi_io_vec;
    src->bi_io_vec = dst->bi_io_vec;

    iob_args->bio = dst;

    $TRACE("Cloned.");

    return  0;
}