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 ...
随机推荐
- Oracle Select into 用Sql server替换
--Oracle: DECLARE n_count int; begin Select count(*) into n_count from from M_Test where ENTITYLSH = ...
- HBase API详解
一.Java API和HBase数据模型的关系 在Java中,与HBase数据库存储管理相关的类包括HBaseAdmin.HBaseConfiguration.HTable.HTableDescrip ...
- Hibernate总结(二)---hibernate中的各种映射
知识的准备: (参考:汤阳光Hibernate3.6(基础)) 一.浅谈javaBean之间的关系 存在的关系: 1.关联(一对一.一对多.多对一.多对多) 2.聚合/组合(最后考虑) 3.继承 所以 ...
- 简单使用 PHP Phar 打包php代码 笔记
Phar简介:Phar 归档的概念来自 Java™ 技术的 JAR 归档,它允许使用单个文件打包应用程序,这个文件中包含运行应用程序所需的所有东西.该文件不同于单个可执行文件,后者通常由编程语言生成, ...
- python之面向对象那点事
一.类与对象 1.什么是类?类,顾名思义,就是具体相同属性的同一类事物的统称及抽象.对象,指是就是具体的抽象类的实例 以上的说法是不是看起来有点云里来雾里去呢.没错,专业的解释总是让人难以理解,这就是 ...
- SQL Server 内存不足引起的并发症
第一:cpu 1.内存不足就会有频繁的页面调入调出.这个过程是要有cpu的参与的.所以这个要影响cpu! 2.内存不足可能会引有用起执行计划被清除.当起次要执行时.这个就要重编译一次!
- 转:一个strcpy的问题(很容易做错)
下面的执行结果是什么? #include<stdio.h> #include<string.h> void main() { "; "; strcpy(d, ...
- POJ 1700 经典过河问题(贪心)
POJ题目链接:http://poj.org/problem?id=1700 N个人过河,船每次最多只能坐两个人,船载每个人过河的所需时间不同,问最快的过河时间. 思路: 当n=1,2,3时所需要的最 ...
- 有道翻译API
轻奢侈品_百度百科 轻奢侈品 有道翻译API 有道翻译API申请成功 API key:72763558 keyfrom:lexus-studio
- 第七届河南省赛H.Rectangles(lis)
10396: H.Rectangles Time Limit: 2 Sec Memory Limit: 128 MB Submit: 229 Solved: 33 [Submit][Status] ...