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 ...
随机推荐
- mysql save or update
原文:http://www.bitscn.com/pdb/mysql/201503/473268.html 背景 在平常的开发中,经常碰到这种更新数据的场景:先判断某一数据在库表中是否存在,存在则 ...
- Hql中占位符(转)
在新的Hibernate 4版本中,对于Hql有一点点改变,如果你还是按照以前的方式去编写HQL并且用了以下占位符的方式,就会得到一个警告. 参考资料:https://hibernate.atlass ...
- Problem F: Exponentiation大数求幂
DescriptionProblems involving the computation of exact values of very large magnitude and precision ...
- leetcode Contains Duplicate II python
Given an array of integers and an integer k, find out whether there are two distinct indices i and j ...
- hadoop搭建杂记:Linux下hadoop的安装配置
VirtualBox搭建伪分布式模式:hadoop的下载与配置 VirtualBox搭建伪分布式模式:hadoop的下载与配置 由于个人机子略渣,无法部署XWindow环境,直接用的Shell来操作, ...
- Android 程序申请权限小知识点
在Google Play 应用商店,显示至少支持设备的数量时候会用到权限数量.其他地方用处不大. Android系统提供为程序提供了权限申请,即在manifest中使用uses-permission来 ...
- ADODB 数据库Access连接
<?php $filepath=__FILE__;//echo __FILE__;$newarray=explode("\\",$filepath);$num=count($ ...
- 未能从程序集“System.ServiceModel, Version=3.0.0.0”中加载类型“System.ServiceModel.Activation.HttpModule” 的解决办法
未能从程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中加载类型“ ...
- 服务启动项 Start类型详解
注册表的服务启动项 Start类型详解 HKLM\SYSTEM\CurrentControlSet\services\ 下的服务项.不论有没有在services.msc服务管理控制台中显示,在注册表中 ...
- 使用自定义脚本扩展程序自动执行 VM 自定义任务
在 Build 开发者大会上推出VM 扩展程序的其中一个称为"自定义脚本扩展程序",它支持 PowerShell.如果这是您第一次访问这些博客,可能需要查看以前的博客,请单击 ...