Linux应用程序通过read(2)读取文件中的数据,read(2)最终调用了文件系统的read函数。在NFS文件系统中,这个函数是do_sync_read(),这也是一个通用函数,调用了文件系统的aio_read()函数。NFS文件系统中的aio_read()是nfs_file_read()。
ssize_t
nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
// 找到文件的索引节点
struct dentry * dentry = iocb->ki_filp->f_path.dentry;
struct inode * inode = dentry->d_inode;
ssize_t result;
// 直接IO
if (iocb->ki_filp->f_flags & O_DIRECT)
return nfs_file_direct_read(iocb, iov, nr_segs, pos, true);
dprintk("NFS: read(%s/%s, %lu@%lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) iov_length(iov, nr_segs), (unsigned long) pos);
// 下面是普通IO
// 这个函数检查了本地缓存的文件属性。如果文件属性无效了就向服务器发起GETATTR请求
// 更新本地缓存的文件属性。
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
if (!result) {
// 现在就可以读数据了。如果缓存中的数据有效,就使用缓存中的数据;
// 否则就调用函数generic_file_aio_read()填充/更新缓存中的数据。
result = generic_file_aio_read(iocb, iov, nr_segs, pos);
if (result > 0)
// 这个函数更新了NFS系统统计信息,不是关键函数。
nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
}
return result; // 返回读取的数据量
}
nfs_file_read()是NFS系统中读取数据的函数,这个函数区分了直接IO和缓存IO。如果是直接直接IO就调用nfs_file_direct_read()&#