上一篇文章中我们讲解了NFS文件系统中读操作的主要流程。如果缓存页中的数据有效,直接将缓存页中的数据拷贝到用户态缓冲区中。如果缓存页中的数据无效,则需要调用nfs_readpages()更新缓存页中的数据。nfs_readpages()完整定义如下:
// 这是NFS文件系统的readpages()函数
// pages是一个缓存页链表,nr_pages是链表中缓存页的数量
// 需要将链表中的缓存页添加到radix树中,然后从服务器中请求数据填充这些缓存页.
int nfs_readpages(struct file *filp, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
struct nfs_pageio_descriptor pgio;
struct nfs_readdesc desc = {
.pgio = &pgio,
};
struct inode *inode = mapping->host;
unsigned long npages;
int ret = -ESTALE;
dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
nr_pages);
nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
if (NFS_STALE(inode))
goto out;
// 步骤1 获取用户信息,发起READ请求时需要使用用户信息.
if (filp == NULL) {
desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
if (desc.ctx == NULL)
return -EBADF;
} else
desc.ctx = get_nfs_open_context(nfs_file_open_context(filp));
/* attempt to read as many of the pages as possible from the cache
* - this returns -ENOBUFS immediately if the cookie is negative
*/
// 步骤2 检查FS-Cache中的数据是否有效,如果有效就用FS-Cache中的数据填充缓存页,
// 不用向服务器发起READ请求了。
ret = nfs_readpages_from_fscache(desc.ctx, inode, mapping,
pages, &nr_pages);
if (ret == 0) // FS-Cache中的数据有效.
goto read_complete; /* all pages were read */
// 现在只能向服务器请求数据了
// 步骤3 初始化pgio
NFS_PROTO(inode)->read_pageio_init(&pgio, inode, &nfs_async_read_completion_ops);
// 步骤4 创建读请求
// 将链表中的缓存页添加到radix树中