600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Linux虚拟文件系统(内核初始化二)

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

时间:2023-10-14 22:40:26

相关推荐

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

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

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

shrinker数据结构介绍

[cpp]view plaincopy print? /* *Acallbackyoucanregistertoapplypressuretoageablecaches. * *'shrink'ispassedacount'nr_to_scan'anda'gfpmask'.Itshould *lookthroughtheleast-recently-used'nr_to_scan'entriesand *attempttofreethemup.Itshouldreturnthenumberofobjects *whichremaininthecache.Ifitreturns-1,itmeansitcannotdo *anyscanningatthistime(eg.thereisariskofdeadlock). * *The'gfpmask'referstotheallocationwearecurrentlytryingto *fulfil. * *Notethat'shrink'willbepassednr_to_scan==0whentheVMis *queryingthecachesize,soafastpathforthatcaseisappropriate. */ structshrinker{ int(*shrink)(intnr_to_scan,gfp_tgfp_mask); intseeks;/*seekstorecreateanobj*/ /*Theseareforinternaluse*/ structlist_headlist; longnr;/*objspendingdelete*/ };

1,注册inodecacheshrinker

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

[cpp]view plaincopy print? /* *Addashrinkercallbacktobecalledfromthevm */ voidregister_shrinker(structshrinker*shrinker) { shrinker->nr=0; down_write(&shrinker_rwsem); list_add_tail(&shrinker->list,&shrinker_list); up_write(&shrinker_rwsem); }

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

[cpp]view plaincopy print? staticstructshrinkerdcache_shrinker={ .shrink=shrink_dcache_memory, .seeks=DEFAULT_SEEKS, };[cpp]view plaincopy print? /* *Scan`nr'dentriesandreturnthenumberwhichremain. * *Weneedtoavoidreenteringthefilesystemifthecallerisperforminga *GFP_NOFSallocationattempt.Oneexampledeadlockis: * *ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache-> *prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->put_inode-> *ext2_discard_prealloc->ext2_free_blocks->lock_super->DEADLOCK. * *Inthiscasewereturn-1totellthecallerthatwebaled. */ staticintshrink_dcache_memory(intnr,gfp_tgfp_mask) { if(nr){ if(!(gfp_mask&__GFP_FS)) return-1; prune_dcache(nr);/*缩减指定大小的cache*/ } return(dentry_stat.nr_unused/100)*sysctl_vfs_cache_pressure; }[cpp]view plaincopy print? /** *prune_dcache-shrinkthedcache *@count:numberofentriestotrytofree * *Shrinkthedcache.Thisisdonewhenweneedmorememory,orsimplywhenwe *needtounmountsomething(atwhichpointweneedtounusealldentries). * *Thisfunctionmayfailtofreeanyresourcesifallthedentriesareinuse. */ /*缩减dcache,count为释放的数量*/ staticvoidprune_dcache(intcount) { structsuper_block*sb; intw_count; intunused=dentry_stat.nr_unused; intprune_ratio; intpruned; if(unused==0||count==0) return; spin_lock(&dcache_lock); restart: if(count>=unused) prune_ratio=1;/*释放率*/ else prune_ratio=unused/count; spin_lock(&sb_lock); list_for_each_entry(sb,&super_blocks,s_list){ if(sb->s_nr_dentry_unused==0) continue; sb->s_count++; /*Now,wereclaimunuseddentrinswithfairness. *Wereclaimthemsamepercentagefromeachsuperblock. *Wecalculatenumberofdentriestoscanonthissb *asfollows,buttheimplementationisarrangedtoavoid *overflows: *numberofdentriestoscanonthissb= *count*(numberofdentriesonthissb/ *numberofdentriesinthemachine) */ spin_unlock(&sb_lock); /*重新利用释放率计算释放量*/ if(prune_ratio!=1) w_count=(sb->s_nr_dentry_unused/prune_ratio)+1; else w_count=sb->s_nr_dentry_unused; pruned=w_count; /* *Weneedtobesurethisfilesystemisn'tbeingunmounted, *otherwisewecouldracewithgeneric_shutdown_super(),and *endupholdingareferencetoaninodewhilethefilesystem *isunmounted.Sowetrytogets_umount,andmakesure *s_rootisn'tNULL. */ if(down_read_trylock(&sb->s_umount)){ if((sb->s_root!=NULL)&& (!list_empty(&sb->s_dentry_lru))){ spin_unlock(&dcache_lock); /*实际释放工作*/ __shrink_dcache_sb(sb,&w_count, DCACHE_REFERENCED); pruned-=w_count; spin_lock(&dcache_lock); } up_read(&sb->s_umount); } spin_lock(&sb_lock); count-=pruned; /* *restartonlywhensbisnolongeronthelistand *wehavemoreworktodo. */ if(__put_super_and_need_restart(sb)&&count>0){ spin_unlock(&sb_lock); gotorestart; } } spin_unlock(&sb_lock); spin_unlock(&dcache_lock); }[cpp]view plaincopy print? /* *ShrinkthedentryLRUonagivensuperblock. *@sb:superblocktoshrinkdentryLRU. *@count:IfcountisNULL,weprunealldentriesonsuperblock. *@flags:Ifflagsisnon-zero,weneedtodospecialprocessingbasedon *whichflagsareset.Thismeanswedon'tneedtomaintainmultiple *similarcopiesofthisloop. */ staticvoid__shrink_dcache_sb(structsuper_block*sb,int*count,intflags) { LIST_HEAD(referenced); LIST_HEAD(tmp); structdentry*dentry; intcnt=0; BUG_ON(!sb); BUG_ON((flags&DCACHE_REFERENCED)&&count==NULL); spin_lock(&dcache_lock); if(count!=NULL) /*calledfromprune_dcache()andshrink_dcache_parent()*/ cnt=*count;/*在下面用到*/ restart: if(count==NULL) list_splice_init(&sb->s_dentry_lru,&tmp); else{ while(!list_empty(&sb->s_dentry_lru)){ dentry=list_entry(sb->s_dentry_lru.prev, structdentry,d_lru); BUG_ON(dentry->d_sb!=sb); spin_lock(&dentry->d_lock); /* *IfwearehonouringtheDCACHE_REFERENCEDflagand *thedentryhasthisflagset,don'tfreeit.Clear *theflagandputitbackontheLRU. */ /*清flag对应位,将链表元素放LRU尾部*/ if((flags&DCACHE_REFERENCED) &&(dentry->d_flags&DCACHE_REFERENCED)){ dentry->d_flags&=~DCACHE_REFERENCED; list_move(&dentry->d_lru,&referenced); spin_unlock(&dentry->d_lock); }else{ /*从d_lru链表中删除,加到tmp链表中*/ list_move_tail(&dentry->d_lru,&tmp); spin_unlock(&dentry->d_lock); cnt--;/*数量减一*/ if(!cnt)/*减到0跳出循环*/ break; } cond_resched_lock(&dcache_lock); } } /*对tmp中的每个元素,其中tmp中的元素为上面移过来的*/ while(!list_empty(&tmp)){ dentry=list_entry(tmp.prev,structdentry,d_lru); /*从tmp中删除相关链表并做重新初始化和数据统计*/ dentry_lru_del_init(dentry); spin_lock(&dentry->d_lock); /* *Wefoundaninusedentrywhichwasnotremovedfrom *theLRUbecauseoflazinessduringlookup.Donotfree *it-justkeepitofftheLRUlist. */ if(atomic_read(&dentry->d_count)){ spin_unlock(&dentry->d_lock); continue; }/*释放dentry和其父dentry*/ prune_one_dentry(dentry); /*dentry->d_lockwasdroppedinprune_one_dentry()*/ cond_resched_lock(&dcache_lock); } if(count==NULL&&!list_empty(&sb->s_dentry_lru)) gotorestart; if(count!=NULL) *count=cnt; if(!list_empty(&referenced)) list_splice(&referenced,&sb->s_dentry_lru); spin_unlock(&dcache_lock); }[cpp]view plaincopy print? staticvoiddentry_lru_del_init(structdentry*dentry) { if(likely(!list_empty(&dentry->d_lru))){ list_del_init(&dentry->d_lru);/*从链表中删除并初始化dentry->d_lru*/ dentry->d_sb->s_nr_dentry_unused--;/*未用数减一*/ dentry_stat.nr_unused--;/*更新统计数据*/ } }[html]view plaincopy print? /* *Throwawayadentry-freetheinode,dputtheparent.Thisrequiresthat *theLRUlisthasalreadybeenremoved. * *Trytopruneancestorsaswell.Thisisnecessarytoprevent *quadraticbehaviorofshrink_dcache_parent(),butisalsoexpected *tobebeneficialinreducingdentrycachefragmentation. */ staticvoidprune_one_dentry(structdentry*dentry) __releases(dentry->d_lock) __releases(dcache_lock) __acquires(dcache_lock) { __d_drop(dentry); dentry=d_kill(dentry);/*释放dentry*/ /* *Pruneancestors.Lockingissimplerthanindput(), *becausedcache_lockneedstobetakenanyway. */ spin_lock(&dcache_lock); while(dentry){ if(!atomic_dec_and_lock(&dentry->d_count,&dentry->d_lock)) return; if(dentry->d_op&&dentry->d_op->d_delete) dentry->d_op->d_delete(dentry); dentry_lru_del_init(dentry); __d_drop(dentry); dentry=d_kill(dentry); spin_lock(&dcache_lock); } }[cpp]view plaincopy print? /** *d_kill-killdentryandreturnparent *@dentry:dentrytokill * *ThedentrymustalreadybeunhashedandremovedfromtheLRU. * *Ifthisistherootofthedentrytree,returnNULL. */ staticstructdentry*d_kill(structdentry*dentry) __releases(dentry->d_lock) __releases(dcache_lock) { structdentry*parent; list_del(&dentry->d_u.d_child);/*删除子目录*/ dentry_stat.nr_dentry--;/*更新统计数据*//*Ford_free,below*/ /*dropsthelocks,atthatpointnobodycanreachthisdentry*/ dentry_iput(dentry);/*"释放"inode*/ if(IS_ROOT(dentry)) parent=NULL; else parent=dentry->d_parent; d_free(dentry);/*释放dentry*/ returnparent; }[cpp]view plaincopy print? /* *Releasethedentry'sinode,usingthefilesystem *d_iput()operationifdefined. */ /*释放inode*/ staticvoiddentry_iput(structdentry*dentry) __releases(dentry->d_lock) __releases(dcache_lock) { structinode*inode=dentry->d_inode; if(inode){ dentry->d_inode=NULL; list_del_init(&dentry->d_alias);/*从同一索引节点目录链表中删除*/ spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); if(!inode->i_nlink)/*如果inode没有硬链接*/ fsnotify_inoderemove(inode); if(dentry->d_op&&dentry->d_op->d_iput) dentry->d_op->d_iput(dentry,inode); else iput(inode);/*释放inode*/ }else{ spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); } }

2.注册inodecacheshrinker

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

其中参数为下面定义

[cpp]view plaincopy print? staticstructshrinkericache_shrinker={ .shrink=shrink_icache_memory, .seeks=DEFAULT_SEEKS, };[cpp]view plaincopy print? staticintshrink_icache_memory(intnr,gfp_tgfp_mask) { if(nr){ /* *Nastydeadlockavoidance.WemayholdvariousFSlocks, *andwedon'twanttorecurseintotheFSthatcalledus *inclear_inode()andfriends.. */ if(!(gfp_mask&__GFP_FS)) return-1; prune_icache(nr); } return(inodes_stat.nr_unused/100)*sysctl_vfs_cache_pressure; }[cpp]view plaincopy print? /* *Scan`goal'inodesontheunusedlistforfreeableones.Theyaremovedto *atemporarylistandthenarefreedoutsideinode_lockbydispose_list(). * *Anyinodeswhicharepinnedpurelybecauseofattachedpagecachehavetheir *pagecacheremoved.Weexpectthefinaliput()onthatinodetoadditto *thefrontoftheinode_unusedlist.Solookforitthereandifthe *inodeisstillfreeable,proceed.Therightinodeisfound99.9%ofthe *timeintestingona4-way. * *Iftheinodehasmetadatabuffersattachedtomapping->private_listthen *trytoremovethem. */ staticvoidprune_icache(intnr_to_scan) { LIST_HEAD(freeable);/*初始化freeable,在下面需要用到,作为临时存放可被释放的inode*/ intnr_pruned=0; intnr_scanned; unsignedlongreap=0; down_read(&iprune_sem); spin_lock(&inode_lock); for(nr_scanned=0;nr_scanned<nr_to_scan;nr_scanned++){ structinode*inode; if(list_empty(&inode_unused)) break; inode=list_entry(inode_unused.prev,structinode,i_list); if(inode->i_state||atomic_read(&inode->i_count)){ /*将ionde从inode_unused链表中删除,加入inode_unused链表头*/ list_move(&inode->i_list,&inode_unused); continue; } if(inode_has_buffers(inode)||inode->i_data.nrpages){ __iget(inode);/*移动到使用链表*/ spin_unlock(&inode_lock); if(remove_inode_buffers(inode))/*从buffer链表中删除所有buffer*/ reap+=invalidate_mapping_pages(&inode->i_data, 0,-1); iput(inode); spin_lock(&inode_lock); if(inode!=list_entry(inode_unused.next, structinode,i_list)) continue;/*wronginodeorlist_empty*/ if(!can_unuse(inode)) continue; } /*移动到freeable链表*/ list_move(&inode->i_list,&freeable); WARN_ON(inode->i_state&I_NEW); inode->i_state|=I_FREEING; nr_pruned++;/*统计移动到freeable链表的元素个数*/ } inodes_stat.nr_unused-=nr_pruned;/*更新统计数据*/ if(current_is_kswapd()) __count_vm_events(KSWAPD_INODESTEAL,reap); else __count_vm_events(PGINODESTEAL,reap); spin_unlock(&inode_lock); dispose_list(&freeable);/*将freeable链表中的数据处理掉*/ up_read(&iprune_sem); }

3,注册文件描述符表释放函数

[cpp]view plaincopy print? /*文件描述符表*/ structfdtable{ unsignedintmax_fds;/*进程能够处理的最大file结构*/ structfile**fd;/*所有打开文件信息*//*currentfdarray*/ fd_set*close_on_exec;/*exec系统调用被关闭的所有文件集合*/ fd_set*open_fds;/*当前打开的所有文件集合*/ structrcu_headrcu; structfdtable*next; };

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

[cpp]view plaincopy print? staticvoidfree_fdtable_work(structwork_struct*work) { structfdtable_defer*f= container_of(work,structfdtable_defer,wq); structfdtable*fdt; spin_lock_bh(&f->lock); fdt=f->next; f->next=NULL; spin_unlock_bh(&f->lock); while(fdt){/*释放工作*/ structfdtable*next=fdt->next; vfree(fdt->fd); free_fdset(fdt); kfree(fdt); fdt=next; } }

4.sysfs文件系统初始化

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

[cpp]view plaincopy print? int__initsysfs_init(void) { interr=-ENOMEM; sysfs_dir_cachep=kmem_cache_create("sysfs_dir_cache", sizeof(structsysfs_dirent), 0,0,NULL); if(!sysfs_dir_cachep) gotoout; /*初始化sysfs的backing_dev_info结构*/ err=sysfs_inode_init(); if(err) gotoout_err; /*注册文件系统*/ err=register_filesystem(&sysfs_fs_type); if(!err){ /*创建sysfsmount*/ sysfs_mount=kern_mount(&sysfs_fs_type); if(IS_ERR(sysfs_mount)){ printk(KERN_ERR"sysfs:couldnotmount!\n"); err=PTR_ERR(sysfs_mount); sysfs_mount=NULL; unregister_filesystem(&sysfs_fs_type); gotoout_err; } }else gotoout_err; out: returnerr; out_err: kmem_cache_destroy(sysfs_dir_cachep); sysfs_dir_cachep=NULL; gotoout; }

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。