<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Soul Of Free Loop &#187; map_info</title>
	<atom:link href="https://zohead.com/archives/tag/map_info/feed" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>Linux kernel DM map_info接口改为per-bio data</title>
		<link>https://zohead.com/archives/dm-mapinfo-perbio/</link>
		<comments>https://zohead.com/archives/dm-mapinfo-perbio/#comments</comments>
		<pubDate>Wed, 11 Mar 2015 15:05:46 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Device mapper]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[map_context]]></category>
		<category><![CDATA[map_info]]></category>
		<category><![CDATA[per-bio data]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=870</guid>
		<description><![CDATA[最近在将一个之前版本的 Linux DM（device mapper）驱动移植到新的 3.18 版本 Linux kernel 上出现编译报错，提示 DM target_type 中的 dm_map_fn 等成员函数指针类型不正确。 看看老版本上 dm_map_fn 函数指针的声明： typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio, union map_info *map_context); 这个是新的 3.18 版本 Linux 上的形式： typedef int (*dm_map_fn) (struct dm_ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>最近在将一个之前版本的 Linux DM（device mapper）驱动移植到新的 3.18 版本 Linux kernel 上出现编译报错，提示 DM target_type 中的 dm_map_fn 等成员函数指针类型不正确。</p>
<p>看看老版本上 dm_map_fn 函数指针的声明：</p>
<p><strong>typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio, union map_info *map_context);</strong></p>
<p>这个是新的 3.18 版本 Linux 上的形式：</p>
<p><strong>typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio);</strong></p>
<p>其它几个报错的函数指针也比较类似，看起来明显就是新 kernel 中去掉了老的 map_info 类型参数。</p>
<p>有些类型 device mapper target（例如：multipath、snapshot 等驱动）需要在 dm_map_fn 处理函数中分配与 bio 相关的辅助数据并在 dm_endio_fn 处理函数中使用，老版本 Linux 中的标准处理流程就是在 dm_map_fn 中按需分配数据，并赋值给 map_info 类型的 map_context 的 ptr 指针，在 dm_endio_fn 中则需要判断 map_context 的 ptr 指针是否非空，并做对应的使用和释放操作。</p>
<p>先上个老版本 kernel 里的代码，以 dm-mirror 驱动为例；</p>
<pre class="brush: cpp; title: dm-raid1.c; notranslate">
static int mirror_map(struct dm_target *ti, struct bio *bio, union map_info *map_context)
{
	struct mirror_set *ms = (struct mirror_set *) ti-&gt;private;
	struct dm_raid1_read_record *read_record = NULL;

	...
	read_record = mempool_alloc(ms-&gt;read_record_pool, GFP_NOIO);
	if (likely(read_record)) {
		dm_bio_record(&amp;read_record-&gt;details, bio);
		map_context-&gt;ptr = read_record;
		read_record-&gt;m = m;
	}
	...
}

static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error, union map_info *map_context)
{
	struct mirror_set *ms = (struct mirror_set *) ti-&gt;private;
	struct dm_raid1_read_record *read_record = map_context-&gt;ptr;

	...
	if (read_record) {
		mempool_free(read_record, ms-&gt;read_record_pool);
		map_context-&gt;ptr = NULL;
	}
	...
}
</pre>
<p>新 kernel 里则去掉了在 target 的处理函数里自己分配并保存自定义数据的方式，由于 kernel 中各种不同的子系统都可以可以请求 bio 子系统创建一个包含额外空余空间的 bio slab cache（per-bio data）并放在 bio 之前，这个空余空间就可以被其它驱动由于各种用途。</p>
<p>DM 中则使用 per-bio data 这一特性存放 target 驱动相关和 device mapper 相关的数据。DM target 驱动可以通过在 dm_ctr_fn 构造处理函数里设置 dm_target 结构体的自定义数据大小<span style="line-height: 19.2000007629395px;">（per-bio data size）</span><span style="line-height: 1.5;">的形式直接将数据保存到 bio 请求中，如果大小为 0 表示不需要额外的数据，如果大于 0 则 DM 会自动给每个 bio 请求加上指定大小的自定义数据，这样 target 驱动也就不需要额外的分配释放操作了。</span></p>
<p><span style="line-height: 1.5;">相对应的 dm_target 的 dm_map_fn 和 dm_endio_fn 处理函数中直接使用 dm_per_bio_data 函数就可以从 bio 里取出自定义数据，不需要自行管理数据也非常方便。</span></p>
<p>这样就可以来看看新版本 kernel 里的 dm-mirror 代码：</p>
<pre class="brush: cpp; title: dm-raid1.c; notranslate">
static int mirror_map(struct dm_target *ti, struct bio *bio)
{
	struct mirror_set *ms = ti-&gt;private;
	struct dm_raid1_bio_record *bio_record =
		dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));

	bio_record-&gt;details.bi_bdev = NULL;
	...
	dm_bio_record(&amp;bio_record-&gt;details, bio);
	bio_record-&gt;m = m;
	...
}

static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
{
	struct mirror_set *ms = (struct mirror_set *) ti-&gt;private;
	struct dm_raid1_bio_record *bio_record =
		dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));

	...
	bio_record-&gt;details.bi_bdev = NULL;
	...
}

static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
	...
	ti-&gt;per_bio_data_size = sizeof(struct dm_raid1_bio_record);
	...
}
</pre>
<p>实际使用中还是要注意 per_bio_data_size 最好不要太大。将 device mapper 驱动按 per-bio data 的形式进行修改，就可完成新 kernel 上的移植。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/dm-mapinfo-perbio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
