Linux 核函数 dm_per_bio_data 有什么作用?

What does the Linux kernel function dm_per_bio_data do?

我正在尝试理解从内核源代码调用一些函数的内核模块的代码。代码在device-mapper.h.

struct dm_target_io {
    struct dm_io *io;
    struct dm_target *ti;
    unsigned target_bio_nr;
    unsigned *len_ptr;
    struct bio clone;
};

static inline void *dm_per_bio_data(struct bio *bio, size_t data_size)
{
    return (char *)bio - offsetof(struct dm_target_io, clone) - data_size;
}

我们在其他地方被告知,在 device_mapper.h 的评论中,"dm_per_bio_data returns the data location." 我不确定为什么会这样。

首先,dm_per_bio_data 接受一个 struct bio* 并用 offsetof(struct dm_target_io, clone) 减去它,这应该给出封闭的 dm_target_io 结构的开始。然后,它减去 data_size,它将指针指向--where?

我一直在寻找 dm_target_io 在另一个结构中声明的位置,以查看减去 data_size 可能带我去哪里。到目前为止还没有这样的运气。

per_io_data_size 是这里的关键。通过设置 struct dm_target 的成员,device-mapper 在 dm_target_io 之前为用户定义的数据分配了额外的 space 所以它们被放置如下:

(额外)(dm_target_io ...(克隆))

so dm_per_bio_data returns 指向 extra space.

开头的指针
struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, enum dm_queue_mode type,
                                            unsigned integrity, unsigned per_io_data_size)
{
        struct dm_md_mempools *pools = kzalloc_node(sizeof(*pools), GFP_KERNEL, md->numa_node_id);
        unsigned int pool_size = 0;
        unsigned int front_pad;

        if (!pools)
                return NULL;

        switch (type) {
        case DM_TYPE_BIO_BASED:
        case DM_TYPE_DAX_BIO_BASED:
                pool_size = dm_get_reserved_bio_based_ios();
                front_pad = roundup(per_io_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone);

                pools->io_pool = mempool_create_slab_pool(pool_size, _io_cache);
                if (!pools->io_pool)
                        goto out;
                break;
        case DM_TYPE_REQUEST_BASED:
        case DM_TYPE_MQ_REQUEST_BASED:
                pool_size = dm_get_reserved_rq_based_ios();
                front_pad = offsetof(struct dm_rq_clone_bio_info, clone);
                /* per_io_data_size is used for blk-mq pdu at queue allocation */
                break;
        default:
                BUG();
        }

        pools->bs = bioset_create(pool_size, front_pad, BIOSET_NEED_RESCUER);
        if (!pools->bs)
                goto out;