准备工作:
核心代码:
第一、这个模块是一个linux的kernel模块,是一个mapper device设备,主要的kernel机制相关的数据结构就是device_target;
static struct target_type flashcache_target = {
.name = "flashcache",
.version= {1, 0, 4},
.module = THIS_MODULE,
.ctr = flashcache_ctr,
.dtr = flashcache_dtr,
.map = flashcache_map,
.status = flashcache_status,
.ioctl = flashcache_ioctl,
};
在代码中flashcache_map主要在flashcache_main中实现,也是这部分代码的最主要部分,代码结构还是相当的清晰地,主体为mapper device机制的策略实现。
第二、flashcache的复制功能主要依托于kcopyd,这个功能同样用于mirror和snapshot,
r = dm_kcopyd_client_create(FLASHCACHE_COPY_PAGES, &flashcache_kcp_client);
dm_kcopyd_client维护了三job队列,一个等待内存页pages_jobs,一个已经获得内存页等待io命令io_jobs,一个等待io完成complete_jobs,对应到flashcache代码中应该是
思路详解:flashcache_do_pending,flashcache_do_io,flashcache_md_write_done;但同样,flashcache_md_write_kickoff这个对应的又是那个呢?
引用:
(接下的工作)
查看linux驱动代码,理解module相关kernel设计,找到mapper device的设备驱动范例,阅读并理解这种机制的原理,验证flashcache策略的正确性,其次,研读flashcache_map正确理解整个flashcache过程。
其次为什么只申请了job_cache和pending_job_cache
从map函数可以看出os如果需要操作bio的时候只是将dm_target、bio、info等句柄传递下来,接下来的任务就任由发挥,如何map并不是os操心的事情,os只关心能否独到,能否写入,能否返回。
介绍完结构后,一定要介绍wb,wr,wt的不同优异如何改进,达到知其所以然的境界
首先的感谢ripwu的分享,以他对dm-cache的代码理解将我带入了flashcache,再次感谢他,并附上rip的dm-cache代码浅析地址
对应到flashcache这个模块最重要的就是map函数,一面的代码是map函数的主体部分:
if (unlikely(sysctl_pid_do_expiry && (dmc->whitelist_head || dmc->blacklist_head))) flashcache_pid_expiry_all_locked(dmc);
if ((to_sector(bio->bi_size) != dmc->block_size) || (bio_data_dir(bio) == WRITE && flashcache_uncacheable(dmc))) {
queued = flashcache_inval_blocks(dmc, bio);
spin_unlock_irq(&dmc->cache_spin_lock);
if (queued) {
if (unlikely(queued < 0))
flashcache_bio_endio(bio, -EIO);
} else {
/* Start uncached IO */
flashcache_start_uncached_io(dmc, bio);
}
} else {
spin_unlock_irq(&dmc->cache_spin_lock);//why should spin unlock in here, because
if (bio_data_dir(bio) == READ)
flashcache_read(dmc, bio);
else
flashcache_write(dmc, bio);
}
1、判断系统是否允许删除过期pid,如果允许择在black和white表中删除掉对应的pid号。
2、如果bio的size过于小不足以填满一个block则直接存储,如果系统设置为write round模式同样直接存储,如果此时ssd没有挂载或者其他原因无法完成cache功能也同样直接存储disk。
3、如果查询的直接存储状态不是由于job_cache不够而直接存储的话,择直接存储。
直接存储的过程以后介绍,有一个问题就是如果涉及到模块状态的情况记得使用自旋锁,对于多线程系统,所有状态多必须自旋锁锁定,反而对硬件的操作则不存在自旋操作,因为在设备操作前必须满足状态自旋锁获得的情况才能进行。
cacheblk = &dmc->cache[index];
这句话在通过bio->bi_size转化为flashcache的block numbers,起到主要转换左右,bi_zise通过一系列hash转换之后得到index,然后通过cache[index]找到合适的block为bio操作。
dbn = sets * block size * set size(how many block in a set, in flashcache a set equal 8 block)
dbn equal byte address。
flashcache的cache缓存机制
flashcache采用和cpu-cache一样的cache机制set-assocutive,这种cache的主要目的就是使cache尽可能的缓存一段连续的原存储空间,每次cache寻址时都必须通过hash寻找对应的set,并通过set中assoc个cacheline寻找可用的cacheline进行缓存,读取的时候同理。
这种缓存机制为N-way assocutive cache。