diff options
-rw-r--r-- | Documentation/filesystems/nfs/nfs41-server.txt | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 24 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 20 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 1 |
4 files changed, 25 insertions, 24 deletions
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt index 392ef637e101..01c2db769791 100644 --- a/Documentation/filesystems/nfs/nfs41-server.txt +++ b/Documentation/filesystems/nfs/nfs41-server.txt | |||
@@ -190,7 +190,7 @@ Nonstandard compound limitations: | |||
190 | ca_maxrequestsize request and a ca_maxresponsesize reply, so we may | 190 | ca_maxrequestsize request and a ca_maxresponsesize reply, so we may |
191 | fail to live up to the promise we made in CREATE_SESSION fore channel | 191 | fail to live up to the promise we made in CREATE_SESSION fore channel |
192 | negotiation. | 192 | negotiation. |
193 | * No more than one IO operation (read, write, readdir) allowed per | 193 | * No more than one read-like operation allowed per compound; encoding |
194 | compound. | 194 | replies that cross page boundaries (except for read data) not handled. |
195 | 195 | ||
196 | See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues. | 196 | See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues. |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 1d2396b79574..87d24e5f3ca4 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -881,6 +881,24 @@ out: | |||
881 | return status; | 881 | return status; |
882 | } | 882 | } |
883 | 883 | ||
884 | static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write) | ||
885 | { | ||
886 | int i = 1; | ||
887 | int buflen = write->wr_buflen; | ||
888 | |||
889 | vec[0].iov_base = write->wr_head.iov_base; | ||
890 | vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len); | ||
891 | buflen -= vec[0].iov_len; | ||
892 | |||
893 | while (buflen) { | ||
894 | vec[i].iov_base = page_address(write->wr_pagelist[i - 1]); | ||
895 | vec[i].iov_len = min_t(int, PAGE_SIZE, buflen); | ||
896 | buflen -= vec[i].iov_len; | ||
897 | i++; | ||
898 | } | ||
899 | return i; | ||
900 | } | ||
901 | |||
884 | static __be32 | 902 | static __be32 |
885 | nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 903 | nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
886 | struct nfsd4_write *write) | 904 | struct nfsd4_write *write) |
@@ -889,6 +907,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
889 | struct file *filp = NULL; | 907 | struct file *filp = NULL; |
890 | __be32 status = nfs_ok; | 908 | __be32 status = nfs_ok; |
891 | unsigned long cnt; | 909 | unsigned long cnt; |
910 | int nvecs; | ||
892 | 911 | ||
893 | /* no need to check permission - this will be done in nfsd_write() */ | 912 | /* no need to check permission - this will be done in nfsd_write() */ |
894 | 913 | ||
@@ -911,8 +930,11 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
911 | write->wr_how_written = write->wr_stable_how; | 930 | write->wr_how_written = write->wr_stable_how; |
912 | gen_boot_verifier(&write->wr_verifier); | 931 | gen_boot_verifier(&write->wr_verifier); |
913 | 932 | ||
933 | nvecs = fill_in_write_vector(rqstp->rq_vec, write); | ||
934 | WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec)); | ||
935 | |||
914 | status = nfsd_write(rqstp, &cstate->current_fh, filp, | 936 | status = nfsd_write(rqstp, &cstate->current_fh, filp, |
915 | write->wr_offset, rqstp->rq_vec, write->wr_vlen, | 937 | write->wr_offset, rqstp->rq_vec, nvecs, |
916 | &cnt, &write->wr_how_written); | 938 | &cnt, &write->wr_how_written); |
917 | if (filp) | 939 | if (filp) |
918 | fput(filp); | 940 | fput(filp); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index cb9f9017af8f..09204f590355 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1139,24 +1139,6 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify | |||
1139 | DECODE_TAIL; | 1139 | DECODE_TAIL; |
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write) | ||
1143 | { | ||
1144 | int i = 1; | ||
1145 | int buflen = write->wr_buflen; | ||
1146 | |||
1147 | vec[0].iov_base = write->wr_head.iov_base; | ||
1148 | vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len); | ||
1149 | buflen -= vec[0].iov_len; | ||
1150 | |||
1151 | while (buflen) { | ||
1152 | vec[i].iov_base = page_address(write->wr_pagelist[i - 1]); | ||
1153 | vec[i].iov_len = min_t(int, PAGE_SIZE, buflen); | ||
1154 | buflen -= vec[i].iov_len; | ||
1155 | i++; | ||
1156 | } | ||
1157 | return i; | ||
1158 | } | ||
1159 | |||
1160 | static __be32 | 1142 | static __be32 |
1161 | nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) | 1143 | nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) |
1162 | { | 1144 | { |
@@ -1204,8 +1186,6 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) | |||
1204 | argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE); | 1186 | argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE); |
1205 | } | 1187 | } |
1206 | argp->p += XDR_QUADLEN(len); | 1188 | argp->p += XDR_QUADLEN(len); |
1207 | write->wr_vlen = fill_in_write_vector(argp->rqstp->rq_vec, write); | ||
1208 | WARN_ON_ONCE(write->wr_vlen > ARRAY_SIZE(argp->rqstp->rq_vec)); | ||
1209 | 1189 | ||
1210 | DECODE_TAIL; | 1190 | DECODE_TAIL; |
1211 | } | 1191 | } |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 152867b8125d..331f8a3277ab 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -385,7 +385,6 @@ struct nfsd4_write { | |||
385 | u64 wr_offset; /* request */ | 385 | u64 wr_offset; /* request */ |
386 | u32 wr_stable_how; /* request */ | 386 | u32 wr_stable_how; /* request */ |
387 | u32 wr_buflen; /* request */ | 387 | u32 wr_buflen; /* request */ |
388 | int wr_vlen; | ||
389 | struct kvec wr_head; | 388 | struct kvec wr_head; |
390 | struct page ** wr_pagelist; /* request */ | 389 | struct page ** wr_pagelist; /* request */ |
391 | 390 | ||