From: Trond Myklebust Date: Mon, 1 Dec 2008 13:21:27 -0500 NFS: Accelerate reads on read/write files Try to schedule writeout of dirty pages asynchronously at the beginning of a read instead of calling nfs_wb_page() on each page as we try to read it. The result should normally be faster because we can write out the entire chunk of data at once by means of writepages(). Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 22 +++++++++++++++++----- 1 files changed, 17 insertions(+), 5 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d319b49..0669646 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -260,18 +260,25 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, struct inode * inode = dentry->d_inode; ssize_t result; size_t count = iov_length(iov, nr_segs); + loff_t end = pos + (loff_t)count; - if (iocb->ki_filp->f_flags & O_DIRECT) + if (iocb->ki_filp->f_flags & O_DIRECT) { + filemap_fdatawrite_range(iocb->ki_filp->f_mapping, pos, end); return nfs_file_direct_read(iocb, iov, nr_segs, pos); + } dprintk("NFS: read(%s/%s, %lu@%lu)\n", dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long) pos); result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); + if (result != 0) + goto out; nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count); - if (!result) - result = generic_file_aio_read(iocb, iov, nr_segs, pos); + /* Write back any outstanding data */ + filemap_fdatawrite_range(iocb->ki_filp->f_mapping, pos, end); + result = generic_file_aio_read(iocb, iov, nr_segs, pos); +out: return result; } @@ -282,6 +289,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; + loff_t end = *ppos + (loff_t)count; ssize_t res; dprintk("NFS: splice_read(%s/%s, %lu@%Lu)\n", @@ -289,8 +297,12 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, (unsigned long) count, (unsigned long long) *ppos); res = nfs_revalidate_mapping(inode, filp->f_mapping); - if (!res) - res = generic_file_splice_read(filp, ppos, pipe, count, flags); + if (res != 0) + goto out; + /* Write back any outstanding data */ + filemap_fdatawrite_range(filp->f_mapping, *ppos, end); + res = generic_file_splice_read(filp, ppos, pipe, count, flags); +out: return res; }