diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 53 |
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 | ||
1063 | out_nfserr: | 1048 | out_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; |