📄 _2_4_050_fs_readdir_c.html
字号:
<html lang="zh-CN" xmlns:gdoc=""> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <style type="text/css">/* default css */table { font-size: 1em; line-height: inherit;}div, address, ol, ul, li, option, select { margin-top: 0px; margin-bottom: 0px;}p { margin: 0px;}body { margin: 0px; padding: 0px; font-family: Verdana, sans-serif; font-size: 10pt; background-color: #ffffff;}h6 { font-size: 10pt }h5 { font-size: 11pt }h4 { font-size: 12pt }h3 { font-size: 13pt }h2 { font-size: 14pt }h1 { font-size: 16pt }blockquote {padding: 10px; border: 1px #DDD dashed }a img {border: 0}div.google_header, div.google_footer { position: relative; margin-top: 1em; margin-bottom: 1em;}/* end default css */ /* default print css */ @media print { body { padding: 0; margin: 0; } div.google_header, div.google_footer { display: block; min-height: 0; border: none; } div.google_header { flow: static(header); } /* used to insert page numbers */ div.google_header::before, div.google_footer::before { position: absolute; top: 0; } div.google_footer { flow: static(footer); } /* always consider this element at the start of the doc */ div#google_footer { flow: static(footer, start); } span.google_pagenumber { content: counter(page); } span.google_pagecount { content: counter(pages); } } @page { @top { content: flow(header); } @bottom { content: flow(footer); } } /* end default print css */ /* custom css *//* end custom css */ /* ui edited css */ body { font-family: Verdana; font-size: 10.0pt; line-height: normal; background-color: #ffffff; } .documentBG { background-color: #ffffff; } /* end ui edited css */</style> </head> <body revision="dcbsxfpf_211fx8xtr7j:41"> <div align=center id=k65l>
<table align=center border=0 cellpadding=0 cellspacing=0 height=5716 id=ux-b width=800>
<tbody id=zkj6>
<tr id=vw.g>
<td height=5716 id=mt62 valign=top width=100%>
<pre id=hi_a>2008-4-22<br id=cz1p><br id=i-2_>fs/readdir.c<br id=g2jk><br id=tpu_>此文件很纯净,就是你ls的时候所调用的函数, 在 <a href=Doc?id=dcbsxfpf_60cr7cm55r id=hry_ title=UML>UML</a> 一文中已经讨论过这个文件,这里忽略64bit的处理,仅简单看看.<br id=cicv><br id=oh2o>int vfs_readdir(struct file *file, filldir_t filler, void *buf)<br id=xfkv>{<br id=nn.l> .....<br id=tdgw> if (!IS_DEADDIR(inode)) {<br id=rqwz> lock_kernel();<br id=fd:k> res = file->f_op->readdir(file, buf, filler); <span id=mo5- style=COLOR:#38761d>/*就是调用fop的readdir*/</span><br id=aiqy> unlock_kernel();<br id=a7ok> }<br id=gr4m> .....<br id=ya48> return res;<br id=lr.2>}<br id=g3d_><br id=y-3c>对于不同文件系统的readdir实现不同, 其中对于像shm fs,ramfs这种纯粹虚拟的文件系统,这里提供了一个统一的实现:<br id=hpu->int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)<br id=q-v.>{<br id=g19z> struct dentry *dentry = filp->f_dentry;<br id=a2z1> struct dentry *cursor = filp->private_data; <span id=jz-v style=COLOR:#0000ff>/*dcache_dir_open 将cursor 设置为dentry ''.''*/</span><br id=p3b7> <span id=bv9. style=COLOR:#0000ff> /* cursor d_child 挂入了filp->f_dentry->d_subdirs */</span><br id=dfnp> struct list_head *p, *q = &cursor->d_child; <br id=o7ia> ino_t ino;<br id=cq5i> int i = filp->f_pos;<br id=bggp><br id=zlu1> switch (i) {<br id=j7i1> .... /*. 和.. 处理,略*/<br id=tz.y> default:<br id=p.rz> spin_lock(&dcache_lock);<br id=tk2:> if (filp->f_pos == 2) { <span id=emxe style=COLOR:#0000ff>/* pos=2 意味从头开始 */</span><br id=alp1> list_del(q);<span id=fh_s style=COLOR:#0000ff>/*将cursor从f_dentry->d_subdirs 删除*/</span><br id=ewme> list_add(q, &dentry->d_subdirs);<span id=uv.x style=COLOR:#0000ff>/*又加回来,从而位于subdir之首*/</span><br id=v11m> }<br id=lr0z><br id=rzmy> <span id=o9j. style=COLOR:#0000ff>/*从cursor 的下一个subdir 开始*/</span><br id=fh8l> for (p=q->next; <span id=vg1: style=COLOR:#0000ff>p != &dentry->d_subdirs</span>; p=p->next) {<br id=kd-a> struct dentry *next;<br id=la:0> next = list_entry(p, struct dentry, d_child);<br id=xt4e> if (<span id=ybnu style=COLOR:#0000ff>d_unhashed(next) || !next->d_inode</span>) /*只有加入hash的dentry并且有inode(未删除)*/<br id=lxrj> continue; /*删除dentry可能还在hash中*/<br id=jl4_><br id=rrvg> spin_unlock(&dcache_lock);<br id=f5_9> if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, <br id=nqmm> next->d_inode->i_ino, dt_type(next->d_inode)) < 0)<br id=pesu> return 0;<br id=x3vz> spin_lock(&dcache_lock);<br id=q3xv> /* next is still alive */<br id=uj6g> list_del(q); <span id=x0qx style=COLOR:#0000ff>/*q 是cursor, 后移一个位置 */</span><br id=i5t_> list_add(q, p);<br id=bhbn> p = q; <span id=zm_b style=COLOR:#0000ff>/*从cursor 取下一个subdir*/</span><br id=v2ti> filp->f_pos++;<br id=podh> }<br id=txii> spin_unlock(&dcache_lock);<br id=w_w2> }<br id=c1a-> return 0;<br id=lo3e>}<br id=w.y_><br id=cedi>至于ext2的readdir操作就不多说了,不是很难.<br id=hq4.>static int ext2_readdir(struct file * filp,<br id=m9v2> void * dirent, filldir_t filldir)<br id=tjln>{<br id=mnh5> offset = filp->f_pos & (sb->s_blocksize - 1); <span id=saiw style=COLOR:#0000ff>/*计算文件pos在blk中的偏移*/</span><br id=bktr><br id=z:7q> while (!error && !stored && filp->f_pos < inode->i_size) { <br id=d7n9> <span id=ana4 style=COLOR:#ff0000>/*stored:如果已读取当前blk内的dentry,就不读下个blk的entry了.. 咋想的呢?*/</span><br id=nnur> blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb); /*计算blk no*/<br id=byg2> bh = ext2_bread (inode, blk, 0, &err); <span id=b4w2 style=COLOR:#0000ff>/*文件内blk到文件系统blk no的换算:ext自己的三级表...*/</span><br id=h9zh> if (!bh) { <span id=pbku style=COLOR:#0000ff>/*有个洞? ...有点问题,打印错误信息,继续*/</span><br id=l.jz> .....<br id=mtds> filp->f_pos += sb->s_blocksize - offset;<br id=fta.> continue;<br id=id9v> }<br id=k9nx> <span id=v.3m style=COLOR:#0000ff>/* Do the readahead :找找文件块到文件系统块的转换表,然后预读,不像ext2_bread是block的*/</span><br id=wr-t> .....<br id=zldw> <br id=pm18>revalidate:<br id=qkim> /*这个修改的侦测只对f_pos所在blk有效,有限的避免竞争情况下的不一致*/<br id=uton> if (filp->f_version != inode->i_version) { <span id=dy5w style=COLOR:#0000ff>/*f_version用于监视文件是否被修改过*/<br id=mvqv> /*不一样的情况下记录的f_ops可能是有问题的,再次从0到offset重新开始扫描下,停到有问题的块上..*/<br id=lp4r></span> for (i = 0; i < sb->s_blocksize && i < offset; ) {<br id=jot1> de = (struct ext2_dir_entry_2 *) <br id=ws10> (bh->b_data + i);<br id=b3w-> <span id=dywj style=COLOR:#0000ff>停到第一个有问题的entry上,</span><br id=ai59> }<br id=ud:j> ....<br id=ptpu> filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) <span id=h0rp style=COLOR:#0000ff>/*更新文件的f_ops*/</span><br id=obqr> | offset;<br id=g400> filp->f_version = inode->i_version; <br id=l3sn> }<br id=krzd> <br id=dtre> while (!error && filp->f_pos < inode->i_size <br id=lz:x> && offset < sb->s_blocksize) { <span id=vrrx style=COLOR:#0000ff>/*尝试读取此blk内所有目录项*/</span><br id=eovc> de = (struct ext2_dir_entry_2 *) (bh->b_data + offset);<br id=yds_> if (!ext2_check_dir_entry ("ext2_readdir", inode, de,<br id=o6-w> bh, offset)) {<br id=m3bs> <span id=sx6b style=COLOR:#0000ff>/*如果有问题,停止读取(ext2删除dentry时把前一个dentry的长度扩大,覆盖被删除的dentry*/</span><br id=y.5l style=COLOR:#0000ff><span id=ztae style=COLOR:#0000ff> .... /*跟新f_pos,返回*/</span><br id=f3fa> return stored;<br id=ttjt> }<br id=q5oa> offset += le16_to_cpu(de->rec_len);<br id=jemp> if (le32_to_cpu(de->inode)) {<br id=f7qk> /* copy 出去一个 */<br id=yxh7> /* 缓冲区满就返回了*/<br id=h.ce> if (version != filp->f_version) <span id=lz25 style=COLOR:#0000ff>/*竞争发生时重新validate*/</span><br id=tqeg> goto revalidate;<br id=gxxw> stored ++;<br id=a4ez> }<br id=cotf> filp->f_pos += le16_to_cpu(de->rec_len);<br id=yla:> }<br id=n_vq> offset = 0;<br id=n:pp> brelse (bh);<br id=lgi.> } //end while<br id=u1:i> UPDATE_ATIME(inode);<br id=ig:a> return 0;<br id=ffxn>}<br id=viyv><br id=y0c.></pre>
</td>
</tr>
</tbody>
</table>
</div></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -