【问题标题】:What does the Linux kernel function dm_per_bio_data do?Linux 内核函数 dm_per_bio_data 有什么作用?
【发布时间】:2017-10-24 20:09:40
【问题描述】:

我正在尝试了解内核模块的代码,该模块从内核源代码进行一些函数调用。代码在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 接受一个结构 bio* 并减去 offsetof(struct dm_target_io, clone),这应该给出封闭 dm_target_io 结构的开始。然后,它减去data_size,它把指针指向--where?

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

【问题讨论】:

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


    【解决方案1】:

    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;
    

    【讨论】:

      猜你喜欢
      • 2017-04-08
      • 2019-11-06
      • 2012-07-21
      • 2014-01-07
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多