Commit 5a80a54d21c96590d013378d8c5f65f879451ab4

Authored by J. Bruce Fields
1 parent 8a61b18c9b

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

... ... @@ -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 }