Commit 5a80a54d21c96590d013378d8c5f65f879451ab4
1 parent
8a61b18c9b
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
nfsd4: reorganize write decoding
In preparation for moving some of it elsewhere. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Showing 1 changed file with 41 additions and 21 deletions Side-by-side Diff
fs/nfsd/nfs4xdr.c
... | ... | @@ -1139,12 +1139,30 @@ |
1139 | 1139 | DECODE_TAIL; |
1140 | 1140 | } |
1141 | 1141 | |
1142 | +static int fill_in_write_vector(struct kvec *vec, struct kvec *head, struct page **pagelist, int buflen) | |
1143 | +{ | |
1144 | + int i = 1; | |
1145 | + | |
1146 | + vec[0].iov_base = head->iov_base; | |
1147 | + vec[0].iov_len = min_t(int, buflen, head->iov_len); | |
1148 | + buflen -= vec[0].iov_len; | |
1149 | + | |
1150 | + while (buflen) { | |
1151 | + vec[i].iov_base = page_address(pagelist[i - 1]); | |
1152 | + vec[i].iov_len = min_t(int, PAGE_SIZE, buflen); | |
1153 | + buflen -= vec[i].iov_len; | |
1154 | + i++; | |
1155 | + } | |
1156 | + return i; | |
1157 | +} | |
1158 | + | |
1142 | 1159 | static __be32 |
1143 | 1160 | nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) |
1144 | 1161 | { |
1145 | 1162 | int avail; |
1146 | - int v; | |
1147 | 1163 | int len; |
1164 | + struct page **pagelist; | |
1165 | + struct kvec head; | |
1148 | 1166 | DECODE_HEAD; |
1149 | 1167 | |
1150 | 1168 | status = nfsd4_decode_stateid(argp, &write->wr_stateid); |
1151 | 1169 | |
... | ... | @@ -1167,27 +1185,29 @@ |
1167 | 1185 | __FILE__, __LINE__); |
1168 | 1186 | goto xdr_error; |
1169 | 1187 | } |
1170 | - argp->rqstp->rq_vec[0].iov_base = p; | |
1171 | - argp->rqstp->rq_vec[0].iov_len = avail; | |
1172 | - v = 0; | |
1173 | - len = write->wr_buflen; | |
1174 | - while (len > argp->rqstp->rq_vec[v].iov_len) { | |
1175 | - len -= argp->rqstp->rq_vec[v].iov_len; | |
1176 | - v++; | |
1177 | - argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]); | |
1178 | - argp->pagelist++; | |
1179 | - if (argp->pagelen >= PAGE_SIZE) { | |
1180 | - argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE; | |
1181 | - argp->pagelen -= PAGE_SIZE; | |
1182 | - } else { | |
1183 | - argp->rqstp->rq_vec[v].iov_len = argp->pagelen; | |
1184 | - argp->pagelen -= len; | |
1185 | - } | |
1188 | + head.iov_base = p; | |
1189 | + head.iov_len = avail; | |
1190 | + WARN_ON(avail != (XDR_QUADLEN(avail) << 2)); | |
1191 | + pagelist = argp->pagelist; | |
1192 | + | |
1193 | + len = XDR_QUADLEN(write->wr_buflen) << 2; | |
1194 | + if (len >= avail) { | |
1195 | + int pages; | |
1196 | + | |
1197 | + len -= avail; | |
1198 | + | |
1199 | + pages = len >> PAGE_SHIFT; | |
1200 | + argp->pagelist += pages; | |
1201 | + argp->pagelen -= pages * PAGE_SIZE; | |
1202 | + len -= pages * PAGE_SIZE; | |
1203 | + | |
1204 | + argp->p = (__be32 *)page_address(argp->pagelist[0]); | |
1205 | + argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE); | |
1186 | 1206 | } |
1187 | - argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); | |
1188 | - argp->p = (__be32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); | |
1189 | - argp->rqstp->rq_vec[v].iov_len = len; | |
1190 | - write->wr_vlen = v+1; | |
1207 | + argp->p += XDR_QUADLEN(len); | |
1208 | + write->wr_vlen = fill_in_write_vector(argp->rqstp->rq_vec, | |
1209 | + &head, pagelist, write->wr_buflen); | |
1210 | + WARN_ON_ONCE(write->wr_vlen > ARRAY_SIZE(argp->rqstp->rq_vec)); | |
1191 | 1211 | |
1192 | 1212 | DECODE_TAIL; |
1193 | 1213 | } |