aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-02-01 14:17:41 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-02-10 08:31:04 -0500
commit7e381172cf6e0282a56374e50667515aed55166a (patch)
tree46d41f354f1bb58153b0bdbea883e7abe94ebddc
parentaa2f1ef10e6ad65c9138ec576f82c08f32e6f32c (diff)
NFS: Improve NFS iostat byte count accuracy for writes
The bytes counted by the performance counters for NFS writes should reflect write and sync errors. If the write(2) system call reports an error, the bytes should not be counted. And, if the write is short, the actual number of bytes that was written should be counted, not the number of bytes that was requested. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/file.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index abbc20281ea4..ae8d02294e46 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -601,6 +601,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
601{ 601{
602 struct dentry * dentry = iocb->ki_filp->f_path.dentry; 602 struct dentry * dentry = iocb->ki_filp->f_path.dentry;
603 struct inode * inode = dentry->d_inode; 603 struct inode * inode = dentry->d_inode;
604 unsigned long written = 0;
604 ssize_t result; 605 ssize_t result;
605 size_t count = iov_length(iov, nr_segs); 606 size_t count = iov_length(iov, nr_segs);
606 607
@@ -627,14 +628,18 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
627 if (!count) 628 if (!count)
628 goto out; 629 goto out;
629 630
630 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
631 result = generic_file_aio_write(iocb, iov, nr_segs, pos); 631 result = generic_file_aio_write(iocb, iov, nr_segs, pos);
632 if (result > 0)
633 written = result;
634
632 /* Return error values for O_DSYNC and IS_SYNC() */ 635 /* Return error values for O_DSYNC and IS_SYNC() */
633 if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { 636 if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
634 int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); 637 int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode);
635 if (err < 0) 638 if (err < 0)
636 result = err; 639 result = err;
637 } 640 }
641 if (result > 0)
642 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
638out: 643out:
639 return result; 644 return result;
640 645
@@ -649,6 +654,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
649{ 654{
650 struct dentry *dentry = filp->f_path.dentry; 655 struct dentry *dentry = filp->f_path.dentry;
651 struct inode *inode = dentry->d_inode; 656 struct inode *inode = dentry->d_inode;
657 unsigned long written = 0;
652 ssize_t ret; 658 ssize_t ret;
653 659
654 dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", 660 dprintk("NFS splice_write(%s/%s, %lu@%llu)\n",
@@ -659,14 +665,17 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
659 * The combination of splice and an O_APPEND destination is disallowed. 665 * The combination of splice and an O_APPEND destination is disallowed.
660 */ 666 */
661 667
662 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
663
664 ret = generic_file_splice_write(pipe, filp, ppos, count, flags); 668 ret = generic_file_splice_write(pipe, filp, ppos, count, flags);
669 if (ret > 0)
670 written = ret;
671
665 if (ret >= 0 && nfs_need_sync_write(filp, inode)) { 672 if (ret >= 0 && nfs_need_sync_write(filp, inode)) {
666 int err = nfs_do_fsync(nfs_file_open_context(filp), inode); 673 int err = nfs_do_fsync(nfs_file_open_context(filp), inode);
667 if (err < 0) 674 if (err < 0)
668 ret = err; 675 ret = err;
669 } 676 }
677 if (ret > 0)
678 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
670 return ret; 679 return ret;
671} 680}
672 681