diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f5fdd39e037a..8d965bddb87e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -24,9 +24,9 @@ | |||
24 | #include <linux/nfs_fs.h> | 24 | #include <linux/nfs_fs.h> |
25 | #include <linux/nfs_mount.h> | 25 | #include <linux/nfs_mount.h> |
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/slab.h> | ||
28 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
29 | #include <linux/aio.h> | 28 | #include <linux/aio.h> |
29 | #include <linux/gfp.h> | ||
30 | 30 | ||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <asm/system.h> | 32 | #include <asm/system.h> |
@@ -123,11 +123,11 @@ nfs_file_open(struct inode *inode, struct file *filp) | |||
123 | filp->f_path.dentry->d_parent->d_name.name, | 123 | filp->f_path.dentry->d_parent->d_name.name, |
124 | filp->f_path.dentry->d_name.name); | 124 | filp->f_path.dentry->d_name.name); |
125 | 125 | ||
126 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); | ||
126 | res = nfs_check_flags(filp->f_flags); | 127 | res = nfs_check_flags(filp->f_flags); |
127 | if (res) | 128 | if (res) |
128 | return res; | 129 | return res; |
129 | 130 | ||
130 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); | ||
131 | res = nfs_open(inode, filp); | 131 | res = nfs_open(inode, filp); |
132 | return res; | 132 | return res; |
133 | } | 133 | } |
@@ -237,9 +237,9 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
237 | dentry->d_parent->d_name.name, | 237 | dentry->d_parent->d_name.name, |
238 | dentry->d_name.name); | 238 | dentry->d_name.name); |
239 | 239 | ||
240 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); | ||
240 | if ((file->f_mode & FMODE_WRITE) == 0) | 241 | if ((file->f_mode & FMODE_WRITE) == 0) |
241 | return 0; | 242 | return 0; |
242 | nfs_inc_stats(inode, NFSIOS_VFSFLUSH); | ||
243 | 243 | ||
244 | /* Flush writes to the server and return any errors */ | 244 | /* Flush writes to the server and return any errors */ |
245 | return nfs_do_fsync(ctx, inode); | 245 | return nfs_do_fsync(ctx, inode); |
@@ -262,9 +262,11 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, | |||
262 | (unsigned long) count, (unsigned long) pos); | 262 | (unsigned long) count, (unsigned long) pos); |
263 | 263 | ||
264 | result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); | 264 | result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); |
265 | nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count); | 265 | if (!result) { |
266 | if (!result) | ||
267 | result = generic_file_aio_read(iocb, iov, nr_segs, pos); | 266 | result = generic_file_aio_read(iocb, iov, nr_segs, pos); |
267 | if (result > 0) | ||
268 | nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result); | ||
269 | } | ||
268 | return result; | 270 | return result; |
269 | } | 271 | } |
270 | 272 | ||
@@ -282,8 +284,11 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
282 | (unsigned long) count, (unsigned long long) *ppos); | 284 | (unsigned long) count, (unsigned long long) *ppos); |
283 | 285 | ||
284 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 286 | res = nfs_revalidate_mapping(inode, filp->f_mapping); |
285 | if (!res) | 287 | if (!res) { |
286 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); | 288 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); |
289 | if (res > 0) | ||
290 | nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, res); | ||
291 | } | ||
287 | return res; | 292 | return res; |
288 | } | 293 | } |
289 | 294 | ||
@@ -486,6 +491,9 @@ static int nfs_release_page(struct page *page, gfp_t gfp) | |||
486 | { | 491 | { |
487 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | 492 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); |
488 | 493 | ||
494 | /* Only do I/O if gfp is a superset of GFP_KERNEL */ | ||
495 | if ((gfp & GFP_KERNEL) == GFP_KERNEL) | ||
496 | nfs_wb_page(page->mapping->host, page); | ||
489 | /* If PagePrivate() is set, then the page is not freeable */ | 497 | /* If PagePrivate() is set, then the page is not freeable */ |
490 | if (PagePrivate(page)) | 498 | if (PagePrivate(page)) |
491 | return 0; | 499 | return 0; |
@@ -581,7 +589,7 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode) | |||
581 | { | 589 | { |
582 | struct nfs_open_context *ctx; | 590 | struct nfs_open_context *ctx; |
583 | 591 | ||
584 | if (IS_SYNC(inode) || (filp->f_flags & O_SYNC)) | 592 | if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC)) |
585 | return 1; | 593 | return 1; |
586 | ctx = nfs_file_open_context(filp); | 594 | ctx = nfs_file_open_context(filp); |
587 | if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) | 595 | if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) |
@@ -594,6 +602,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
594 | { | 602 | { |
595 | struct dentry * dentry = iocb->ki_filp->f_path.dentry; | 603 | struct dentry * dentry = iocb->ki_filp->f_path.dentry; |
596 | struct inode * inode = dentry->d_inode; | 604 | struct inode * inode = dentry->d_inode; |
605 | unsigned long written = 0; | ||
597 | ssize_t result; | 606 | ssize_t result; |
598 | size_t count = iov_length(iov, nr_segs); | 607 | size_t count = iov_length(iov, nr_segs); |
599 | 608 | ||
@@ -620,14 +629,18 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
620 | if (!count) | 629 | if (!count) |
621 | goto out; | 630 | goto out; |
622 | 631 | ||
623 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | ||
624 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); | 632 | result = generic_file_aio_write(iocb, iov, nr_segs, pos); |
625 | /* Return error values for O_SYNC and IS_SYNC() */ | 633 | if (result > 0) |
634 | written = result; | ||
635 | |||
636 | /* Return error values for O_DSYNC and IS_SYNC() */ | ||
626 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { | 637 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
627 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); | 638 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); |
628 | if (err < 0) | 639 | if (err < 0) |
629 | result = err; | 640 | result = err; |
630 | } | 641 | } |
642 | if (result > 0) | ||
643 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); | ||
631 | out: | 644 | out: |
632 | return result; | 645 | return result; |
633 | 646 | ||
@@ -642,6 +655,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
642 | { | 655 | { |
643 | struct dentry *dentry = filp->f_path.dentry; | 656 | struct dentry *dentry = filp->f_path.dentry; |
644 | struct inode *inode = dentry->d_inode; | 657 | struct inode *inode = dentry->d_inode; |
658 | unsigned long written = 0; | ||
645 | ssize_t ret; | 659 | ssize_t ret; |
646 | 660 | ||
647 | dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", | 661 | dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", |
@@ -652,14 +666,17 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
652 | * The combination of splice and an O_APPEND destination is disallowed. | 666 | * The combination of splice and an O_APPEND destination is disallowed. |
653 | */ | 667 | */ |
654 | 668 | ||
655 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | ||
656 | |||
657 | ret = generic_file_splice_write(pipe, filp, ppos, count, flags); | 669 | ret = generic_file_splice_write(pipe, filp, ppos, count, flags); |
670 | if (ret > 0) | ||
671 | written = ret; | ||
672 | |||
658 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | 673 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { |
659 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | 674 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); |
660 | if (err < 0) | 675 | if (err < 0) |
661 | ret = err; | 676 | ret = err; |
662 | } | 677 | } |
678 | if (ret > 0) | ||
679 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); | ||
663 | return ret; | 680 | return ret; |
664 | } | 681 | } |
665 | 682 | ||