入口函数
nfs3d_proc_readdir(): 完成对resp中相关字段的处理:fhp,count,buff等
然后调用nfsd_readdir(),函数返回后resp->count = resp->buff - argp->buff,这个说明了什么?
nfsd_readdir():打开要读取的文件,设置文件内偏移的指针(应该是由于RPC传输长度限制,需要多次读一个文件的原因),然后调用nfsd_buffered_readdir();
nfsd_buffered_readdir(这个是完成读操作的主要函数)
首先定义了两个变量:
struct readdir_data buf;
struct buffered_dirent *de
buf中包含一个char 指针以及长度和full标志;
struct buffered_dirent {
u64 ino;
loff_t offset;
int namlen;
unsigned int d_type;
char name[];
};
看上述的定义,可知其与单个dentry对应。
static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
struct readdir_cd *cdp, loff_t *offsetp)
{
struct readdir_data buf;
struct buffered_dirent *de;
int host_err;
int size;
loff_t offset;
buf.dirent = (void *)__get_free_page(GFP_KERNEL);
if (!buf.dirent)
return nfserrno(-ENOMEM);
offset = *offsetp;
while (1) {
struct inode *dir_inode = file->f_path.dentry->d_inode;
unsigned int reclen;
cdp->err = nfserr_eof; /* will be cleared on successful read */
buf.used = 0;
buf.full = 0;
host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf);
if (buf.full)
host_err = 0;
if (host_err < 0)
break;
size = buf.used;
if (!size)
break;
/*
* Various filldir functions may end up calling back into
* lookup_one_len() and the file system's ->lookup() method.
* These expect i_mutex to be held, as it would within readdir.
*/
host_err = mutex_lock_killable(&dir_inode->i_mutex);
if (host_err)
break;
de = (struct buffered_dirent *)buf.dirent;
while (size > 0) {
offset = de->offset;
if (func(cdp, de->name, de->namlen, de->offset,
de->ino, de->d_type))
break;
if (cdp->err != nfs_ok)
break;
= ALIGN(sizeof(*de) + de->namlen,
sizeof(u64));
size -= reclen;
de = (struct buffered_dirent *)((char *)de + reclen);
}
mutex_unlock(&dir_inode->i_mutex);
if (size > 0) /* We bailed out early */
break;
offset = vfs_llseek(file, 0, SEEK_CUR);
}
free_page((unsigned long)(buf.dirent));
if (host_err)
return nfserrno(host_err);
*offsetp = offset;
return cdp->err;
}
函数 先申请一个内存页,然后每次循环调用 vfs_readdir,从下层(即VFS下层文件系统)读出每个dentry的内容,buffer的地址就是struct readdir_data buf
这里涉及到指针转换问题------把一个char* 型指针,转换成一个结构体的指针。
vfs_readdir读出dentry之后,使用while()循环把buff中的内容读出来,之后用上层传下来的func()函数,编码并存到别的地方中,根据人口函数推测是resp->buff。
这样就完成了整个流程。