手机版
你好,游客 登录 注册 搜索
背景:
阅读新闻

Linux虚拟文件系统(内核初始化<二>)

[日期:2012-02-09] 来源:Linux社区  作者:bullbat [字体: ]

这部分主要对linux虚拟文件系统内核初始化部分做些补充。

关于shrinkerinodedentry cache初始化阶段都需要注册自己的shrinker,用于缩减cache。两个操作原理类似。

shrinker数据结构介绍

[cpp]
  1. /* 
  2.  * A callback you can register to apply pressure to ageable caches. 
  3.  * 
  4.  * 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'.  It should 
  5.  * look through the least-recently-used 'nr_to_scan' entries and 
  6.  * attempt to free them up.  It should return the number of objects 
  7.  * which remain in the cache.  If it returns -1, it means it cannot do 
  8.  * any scanning at this time (eg. there is a risk of deadlock). 
  9.  * 
  10.  * The 'gfpmask' refers to the allocation we are currently trying to 
  11.  * fulfil. 
  12.  * 
  13.  * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is 
  14.  * querying the cache size, so a fastpath for that case is appropriate. 
  15.  */  
  16. struct shrinker {  
  17.     int (*shrink)(int nr_to_scan, gfp_t gfp_mask);  
  18.     int seeks;  /* seeks to recreate an obj */  
  19.   
  20.     /* These are for internal use */  
  21.     struct list_head list;  
  22.     long nr;    /* objs pending delete */  
  23. };  

1,注册inode cache shrinker

Start_kernel()->vfs_caches_init()->dcache_init()->register_shrinker(&dcache_shrinker);

[cpp]
  1. /* 
  2.  * Add a shrinker callback to be called from the vm 
  3.  */  
  4. void register_shrinker(struct shrinker *shrinker)  
  5. {  
  6.     shrinker->nr = 0;  
  7.     down_write(&shrinker_rwsem);  
  8.     list_add_tail(&shrinker->list, &shrinker_list);  
  9.     up_write(&shrinker_rwsem);  
  10. }  

其中相关的函数在这里定义。

[cpp]
  1. static struct shrinker dcache_shrinker = {  
  2.     .shrink = shrink_dcache_memory,  
  3.     .seeks = DEFAULT_SEEKS,  
  4. };  
[cpp]
  1. /* 
  2.  * Scan `nr' dentries and return the number which remain. 
  3.  * 
  4.  * We need to avoid reentering the filesystem if the caller is performing a 
  5.  * GFP_NOFS allocation attempt.  One example deadlock is: 
  6.  * 
  7.  * ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache-> 
  8.  * prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->put_inode-> 
  9.  * ext2_discard_prealloc->ext2_free_blocks->lock_super->DEADLOCK. 
  10.  * 
  11.  * In this case we return -1 to tell the caller that we baled. 
  12.  */  
  13. static int shrink_dcache_memory(int nr, gfp_t gfp_mask)  
  14. {  
  15.     if (nr) {  
  16.         if (!(gfp_mask & __GFP_FS))  
  17.             return -1;  
  18.         prune_dcache(nr);/*缩减指定大小的cache*/  
  19.     }  
  20.     return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;  
  21. }  
[cpp]
  1. /** 
  2.  * prune_dcache - shrink the dcache 
  3.  * @count: number of entries to try to free 
  4.  * 
  5.  * Shrink the dcache. This is done when we need more memory, or simply when we 
  6.  * need to unmount something (at which point we need to unuse all dentries). 
  7.  * 
  8.  * This function may fail to free any resources if all the dentries are in use. 
  9.  */  
  10.  /*缩减dcache,count为释放的数量*/  
  11. static void prune_dcache(int count)  
  12. {  
  13.     struct super_block *sb;  
  14.     int w_count;  
  15.     int unused = dentry_stat.nr_unused;  
  16.     int prune_ratio;  
  17.     int pruned;  
  18.   
  19.     if (unused == 0 || count == 0)  
  20.         return;  
  21.     spin_lock(&dcache_lock);  
  22. restart:  
  23.     if (count >= unused)  
  24.         prune_ratio = 1;/*释放率*/  
  25.     else  
  26.         prune_ratio = unused / count;  
  27.     spin_lock(&sb_lock);  
  28.     list_for_each_entry(sb, &super_blocks, s_list) {  
  29.         if (sb->s_nr_dentry_unused == 0)  
  30.             continue;  
  31.         sb->s_count++;  
  32.         /* Now, we reclaim unused dentrins with fairness. 
  33.          * We reclaim them same percentage from each superblock. 
  34.          * We calculate number of dentries to scan on this sb 
  35.          * as follows, but the implementation is arranged to avoid 
  36.          * overflows: 
  37.          * number of dentries to scan on this sb = 
  38.          * count * (number of dentries on this sb / 
  39.          * number of dentries in the machine) 
  40.          */  
  41.         spin_unlock(&sb_lock);  
  42.         /*重新利用释放率计算释放量*/  
  43.         if (prune_ratio != 1)  
  44.             w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1;  
  45.         else  
  46.             w_count = sb->s_nr_dentry_unused;  
  47.         pruned = w_count;  
  48.         /* 
  49.          * We need to be sure this filesystem isn't being unmounted, 
  50.          * otherwise we could race with generic_shutdown_super(), and 
  51.          * end up holding a reference to an inode while the filesystem 
  52.          * is unmounted.  So we try to get s_umount, and make sure 
  53.          * s_root isn't NULL. 
  54.          */  
  55.         if (down_read_trylock(&sb->s_umount)) {  
  56.             if ((sb->s_root != NULL) &&  
  57.                 (!list_empty(&sb->s_dentry_lru))) {  
  58.                 spin_unlock(&dcache_lock);  
  59.                 /*实际释放工作*/  
  60.                 __shrink_dcache_sb(sb, &w_count,  
  61.                         DCACHE_REFERENCED);  
  62.                 pruned -= w_count;  
  63.                 spin_lock(&dcache_lock);  
  64.             }  
  65.             up_read(&sb->s_umount);  
  66.         }  
  67.         spin_lock(&sb_lock);  
  68.         count -= pruned;  
  69.         /* 
  70.          * restart only when sb is no longer on the list and 
  71.          * we have more work to do. 
  72.          */  
  73.         if (__put_super_and_need_restart(sb) && count > 0) {  
  74.             spin_unlock(&sb_lock);  
  75.             goto restart;  
  76.         }  
  77.     }  
  78.     spin_unlock(&sb_lock);  
  79.     spin_unlock(&dcache_lock);  
  80. }  
linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款