linux内核源码阅读之facebook硬盘加速flashcache之二
302struct flash_superblock {
303 sector_t size; /* Cache size */
304 u_int32_t block_size; /* Cache block size */
305 u_int32_t assoc; /* Cache associativity */
306 u_int32_t cache_sb_state; /* Clean shutdown ? */
307 char cache_devname[DEV_PATHLEN];
308 sector_t cache_devsize;
309 char disk_devname[DEV_PATHLEN];
310 sector_t disk_devsize;
311 u_int32_t cache_version;
312};
那是怎么知道的呢?猜的呀,超级块就叫superblock,放在SSD上的超级块就叫flash_superblock。猜归猜,有什么证据吗?看,代码在此:
704static int
705flashcache_md_create(struct cache_c *dmc, int force)
706{
707 struct flash_cacheblock *meta_data_cacheblock, *next_ptr;
708 struct flash_superblock *header;
709#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
710 struct io_region where;
711#else
712 struct dm_io_region where;
713#endif
714 int i, j, error;
715 sector_t cache_size, dev_size;
716 sector_t order;
717 int sectors_written = 0, sectors_expected = 0; /* debug */
718 int slots_written = 0; /* How many cache slots did we fill in this MD io block ? */
719
720 header = (struct flash_superblock *)vmalloc(512);
721 if (!header) {
722 DMERR("flashcache_md_create: Unable to allocate sector");
723 return 1;
724 }
725 where.bdev = dmc->cache_dev->bdev;
726 where.sector = 0;
727 where.count = 1;
728#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
729 error = flashcache_dm_io_sync_vm(&where, READ, header);
730#else
731 error = flashcache_dm_io_sync_vm(dmc, &where, READ, header);
732#endif
static struct target_type flashcache_target = {
.name = "flashcache",
.version= {1, 0, 1},
.module = THIS_MODULE,
.ctr = flashcache_ctr,
.dtr = flashcache_dtr,
.map = flashcache_map,
.status = flashcache_status,
.ioctl = flashcache_ioctl,
};
创建flashcache设备之后就会调用构造函数flashcache_ctr,再找到:
1290 if (persistence == CACHE_CREATE) {
1291 if (flashcache_md_create(dmc, 0)) {
1292 ti->error = "flashcache: Cache Create Failed";
1293 r = -EINVAL;
1294 goto bad5;
1295 }
1296 } else {
就看到了flashcache_md_create函数,追根溯源,我们知道了结构体flash_superblock就是在这里写到SSD的第0个扇区的。
302struct flash_superblock {
303 sector_t size; /* Cache size */
304 u_int32_t block_size; /* Cache block size */
305 u_int32_t assoc; /* Cache associativity */
306 u_int32_t cache_sb_state; /* Clean shutdown ? */
307 char cache_devname[DEV_PATHLEN];
308 sector_t cache_devsize;
309 char disk_devname[DEV_PATHLEN];
310 sector_t disk_devsize;
311 u_int32_t cache_version;
312};
size 是表示SSD上用作cache的block数量,这里的block是指SSD缓存的块大小,也就是用flashcache_create命令创建时指定的block_size大小。
788 meta_data_cacheblock = (struct flash_cacheblock *)vmalloc(METADATA_IO_BLOCKSIZE);
789 if (!meta_data_cacheblock) {
790 DMERR("flashcache_md_store: Unable to allocate memory");
791 DMERR("flashcache_md_store: Could not write out cache metadata !");
792 return 1;
793 }
794 where.sector = 1;
795 slots_written = 0;
796 next_ptr = meta_data_cacheblock;
797 j = MD_BLOCKS_PER_SECTOR;
798 for (i = 0 ; i < dmc->size ; i++) {
799 next_ptr->dbn = dmc->cache[i].dbn;
800#ifdef FLASHCACHE_DO_CHECKSUMS
801 next_ptr->checksum = dmc->cache[i].checksum;
802#endif
803 next_ptr->cache_state = dmc->cache[i].cache_state &
804 (INVALID | VALID | DIRTY);
805 next_ptr++;
806 slots_written++;
807 j--;
808 if (j == 0) {
809 /*
810 * Filled the sector, goto the next sector.
811 */
812 if (slots_written == MD_BLOCKS_PER_SECTOR * METADATA_IO_BLOCKSIZE_SECT) {
813 /*
814 * Wrote out an entire metadata IO block, write the block to the ssd.
815 */
816 where.count = slots_written / MD_BLOCKS_PER_SECTOR;
817 slots_written = 0;
818 sectors_written += where.count; /* debug */
819#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
820 error = flashcache_dm_io_sync_vm(&where, WRITE,
821 meta_data_cacheblock);
822#else
823 error = flashcache_dm_io_sync_vm(dmc, &where, WRITE,
824 meta_data_cacheblock);
825#endif
826 if (error) {
827 vfree((void *)header);
828 vfree((void *)meta_data_cacheblock);
829 vfree(dmc->cache);
830 DMERR("flashcache_md_create: Could not write cache metadata sector %lu error %d !",
831 where.sector, error);
832 return 1;
833 }
834 where.sector += where.count; /* Advance offset */
835 }
836 /* Move next slot pointer into next sector */
837 next_ptr = (struct flash_cacheblock *)
838 ((caddr_t)meta_data_cacheblock + ((slots_written / MD_BLOCKS_PER_SECTOR) * 512));
839 j = MD_BLOCKS_PER_SECTOR;
840 }
841 }
836 /* Move next slot pointer into next sector */
837 next_ptr = (struct flash_cacheblock *)
838 ((caddr_t)meta_data_cacheblock + ((slots_written / MD_BLOCKS_PER_SECTOR) * 512));
839 j = MD_BLOCKS_PER_SECTOR;
#define METADATA_IO_BLOCKSIZE_SECT (METADATA_IO_BLOCKSIZE / 512)
((caddr_t)meta_data_cacheblock + ((slots_written / MD_BLOCKS_PER_SECTOR) * 512));
Note dmc->size is in raw sectors */
dmc->md_sectors = INDEX_TO_MD_SECTOR(dmc->size / dmc->block_size) + 1 + 1;
dmc->size -= dmc->md_sectors; /* total sectors available for cache */
dmc->size /= dmc->block_size;
dmc->size = (dmc->size / dmc->assoc) * dmc->assoc;
/* Recompute since dmc->size was possibly trunc'ed down */
dmc->md_sectors = INDEX_TO_MD_SECTOR(dmc->size) + 1 + 1;
747 /* Compute the size of the metadata, including header.
748 Note dmc->size is in raw sectors */
749 dmc->md_sectors = INDEX_TO_MD_SECTOR(dmc->size / dmc->block_size) + 1 + 1;
750 dmc->size -= dmc->md_sectors; /* total sectors available for cache */
751 dmc->size /= dmc->block_size;
752 dmc->size = (dmc->size / dmc->assoc) * dmc->assoc;
753 /* Recompute since dmc->size was possibly trunc'ed down */
754 dmc->md_sectors = INDEX_TO_MD_SECTOR(dmc->size) + 1 + 1;
755 DMINFO("flashcache_md_create: md_sectors = %d\n", dmc->md_sectors);
756 dev_size = to_sector(dmc->cache_dev->bdev->bd_inode->i_size);
757 cache_size = dmc->md_sectors + (dmc->size * dmc->block_size);
758 if (cache_size > dev_size) {
759 DMERR("Requested cache size exceeds the cache device's capacity" \
760 "(%lu>%lu)",
761 cache_size, dev_size);
762 vfree((void *)header);
763 return 1;
764 }
322struct flash_cacheblock {
323 sector_t dbn; /* Sector number of the cached block */
324#ifdef FLASHCACHE_DO_CHECKSUMS
325 u_int64_t checksum;
326#endif
327 u_int32_t cache_state; /* INVALID | VALID | DIRTY */
328};
307struct kcached_job *
308new_kcached_job(struct cache_c *dmc, struct bio* bio,
309 int index)
310{
311 struct kcached_job *job;
312
313 job = flashcache_alloc_cache_job();
314 if (unlikely(job == NULL)) {
315 dmc->memory_alloc_errors++;
316 return NULL;
317 }
318 job->dmc = dmc;
319 job->index = index;
320 job->cache.bdev = dmc->cache_dev->bdev;
321 if (index != -1) {
322 job->cache.sector = (index << dmc->block_shift) + dmc->md_sectors;
323 job->cache.count = dmc->block_size;
324 }
325 job->error = 0;
326 job->bio = bio;
327 job->disk.bdev = dmc->disk_dev->bdev;
328 if (index != -1) {
329 job->disk.sector = dmc->cache[index].dbn;
330 job->disk.count = dmc->block_size;
331 } else {
332 job->disk.sector = bio->bi_sector;
333 job->disk.count = to_sector(bio->bi_size);
334 }
335 job->next = NULL;
336 job->md_sector = NULL;
337 return job;
338}
linux内核源码阅读之facebook硬盘加速flashcache之二的更多相关文章
- linux内核源码阅读之facebook硬盘加速flashcache之八
前面我们的分析中重点关注正常的数据流程,这一小节关注如果有异常,那么流程是怎么走完的呢? 1)创建新任务时kcached_job申请不到 2)读写命中时cache块为忙 3)系统关机时处理,系统开机时 ...
- linux内核源码阅读之facebook硬盘加速flashcache之三
上一节讲到在刷缓存的时候会调用new_kcahed_job创建kcached_job,由此我们也可以看到cache数据块与磁盘数据的对应关系.上一篇:http://blog.csdn.net/lium ...
- linux内核源码阅读之facebook硬盘加速flashcache之四
这一小节介绍一下flashcache读写入口和读写的基础实现. 首先,不管是模块还是程序,必须先找到入口,用户态代码会经常去先看main函数,内核看module_init,同样看IO流时候也要找到入口 ...
- linux内核源码阅读之facebook硬盘加速flashcache之六
其实到目前为止,如果对读流程已经能轻松地看懂了,那么写流程不需要太多脑细胞.我觉得再写下去没有太大的必要了,后面想想为了保持flashcache完整性,还是写出来吧.接着到写流程: 1530stati ...
- linux内核源码阅读之facebook硬盘加速flashcache之五
正常流程到flashcache_map的1623行或1625行,按顺序先看读流程: 1221static void 1222flashcache_read(struct cache_c *dmc, s ...
- linux内核源码阅读之facebook硬盘加速利器flashcache
从来没有写过源码阅读,这种感觉越来越强烈,虽然劣于文笔,但还是下定决心认真写一回. 源代码下载请参见上一篇flashcache之我见 http://blog.csdn.net/liumangxiong ...
- ubuntu下linux内核源码阅读工具和调试方法总结
http://blog.chinaunix.net/uid-20940095-id-66148.html 一 linux内核源码阅读工具 windows下当然首选source insight, 但是l ...
- Linux内核源码阅读记录一之分析存储在不同段中的函数调用过程
在写驱动的过程中,对于入口函数与出口函数我们会用一句话来修饰他们:module_init与module_exit,那会什么经过修饰后,内核就能狗调用我们编写的入口函数与出口函数呢?下面就来分析内核调用 ...
- Linux内核源码分析
Linux源码下载: https://www.kernel.org/ https://git.kernel.org/ Linux内核源码阅读以及工具(转): https://blog.csdn.net ...
随机推荐
- .Net平台-MVP模式再探(二)
PS: 本文与 上一遍文章 没有什么必然的联系,可以说是对于MVP的一定的加深,或许在理解上比上一篇多有点难度. 正文 一.简单讲讲MVP是什么玩意儿 如果从层次关系来讲,MVP属于P ...
- MQ学习(一)----JMS规范(转发整合)
最近进行ActiveMQ的学习,总结下已被不时之需. JMS规范: JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的A ...
- Java动态代理机制——Cglib
上一篇说过JDK动态代理机制,只能代理实现了接口的类,这就造成了限制.对于没有实现接口的类,我们可以用Cglib动态代理机制来实现. Cglib是针对类生成代理,主要是对用户类生成一个子类.因为有继承 ...
- VirtualBox扩展磁盘空间
进入VB的安装目录, 输入命令 VBoxManage list hdds获得当前所有虚拟机的uuid 选择需要扩展的磁盘, 输入 VBoxManage modifyhd uuid –resize 81 ...
- MySQL 二进制日志过滤
binlog_do_db; binlog_ignore_db; 这个两个参数是用来控制对哪个数据库的更改要记录日志:下面以binlog_ignore_db为例子. 假如binlog_ignore_db ...
- QPointer很大程度上避免了野指针(使用if语句判断即可,类似于dynamic_cast),而且使用非常方便 good
QPointer 如何翻译呢?我不太清楚,保留英文吧. The QPointer class is a template class that provides guarded pointers ...
- bootstrap 更改container 的width
参考:http://stackoverflow.com/questions/15884102/bootstrap-how-do-i-change-the-width-of-the-container ...
- HDU 2588 GCD
题目大意:给定N,M, 求1<=X<=N 且gcd(X,N)>=M的个数. 题解:首先,我们求出数字N的约数,保存在约数表中,然后,对于大于等于M的约数p[i],求出Euler(n/ ...
- ubuntu openStack icehouse dashboard theme自定义
1,ubuntu openStack 语言包locate
- SSD磁盘,CPU居高不下,高并发的情况下,是不是mysql解析器耗费的cpu资源高?
你看看我做的实验,这个user表是300多W纪录,普通磁盘下,消耗时间最多的是Copy to tmp table 0.81秒,当然在ssd下,这个可以减少很多很多的,第二高就是sending data ...