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 ...
随机推荐
- EL表达式(Expression Language)
语法: ${Expression} 来取代难以维护的Java脚本元素,或笨拙的jsp:useBean和jsp:getProperty; 尤其重要的是,表达式语言支持下面的功能: 1.精确地访问存储对象 ...
- BZOJ 2324: [ZJOI2011]营救皮卡丘( floyd + 费用流 )
昨晚写的题...补发一下题解... 把1~N每个点拆成xi, yi 2个. 预处理i->j经过编号不超过max(i,j)的最短路(floyd) S->0(K, 0), S->xi(1 ...
- c#实现pdf另存为功能
c#实现pdf另存为功能 /// <summary> /// PDF另存为效果 /// </summary> /// <param name="fileName ...
- 【基础】常用的机器学习&数据挖掘知识点
Basis(基础): MSE(Mean Square Error 均方误差),LMS(LeastMean Square 最小均方),LSM(Least Square Methods 最小二乘法),ML ...
- android下tcpdump抓包
tcpdump是最快捷方便的抓包方式,还可以加深对网络协议的理解.android下可以通过如下方式抓包: 1 Android上启动tcpdump Android设备可以把tcpdump的可执行文件上传 ...
- HDU 1512 Monkey King(左偏树+并查集)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1512 [题目大意] 现在有 一群互不认识的猴子,每个猴子有一个能力值,每次选择两个猴子,挑出他们所 ...
- 向前辈致敬 strspn
把8位的CHAR型数据分解为:前5位和后3位,这样2^5 = 32个CHAR型数+值就可表示所有的CHAR型数据 这样做的好处:在给出子串后,不用比较256次,最多比较32次即可判断出是否一个数在子串 ...
- tar.xz文件怎样解压
XZ压缩最新压缩率之王 xz这个压缩可能非常多都非常陌生,只是您可知道xz是绝大数linux默认就带的一个压缩工具. 之前xz使用一直非常少,所以差点儿没有什么提起. 我是在下载phpmyadmin的 ...
- codeforces #260 DIV 2 C题Boredom(DP)
题目地址:http://codeforces.com/contest/456/problem/C 脑残了. .DP仅仅DP到了n. . 应该DP到10w+的. . 代码例如以下: #include & ...
- Jquery $.extend的重载方法详述
1 $.extend(result,item1,item2,item3,........) -这个重载方法主要是用来合并,将所有的参数都合并到result中,并返回result,但是这样会破坏res ...