1.nfs_writepages
nfs_file_write()是NFS系统中的写操作函数,这个函数将用户态缓冲区中的数据写入到内核态缓存页中。如果是同步写操作,则马上调用vfs_fsync()将缓存页中的数据刷新到服务器中。如果不是同步写操作,则客户端定期将缓存页中的数据刷新到服务器中。无论哪种情况,最终都需要调用address_space_operations结构中的writepages函数,NFS系统中这个函数是nfs_writepages(),这个函数的定义如下:
// 这是NFS文件系统中的writepages()函数.
// 将缓存中的数据刷新到NFS服务器中 wbc中记录了数据刷新范围
int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
struct inode *inode = mapping->host; // 找到文件索引节点
unsigned long *bitlock = &NFS_I(inode)->flags; // 一些标志位
struct nfs_pageio_descriptor pgio;
int err;
/* Stop dirtying of new pages while we sync */
// 等待标志位NFS_INO_FLUSHING复位,然后设置这个标志位. NFS_INO_FLUSHING表示正在刷新数据
err = wait_on_bit_lock(bitlock, NFS_INO_FLUSHING,
nfs_wait_bit_killable, TASK_KILLABLE);
if (err)
goto out_err;
nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); // 增加事件计数
// nfs_pageio_init_write() 初始化nfs_pageio_descriptor结构 步骤(1)
// 这个函数主要设置下面两个参数
// desc->pg_ops = nfs_pageio_write_ops
// desc->pg_completion_ops = nfs_async_write_completion_ops
NFS_PROTO(inode)->write_pageio_init(&pgio, inode, wb_priority(wbc), &nfs_async_write_completion_ops);
// mm/page-writeback.c
// write_cache_pages在缓存中查找脏页,对查找到的脏页执行函数nfs_writepages_callback
// pgio是传递给nfs_writepages_callback的参数
// nfs_writepages_callback()将查找到的符合条件的缓存页面添加到pgio中 步骤(2)
// 现在pgio中就包含了大量的缓存页,这些缓存页需要处理.所有的缓存页添加到链表pgio->pg_list中了.
err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
// 这个函数根据pgio中的数据创建了一个nfs_pgio_header结构以及若干个nfs_write_data结构
// 每个nfs_write_data结构发起一次WRITE请求,将缓存页中的数据写到服务器中
nfs_pageio_complete(&pgio); // 这个函数负责处理数据写请求 步骤(3)
// 数据刷新完毕,可以清除标志位NFS_INO_FLUSHING了,其他用户可以向服务器传输数据了
clear_bit_unlock(NFS_INO_FLUSHING, bitlock);
smp_mb__after_clear_bit();
wake_up_bit(bitlock, NFS_INO_FLUSHING); // 唤醒其他进程
if (err < 0)
goto out_err;
err = pgio.pg_error;
if (err < 0)
goto out_err;
return 0;
out_err:
return err;
}