aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c53
1 files changed, 22 insertions, 31 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c120b48ec305..f0a6d88d7fff 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -886,7 +886,7 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
886 struct splice_desc *sd) 886 struct splice_desc *sd)
887{ 887{
888 struct svc_rqst *rqstp = sd->u.data; 888 struct svc_rqst *rqstp = sd->u.data;
889 struct page **pp = rqstp->rq_respages + rqstp->rq_resused; 889 struct page **pp = rqstp->rq_next_page;
890 struct page *page = buf->page; 890 struct page *page = buf->page;
891 size_t size; 891 size_t size;
892 892
@@ -894,17 +894,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
894 894
895 if (rqstp->rq_res.page_len == 0) { 895 if (rqstp->rq_res.page_len == 0) {
896 get_page(page); 896 get_page(page);
897 put_page(*pp); 897 put_page(*rqstp->rq_next_page);
898 *pp = page; 898 *(rqstp->rq_next_page++) = page;
899 rqstp->rq_resused++;
900 rqstp->rq_res.page_base = buf->offset; 899 rqstp->rq_res.page_base = buf->offset;
901 rqstp->rq_res.page_len = size; 900 rqstp->rq_res.page_len = size;
902 } else if (page != pp[-1]) { 901 } else if (page != pp[-1]) {
903 get_page(page); 902 get_page(page);
904 if (*pp) 903 if (*rqstp->rq_next_page)
905 put_page(*pp); 904 put_page(*rqstp->rq_next_page);
906 *pp = page; 905 *(rqstp->rq_next_page++) = page;
907 rqstp->rq_resused++;
908 rqstp->rq_res.page_len += size; 906 rqstp->rq_res.page_len += size;
909 } else 907 } else
910 rqstp->rq_res.page_len += size; 908 rqstp->rq_res.page_len += size;
@@ -936,7 +934,8 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
936 .u.data = rqstp, 934 .u.data = rqstp,
937 }; 935 };
938 936
939 rqstp->rq_resused = 1; 937 WARN_ON_ONCE(rqstp->rq_next_page != rqstp->rq_respages + 1);
938 rqstp->rq_next_page = rqstp->rq_respages + 1;
940 host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); 939 host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
941 } else { 940 } else {
942 oldfs = get_fs(); 941 oldfs = get_fs();
@@ -1020,28 +1019,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1020 inode = dentry->d_inode; 1019 inode = dentry->d_inode;
1021 exp = fhp->fh_export; 1020 exp = fhp->fh_export;
1022 1021
1023 /*
1024 * Request sync writes if
1025 * - the sync export option has been set, or
1026 * - the client requested O_SYNC behavior (NFSv3 feature).
1027 * - The file system doesn't support fsync().
1028 * When NFSv2 gathered writes have been configured for this volume,
1029 * flushing the data to disk is handled separately below.
1030 */
1031 use_wgather = (rqstp->rq_vers == 2) && EX_WGATHER(exp); 1022 use_wgather = (rqstp->rq_vers == 2) && EX_WGATHER(exp);
1032 1023
1033 if (!file->f_op->fsync) {/* COMMIT3 cannot work */
1034 stable = 2;
1035 *stablep = 2; /* FILE_SYNC */
1036 }
1037
1038 if (!EX_ISSYNC(exp)) 1024 if (!EX_ISSYNC(exp))
1039 stable = 0; 1025 stable = 0;
1040 if (stable && !use_wgather) {
1041 spin_lock(&file->f_lock);
1042 file->f_flags |= O_SYNC;
1043 spin_unlock(&file->f_lock);
1044 }
1045 1026
1046 /* Write the data. */ 1027 /* Write the data. */
1047 oldfs = get_fs(); set_fs(KERNEL_DS); 1028 oldfs = get_fs(); set_fs(KERNEL_DS);
@@ -1057,8 +1038,12 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1057 if (inode->i_mode & (S_ISUID | S_ISGID)) 1038 if (inode->i_mode & (S_ISUID | S_ISGID))
1058 kill_suid(dentry); 1039 kill_suid(dentry);
1059 1040
1060 if (stable && use_wgather) 1041 if (stable) {
1061 host_err = wait_for_concurrent_writes(file); 1042 if (use_wgather)
1043 host_err = wait_for_concurrent_writes(file);
1044 else
1045 host_err = vfs_fsync_range(file, offset, offset+*cnt, 0);
1046 }
1062 1047
1063out_nfserr: 1048out_nfserr:
1064 dprintk("nfsd: write complete host_err=%d\n", host_err); 1049 dprintk("nfsd: write complete host_err=%d\n", host_err);
@@ -1485,13 +1470,19 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1485 case NFS3_CREATE_EXCLUSIVE: 1470 case NFS3_CREATE_EXCLUSIVE:
1486 if ( dchild->d_inode->i_mtime.tv_sec == v_mtime 1471 if ( dchild->d_inode->i_mtime.tv_sec == v_mtime
1487 && dchild->d_inode->i_atime.tv_sec == v_atime 1472 && dchild->d_inode->i_atime.tv_sec == v_atime
1488 && dchild->d_inode->i_size == 0 ) 1473 && dchild->d_inode->i_size == 0 ) {
1474 if (created)
1475 *created = 1;
1489 break; 1476 break;
1477 }
1490 case NFS4_CREATE_EXCLUSIVE4_1: 1478 case NFS4_CREATE_EXCLUSIVE4_1:
1491 if ( dchild->d_inode->i_mtime.tv_sec == v_mtime 1479 if ( dchild->d_inode->i_mtime.tv_sec == v_mtime
1492 && dchild->d_inode->i_atime.tv_sec == v_atime 1480 && dchild->d_inode->i_atime.tv_sec == v_atime
1493 && dchild->d_inode->i_size == 0 ) 1481 && dchild->d_inode->i_size == 0 ) {
1482 if (created)
1483 *created = 1;
1494 goto set_attr; 1484 goto set_attr;
1485 }
1495 /* fallthru */ 1486 /* fallthru */
1496 case NFS3_CREATE_GUARDED: 1487 case NFS3_CREATE_GUARDED:
1497 err = nfserr_exist; 1488 err = nfserr_exist;