diff options
| -rw-r--r-- | fs/nfs/direct.c | 91 |
1 files changed, 41 insertions, 50 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index f8b0a81c340e..cbfbd17eae85 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
| @@ -898,40 +898,6 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
| 898 | return 0; | 898 | return 0; |
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | ||
| 902 | unsigned long nr_segs, loff_t pos, | ||
| 903 | size_t count, bool uio) | ||
| 904 | { | ||
| 905 | ssize_t result = -ENOMEM; | ||
| 906 | struct inode *inode = iocb->ki_filp->f_mapping->host; | ||
| 907 | struct nfs_direct_req *dreq; | ||
| 908 | struct nfs_lock_context *l_ctx; | ||
| 909 | |||
| 910 | dreq = nfs_direct_req_alloc(); | ||
| 911 | if (!dreq) | ||
| 912 | goto out; | ||
| 913 | |||
| 914 | dreq->inode = inode; | ||
| 915 | dreq->bytes_left = count; | ||
| 916 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | ||
| 917 | l_ctx = nfs_get_lock_context(dreq->ctx); | ||
| 918 | if (IS_ERR(l_ctx)) { | ||
| 919 | result = PTR_ERR(l_ctx); | ||
| 920 | goto out_release; | ||
| 921 | } | ||
| 922 | dreq->l_ctx = l_ctx; | ||
| 923 | if (!is_sync_kiocb(iocb)) | ||
| 924 | dreq->iocb = iocb; | ||
| 925 | |||
| 926 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio); | ||
| 927 | if (!result) | ||
| 928 | result = nfs_direct_wait(dreq); | ||
| 929 | out_release: | ||
| 930 | nfs_direct_req_release(dreq); | ||
| 931 | out: | ||
| 932 | return result; | ||
| 933 | } | ||
| 934 | |||
| 935 | /** | 901 | /** |
| 936 | * nfs_file_direct_write - file direct write operation for NFS files | 902 | * nfs_file_direct_write - file direct write operation for NFS files |
| 937 | * @iocb: target I/O control block | 903 | * @iocb: target I/O control block |
| @@ -957,9 +923,12 @@ out: | |||
| 957 | ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | 923 | ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, |
| 958 | unsigned long nr_segs, loff_t pos, bool uio) | 924 | unsigned long nr_segs, loff_t pos, bool uio) |
| 959 | { | 925 | { |
| 960 | ssize_t retval = -EINVAL; | 926 | ssize_t result = -EINVAL; |
| 961 | struct file *file = iocb->ki_filp; | 927 | struct file *file = iocb->ki_filp; |
| 962 | struct address_space *mapping = file->f_mapping; | 928 | struct address_space *mapping = file->f_mapping; |
| 929 | struct inode *inode = mapping->host; | ||
| 930 | struct nfs_direct_req *dreq; | ||
| 931 | struct nfs_lock_context *l_ctx; | ||
| 963 | size_t count; | 932 | size_t count; |
| 964 | 933 | ||
| 965 | count = iov_length(iov, nr_segs); | 934 | count = iov_length(iov, nr_segs); |
| @@ -968,35 +937,57 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 968 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", | 937 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", |
| 969 | file, count, (long long) pos); | 938 | file, count, (long long) pos); |
| 970 | 939 | ||
| 971 | retval = generic_write_checks(file, &pos, &count, 0); | 940 | result = generic_write_checks(file, &pos, &count, 0); |
| 972 | if (retval) | 941 | if (result) |
| 973 | goto out; | 942 | goto out; |
| 974 | 943 | ||
| 975 | retval = -EINVAL; | 944 | result = -EINVAL; |
| 976 | if ((ssize_t) count < 0) | 945 | if ((ssize_t) count < 0) |
| 977 | goto out; | 946 | goto out; |
| 978 | retval = 0; | 947 | result = 0; |
| 979 | if (!count) | 948 | if (!count) |
| 980 | goto out; | 949 | goto out; |
| 981 | 950 | ||
| 982 | retval = nfs_sync_mapping(mapping); | 951 | result = nfs_sync_mapping(mapping); |
| 983 | if (retval) | 952 | if (result) |
| 984 | goto out; | 953 | goto out; |
| 985 | 954 | ||
| 986 | task_io_account_write(count); | 955 | task_io_account_write(count); |
| 987 | 956 | ||
| 988 | retval = nfs_direct_write(iocb, iov, nr_segs, pos, count, uio); | 957 | result = -ENOMEM; |
| 989 | if (retval > 0) { | 958 | dreq = nfs_direct_req_alloc(); |
| 990 | struct inode *inode = mapping->host; | 959 | if (!dreq) |
| 960 | goto out; | ||
| 991 | 961 | ||
| 992 | iocb->ki_pos = pos + retval; | 962 | dreq->inode = inode; |
| 993 | spin_lock(&inode->i_lock); | 963 | dreq->bytes_left = count; |
| 994 | if (i_size_read(inode) < iocb->ki_pos) | 964 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
| 995 | i_size_write(inode, iocb->ki_pos); | 965 | l_ctx = nfs_get_lock_context(dreq->ctx); |
| 996 | spin_unlock(&inode->i_lock); | 966 | if (IS_ERR(l_ctx)) { |
| 967 | result = PTR_ERR(l_ctx); | ||
| 968 | goto out_release; | ||
| 969 | } | ||
| 970 | dreq->l_ctx = l_ctx; | ||
| 971 | if (!is_sync_kiocb(iocb)) | ||
| 972 | dreq->iocb = iocb; | ||
| 973 | |||
| 974 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio); | ||
| 975 | if (!result) { | ||
| 976 | result = nfs_direct_wait(dreq); | ||
| 977 | if (result > 0) { | ||
| 978 | struct inode *inode = mapping->host; | ||
| 979 | |||
| 980 | iocb->ki_pos = pos + result; | ||
| 981 | spin_lock(&inode->i_lock); | ||
| 982 | if (i_size_read(inode) < iocb->ki_pos) | ||
| 983 | i_size_write(inode, iocb->ki_pos); | ||
| 984 | spin_unlock(&inode->i_lock); | ||
| 985 | } | ||
| 997 | } | 986 | } |
| 987 | out_release: | ||
| 988 | nfs_direct_req_release(dreq); | ||
| 998 | out: | 989 | out: |
| 999 | return retval; | 990 | return result; |
| 1000 | } | 991 | } |
| 1001 | 992 | ||
| 1002 | /** | 993 | /** |
