本文的目的
由于Device Mapper框架的相关文章真的太少了,就想从项目来进行学习,深入了解DM框架的底层原理。收集了GitHub上前20页,有关Device-Mapper target的repos。从简单到复杂,依次进行深入地学习与分析。
1,device-mapper
整体比较简单,基本就是最简单的device mapper壳子,dm_template遇到非零bio就原地映射,学会了一个函数和一个宏:
static inline void bio_set_dev(struct bio *bio, struct block_device *bdev) { bio_clear_flag(bio, BIO_REMAPPED); if (bio->bi_bdev != bdev) bio_clear_flag(bio, BIO_THROTTLED); bio->bi_bdev = bdev; bio_associate_blkg(bio); } <!--0--> 这个宏通常用在"\_map"函数中,mapped之后,对bi\_sector赋值时。
”_map“函数的几种返回状态:
1
2
3
4DM_MAPIO_SUBMITTED: map函数将bio赋值后又分发出去,告诉DM不要再处理了。
DM_MAPIO_REMAPPED: map函数修改了bio的内容,希望DM将bio按照新内容再分发。
DM_MAPIO_REQUEUE: map函数将bio加入队列中等待后续处理
DM_MAPIO_KILL: 结束一个bio? 暂时没找到说法。。若返回DM_MAPIO_SUBMITTED,后续DM框架就不会处理了,这样就可以更加灵活地添加/删除bio。
2,dm_invert
整体也不难,但是学到了很多。主要是通过.message
方法与target进行交互,并将block进行管理,以红黑树的结构进行维护。
DMINFO可以用来发出判断函数进出口,DMERR发出错误报告,例如:
1
2
3
4DMINFO("Entry: %s", __func__);
char *emsg = "Block size is too large";
DMERR("%s\n", emsg);
DMINFO("Exit: %s", __func__);splinlock_t,是一种自旋锁,会忙等待,常用于短时间的轻量级加锁机制。
在”_map”函数中,不仅可以通过cdir来获得请求的方向,还可以用宏(blk_types.h - include/linux/blk_types.h - Linux source code (v4.9) - Bootlin)来得到请求的类型。这些宏包括:
1
2
3
4
5
6
7
8enum req_op {
REQ_OP_READ,
REQ_OP_WRITE,
REQ_OP_DISCARD, /* request to discard sectors */
REQ_OP_SECURE_ERASE, /* request to securely erase sectors */
REQ_OP_WRITE_SAME, /* write same block many times */
REQ_OP_FLUSH, /* request for cache flush */
};这里竟然看到了安全删除!太好了!说明有种方式能够把安全删除的请求传递到底层设备了。
一个新的map状态:DM_MAPIO_KILL。在搜索相关资料时发现一个山东大学的大佬发了10多篇有关device mapper相关工作,可以去学习学习。((4条消息) qq_51946537的博客_CSDN博客-软件工程应用与实践,项目实训,笔记领域博主)
一个方法:
void **bio_endio** (struct bio * bio)
will end I/O on the whole bio.遍历bio的所有segment,并将这些segment赋值为1。提供了一种
bio_for_each_segment()
函数的用法,之前看着都一直不太会用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16static void one_fill_bio(struct bio *bio)
{
struct bio_vec bvec;
struct bvec_iter i;
unsigned long flags;
DMINFO("Entry: %s", __func__);
bio_for_each_segment(bvec, bio, i) {
char *buf;
buf = bvec_kmap_irq(&bvec, &flags);
memset(buf, 0xff, bvec.bv_len);
flush_dcache_page(bvec.bv_page);
bvec_kunmap_irq(buf, &flags);
}
}还有 linux/bio.c 中定义的zero_fill_bio()函数(https://elixir.bootlin.com/linux/latest/source/block/bio.c#L531),以下是其内核中的实现。
1
2
3
4
5
6
7
8
9void zero_fill_bio(struct bio *bio)
{
struct bio_vec bv;
struct bvec_iter iter;
bio_for_each_segment(bv, bio, iter)
memzero_bvec(&bv);
}
EXPORT_SYMBOL(zero_fill_bio);target_type的
.message
是什么意思?红黑树插入元素,以及相关红黑树结构体。
1
2
3参考的一些博客:
1,https://blog.csdn.net/u013590407/article/details/52229330
2,https://tanglinux.blog.csdn.net/article/details/7420689
先想清楚一个问题,再继续看这个代码。
安全删除可以依靠什么进行具体的实现。
A:其实不论ATA command还是TRIM command都只是建立一个通信协议,而底层需要做的实现方面的工作其实与发来的命令无关。