⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _2_4_054_fs_super_c.html

📁 重读linux 2.4.2o所写的笔记
💻 HTML
📖 第 1 页 / 共 3 页
字号:
        font-size: 10.0pt;    line-height: normal;    background-color: #ffffff;  }    .documentBG {    background-color: #ffffff;  }  /* end ui edited css */</style>   </head>  <body  revision="dcbsxfpf_215fb9cjsgv:253">      <DIV ALIGN=center ID=qf-i>
  <TABLE ALIGN=center BORDER=0 CELLPADDING=0 CELLSPACING=0 HEIGHT=5716 ID=u3_i WIDTH=801>
    <TBODY ID=jsmi>
    <TR ID=fyzl>
      <TD HEIGHT=5716 ID=ci:d VALIGN=top WIDTH=100%>
        <PRE ID=vvtc>2007-8-22<BR ID=ydur>fs/super.c<BR ID=sly1><BR ID=o:82>  重读2.4,这是最后一篇了, 之后该读2.6..<BR ID=b9n5><BR ID=cuzh>内存管理和vfs文件系统,是学习的基础(for me),process也非常重要融入其中把...<BR ID=x27p></PRE>
        <HR ID=jrti STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=xqu2 SIZE=4><B ID=gc43>filesystems</B></FONT><BR ID=wsk5><BR ID=w1t0>这个模块分成三个部分的内容:filesystem管理, super块管理, mount/umount管理. 先看简单的filesystem管理,此乃一链表,够简单.<BR ID=dod5>struct file_system_type {<BR ID=xb.5>	const char *name;<BR ID=z2yv>	int fs_flags;<BR ID=c.a4>	struct super_block *(*read_super) (struct super_block *, void *, int);<BR ID=az8q>	struct module *owner;<BR ID=hawc>	struct vfsmount *kern_mnt; /* For kernel mount, if it's FS_SINGLE fs */<BR ID=g70l>	struct file_system_type * next;<BR ID=ms.u>};<BR ID=zla1><BR ID=dy.k>注意下do_mount函数获取super block的方式: 想ext2是 required dev, 代表着只要是同一个dev,使用同一个superblock, 而像虚拟文<BR ID=g8gq>件系统devpts则指明了SINGLE属性,多次安装都是同一个super block. 同一个superblock的含义是:同一目录棵树. 到2.6, 这些属性消<BR ID=zce7>失不见,代替为各个文件系统自己的read_super自己处理安装方式.<BR ID=wg_a><BR ID=ywoe>具体细节不再罗列.<BR ID=zy.g><FONT COLOR=#0000ff ID=ro:e>/*<BR ID=mg4u> * Handling of filesystem drivers list.<BR ID=a9e-> * Rules:<BR ID=q0y:> *	Inclusion to/removals from/scanning of list are protected by spinlock.<BR ID=n6g-> *	During the unload module must call unregister_filesystem().<BR ID=fix8> *	We can access the fields of list element if:<BR ID=i66e> *		1) spinlock is held or<BR ID=i0-q> *		2) we hold the reference to the module.<BR ID=ojqz> *	The latter can be guaranteed by call of try_inc_mod_count(); if it<BR ID=iotr> *	returned 0 we must skip the element, otherwise we got the reference.<BR ID=ff56> *	Once the reference is obtained we can drop the spinlock.<BR ID=x1-s> */<BR ID=ax8_></FONT><BR ID=i3et>static struct file_system_type *file_systems;<BR ID=x0xj>static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;<BR ID=jm:v><BR ID=huos>asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2) /*非常*/<BR ID=xoce><BR ID=tjxc></PRE>
        <HR ID=xv8d STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=cvt8 SIZE=4><SPAN ID=ytz8><B ID=kjrt>super block的简单管理</B></SPAN></FONT><BR ID=csay><BR ID=olnf>一个链表,然后,如果是SINGLE类型的文件系统,super block还挂接到file_system_type::kern_mnt-&gt;mnt_sb.<BR ID=pnp_>int nr_super_blocks;<BR ID=gjtn>int max_super_blocks = NR_SUPER;<BR ID=gzau>LIST_HEAD(super_blocks);<BR ID=mtwu><BR ID=pbln>struct super_block * <FONT COLOR=#38761d ID=u3xm><B ID=po6q>get_super</B></FONT>(kdev_t dev) <BR ID=ltla>/*<FONT ID=ctme><FONT COLOR=#38761d ID=u3xm>get_super </FONT></FONT>遍历上面的superblock链表,找到指定dev的sb,如果没有就返回NULL,代表需要创建. 给mount_root和required dev类型的<BR ID=maoq>文件系统使用 dev相同就. 或者用此函数超找已经安装文件的sb */ <BR ID=o-py><BR ID=qm93>struct super_block *get_empty_super(void) /*不用说了,分配新sb,挂入链表*/<BR ID=nkjz><BR ID=bf06>static struct super_block *<FONT COLOR=#0000ff ID=j1q5><SPAN ID=kbur><B ID=cyum>get_sb_nodev</B></SPAN></FONT>(struct file_system_type *fs_type,int flags, void * data)<BR ID=cbre>{ <FONT COLOR=#0000ff ID=ifwc>/*为不需要dev的文件系统:(非single并且不是requied dev类型, 如shm,nfs等)*/</FONT><BR ID=uwab>	kdev_t dev;<BR ID=zy0_>	int error = -EMFILE;<BR ID=db9i>	down(&amp;mount_sem);<BR ID=l-2e>	dev = get_unnamed_dev(); /*Major:0 */<BR ID=v2_0>	if (dev) {<BR ID=akzb>		struct super_block * sb;<BR ID=otoc>		error = -EINVAL;<BR ID=sfme>		sb = read_super(dev, NULL, fs_type, flags, data, 0); /*直接分配新的sb,除非filesystem另有考虑(2.4没有)*/<BR ID=pp1h>		......<BR ID=or90>}<BR ID=afa4><BR ID=ytkr>static struct super_block *<FONT COLOR=#0b5394 ID=t1q.><SPAN ID=pa4n><B ID=efav>get_sb_single</B></SPAN></FONT>(struct file_system_type *fs_type,<BR ID=og_u>	int flags, void *data)<BR ID=gkf4>{<FONT COLOR=#0b5394 ID=ynxl> /*上面说了比如devpts之类文件系统*/</FONT><BR ID=y16_>	/*<BR ID=a0_i>	 * Get the superblock of kernel-wide instance, but<BR ID=ttp_>	 * keep the reference to fs_type.<BR ID=qjk_>	 */<BR ID=os5_>        ...<BR ID=g9.5>	sb = fs_type-&gt;kern_mnt-&gt;mnt_sb;<FONT COLOR=#0000ff ID=sgul> /*绝对共享superblock*/</FONT><BR ID=us33>        ....<BR ID=vfvl>	do_remount_sb(sb, flags, data); <FONT COLOR=#0000ff ID=gevv>/*sb-&gt;s_op-&gt;remount_fs, 给文件系统的重新安装准备的,不是专门给SINGLE类型使用的*/</FONT><BR ID=bzb.>	return sb;<BR ID=kpcq>}<BR ID=fs6:>static struct super_block *<FONT COLOR=#0b5394 ID=bdql><SPAN ID=zg2h><B ID=w_5p>get_sb_bdev</B></SPAN></FONT>(struct file_system_type *fs_type,<BR ID=cvan>	char *dev_name, int flags, void * data)<BR ID=uqsf>{ <FONT COLOR=#0000ff ID=kr8v>/*普通文件系统, 需要dev支持*/</FONT><BR ID=p2xf>	....<BR ID=sks3>	if (path_init(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &amp;nd)) <FONT COLOR=#0000ff ID=r5jy>/*打开设备文件*/</FONT><BR ID=svd7>		error = path_walk(dev_name, &amp;nd);<BR ID=hj_q>        ...<BR ID=t1a4>       &nbsp;bdev = inode-&gt;i_bdev; <FONT COLOR=#0000ff ID=o21s>/*获取bdev以及其ops*/</FONT><BR ID=l1.n>	bdops = devfs_get_ops ( devfs_get_handle_from_inode (inode) );<FONT COLOR=#0000ff ID=kf9i>/*尝试从devpts文件系统获取...没有devpts就没有*/</FONT><BR ID=amxa>	if (bdops) bdev-&gt;bd_op = bdops;<BR ID=hkx7>        ...<BR ID=po95>	sb = get_super(dev); <FONT COLOR=#0000ff ID=nm7j>/*看看是否已经安装*/</FONT><BR ID=icxy>	if (sb) {<BR ID=e7az>		if (fs_type == sb-&gt;s_type &amp;&amp;<BR ID=k7:s>		    ((flags ^ sb-&gt;s_flags) &amp; MS_RDONLY) == 0) { <FONT COLOR=#0000ff ID=hsci>/*安装两次的dev设备不能改变其只读属性,否则出错*/</FONT><BR ID=wjm6>			.... /*没有改变*/<BR ID=cvuy>			return sb;<BR ID=o40y>		}<BR ID=wtg3>	} else {<BR ID=k4sa>		.....<BR ID=oukz>		error = blkdev_get(bdev, mode, 0, BDEV_FS); <FONT COLOR=#0000ff ID=j1uo>/*还会尝试获取bdev ops*/</FONT><BR ID=wshk>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... /*disk change ,略...*/<BR ID=tb6s>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb = read_super(dev, bdev, fs_type, flags, data, 0); <FONT COLOR=#0000ff ID=lu4c>/*通过filesystem注册的read_super读入超级块*/</FONT><BR ID=z5i2>		......<BR ID=rkht>}<BR ID=vcfm>  <BR ID=a76v>void sync_supers(kdev_t dev)  <FONT COLOR=#0000ff ID=zo3y>/*找到指定dev的super调用sb-&gt;s_op-&gt;write_super*/<BR ID=thed><BR ID=o:.c></FONT>static void <FONT COLOR=#0b5394 ID=zz9c><SPAN ID=hhbb><B ID=flwn>kill_super</B></SPAN></FONT>(struct super_block *sb, int umount_root) <FONT COLOR=#0000ff ID=u9u_>/*给mount/umount准备的函数*/</FONT><BR ID=slhx>{ <FONT COLOR=#0000ff ID=lv5w>/*kill super的时候已经做过fsyn_dev,shrink_dcache_sb了*/</FONT><BR ID=wekx>        ........<BR ID=f:5q>	sb-&gt;s_root = NULL; /**/<BR ID=obvz>	/* Need to clean after the sucker */<BR ID=kcfm>	if (fs-&gt;fs_flags &amp; <FONT COLOR=#0000ff ID=n8td>FS_LITTER</FONT>)<BR ID=wdf3>		d_genocide(root);<FONT COLOR=#0000ff ID=v2nm> /*把dentry的引用技术减1,种族灭绝....keep dentry in memory... tmpfs(shm),ramfs*/</FONT><BR ID=r:dw>	if (fs-&gt;fs_flags &amp; (FS_SINGLE|FS_LITTER))<BR ID=kxzl>		shrink_dcache_parent(root); <FONT COLOR=#38761d ID=ipsj>/*引用计数为0的放入unused队然后最终释放掉.<FONT COLOR=#ff0000 ID=ukp5>2.6 umount的时候都要调用这个函数的</FONT>*/</FONT><BR ID=hsoz>	dput(root); <FONT COLOR=#0000ff ID=kj0y>/*释放root dentry*/</FONT><BR ID=ovu3>	lock_super(sb);<BR ID=vzep>	if (sop) { <FONT COLOR=#0000ff ID=u6y5>/*回写super block*/</FONT><BR ID=q6od>		if (sop-&gt;write_super &amp;&amp; sb-&gt;s_dirt)<BR ID=mtml>			sop-&gt;write_super(sb);<BR ID=w35o>		if (sop-&gt;put_super)<BR ID=nohq>			sop-&gt;put_super(sb);<BR ID=ec2f>	}<BR ID=s8:b><BR ID=n1bw>	/* Forget any remaining inodes */<BR ID=sk6g>	if (invalidate_inodes(sb)) { <FONT COLOR=#ff0000 ID=zffb>/*强制释放所有还没有释放的inode,如果有,呵呵....*/</FONT><BR ID=ohb5>		...."Self-destruct in 5 seconds.  Have a nice day...\n");<BR ID=ztxl>	}<BR ID=uwpc><BR ID=pqhi>	dev = sb-&gt;s_dev;<BR ID=z_:y>	sb-&gt;s_dev = 0;		<FONT COLOR=#0000ff ID=xk87>/* Free the superblock,<FONT COLOR=#ff00ff ID=xdka>见get_empty_super,只分配不会最终释放的...</FONT> */</FONT><BR ID=l.-c>	.....<BR ID=c_-e>	if (umount_root) {<BR ID=an7y>		/* special: the old device driver is going to be<BR ID=i3g2>		   a ramdisk and the point of this call is to free its<BR ID=s7yu>		   protected memory (even if dirty). */<BR ID=cb:j>		destroy_buffers(dev); <FONT COLOR=#0000ff ID=r.kc>/*chang root.....释放dev相关的buffer cache*/</FONT><BR ID=y2tj>	}<BR ID=uvy6>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<BR ID=hu.->}<BR ID=eepc><BR ID=iw8f><BR ID=a-y9>这里着重介绍一下这个flag,..在2.6中被<CODE ID=uwns>kill_super_litter所代替,先看网上关于这个的一点介绍:</CODE><BR ID=uch:><FONT COLOR=#ff0000 ID=ils-><SPAN ID=vupq><B ID=fhb5>FS_LITTER</B></SPAN></FONT> (gone)  /*dentry创建的时候引用计数被加了1....*/</PRE>
        <P ID=pu1t>
          The <CODE ID=c.-m>FS_LITTER</CODE> flag (2.4.0test3-2.5.7) says that after umount a <CODE ID=yvhw>d_genocide()</CODE> is
          needed. This will remove one reference<BR ID=df63>
        </P>
        <P ID=pu1t>
          from all dentries in that tree, probably killing all of them, which is
          necessary in case at creation time the dentries already
        </P>
        <P ID=pu1t>
          got reference count 1. (This is typically done for an in-core
          filesystem where dentries cannot be recreated when needed.)<BR ID=u.s_>
        </P>
        <P ID=pu1t>
          This flag disappeared in Linux 2.5.7 when the explicit <CODE ID=uwns>kill_super</CODE> method
          <CODE ID=t3.4>kill_litter_super</CODE> was introduced.
        </P>
        <PRE ID=vvtc>This flag for in-memory filesystems without backing store - they need an additional <CODE ID=fix:>dget()</CODE><BR ID=kxat>when a file is created (so that their dentries always have a nonzero reference count and are not garbage collected), <BR ID=c9gi>and the <CODE ID=g8v3>d_genocide() </CODE>that is the difference between <CODE ID=dwqh>kill_anon_super</CODE> and <CODE ID=ak_d>kill_litter_super</CODE> does the balancing <CODE ID=qm77>dput()</CODE>.<BR ID=z9pz><BR ID=urzg>大意是,纯粹呆在内存的文件系统, 为了达到denty不被flush出去的目的,在创建文件的时候对dentry的引用计数凭空增加了1,所以需要在<BR ID=rihf>kill_super中 d_genocide(root), 比如shmem的create函数:<BR ID=jlxo>static int <SPAN ID=xiwq><B ID=p83g>shmem_mknod</B></SPAN>(struct inode *dir, struct dentry *dentry, int mode, int dev)<BR ID=orty>{<BR ID=pqxw>	struct inode * inode = shmem_get_inode(dir-&gt;i_sb, mode, dev);<BR ID=ofx5>	int error = -ENOSPC;<BR ID=bhoz><BR ID=iupv>	if (inode) {<BR ID=dhk4>		d_instantiate(dentry, inode);<BR ID=hvkk>		<FONT COLOR=#cc0000 ID=ein2>dget(dentry); /* Extra count - pin the dentry in core */</FONT><BR ID=ajc4>		error = 0;<BR ID=h:5c>	}<BR ID=t:je>	return error;<BR ID=e6ia>}<BR ID=fwzd></PRE>
        <HR ID=hs4g STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=u:i: SIZE=4><SPAN ID=ieb2><B ID=cpm9>kernel mount 以及杂项</B></SPAN></FONT><BR ID=fdkh><BR ID=ihux>static LIST_HEAD(vfsmntlist); <BR ID=rwjf><BR ID=qdgk>static struct vfsmount *add_vfsmnt(struct nameidata *nd,struct dentry *root,const char *dev_name)<BR ID=k.8z><IMG ALT="" ID=nmw1><IMG ALT="" ID=q3tw>static void remove_vfsmnt(struct vfsmount *mnt) /*从链表删除,释放对其他节点引用,释放mnt占用内存*/<BR ID=pmdv>代码不说了,就是建立下面的指针关系: vfsmnt是联系mount point/mount root/super block的一个纽带<BR ID=lx3m><DIV ID=j1ag STYLE="PADDING:1em 0pt; TEXT-ALIGN:left"><DIV ID=jp_u STYLE="PADDING:1em 0pt; TEXT-ALIGN:left"><IMG ID=y5-e SRC=_2_4_054_fs_super_c_images/dcbsxfpf_217dmmkkvfg_b.jpg STYLE="WIDTH:608px; HEIGHT:726px"></DIV><BR ID=k:b0></DIV><BR ID=g5rv><FONT COLOR=#0000ff ID=homf>/*<BR ID=az76>  * 安装到filesystem-&gt;kern_mnt<BR ID=rxjp>  */<BR ID=i_4m>/*  使用kernel_mount安装的虚拟文件系统与do_mount安装的文件系统有可能<BR ID=ry:5> * 不使用同一个sb(以及root),除非文件系统的性质是FS_SINGLE.<BR ID=xwkk> */</FONT><BR ID=at.9>struct vfsmount *<FONT COLOR=#0b5394 ID=izbp><B ID=o515>kern_mount</B></FONT>(struct file_system_type *type)<BR ID=z_is>{<BR ID=z5c1>	kdev_t dev = get_unnamed_dev();<FONT COLOR=#0000ff ID=ulcf>/*获得一个unnamed dev,专门为虚拟文件系统准备*/</FONT><BR ID=jc8g>	struct super_block *sb;<BR ID=k8px>	struct vfsmount *mnt;<BR ID=yjsg>	if (!dev)<BR ID=neqo>		return ERR_PTR(-EMFILE);<BR ID=qqly><BR ID=joo3>	 <FONT COLOR=#0000ff ID=w_s0>/*malloc sb, and type-&gt;read_super,like shmem_read_super*/</FONT><BR ID=f5xh>	sb = read_super(dev, NULL, type, 0, NULL, 0);<BR ID=nxzl>	if (!sb) {<BR ID=uobs>		put_unnamed_dev(dev);<BR ID=go3->		return ERR_PTR(-EINVAL);<BR ID=c3e5>	}<BR ID=u:7q><BR ID=mg9v>	<FONT COLOR=#0000ff ID=a2_1>/*仅仅获得一个mnt 结构, 安装点是自己(自环), mnt_parent也是自己*/</FONT><BR ID=inaw>	mnt = add_vfsmnt(NULL, sb-&gt;s_root, NULL);<BR ID=xl58>	if (!mnt) {<BR ID=mxtq>		kill_super(sb, 0);<BR ID=ismc>		return ERR_PTR(-ENOMEM);<BR ID=hmch>	}<BR ID=frm1>	<BR ID=w-g2>	type-&gt;kern_mnt = mnt; <FONT COLOR=#0000ff ID=cr9.>/*内核可以使用此文件系统,对kernel 的user不可见*/</FONT><BR ID=b3os>	return mnt;<BR ID=dyow>}<BR ID=k16z><BR ID=udlw>/* Call only after unregister_filesystem() - it's a final cleanup */<BR ID=ez4t>void <SPAN ID=l:wa><FONT COLOR=#0b5394 ID=vted><B ID=wu4f>kern_umount</B></FONT></SPAN>(struct vfsmount *mnt)<BR ID=zyk7><BR ID=pcu:>int <SPAN ID=v2ge><B ID=lurs>get_filesystem_info</B></SPAN>( char *buf ) /*获取文件系统信息... 略*/<BR ID=al:y>asmlinkage long <SPAN ID=s6x1><B ID=f_x9>sys_ustat</B></SPAN>(dev_t dev, struct ustat * ubuf) /*获系统信息... 略*/<BR ID=monf><BR ID=sl:x></PRE>
        <HR ID=cbih STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=ozjx SIZE=4><SPAN ID=vr4-><B ID=r.2.>sys_mount</B></SPAN><BR ID=uhkv></FONT><BR ID=b1.t>asmlinkage long <FONT COLOR=#0b5394 ID=b:0w><SPAN ID=nid7><B ID=pnvp>sys_mount</B></SPAN></FONT>(char * dev_name, char * dir_name, char * type,<BR ID=yd5q>			  unsigned long flags, void * data)<BR ID=b.16>{<BR ID=t2l5>        ...  <FONT COLOR=#0000ff ID=tvbu>/*从用户空间copy安装参数*/</FONT><BR ID=twtn><BR ID=dy.x>	lock_kernel();<BR ID=gt9i>	retval = <FONT COLOR=#38761d ID=mp2c><SPAN ID=gb7r><B ID=dic4>do_mount</B></SPAN></FONT>((char*)dev_page, dir_page, (char*)type_page,<BR ID=o-jt>			  flags, (void*)data_page);<BR ID=f2m:>	unlock_kernel();<BR ID=x_op>	.......<BR ID=vr6d>	return retval;<BR ID=u2g1>}<BR ID=kbnu><BR ID=rzw2>long do_mount(char * dev_name, char * dir_name, char *type_page,<BR ID=yuj6>		  unsigned long flags, void *data_page)<BR ID=dfq_>{<BR ID=lnzg>	..... <FONT COLOR=#0000ff ID=nm10>/*sanity check*/</FONT><BR ID=t0gj>	<FONT COLOR=#0000ff ID=bo48>/* just change the flags? - capabilities are checked in do_remount() */</FONT><BR ID=f_bs>	if (flags &amp; MS_REMOUNT) <FONT COLOR=#0000ff ID=yoz3>/*remount处理*/</FONT><BR ID=ke1h>		return <FONT COLOR=#38761d ID=ozn5><SPAN ID=eppk><B ID=my7_>do_remount</B></SPAN></FONT>(dir_name, flags &amp; ~MS_REMOUNT,(char *) data_page);<BR ID=ej1-><BR ID=up.d>	<FONT COLOR=#0000ff ID=dm17>/* "mount --bind"? Equivalent to older "mount -t bind" */<BR ID=bmz->	/* No capabilities? What if users do thousands of these? */</FONT><BR ID=i598>	if (flags &amp; MS_BIND) <FONT COLOR=#0000ff ID=x0:2>/*loopback mount处理*/</FONT><BR ID=h2vu>		return <FONT COLOR=#38761d ID=jnp6><B ID=czt_>do_loopback</B></FONT>(dev_name, dir_name);<BR ID=a16y><BR ID=c3v7>	/* For the rest we need the type */<BR ID=w:.j>	....<FONT COLOR=#0000ff ID=vln6> /*sanity check和权限检查*/</FONT><BR ID=l5kc><BR ID=rngv>	/* ... filesystem driver... */<BR ID=ckid>	fstype = <FONT COLOR=#38761d ID=x20a><SPAN ID=zlss><B ID=pdo0>get_fs_type</B></SPAN></FONT>(type_page); <FONT COLOR=#0000ff ID=t7f1>/*获取文件系统类型,前边分析了,这里清楚了...*/</FONT><BR ID=fivz>	.....<BR ID=k-2j>	/* ... and mountpoint. Do the lookup first to force automounting. */<BR ID=zjeb>	if (path_init(dir_name,<BR ID=s-nm>		      LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &amp;nd))<BR ID=l3ro>		retval = <FONT COLOR=#38761d ID=bbvn><SPAN ID=rxi_><B ID=er_i>path_walk</B></SPAN></FONT>(dir_name, &amp;nd); <FONT COLOR=#0000ff ID=hfu7>/*获取安装点*/</FONT><BR ID=eba0>	if (retval)<BR ID=ox97>		goto fs_out;<BR ID=uto6><BR ID=x5oc>	<FONT COLOR=#ff0000 ID=d7te>/* get superblock, locks mount_sem on success */<BR ID=kh.8>        /*前边已经分析过各种类型的文件系统在获取super block的异同了.*/<BR ID=eo28></FONT>	if (fstype-&gt;fs_flags &amp; FS_NOMOUNT)<BR ID=q29k>		sb = ERR_PTR(-EINVAL);<BR ID=m:7n>	else if (fstype-&gt;fs_flags &amp; FS_REQUIRES_DEV)<BR ID=gdup>		sb = <FONT COLOR=#38761d ID=e_.5><SPAN ID=ncqk><B ID=u.gn>get_sb_bdev</B></SPAN></FONT>(fstype, dev_name, flags, data_page); <FONT COLOR=#0000ff ID=r7zd>/*设备相关的文件系统*/</FONT><BR ID=any1>	else if (fstype-&gt;fs_flags &amp; FS_SINGLE)<BR ID=easu>		sb = <FONT COLOR=#38761d ID=fam-><SPAN ID=d.hx><B ID=sr.q>get_sb_single</B></SPAN></FONT>(fstype, flags, data_page); <FONT COLOR=#0000ff ID=dgb2>/*SINGLE super block 的虚拟文件系统*/</FONT><BR ID=qbbv>	else<BR ID=shdx>		sb = <FONT COLOR=#38761d ID=taor><SPAN ID=o283><B ID=r69g>get_sb_nodev</B></SPAN></FONT>(fstype, flags, data_page); <FONT COLOR=#0000ff ID=q__d>/*比较纯粹的虚拟文件系统,每安装一次产生一个super block*/</FONT><BR ID=e:qm><BR ID=nwpx>	......<BR ID=wvkd><BR ID=o680>	<FONT COLOR=#ff0000 ID=rcmh>/* Something was mounted here while we slept */</FONT><BR ID=r1py>	while(d_mountpoint(nd.dentry) &amp;&amp; follow_down(&amp;nd.mnt, &amp;nd.dentry))<BR ID=zku_>		;<BR ID=jh2v><BR ID=z_if>	<FONT COLOR=#ff0000 ID=hi7i>/* Refuse the same filesystem on the same mount point */</FONT><BR ID=do5v>	retval = -EBUSY;<BR ID=j7jq>	if (nd.mnt &amp;&amp; nd.mnt-&gt;mnt_sb == sb<BR ID=zr7c>	    	   &amp;&amp; nd.mnt-&gt;mnt_root == nd.dentry)<BR ID=ll6x>		goto fail;<BR ID=nq2w><BR ID=f5hn>	retval = -ENOENT;<BR ID=dxnr>	if (!nd.dentry-&gt;d_inode)<BR ID=l5b0>		goto fail;<BR ID=h3y->     <FONT COLOR=#0000ff ID=iifc>   /*真正的安装也比较简单的,就是上面所说的add_vfsmnt*/</FONT><BR ID=v6l7>	down(&amp;nd.dentry-&gt;d_inode-&gt;i_zombie);<BR ID=o_gx>	if (!IS_DEADDIR(nd.dentry-&gt;d_inode)) {<BR ID=p.05>		retval = -ENOMEM;<BR ID=lxxa>		mnt = <FONT COLOR=#38761d ID=kdgj><SPAN ID=mx4i><B ID=qtxx>add_vfsmnt</B></SPAN></FONT>(&amp;nd, sb-&gt;s_root, dev_name);<BR ID=gpnr>	}<BR ID=hq8k>	......<BR ID=rmk0>}<BR ID=c13k><BR ID=th53>安装文件系统, 主要还是建立内存中mount point,mount root,mnt,super block之间的关系,设置好各个ops. 这里就是super block需要从<BR ID=cock>设备上读取,或者从内存中'凭空'产生.<BR ID=ziz->下面看第一分支, remount:<BR ID=c26b>static int <FONT COLOR=#0b5394 ID=ftr_><SPAN ID=la:h><B ID=pxi8>do_remount</B></SPAN></FONT>(const char *dir,int flags,char *data)<BR ID=if4g>{<BR ID=h2.x>	<FONT COLOR=#0000ff ID=mx_5>.... /*sanity 和权限检查*/</FONT><BR ID=mc3p>	if (path_init(dir, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &amp;nd))<BR ID=rit2>		retval = path_walk(dir, &amp;nd); <FONT COLOR=#0000ff ID=zl6e>/*找到要重新安装的文件系统root:path walk跳过安装点到达安装的文件系<BR ID=jdnm>                                                统的root dentry*/</FONT><BR ID=z:jr>	if (!retval) {<BR ID=ddam>		struct super_block * sb = nd.dentry-&gt;d_inode-&gt;i_sb;<FONT COLOR=#0000ff ID=qgbp> /*找到super block*/</FONT><BR ID=dzsu>		retval = -ENODEV;<BR ID=pqzw>		if (sb) {<BR ID=tvz6>			retval = -EINVAL;<BR ID=byqm>			if (nd.dentry == sb-&gt;s_root) { <FONT COLOR=#ff0000 ID=uzen>/*如果你安装到了 /mnt/hgfs/, 你不应用/mnt/hgfs/cross remount*/</FONT><BR ID=ubmz>				/*<BR ID=kzks>				 * Shrink the dcache and sync the device.<BR ID=xl6h>				 */<BR ID=tfr.>				shrink_dcache_sb(sb); <FONT COLOR=#0000ff ID=sx22>/*释放不用的dentry*/</FONT><BR ID=selx>				fsync_dev(sb-&gt;s_dev); <FONT COLOR=#0000ff ID=ebdd>/*向磁盘写入所有数据*/</FONT><BR ID=a58v>				if (flags &amp; MS_RDONLY)<BR ID=cr6o>					acct_auto_close(sb-&gt;s_dev);<BR ID=nja9>				retval =<FONT COLOR=#0000ff ID=bgbg><SPAN ID=q4lq><B ID=mha-> do_remount_sb</B></SPAN></FONT>(sb, flags, data); <FONT COLOR=#0000ff ID=p44l>/*目的就是改变安装参数,要通知具体文件系统*/</FONT><BR ID=q6sh>			}<BR ID=lj17>		}<BR ID=y:d0>		path_release(&amp;nd);<BR ID=a48i>	}<BR ID=ahsk>	return retval;<BR ID=fuhd>}<FONT COLOR=#0000ff ID=o28-><BR ID=cc0-><BR ID=n:od>第二个安装分支是loopback安装: 不要误以为是mount -loop, 而是mount -bind.. 剩下的.. 就很简单了</FONT><BR ID=lpos>/*<BR ID=rbxk> * do loopback mount.<BR ID=u_ye> */<BR ID=zevc>static int do_loopback(char *old_name, char *new_name)<BR ID=x5wk>{<BR ID=c.ep>  <FONT COLOR=#0000ff ID=rwrb>  /* 找到oldname和newname的dentry, 用一个add_vfsmnt把他们连接起来就可以了 */</FONT><BR ID=b3tq>    add_vfsmnt(&amp;new_nd, old_nd.dentry, old_nd.mnt-&gt;mnt_devname));<BR ID=tvhn>}<BR ID=ehzq></PRE>
        <HR ID=xum. STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=ehum SIZE=4><b>sys_umount</b></FONT><BR ID=r7s4><BR ID=hk15>直接看do_umount吧:<BR ID=ij6e>umount主要考虑被多次安装的情况. 然后需要sync...<BR ID=zv9i>static int <FONT COLOR=#38761d ID=w_yr><SPAN ID=h6er><B ID=r-nj>do_umount</B></SPAN></FONT>(struct vfsmount *mnt, int umount_root, int flags)<BR ID=uzca>{<BR ID=j:8b>	struct super_block * sb = mnt-&gt;mnt_sb;<BR ID=uzoc>	if (mnt == current-&gt;fs-&gt;rootmnt &amp;&amp; !umount_root) {<FONT COLOR=#0000ff ID=ooft> /*如果要umount 进程rootmnt又没有明确指定*/</FONT><BR ID=ocwm>		int retval = 0;<BR ID=tk0z>		mntput(mnt);<BR ID=mkyt>		if (!(sb-&gt;s_flags &amp; MS_RDONLY))<BR ID=a47q>			retval = do_remount_sb(sb, MS_RDONLY, 0);<FONT COLOR=#0000ff ID=r9z4> /*就改变安装类型为readonly*/</FONT><BR ID=o75m>		return retval;<BR ID=mjw8>	}<BR ID=bp:y>	spin_lock(&amp;dcache_lock);<BR ID=f784>	if (mnt-&gt;<FONT COLOR=#38761d ID=t51a>mnt_instances</FONT>.next != mnt-&gt;mnt_instances.prev) {<FONT COLOR=#0000ff ID=g6ht> /*文件系统被多次安装*/</FONT><BR ID=eohy>		if (atomic_read(&amp;mnt-&gt;mnt_count) &gt; 2) { <FONT COLOR=#0000ff ID=msju>/*看看这个安装实例是否可以释放*/</FONT><BR ID=apz:>			spin_unlock(&amp;dcache_lock);<BR ID=vp85>			mntput(mnt);<BR ID=o2-v>			return -EBUSY;<BR ID=zstd>		}<BR ID=tyx1>		.... <FONT COLOR=#0000ff ID=azci>/*仅释放这个安装*/</FONT><BR ID=e2u6>		return 0;<BR ID=jvph>	}<BR ID=r_03>	spin_unlock(&amp;dcache_lock);<BR ID=ar8q><FONT COLOR=#0000ff ID=d56r>        /*先关闭quta*/</FONT><BR ID=bcd2>	DQUOT_OFF(sb);<BR ID=ufep>	acct_auto_close(sb-&gt;s_dev);<BR ID=zoj2>	if( (flags&amp;MNT_FORCE) &amp;&amp; sb-&gt;s_op-&gt;umount_begin)<FONT COLOR=#0000ff ID=wbji> /*这个考虑挺玄,没有理解,nfs的人得出来说说...*/</FONT><BR ID=pmuw>		sb-&gt;s_op-&gt;umount_begin(sb);<BR ID=g_i6>	shrink_dcache_sb(sb); <FONT COLOR=#0000ff ID=mivn>/*当文件系统被多次安装,不做这个动作*/</FONT><BR ID=uyor>	fsync_dev(sb-&gt;s_dev); <FONT COLOR=#0000ff ID=l23n>/*这些保证只有root在使用中,并且是clean的*/<BR ID=pbqa></FONT>	if (sb-&gt;s_root-&gt;d_inode-&gt;i_state) {<BR ID=kc03>		mntput(mnt);<BR ID=h30l>		return -EBUSY;<BR ID=m9qg>	}<BR ID=qlp0>	/* Something might grab it again - redo checks */<BR ID=xz73>	spin_lock(&amp;dcache_lock);<BR ID=ttem>	if (atomic_read(&amp;mnt-&gt;mnt_count) &gt; 2) { <FONT COLOR=#0000ff ID=ylnx>/*看看是否被抢先了...(前边没有检查啊...?)*/</FONT><BR ID=d0d9>		spin_unlock(&amp;dcache_lock);<BR ID=f9je>		mntput(mnt);<BR ID=imy_>		return -EBUSY;<BR ID=hta3>	}<BR ID=uc41>	/* OK, that's the point of no return */<BR ID=p0bl>	mntput(mnt);<BR ID=em:q>	remove_vfsmnt(mnt); <FONT COLOR=#0000ff ID=oad:>/*最终撤销安装*/</FONT><BR ID=qygq>	kill_super(sb, umount_root);<BR ID=xtuy>	return 0;<BR ID=ma42>}<BR ID=sjo8><BR ID=udv.></PRE>
        <HR ID=cca5 STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc>mount root<BR ID=neb0><BR ID=nrkr>关于mount root,我们现在只关心下initrd吧.2.6的一篇分析文章请参考:<BR ID=btvf><A HREF=Doc?id=dcbsxfpf_210dcjjrbd2 ID=jsyj TITLE=http://docs.google.com/Doc?id=dcbsxfpf_210dcjjrbd2>http://docs.google.com/Doc?id=dcbsxfpf_210dcjjrbd2</A> <BR ID=h4op><BR ID=paur>void __init <FONT COLOR=#0c343d ID=o5hl><SPAN ID=itpl><b>mount_root</b></SPAN></FONT>(void)<BR ID=ezz:>{<BR ID=wtl2>	.....<BR ID=agsz>#ifdef CONFIG_ROOT_NFS <FONT COLOR=#0000ff ID=ak1o>/*by pass*/</FONT><BR ID=w-0t>	<BR ID=eet9>#endif<BR ID=j3.l>#ifdef CONFIG_BLK_DEV_FD<BR ID=o.yk>	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { <FONT COLOR=#0000ff ID=tk2w>/*需要floppy的,跳过...*/</FONT><BR ID=szha>        }<BR ID=ioi1>#endif<BR ID=gxhh>        ......... <FONT COLOR=#0000ff ID=q6ni>/*通过devfs查找root dev,不看...现在都sysfs+udev了..*/</FONT><BR ID=kzyx><BR ID=lx8m>	/* <FONT COLOR=#0000ff ID=x:bx>那么谁能设置ROOT_DEV这个全局变量呢..</FONT>就是:<FONT COLOR=#38761d ID=b:53><SPAN ID=b70.><b>initrd_load</b></SPAN></FONT> */<BR ID=zah:>	if (!ROOT_DEV)<BR ID=q6ed>		panic("I have no root and I want to scream");<BR ID=d24y>       <FONT COLOR=#0000ff ID=w9:f> <FONT COLOR=#ff0000 ID=yivr>/*2.4里处理initrd比较特殊:直接模拟open,mount来安装rootfs, 2.6可以直接使用open和mount*/<BR ID=ub:2>    <FONT COLOR=#0000ff ID=r3l:>    /*step1: 避开文件系统的open,打开dev设备*/</FONT><BR ID=simi></FONT></FONT>	bdev = <FONT COLOR=#38761d ID=t2wg><SPAN ID=pywf><b>bdget</b></SPAN></FONT>(kdev_t_to_nr(ROOT_DEV)); <FONT COLOR=#0000ff ID=xkki>/*分配bdev结构*/</FONT><BR ID=ptb0>	if (!bdev)<BR ID=qdvm>		panic(__FUNCTION__ ": unable to allocate root device");<BR ID=i9gs>	bdev-&gt;bd_op = <FONT COLOR=#38761d ID=v5rp><SPAN ID=js4v><b>devfs_get_ops</b></SPAN></FONT> (handle); <FONT COLOR=#0000ff ID=as1x>/*获取bd_ops, 这里是rd.c,ramdisk的blk dev*/</FONT><BR ID=n6vo>        ... <FONT COLOR=#0000ff ID=hbbo>/*devpts*/</FONT><BR ID=lv0c>       &nbsp;mode = FMODE_READ;<BR ID=f-3h>	if (!(root_mountflags &amp; MS_RDONLY))<BR ID=j87f>		mode |= FMODE_WRITE;<BR ID=iaoi>	retval = <FONT COLOR=#38761d ID=znj6><b>blkdev_get</b></FONT>(bdev, mode, 0, BDEV_FS); <FONT COLOR=#0000ff ID=szrf>/*be_ops-&gt;open*/<BR ID=q.5h>        ....<BR ID=ox1r></FONT>	if (retval) { <FONT COLOR=#0000ff ID=qlgv>/*error process*/</FONT><BR ID=b9a->	   ....<BR ID=mj4v>	}<BR ID=p9qh>	check_disk_change(ROOT_DEV);<BR ID=sjc7>	sb = get_super(ROOT_DEV);<FONT COLOR=#0000ff ID=yyss> /*看看是否已经安装, initrd不会的....*/</FONT><BR ID=z-gi>	if (sb) {<BR ID=k:vk>		fs_type = sb-&gt;s_type;<BR ID=o5jo>		goto mount_it;<BR ID=gpf.>	}<BR ID=s2w0>       <FONT COLOR=#0000ff ID=ndzk> /*尝试所有文件系统,看看能否支持initrd*/</FONT><BR ID=bkw7>	read_lock(&amp;file_systems_lock);<BR ID=ifma>	for (fs_type = <FONT COLOR=#990000 ID=fdpq><b>file_systems</b></FONT> ; fs_type ; fs_type = fs_type-&gt;next) {<BR ID=v_4k>  	         .... /*sanity check*/<BR ID=jdn_>  		sb = <FONT COLOR=#38761d ID=d9uk><SPAN ID=u.mu><b>read_super</b></SPAN></FONT>(ROOT_DEV,bdev,fs_type,root_mountflags,NULL,1);<BR ID=kn11>		if (sb) <FONT COLOR=#0000ff ID=gtmg>/*got ...*/</FONT><BR ID=pd:e>			goto mount_it;<BR ID=vz3z>		.....<BR ID=dd9x>	}<BR ID=nsmc>        .....<BR ID=zmak>mount_it:<BR ID=zp_u>	... <FONT COLOR=#0000ff ID=q3w1>/*devpts处理略...*/</FONT><BR ID=t24-><BR ID=rbix>	vfsmnt = add_vfsmnt(NULL, sb-&gt;s_root, "/dev/root"); <FONT COLOR=#0000ff ID=uwv1>/*安装.... 注:/dev/root只是个名字,没有pathwalk*/</FONT><BR ID=stwt>	/* FIXME: if something will try to umount us right now... */<BR ID=je:f>	if (vfsmnt) { <FONT COLOR=#0000ff ID=urcs>/*更新init进程的root和pwd*/</FONT><BR ID=j_7l>		set_fs_root(current-&gt;fs, vfsmnt, sb-&gt;s_root);<BR ID=hj6d>		set_fs_pwd(current-&gt;fs, vfsmnt, sb-&gt;s_root);<BR ID=krfi>        ....<BR ID=t9ep>}<BR ID=v.7t><BR ID=l850><FONT COLOR=#0000ff ID=h8oc>下面看看initrd的load: (就不详细看了,只看看ROOT_DEV的设置过程吧...)</FONT><BR ID=p2jn>/*<BR ID=ef22> * This routine loads in the RAM disk image.<BR ID=d0y4> */<BR ID=mutz>static void __init <FONT COLOR=#274e13 ID=fp48><SPAN ID=kxz4><b>rd_load_image</b></SPAN></FONT>(kdev_t device, int offset, int unit)<BR ID=cqrh>{<BR ID=vkxs> 	ram_device = MKDEV(MAJOR_NR, unit);<BR ID=nl_0>        /<FONT COLOR=#0000ff ID=xc2l>*模拟文件创建过程:open infile(initrd),outfile*/</FONT><BR ID=c0es>	if ((inode = get_empty_inode()) == NULL) <BR ID=dphl>		return;<BR ID=faxo>	memset(&amp;infile, 0, sizeof(infile));<BR ID=a2kr>	memset(&amp;in_dentry, 0, sizeof(in_dentry));<BR ID=yctd>	infile.f_mode = 1; /* read only */<BR ID=qk4z>	infile.f_dentry = &amp;in_dentry;<BR ID=c0ev>	in_dentry.d_inode = inode;<BR ID=ow13>	infile.f_op = &amp;<FONT COLOR=#990000 ID=ye8c><SPAN ID=gfg_><b>def_blk_fops</b></SPAN></FONT>; <FONT COLOR=#cc0000 ID=hjd.>/*blkdev是ramdisk*/</FONT><BR ID=jk_i>	<FONT COLOR=#274e13 ID=q17d><SPAN ID=t:k_><b>init_special_inode</b></SPAN></FONT>(inode, S_IFBLK | S_IRUSR, kdev_t_to_nr(device));<FONT COLOR=#ff0000 ID=fxmd> /*file: ramdisk dev [1,250]*/</FONT><BR ID=vmw_>        ..  <FONT COLOR=#ff0000 ID=rnz5>/*outfile: ramdiks dev [1,0],即/dev/ram*/<BR ID=ch-j></FONT><BR ID=qwym><FONT COLOR=#ff0000 ID=kbt->       /*打开设备*/</FONT><BR ID=hi_:>      &nbsp;if (<FONT COLOR=#38761d ID=k-os><SPAN ID=af.1><b>blkdev_open</b></SPAN></FONT>(inode, &amp;infile) != 0) <FONT COLOR=#990000 ID=fnxp><SPAN ID=fpl4><b>/*rd_open :filp-&gt;f_op = &amp;initrd_fops :</b></SPAN></FONT><FONT COLOR=#274e13 ID=up_w><b>initrd_read</b></FONT>*/<BR ID=n0ow>		goto free_inode;<BR ID=uikb>	if (blkdev_open(out_inode, &amp;outfile) != 0) <FONT COLOR=#38761d ID=o8no><b>/*这个就是是def_blk_fops了*/</b></FONT><BR ID=p-yv>		goto free_inodes;<BR ID=owod>        ...<BR ID=z-3m>      &nbsp; nblocks = <FONT COLOR=#38761d ID=tfw_><SPAN ID=wy7x><b>identify_ramdisk_image</b></SPAN></FONT>(device, &amp;infile, offset); <FONT COLOR=#0000ff ID=mhg4>/*看看initrd有多少block*/</FONT><BR ID=ol1c>	if (nblocks &lt; 0)<BR ID=kr_x>		goto done;<BR ID=h.tw>        .....<FONT COLOR=#0000ff ID=ycn2> /*sanity check*/</FONT><BR ID=q9rr>	<BR ID=slho>	for (i=0; i &lt; nblocks; i++) {<BR ID=pfx3>		if (i &amp;&amp; (i % devblocks == 0)) {<BR ID=j.5d>			printk("done disk #%d.\n", i/devblocks);<BR ID=a7gd>			......<BR ID=k31.>			printk("Loading disk #%d... ", i/devblocks+1);<BR ID=ed-v>		}<BR ID=a9hb>		infile.f_op-&gt;<FONT COLOR=#38761d ID=inrm><SPAN ID=v0u-><b>read</b></SPAN></FONT>(&amp;infile, buf, BLOCK_SIZE, &amp;infile.f_pos); /*从[1,250]copy到[1,0]*/<BR ID=k95r>		outfile.f_op-&gt;<FONT COLOR=#38761d ID=mj:q><SPAN ID=y-l6><b>write</b></SPAN></FONT>(&amp;outfile, buf, BLOCK_SIZE, &amp;outfile.f_pos);<BR ID=um2r>         ...... <BR ID=vu5y>	}<BR ID=sfax>	....<BR ID=xmuz>}<BR ID=nlc2>这里明了了initrd如何进入一个ramdisk...<BR ID=b2oa></PRE>
        <HR ID=a3j. STYLE="WIDTH:100%; HEIGHT:4px; FONT-WEIGHT:bold">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=su_o SIZE=4><b>change root</b></FONT><BR ID=c6qj><BR ID=eond>int __init <FONT COLOR=#0b5394 ID=zzz-><SPAN ID=uq.2><b>change_root</b></SPAN></FONT>(kdev_t new_root_dev,const char *put_old)<BR ID=lli9>{<BR ID=g45f><FONT COLOR=#0000ff ID=k:g7>/*将root 安装到new_root_dev,然后将现有的root 放到新安装的root文件系统的 put_old*/<BR ID=mtpd>        ...<BR ID=fe9u></FONT>	read_lock(&amp;current-&gt;fs-&gt;lock);<BR ID=dbew>	old_rootmnt = <FONT COLOR=#38761d ID=lstu><SPAN ID=g:8d><b>mntget</b></SPAN></FONT>(current-&gt;fs-&gt;rootmnt); <FONT COLOR=#0000ff ID=gjim>/*保存老的root mnt*/</FONT><BR ID=yvwa>	read_unlock(&amp;current-&gt;fs-&gt;lock);<BR ID=ewgo>	<FONT COLOR=#0000ff ID=jt4v>/* devfs 处理略.*/</FONT><BR ID=nc2k>	<FONT COLOR=#990000 ID=dkh9><SPAN ID=ccvj><b>ROOT_DEV</b></SPAN></FONT> = new_root_dev; <FONT COLOR=#0000ff ID=z5b8>/*安装新的root*/</FONT><BR ID=qhic>	mount_root();  <BR ID=maue>#if 1<BR ID=xhs_>	shrink_dcache();<FONT COLOR=#0000ff ID=lad_> /*将老的decahe 清除...*/</FONT><BR ID=iy83>#endif<BR ID=ccjr>	<FONT COLOR=#0000ff ID=tpfn>/*devfs略*/</FONT><BR ID=vjw1>	<FONT COLOR=#0000ff ID=ho3w>/*找找新文件系统的put_old目录*/</FONT><BR ID=o4-l>	if (path_init(put_old, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &amp;nd))<BR ID=c-5t>		error = path_walk(put_old, &amp;nd);<BR ID=a4mj>	if (error) {.....<BR ID=fl0c>	}<BR ID=fz_3>	/* FIXME: we should hold i_zombie on nd.dentry */<BR ID=knnw>	move_vfsmnt(old_rootmnt, nd.dentry, nd.mnt, "/dev/root.old"); /*"/dev/root.ol"只是名字...*/<BR ID=w66q>	.....<BR ID=wcvh>}<BR ID=pthl><BR ID=t99g><BR ID=l5sw>static void <FONT COLOR=#38761d ID=f_ir><SPAN ID=c:ia><b>move_vfsmnt</b></SPAN></FONT>(struct vfsmount *mnt,<BR ID=u85c>			struct dentry *mountpoint,<BR ID=jl.r>			struct vfsmount *parent,<BR ID=u8i9>			const char *dev_name)<BR ID=ib:a>{  /*把mnt从老的的安装点摘除,放到新的mount point*/<BR ID=h456>	.....<BR ID=r2nt>	spin_lock(&amp;dcache_lock);<BR ID=fq55>	old_mountpoint = mnt-&gt;mnt_mountpoint;<BR ID=dq4j>	old_parent = mnt-&gt;mnt_parent;<BR ID=uckj>        ...<FONT COLOR=#0000ff ID=quae>//copy name</FONT><BR ID=sa:g>	/* flip the linkage */<BR ID=zv0y>	mnt-&gt;mnt_mountpoint = dget(mountpoint);<BR ID=pcfw>	mnt-&gt;mnt_parent = parent ? mntget(parent) : mnt;<BR ID=pv.d>	list_del(&amp;mnt-&gt;mnt_clash); <FONT COLOR=#38761d ID=s65f>/*把oldmnt从老安装点dentry的(链表)摘除*/</FONT><BR ID=vzz0>	list_del(&amp;mnt-&gt;mnt_child);  <FONT COLOR=#38761d ID=ht0b>/*从mnt tree摘除*/</FONT><BR ID=i9jl>	if (parent) { <FONT COLOR=#ff0000 ID=t51c>/*设置新的链表*/</FONT><BR ID=mpjt>		list_add(&amp;mnt-&gt;mnt_child, &amp;parent-&gt;mnt_mounts);<BR ID=pm59>		list_add(&amp;mnt-&gt;mnt_clash, &amp;mountpoint-&gt;d_vfsmnt);<BR ID=bfqf>	} else {<BR ID=lp19>		INIT_LIST_HEAD(&amp;mnt-&gt;mnt_child);<BR ID=ubx_>		INIT_LIST_HEAD(&amp;mnt-&gt;mnt_clash);<BR ID=t3cg>	}<BR ID=fy3a>	spin_unlock(&amp;dcache_lock);<BR ID=klan>	<FONT COLOR=#0000ff ID=zy11>/* put the old stuff */<BR ID=gq.j>        ... /*减引用计数*/</FONT><BR ID=s3km>}<BR ID=wzp7></PRE>
        <HR ID=v07b STYLE="WIDTH:100%; HEIGHT:2px">
        <PRE ID=vvtc><FONT COLOR=#0b5394 ID=uz6- SIZE=4><SPAN ID=e.j8><b>给用户使用的change root: pivot root </b></SPAN></FONT>(翻译成旋转?)<BR ID=gmln><FONT COLOR=#0000ff ID=lzrm><BR ID=kvff>/*<BR ID=qnz4> * 比如吧现在的/mnt/hda1这个安装点设置成新的根目录, 吧现在的'/'放到/mnt/hda1/mnt/old.</FONT><BR ID=w4yt> * <FONT COLOR=#990000 ID=t:2h>注意了:这两个目录都要求不能在老的根文件系统内...</FONT><BR ID=oui2> */<BR ID=naz0>为了好理解,奉图一张...<BR ID=xt9s><DIV ID=lflz STYLE="PADDING:1em 0pt; TEXT-ALIGN:left"><IMG ID=fzwq SRC=_2_4_054_fs_super_c_images/dcbsxfpf_218g6q2qfcj_b.jpg STYLE="WIDTH:530px; HEIGHT:484px"></DIV><BR ID=ajn3>asmlinkage long <FONT COLOR=#0b5394 ID=ar1f><SPAN ID=w-iw><b>sys_pivot_root</b></SPAN></FONT>(const char *new_root, const char *put_old)<BR ID=hglv>{<BR ID=jv0y>         .... <FONT COLOR=#0000ff ID=m900>/*权限检查, sanity check, old name,new_root的path walk*/</FONT><BR ID=m-sd><BR ID=u6tg>	read_lock(&amp;current-&gt;fs-&gt;lock);<BR ID=z-xa>	<SPAN ID=uwcr><b>root_mnt</b></SPAN> = mntget(current-&gt;fs-&gt;rootmnt);<BR ID=lrzd>	<SPAN ID=tf1e><b>root </b></SPAN>= dget(current-&gt;fs-&gt;root);<BR ID=hw6l>	read_unlock(&amp;current-&gt;fs-&gt;lock);<BR ID=kf8:>	..... <FONT COLOR=#3d85c6 ID=r8mw>/*sanity check*/</FONT><BR ID=yn_6>	if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt) <FONT COLOR=#0000ff ID=i5y6><SPAN ID=b4hs><b>/*new_root 和old_nd 等于rootmnd? 看上图即可明了*/</b></SPAN></FONT><BR ID=gs_6>		goto out2; /* loop */<BR ID=sd2x>	error = -EINVAL;<BR ID=fatz>	tmp = old_nd.mnt;<FONT COLOR=#0000ff ID=hset> /* 检查从new root 是否能找的到put old */</FONT><BR ID=lk8q>	spin_lock(&amp;dcache_lock);<BR ID=jmor>	if (tmp != new_nd.mnt) {<BR ID=v4e4>		for (;;) {<BR ID=gi4j>			if (tmp-&gt;mnt_parent == tmp)<BR ID=jyrw>				goto out3;<BR ID=pg6s>			if (tmp-&gt;mnt_parent == new_nd.mnt) <FONT COLOR=#0000ff ID=mh0o>/*从put old的nnt parent可以到达new root即可*/</FONT><BR ID=z8oa>				break;<BR ID=k_bj>			tmp = tmp-&gt;mnt_parent;<BR ID=mt.b>		}<BR ID=z9:7>		if (!is_subdir(tmp-&gt;mnt_mountpoint, new_nd.dentry))<BR ID=fxw->			goto out3;<BR ID=oh.0>	} else if (!is_subdir(old_nd.dentry, new_nd.dentry))<BR ID=kxcl>		goto out3;<BR ID=izcu>	spin_unlock(&amp;dcache_lock);<BR ID=wjn2><BR ID=ayhd>	<FONT COLOR=#38761d ID=j8it><SPAN ID=h0q3><b>move_vfsmnt</b></SPAN></FONT>(new_nd.mnt, new_nd.dentry, NULL, NULL); /<FONT COLOR=#ff0000 ID=sttc>*升级new root, parent为0*/</FONT><BR ID=tdt1>	<FONT COLOR=#38761d ID=cz9d><SPAN ID=l7yw><b>move_vfsmnt</b></SPAN></FONT>(root_mnt, old_nd.dentry, old_nd.mnt, NULL); <FONT COLOR=#990000 ID=oszi>/*把当前root安装到put_old*/</FONT><BR ID=nhv0>	chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt); <FONT COLOR=#0000ff ID=jjc->/*更改所有进程的fs/pwd等*/</FONT><BR ID=jixq>	error = 0;<BR ID=n3m3>        .....  <FONT COLOR=#0000ff ID=wue3>/*出错处理*/</FONT><BR ID=ak7.>	<BR ID=okjd>}<BR ID=wq1q><BR ID=i.ox><BR ID=l316><BR ID=y35r></PRE>
      </TD>
    </TR>
    </TBODY>
  </TABLE>
</DIV></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -