diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index ec7e27d00bc6..0055b813ec2c 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -48,6 +48,9 @@ static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
48 | size_t count, unsigned int flags); | 48 | size_t count, unsigned int flags); |
49 | static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, | 49 | static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, |
50 | unsigned long nr_segs, loff_t pos); | 50 | unsigned long nr_segs, loff_t pos); |
51 | static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | ||
52 | struct file *filp, loff_t *ppos, | ||
53 | size_t count, unsigned int flags); | ||
51 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, | 54 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, |
52 | unsigned long nr_segs, loff_t pos); | 55 | unsigned long nr_segs, loff_t pos); |
53 | static int nfs_file_flush(struct file *, fl_owner_t id); | 56 | static int nfs_file_flush(struct file *, fl_owner_t id); |
@@ -73,6 +76,7 @@ const struct file_operations nfs_file_operations = { | |||
73 | .lock = nfs_lock, | 76 | .lock = nfs_lock, |
74 | .flock = nfs_flock, | 77 | .flock = nfs_flock, |
75 | .splice_read = nfs_file_splice_read, | 78 | .splice_read = nfs_file_splice_read, |
79 | .splice_write = nfs_file_splice_write, | ||
76 | .check_flags = nfs_check_flags, | 80 | .check_flags = nfs_check_flags, |
77 | .setlease = nfs_setlease, | 81 | .setlease = nfs_setlease, |
78 | }; | 82 | }; |
@@ -587,12 +591,38 @@ out_swapfile: | |||
587 | goto out; | 591 | goto out; |
588 | } | 592 | } |
589 | 593 | ||
594 | static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | ||
595 | struct file *filp, loff_t *ppos, | ||
596 | size_t count, unsigned int flags) | ||
597 | { | ||
598 | struct dentry *dentry = filp->f_path.dentry; | ||
599 | struct inode *inode = dentry->d_inode; | ||
600 | ssize_t ret; | ||
601 | |||
602 | dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", | ||
603 | dentry->d_parent->d_name.name, dentry->d_name.name, | ||
604 | (unsigned long) count, (unsigned long long) *ppos); | ||
605 | |||
606 | /* | ||
607 | * The combination of splice and an O_APPEND destination is disallowed. | ||
608 | */ | ||
609 | |||
610 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | ||
611 | |||
612 | ret = generic_file_splice_write(pipe, filp, ppos, count, flags); | ||
613 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | ||
614 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | ||
615 | if (err < 0) | ||
616 | ret = err; | ||
617 | } | ||
618 | return ret; | ||
619 | } | ||
620 | |||
590 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 621 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) |
591 | { | 622 | { |
592 | struct inode *inode = filp->f_mapping->host; | 623 | struct inode *inode = filp->f_mapping->host; |
593 | int status = 0; | 624 | int status = 0; |
594 | 625 | ||
595 | lock_kernel(); | ||
596 | /* Try local locking first */ | 626 | /* Try local locking first */ |
597 | posix_test_lock(filp, fl); | 627 | posix_test_lock(filp, fl); |
598 | if (fl->fl_type != F_UNLCK) { | 628 | if (fl->fl_type != F_UNLCK) { |
@@ -608,7 +638,6 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
608 | 638 | ||
609 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 639 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
610 | out: | 640 | out: |
611 | unlock_kernel(); | ||
612 | return status; | 641 | return status; |
613 | out_noconflict: | 642 | out_noconflict: |
614 | fl->fl_type = F_UNLCK; | 643 | fl->fl_type = F_UNLCK; |
@@ -650,13 +679,11 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | |||
650 | * If we're signalled while cleaning up locks on process exit, we | 679 | * If we're signalled while cleaning up locks on process exit, we |
651 | * still need to complete the unlock. | 680 | * still need to complete the unlock. |
652 | */ | 681 | */ |
653 | lock_kernel(); | ||
654 | /* Use local locking if mounted with "-onolock" */ | 682 | /* Use local locking if mounted with "-onolock" */ |
655 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 683 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) |
656 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 684 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
657 | else | 685 | else |
658 | status = do_vfs_lock(filp, fl); | 686 | status = do_vfs_lock(filp, fl); |
659 | unlock_kernel(); | ||
660 | return status; | 687 | return status; |
661 | } | 688 | } |
662 | 689 | ||
@@ -673,13 +700,11 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
673 | if (status != 0) | 700 | if (status != 0) |
674 | goto out; | 701 | goto out; |
675 | 702 | ||
676 | lock_kernel(); | ||
677 | /* Use local locking if mounted with "-onolock" */ | 703 | /* Use local locking if mounted with "-onolock" */ |
678 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 704 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) |
679 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 705 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
680 | else | 706 | else |
681 | status = do_vfs_lock(filp, fl); | 707 | status = do_vfs_lock(filp, fl); |
682 | unlock_kernel(); | ||
683 | if (status < 0) | 708 | if (status < 0) |
684 | goto out; | 709 | goto out; |
685 | /* | 710 | /* |