2017-10-24 18 views
2

カーネルソースから関数呼び出しを行うカーネルモジュールのコードを理解しようとしています。コードはdevice-mapper.hです。Linuxカーネルのdm_per_bio_data関数は何をしますか?

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; 
} 

私たちは「dm_per_bio_dataは、データの場所を返します。」という、device_mapper.hにコメントで、他の場所で言われますなぜこれが当てはまるのか分かりません。

まず、dm_per_bio_dataはstruct bio *をとり、offsetof(struct dm_target_io、clone)で減算します。これは、囲むdm_target_io構造体の先頭を与える必要があります。次に、data_sizeを減算します。

私は、dm_target_ioが別の構造体の中でどこで宣言されて、data_sizeで減算するとどこがわかりますかを見てきました。そのような運はこれまでのところありません。

答えて

1

per_io_data_sizeがここにあります。そう

(エクストラ)(dm_target_io ...(クローン))

:彼らはこのように配置されているので、struct dm_targetのメンバーを設定することで、デバイスマッパーは、先に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;