c - Linux 内核函数 dm_per_bio_data 有什么作用?

标签 c struct linux-kernel linux-device-driver memory-alignment

我正在尝试理解内核模块的代码,该模块从内核源代码进行一些函数调用。密码在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 返回数据位置”。我不确定为什么会这样。

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

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

最佳答案

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

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

所以 dm_per_bio_data 返回指向额外空间开头的指针。

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;

关于c - Linux 内核函数 dm_per_bio_data 有什么作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46919206/

相关文章:

C多维数组指向问题?

python - 传递 Python 元组代替 C++ 结构函数参数是否对性能有影响?

c++ - 如何以编程方式删除 Windows 中损坏的快捷方式

c - 识别阿姆斯特朗数

不透明结构的 C typedef 编码风格

使用 malloc 创建动态结构数组

c - hrtimers 和 clockid_t 问题

tcp - 什么时候在 tcp 段中设置推送标志

c - 多个进程如何能够同时使用 STDIN/STDOUT?

c - 使用内联汇编从 C 函数获取返回的字符