一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Linux虛擬文件系統(tǒng)(內(nèi)核初始化<二>)

 lifei_szdz 2013-06-23

這部分主要對linux虛擬文件系統(tǒng)內(nèi)核初始化部分做些補充。

關(guān)于shrinker,inodedentry cache初始化階段都需要注冊自己的shrinker,用于縮減cache。兩個操作原理類似。

shrinker數(shù)據(jù)結(jié)構(gòu)介紹

[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. }  

其中相關(guān)的函數(shù)在這里定義。

[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為釋放的數(shù)量*/  
  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. }  

[cpp]
  1. /* 
  2.  * Shrink the dentry LRU on a given superblock. 
  3.  * @sb   : superblock to shrink dentry LRU. 
  4.  * @count: If count is NULL, we prune all dentries on superblock. 
  5.  * @flags: If flags is non-zero, we need to do special processing based on 
  6.  * which flags are set. This means we don't need to maintain multiple 
  7.  * similar copies of this loop. 
  8.  */  
  9. static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)  
  10. {  
  11.     LIST_HEAD(referenced);  
  12.     LIST_HEAD(tmp);  
  13.     struct dentry *dentry;  
  14.     int cnt = 0;  
  15.   
  16.     BUG_ON(!sb);  
  17.     BUG_ON((flags & DCACHE_REFERENCED) && count == NULL);  
  18.     spin_lock(&dcache_lock);  
  19.     if (count != NULL)  
  20.         /* called from prune_dcache() and shrink_dcache_parent() */  
  21.         cnt = *count;/*在下面用到*/  
  22. restart:  
  23.     if (count == NULL)  
  24.         list_splice_init(&sb->s_dentry_lru, &tmp);  
  25.     else {  
  26.         while (!list_empty(&sb->s_dentry_lru)) {  
  27.             dentry = list_entry(sb->s_dentry_lru.prev,  
  28.                     struct dentry, d_lru);  
  29.             BUG_ON(dentry->d_sb != sb);  
  30.   
  31.             spin_lock(&dentry->d_lock);  
  32.             /* 
  33.              * If we are honouring the DCACHE_REFERENCED flag and 
  34.              * the dentry has this flag set, don't free it. Clear 
  35.              * the flag and put it back on the LRU. 
  36.              */  
  37.              /*清flag對應(yīng)位,將鏈表元素放LRU尾部*/  
  38.             if ((flags & DCACHE_REFERENCED)  
  39.                 && (dentry->d_flags & DCACHE_REFERENCED)) {  
  40.                 dentry->d_flags &= ~DCACHE_REFERENCED;  
  41.                 list_move(&dentry->d_lru, &referenced);  
  42.                 spin_unlock(&dentry->d_lock);  
  43.             } else {  
  44.                 /*從d_lru鏈表中刪除,加到tmp鏈表中*/  
  45.                 list_move_tail(&dentry->d_lru, &tmp);  
  46.                 spin_unlock(&dentry->d_lock);  
  47.                 cnt--;/*數(shù)量減一*/  
  48.                 if (!cnt)/*減到0跳出循環(huán)*/  
  49.                     break;  
  50.             }  
  51.             cond_resched_lock(&dcache_lock);  
  52.         }  
  53.     }  
  54.     /*對tmp中的每個元素,其中tmp中的元素為上面移過來的*/  
  55.     while (!list_empty(&tmp)) {  
  56.         dentry = list_entry(tmp.prev, struct dentry, d_lru);  
  57.         /*從tmp中刪除相關(guān)鏈表并做重新初始化和數(shù)據(jù)統(tǒng)計*/  
  58.         dentry_lru_del_init(dentry);  
  59.         spin_lock(&dentry->d_lock);  
  60.         /* 
  61.          * We found an inuse dentry which was not removed from 
  62.          * the LRU because of laziness during lookup.  Do not free 
  63.          * it - just keep it off the LRU list. 
  64.          */  
  65.         if (atomic_read(&dentry->d_count)) {  
  66.             spin_unlock(&dentry->d_lock);  
  67.             continue;  
  68.         }/*釋放dentry和其父dentry*/  
  69.         prune_one_dentry(dentry);  
  70.         /* dentry->d_lock was dropped in prune_one_dentry() */  
  71.         cond_resched_lock(&dcache_lock);  
  72.     }  
  73.     if (count == NULL && !list_empty(&sb->s_dentry_lru))  
  74.         goto restart;  
  75.     if (count != NULL)  
  76.         *count = cnt;  
  77.     if (!list_empty(&referenced))  
  78.         list_splice(&referenced, &sb->s_dentry_lru);  
  79.     spin_unlock(&dcache_lock);  
  80. }  
[cpp]
  1. static void dentry_lru_del_init(struct dentry *dentry)  
  2. {  
  3.     if (likely(!list_empty(&dentry->d_lru))) {  
  4.         list_del_init(&dentry->d_lru);/*從鏈表中刪除并初始化dentry->d_lru*/  
  5.         dentry->d_sb->s_nr_dentry_unused--;/*未用數(shù)減一*/  
  6.         dentry_stat.nr_unused--;/*更新統(tǒng)計數(shù)據(jù)*/  
  7.     }  
  8. }  
[html]
  1. /*  
  2.  * Throw away a dentry - free the inode, dput the parent.  This requires that  
  3.  * the LRU list has already been removed.  
  4.  *  
  5.  * Try to prune ancestors as well.  This is necessary to prevent  
  6.  * quadratic behavior of shrink_dcache_parent(), but is also expected  
  7.  * to be beneficial in reducing dentry cache fragmentation.  
  8.  */  
  9. static void prune_one_dentry(struct dentry * dentry)  
  10.     __releases(dentry->d_lock)  
  11.     __releases(dcache_lock)  
  12.     __acquires(dcache_lock)  
  13. {  
  14.     __d_drop(dentry);  
  15.     dentry = d_kill(dentry);/*釋放dentry*/  
  16.   
  17.     /*  
  18.      * Prune ancestors.  Locking is simpler than in dput(),  
  19.      * because dcache_lock needs to be taken anyway.  
  20.      */  
  21.     spin_lock(&dcache_lock);  
  22.     while (dentry) {  
  23.         if (!atomic_dec_and_lock(&dentry->d_count, &dentry->d_lock))  
  24.             return;  
  25.   
  26.         if (dentry->d_op && dentry->d_op->d_delete)  
  27.             dentry->d_op->d_delete(dentry);  
  28.         dentry_lru_del_init(dentry);  
  29.         __d_drop(dentry);  
  30.         dentry = d_kill(dentry);  
  31.         spin_lock(&dcache_lock);  
  32.     }  
  33. }  

[cpp]
  1. /** 
  2.  * d_kill - kill dentry and return parent 
  3.  * @dentry: dentry to kill 
  4.  * 
  5.  * The dentry must already be unhashed and removed from the LRU. 
  6.  * 
  7.  * If this is the root of the dentry tree, return NULL. 
  8.  */  
  9. static struct dentry *d_kill(struct dentry *dentry)  
  10.     __releases(dentry->d_lock)  
  11.     __releases(dcache_lock)  
  12. {  
  13.     struct dentry *parent;  
  14.   
  15.     list_del(&dentry->d_u.d_child);/*刪除子目錄*/  
  16.     dentry_stat.nr_dentry--;/*更新統(tǒng)計數(shù)據(jù)*/  /* For d_free, below */  
  17.     /*drops the locks, at that point nobody can reach this dentry */  
  18.     dentry_iput(dentry);/*"釋放"inode*/  
  19.     if (IS_ROOT(dentry))  
  20.         parent = NULL;  
  21.     else  
  22.         parent = dentry->d_parent;  
  23.     d_free(dentry);/*釋放dentry*/  
  24.     return parent;  
  25. }  
[cpp]
  1. /* 
  2.  * Release the dentry's inode, using the filesystem 
  3.  * d_iput() operation if defined. 
  4.  */  
  5.  /*釋放inode*/  
  6. static void dentry_iput(struct dentry * dentry)  
  7.     __releases(dentry->d_lock)  
  8.     __releases(dcache_lock)  
  9. {  
  10.     struct inode *inode = dentry->d_inode;  
  11.     if (inode) {  
  12.         dentry->d_inode = NULL;  
  13.         list_del_init(&dentry->d_alias);/*從同一索引節(jié)點目錄鏈表中刪除*/  
  14.         spin_unlock(&dentry->d_lock);  
  15.         spin_unlock(&dcache_lock);  
  16.         if (!inode->i_nlink)/*如果inode沒有硬鏈接*/  
  17.             fsnotify_inoderemove(inode);  
  18.         if (dentry->d_op && dentry->d_op->d_iput)  
  19.             dentry->d_op->d_iput(dentry, inode);  
  20.         else  
  21.             iput(inode);/*釋放inode*/  
  22.     } else {  
  23.         spin_unlock(&dentry->d_lock);  
  24.         spin_unlock(&dcache_lock);  
  25.     }  
  26. }  

2.注冊inode cache shrinker

Start_kernel()->vfs_caches_init()->inode_init()->register_shrinker(&icache_shrinker);

其中參數(shù)為下面定義

[cpp]
  1. static struct shrinker icache_shrinker = {  
  2.     .shrink = shrink_icache_memory,  
  3.     .seeks = DEFAULT_SEEKS,  
  4. };  
[cpp]
  1. static int shrink_icache_memory(int nr, gfp_t gfp_mask)  
  2. {  
  3.     if (nr) {  
  4.         /* 
  5.          * Nasty deadlock avoidance.  We may hold various FS locks, 
  6.          * and we don't want to recurse into the FS that called us 
  7.          * in clear_inode() and friends.. 
  8.          */  
  9.         if (!(gfp_mask & __GFP_FS))  
  10.             return -1;  
  11.         prune_icache(nr);  
  12.     }  
  13.     return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;  
  14. }  
[cpp]
  1. /* 
  2.  * Scan `goal' inodes on the unused list for freeable ones. They are moved to 
  3.  * a temporary list and then are freed outside inode_lock by dispose_list(). 
  4.  * 
  5.  * Any inodes which are pinned purely because of attached pagecache have their 
  6.  * pagecache removed.  We expect the final iput() on that inode to add it to 
  7.  * the front of the inode_unused list.  So look for it there and if the 
  8.  * inode is still freeable, proceed.  The right inode is found 99.9% of the 
  9.  * time in testing on a 4-way. 
  10.  * 
  11.  * If the inode has metadata buffers attached to mapping->private_list then 
  12.  * try to remove them. 
  13.  */  
  14. static void prune_icache(int nr_to_scan)  
  15. {  
  16.     LIST_HEAD(freeable);/*初始化freeable,在下面需要用到,作為臨時存放可被釋放的inode*/  
  17.     int nr_pruned = 0;  
  18.     int nr_scanned;  
  19.     unsigned long reap = 0;  
  20.   
  21.     down_read(&iprune_sem);  
  22.     spin_lock(&inode_lock);  
  23.     for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) {  
  24.         struct inode *inode;  
  25.   
  26.         if (list_empty(&inode_unused))  
  27.             break;  
  28.   
  29.         inode = list_entry(inode_unused.prev, struct inode, i_list);  
  30.   
  31.         if (inode->i_state || atomic_read(&inode->i_count)) {  
  32.             /*將ionde從inode_unused鏈表中刪除,加入inode_unused鏈表頭*/  
  33.             list_move(&inode->i_list, &inode_unused);  
  34.             continue;  
  35.         }  
  36.         if (inode_has_buffers(inode) || inode->i_data.nrpages) {  
  37.             __iget(inode);/*移動到使用鏈表*/  
  38.             spin_unlock(&inode_lock);  
  39.             if (remove_inode_buffers(inode))/*從buffer鏈表中刪除所有buffer*/  
  40.                 reap += invalidate_mapping_pages(&inode->i_data,  
  41.                                 0, -1);  
  42.             iput(inode);  
  43.             spin_lock(&inode_lock);  
  44.   
  45.             if (inode != list_entry(inode_unused.next,  
  46.                         struct inode, i_list))  
  47.                 continue;   /* wrong inode or list_empty */  
  48.             if (!can_unuse(inode))  
  49.                 continue;  
  50.         }  
  51.         /*移動到freeable鏈表*/  
  52.         list_move(&inode->i_list, &freeable);  
  53.         WARN_ON(inode->i_state & I_NEW);  
  54.         inode->i_state |= I_FREEING;  
  55.         nr_pruned++;/*統(tǒng)計移動到freeable鏈表的元素個數(shù)*/  
  56.     }  
  57.     inodes_stat.nr_unused -= nr_pruned;/*更新統(tǒng)計數(shù)據(jù)*/  
  58.     if (current_is_kswapd())  
  59.         __count_vm_events(KSWAPD_INODESTEAL, reap);  
  60.     else  
  61.         __count_vm_events(PGINODESTEAL, reap);  
  62.     spin_unlock(&inode_lock);  
  63.   
  64.     dispose_list(&freeable);/*將freeable鏈表中的數(shù)據(jù)處理掉*/  
  65.     up_read(&iprune_sem);  
  66. }  

3,注冊文件描述符表釋放函數(shù)

[cpp]
  1. /*文件描述符表*/  
  2. struct fdtable {  
  3.     unsigned int max_fds;/*進程能夠處理的最大file結(jié)構(gòu)*/  
  4.     struct file ** fd;/*所有打開文件信息*//* current fd array */  
  5.     fd_set *close_on_exec;/*exec系統(tǒng)調(diào)用被關(guān)閉的所有文件集合*/  
  6.     fd_set *open_fds;/*當(dāng)前打開的所有文件集合*/  
  7.     struct rcu_head rcu;  
  8.     struct fdtable *next;  
  9. };  

Start_kernel()->vfs_caches_init()->files_init()->files_defer_init()->fdtable_defer_list_init()->INIT_WORK(&fddef->wq, free_fdtable_work);

[cpp]
  1. static void free_fdtable_work(struct work_struct *work)  
  2. {  
  3.     struct fdtable_defer *f =  
  4.         container_of(work, struct fdtable_defer, wq);  
  5.     struct fdtable *fdt;  
  6.   
  7.     spin_lock_bh(&f->lock);  
  8.     fdt = f->next;  
  9.     f->next = NULL;  
  10.     spin_unlock_bh(&f->lock);  
  11.     while(fdt) {/*釋放工作*/  
  12.         struct fdtable *next = fdt->next;  
  13.         vfree(fdt->fd);  
  14.         free_fdset(fdt);  
  15.         kfree(fdt);  
  16.         fdt = next;  
  17.     }  
  18. }  

4.sysfs文件系統(tǒng)初始化

Start_kernel()->vfs_caches_init()->mnt_init()->sysfs_init()

[cpp]
  1. int __init sysfs_init(void)  
  2. {  
  3.     int err = -ENOMEM;  
  4.   
  5.     sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",  
  6.                           sizeof(struct sysfs_dirent),  
  7.                           0, 0, NULL);  
  8.     if (!sysfs_dir_cachep)  
  9.         goto out;  
  10.     /*初始化sysfs的backing_dev_info結(jié)構(gòu)*/  
  11.     err = sysfs_inode_init();  
  12.     if (err)  
  13.         goto out_err;  
  14.     /*注冊文件系統(tǒng)*/  
  15.     err = register_filesystem(&sysfs_fs_type);  
  16.     if (!err) {  
  17.         /*創(chuàng)建sysfs mount*/  
  18.         sysfs_mount = kern_mount(&sysfs_fs_type);  
  19.         if (IS_ERR(sysfs_mount)) {  
  20.             printk(KERN_ERR "sysfs: could not mount!\n");  
  21.             err = PTR_ERR(sysfs_mount);  
  22.             sysfs_mount = NULL;  
  23.             unregister_filesystem(&sysfs_fs_type);  
  24.             goto out_err;  
  25.         }  
  26.     } else  
  27.         goto out_err;  
  28. out:  
  29.     return err;  
  30. out_err:  
  31.     kmem_cache_destroy(sysfs_dir_cachep);  
  32.     sysfs_dir_cachep = NULL;  
  33.     goto out;  
  34. }  
linux

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    91精品视频免费播放| 色一情一伦一区二区三| 欧美性高清一区二区三区视频| 久久精品一区二区少妇| 日本欧美一区二区三区就| 亚洲综合精品天堂夜夜| 国产成人亚洲欧美二区综| 美日韩一区二区精品系列| 午夜亚洲少妇福利诱惑| 国产级别精品一区二区视频| 好吊日在线观看免费视频| 午夜福利视频六七十路熟女| 国产精品久久精品国产| 国产女同精品一区二区| 日本高清不卡一二三区| 麻豆91成人国产在线观看| 国产欧美日本在线播放| 久久国产精品热爱视频| 亚洲中文字幕在线观看四区| 日韩一区二区免费在线观看| 亚洲一区二区三区精选| 日韩成人动画在线观看| 樱井知香黑人一区二区| 中文久久乱码一区二区| 激情五月天免费在线观看| 精品久久综合日本欧美| 青青操成人免费在线视频| 欧美日韩亚洲精品在线观看| 九七人妻一区二区三区| 欧美中文字幕一区在线 | 一级欧美一级欧美在线播| 九九久久精品久久久精品| 亚洲精品有码中文字幕在线观看| 黄片在线免费观看全集| 国产又粗又猛又爽又黄的文字| 国产目拍亚洲精品区一区| 午夜精品一区二区三区国产| 精品午夜福利无人区乱码| 国产麻豆视频一二三区| 色婷婷视频免费在线观看| 久久精品国产99精品最新|