diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 234 |
1 files changed, 198 insertions, 36 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5446a0861d1d..41fc241b729a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -60,6 +60,14 @@ | |||
60 | 60 | ||
61 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 61 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
62 | 62 | ||
63 | /* | ||
64 | * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing | ||
65 | * directory in order to indicate to the client that a filesystem boundary is present | ||
66 | * We use a fixed fsid for a referral | ||
67 | */ | ||
68 | #define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL | ||
69 | #define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL | ||
70 | |||
63 | static int | 71 | static int |
64 | check_filename(char *str, int len, int err) | 72 | check_filename(char *str, int len, int err) |
65 | { | 73 | { |
@@ -198,8 +206,7 @@ static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes) | |||
198 | p = new; | 206 | p = new; |
199 | memcpy(p, argp->tmp, nbytes); | 207 | memcpy(p, argp->tmp, nbytes); |
200 | } else { | 208 | } else { |
201 | if (p != argp->tmpp) | 209 | BUG_ON(p != argp->tmpp); |
202 | BUG(); | ||
203 | argp->tmpp = NULL; | 210 | argp->tmpp = NULL; |
204 | } | 211 | } |
205 | if (defer_free(argp, kfree, p)) { | 212 | if (defer_free(argp, kfree, p)) { |
@@ -927,26 +934,26 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) | |||
927 | printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); | 934 | printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); |
928 | goto xdr_error; | 935 | goto xdr_error; |
929 | } | 936 | } |
930 | write->wr_vec[0].iov_base = p; | 937 | argp->rqstp->rq_vec[0].iov_base = p; |
931 | write->wr_vec[0].iov_len = avail; | 938 | argp->rqstp->rq_vec[0].iov_len = avail; |
932 | v = 0; | 939 | v = 0; |
933 | len = write->wr_buflen; | 940 | len = write->wr_buflen; |
934 | while (len > write->wr_vec[v].iov_len) { | 941 | while (len > argp->rqstp->rq_vec[v].iov_len) { |
935 | len -= write->wr_vec[v].iov_len; | 942 | len -= argp->rqstp->rq_vec[v].iov_len; |
936 | v++; | 943 | v++; |
937 | write->wr_vec[v].iov_base = page_address(argp->pagelist[0]); | 944 | argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]); |
938 | argp->pagelist++; | 945 | argp->pagelist++; |
939 | if (argp->pagelen >= PAGE_SIZE) { | 946 | if (argp->pagelen >= PAGE_SIZE) { |
940 | write->wr_vec[v].iov_len = PAGE_SIZE; | 947 | argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE; |
941 | argp->pagelen -= PAGE_SIZE; | 948 | argp->pagelen -= PAGE_SIZE; |
942 | } else { | 949 | } else { |
943 | write->wr_vec[v].iov_len = argp->pagelen; | 950 | argp->rqstp->rq_vec[v].iov_len = argp->pagelen; |
944 | argp->pagelen -= len; | 951 | argp->pagelen -= len; |
945 | } | 952 | } |
946 | } | 953 | } |
947 | argp->end = (u32*) (write->wr_vec[v].iov_base + write->wr_vec[v].iov_len); | 954 | argp->end = (u32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); |
948 | argp->p = (u32*) (write->wr_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); | 955 | argp->p = (u32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); |
949 | write->wr_vec[v].iov_len = len; | 956 | argp->rqstp->rq_vec[v].iov_len = len; |
950 | write->wr_vlen = v+1; | 957 | write->wr_vlen = v+1; |
951 | 958 | ||
952 | DECODE_TAIL; | 959 | DECODE_TAIL; |
@@ -1224,6 +1231,119 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1224 | stateowner->so_replay.rp_buflen); \ | 1231 | stateowner->so_replay.rp_buflen); \ |
1225 | } } while (0); | 1232 | } } while (0); |
1226 | 1233 | ||
1234 | /* Encode as an array of strings the string given with components | ||
1235 | * seperated @sep. | ||
1236 | */ | ||
1237 | static int nfsd4_encode_components(char sep, char *components, | ||
1238 | u32 **pp, int *buflen) | ||
1239 | { | ||
1240 | u32 *p = *pp; | ||
1241 | u32 *countp = p; | ||
1242 | int strlen, count=0; | ||
1243 | char *str, *end; | ||
1244 | |||
1245 | dprintk("nfsd4_encode_components(%s)\n", components); | ||
1246 | if ((*buflen -= 4) < 0) | ||
1247 | return nfserr_resource; | ||
1248 | WRITE32(0); /* We will fill this in with @count later */ | ||
1249 | end = str = components; | ||
1250 | while (*end) { | ||
1251 | for (; *end && (*end != sep); end++) | ||
1252 | ; /* Point to end of component */ | ||
1253 | strlen = end - str; | ||
1254 | if (strlen) { | ||
1255 | if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0) | ||
1256 | return nfserr_resource; | ||
1257 | WRITE32(strlen); | ||
1258 | WRITEMEM(str, strlen); | ||
1259 | count++; | ||
1260 | } | ||
1261 | else | ||
1262 | end++; | ||
1263 | str = end; | ||
1264 | } | ||
1265 | *pp = p; | ||
1266 | p = countp; | ||
1267 | WRITE32(count); | ||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | /* | ||
1272 | * encode a location element of a fs_locations structure | ||
1273 | */ | ||
1274 | static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, | ||
1275 | u32 **pp, int *buflen) | ||
1276 | { | ||
1277 | int status; | ||
1278 | u32 *p = *pp; | ||
1279 | |||
1280 | status = nfsd4_encode_components(':', location->hosts, &p, buflen); | ||
1281 | if (status) | ||
1282 | return status; | ||
1283 | status = nfsd4_encode_components('/', location->path, &p, buflen); | ||
1284 | if (status) | ||
1285 | return status; | ||
1286 | *pp = p; | ||
1287 | return 0; | ||
1288 | } | ||
1289 | |||
1290 | /* | ||
1291 | * Return the path to an export point in the pseudo filesystem namespace | ||
1292 | * Returned string is safe to use as long as the caller holds a reference | ||
1293 | * to @exp. | ||
1294 | */ | ||
1295 | static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp) | ||
1296 | { | ||
1297 | struct svc_fh tmp_fh; | ||
1298 | char *path, *rootpath; | ||
1299 | int stat; | ||
1300 | |||
1301 | fh_init(&tmp_fh, NFS4_FHSIZE); | ||
1302 | stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); | ||
1303 | if (stat) | ||
1304 | return ERR_PTR(stat); | ||
1305 | rootpath = tmp_fh.fh_export->ex_path; | ||
1306 | |||
1307 | path = exp->ex_path; | ||
1308 | |||
1309 | if (strncmp(path, rootpath, strlen(rootpath))) { | ||
1310 | printk("nfsd: fs_locations failed;" | ||
1311 | "%s is not contained in %s\n", path, rootpath); | ||
1312 | return ERR_PTR(-EOPNOTSUPP); | ||
1313 | } | ||
1314 | |||
1315 | return path + strlen(rootpath); | ||
1316 | } | ||
1317 | |||
1318 | /* | ||
1319 | * encode a fs_locations structure | ||
1320 | */ | ||
1321 | static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp, | ||
1322 | struct svc_export *exp, | ||
1323 | u32 **pp, int *buflen) | ||
1324 | { | ||
1325 | int status, i; | ||
1326 | u32 *p = *pp; | ||
1327 | struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; | ||
1328 | char *root = nfsd4_path(rqstp, exp); | ||
1329 | |||
1330 | if (IS_ERR(root)) | ||
1331 | return PTR_ERR(root); | ||
1332 | status = nfsd4_encode_components('/', root, &p, buflen); | ||
1333 | if (status) | ||
1334 | return status; | ||
1335 | if ((*buflen -= 4) < 0) | ||
1336 | return nfserr_resource; | ||
1337 | WRITE32(fslocs->locations_count); | ||
1338 | for (i=0; i<fslocs->locations_count; i++) { | ||
1339 | status = nfsd4_encode_fs_location4(&fslocs->locations[i], | ||
1340 | &p, buflen); | ||
1341 | if (status) | ||
1342 | return status; | ||
1343 | } | ||
1344 | *pp = p; | ||
1345 | return 0; | ||
1346 | } | ||
1227 | 1347 | ||
1228 | static u32 nfs4_ftypes[16] = { | 1348 | static u32 nfs4_ftypes[16] = { |
1229 | NF4BAD, NF4FIFO, NF4CHR, NF4BAD, | 1349 | NF4BAD, NF4FIFO, NF4CHR, NF4BAD, |
@@ -1273,6 +1393,25 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, | |||
1273 | return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); | 1393 | return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); |
1274 | } | 1394 | } |
1275 | 1395 | ||
1396 | #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ | ||
1397 | FATTR4_WORD0_RDATTR_ERROR) | ||
1398 | #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID | ||
1399 | |||
1400 | static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) | ||
1401 | { | ||
1402 | /* As per referral draft: */ | ||
1403 | if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS || | ||
1404 | *bmval1 & ~WORD1_ABSENT_FS_ATTRS) { | ||
1405 | if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR || | ||
1406 | *bmval0 & FATTR4_WORD0_FS_LOCATIONS) | ||
1407 | *rdattr_err = NFSERR_MOVED; | ||
1408 | else | ||
1409 | return nfserr_moved; | ||
1410 | } | ||
1411 | *bmval0 &= WORD0_ABSENT_FS_ATTRS; | ||
1412 | *bmval1 &= WORD1_ABSENT_FS_ATTRS; | ||
1413 | return 0; | ||
1414 | } | ||
1276 | 1415 | ||
1277 | /* | 1416 | /* |
1278 | * Note: @fhp can be NULL; in this case, we might have to compose the filehandle | 1417 | * Note: @fhp can be NULL; in this case, we might have to compose the filehandle |
@@ -1295,6 +1434,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1295 | u32 *attrlenp; | 1434 | u32 *attrlenp; |
1296 | u32 dummy; | 1435 | u32 dummy; |
1297 | u64 dummy64; | 1436 | u64 dummy64; |
1437 | u32 rdattr_err = 0; | ||
1298 | u32 *p = buffer; | 1438 | u32 *p = buffer; |
1299 | int status; | 1439 | int status; |
1300 | int aclsupport = 0; | 1440 | int aclsupport = 0; |
@@ -1304,6 +1444,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1304 | BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); | 1444 | BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); |
1305 | BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); | 1445 | BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); |
1306 | 1446 | ||
1447 | if (exp->ex_fslocs.migrated) { | ||
1448 | status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err); | ||
1449 | if (status) | ||
1450 | goto out; | ||
1451 | } | ||
1452 | |||
1307 | status = vfs_getattr(exp->ex_mnt, dentry, &stat); | 1453 | status = vfs_getattr(exp->ex_mnt, dentry, &stat); |
1308 | if (status) | 1454 | if (status) |
1309 | goto out_nfserr; | 1455 | goto out_nfserr; |
@@ -1335,6 +1481,11 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1335 | goto out_nfserr; | 1481 | goto out_nfserr; |
1336 | } | 1482 | } |
1337 | } | 1483 | } |
1484 | if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { | ||
1485 | if (exp->ex_fslocs.locations == NULL) { | ||
1486 | bmval0 &= ~FATTR4_WORD0_FS_LOCATIONS; | ||
1487 | } | ||
1488 | } | ||
1338 | if ((buflen -= 16) < 0) | 1489 | if ((buflen -= 16) < 0) |
1339 | goto out_resource; | 1490 | goto out_resource; |
1340 | 1491 | ||
@@ -1344,12 +1495,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1344 | attrlenp = p++; /* to be backfilled later */ | 1495 | attrlenp = p++; /* to be backfilled later */ |
1345 | 1496 | ||
1346 | if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { | 1497 | if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { |
1498 | u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0; | ||
1347 | if ((buflen -= 12) < 0) | 1499 | if ((buflen -= 12) < 0) |
1348 | goto out_resource; | 1500 | goto out_resource; |
1501 | if (!aclsupport) | ||
1502 | word0 &= ~FATTR4_WORD0_ACL; | ||
1503 | if (!exp->ex_fslocs.locations) | ||
1504 | word0 &= ~FATTR4_WORD0_FS_LOCATIONS; | ||
1349 | WRITE32(2); | 1505 | WRITE32(2); |
1350 | WRITE32(aclsupport ? | 1506 | WRITE32(word0); |
1351 | NFSD_SUPPORTED_ATTRS_WORD0 : | ||
1352 | NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL); | ||
1353 | WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); | 1507 | WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); |
1354 | } | 1508 | } |
1355 | if (bmval0 & FATTR4_WORD0_TYPE) { | 1509 | if (bmval0 & FATTR4_WORD0_TYPE) { |
@@ -1403,7 +1557,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1403 | if (bmval0 & FATTR4_WORD0_FSID) { | 1557 | if (bmval0 & FATTR4_WORD0_FSID) { |
1404 | if ((buflen -= 16) < 0) | 1558 | if ((buflen -= 16) < 0) |
1405 | goto out_resource; | 1559 | goto out_resource; |
1406 | if (is_fsid(fhp, rqstp->rq_reffh)) { | 1560 | if (exp->ex_fslocs.migrated) { |
1561 | WRITE64(NFS4_REFERRAL_FSID_MAJOR); | ||
1562 | WRITE64(NFS4_REFERRAL_FSID_MINOR); | ||
1563 | } else if (is_fsid(fhp, rqstp->rq_reffh)) { | ||
1407 | WRITE64((u64)exp->ex_fsid); | 1564 | WRITE64((u64)exp->ex_fsid); |
1408 | WRITE64((u64)0); | 1565 | WRITE64((u64)0); |
1409 | } else { | 1566 | } else { |
@@ -1426,7 +1583,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1426 | if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { | 1583 | if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { |
1427 | if ((buflen -= 4) < 0) | 1584 | if ((buflen -= 4) < 0) |
1428 | goto out_resource; | 1585 | goto out_resource; |
1429 | WRITE32(0); | 1586 | WRITE32(rdattr_err); |
1430 | } | 1587 | } |
1431 | if (bmval0 & FATTR4_WORD0_ACL) { | 1588 | if (bmval0 & FATTR4_WORD0_ACL) { |
1432 | struct nfs4_ace *ace; | 1589 | struct nfs4_ace *ace; |
@@ -1514,6 +1671,13 @@ out_acl: | |||
1514 | goto out_resource; | 1671 | goto out_resource; |
1515 | WRITE64((u64) statfs.f_files); | 1672 | WRITE64((u64) statfs.f_files); |
1516 | } | 1673 | } |
1674 | if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { | ||
1675 | status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); | ||
1676 | if (status == nfserr_resource) | ||
1677 | goto out_resource; | ||
1678 | if (status) | ||
1679 | goto out; | ||
1680 | } | ||
1517 | if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { | 1681 | if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { |
1518 | if ((buflen -= 4) < 0) | 1682 | if ((buflen -= 4) < 0) |
1519 | goto out_resource; | 1683 | goto out_resource; |
@@ -1537,12 +1701,12 @@ out_acl: | |||
1537 | if (bmval0 & FATTR4_WORD0_MAXREAD) { | 1701 | if (bmval0 & FATTR4_WORD0_MAXREAD) { |
1538 | if ((buflen -= 8) < 0) | 1702 | if ((buflen -= 8) < 0) |
1539 | goto out_resource; | 1703 | goto out_resource; |
1540 | WRITE64((u64) NFSSVC_MAXBLKSIZE); | 1704 | WRITE64((u64) svc_max_payload(rqstp)); |
1541 | } | 1705 | } |
1542 | if (bmval0 & FATTR4_WORD0_MAXWRITE) { | 1706 | if (bmval0 & FATTR4_WORD0_MAXWRITE) { |
1543 | if ((buflen -= 8) < 0) | 1707 | if ((buflen -= 8) < 0) |
1544 | goto out_resource; | 1708 | goto out_resource; |
1545 | WRITE64((u64) NFSSVC_MAXBLKSIZE); | 1709 | WRITE64((u64) svc_max_payload(rqstp)); |
1546 | } | 1710 | } |
1547 | if (bmval1 & FATTR4_WORD1_MODE) { | 1711 | if (bmval1 & FATTR4_WORD1_MODE) { |
1548 | if ((buflen -= 4) < 0) | 1712 | if ((buflen -= 4) < 0) |
@@ -1846,7 +2010,6 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_ge | |||
1846 | nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, | 2010 | nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, |
1847 | resp->p, &buflen, getattr->ga_bmval, | 2011 | resp->p, &buflen, getattr->ga_bmval, |
1848 | resp->rqstp); | 2012 | resp->rqstp); |
1849 | |||
1850 | if (!nfserr) | 2013 | if (!nfserr) |
1851 | resp->p += buflen; | 2014 | resp->p += buflen; |
1852 | return nfserr; | 2015 | return nfserr; |
@@ -2040,7 +2203,8 @@ nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct n | |||
2040 | } | 2203 | } |
2041 | 2204 | ||
2042 | static int | 2205 | static int |
2043 | nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read) | 2206 | nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, |
2207 | struct nfsd4_read *read) | ||
2044 | { | 2208 | { |
2045 | u32 eof; | 2209 | u32 eof; |
2046 | int v, pn; | 2210 | int v, pn; |
@@ -2055,31 +2219,33 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read | |||
2055 | 2219 | ||
2056 | RESERVE_SPACE(8); /* eof flag and byte count */ | 2220 | RESERVE_SPACE(8); /* eof flag and byte count */ |
2057 | 2221 | ||
2058 | maxcount = NFSSVC_MAXBLKSIZE; | 2222 | maxcount = svc_max_payload(resp->rqstp); |
2059 | if (maxcount > read->rd_length) | 2223 | if (maxcount > read->rd_length) |
2060 | maxcount = read->rd_length; | 2224 | maxcount = read->rd_length; |
2061 | 2225 | ||
2062 | len = maxcount; | 2226 | len = maxcount; |
2063 | v = 0; | 2227 | v = 0; |
2064 | while (len > 0) { | 2228 | while (len > 0) { |
2065 | pn = resp->rqstp->rq_resused; | 2229 | pn = resp->rqstp->rq_resused++; |
2066 | svc_take_page(resp->rqstp); | 2230 | resp->rqstp->rq_vec[v].iov_base = |
2067 | read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); | 2231 | page_address(resp->rqstp->rq_respages[pn]); |
2068 | read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; | 2232 | resp->rqstp->rq_vec[v].iov_len = |
2233 | len < PAGE_SIZE ? len : PAGE_SIZE; | ||
2069 | v++; | 2234 | v++; |
2070 | len -= PAGE_SIZE; | 2235 | len -= PAGE_SIZE; |
2071 | } | 2236 | } |
2072 | read->rd_vlen = v; | 2237 | read->rd_vlen = v; |
2073 | 2238 | ||
2074 | nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, | 2239 | nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, |
2075 | read->rd_offset, read->rd_iov, read->rd_vlen, | 2240 | read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, |
2076 | &maxcount); | 2241 | &maxcount); |
2077 | 2242 | ||
2078 | if (nfserr == nfserr_symlink) | 2243 | if (nfserr == nfserr_symlink) |
2079 | nfserr = nfserr_inval; | 2244 | nfserr = nfserr_inval; |
2080 | if (nfserr) | 2245 | if (nfserr) |
2081 | return nfserr; | 2246 | return nfserr; |
2082 | eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size); | 2247 | eof = (read->rd_offset + maxcount >= |
2248 | read->rd_fhp->fh_dentry->d_inode->i_size); | ||
2083 | 2249 | ||
2084 | WRITE32(eof); | 2250 | WRITE32(eof); |
2085 | WRITE32(maxcount); | 2251 | WRITE32(maxcount); |
@@ -2089,7 +2255,6 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read | |||
2089 | resp->xbuf->page_len = maxcount; | 2255 | resp->xbuf->page_len = maxcount; |
2090 | 2256 | ||
2091 | /* Use rest of head for padding and remaining ops: */ | 2257 | /* Use rest of head for padding and remaining ops: */ |
2092 | resp->rqstp->rq_restailpage = 0; | ||
2093 | resp->xbuf->tail[0].iov_base = p; | 2258 | resp->xbuf->tail[0].iov_base = p; |
2094 | resp->xbuf->tail[0].iov_len = 0; | 2259 | resp->xbuf->tail[0].iov_len = 0; |
2095 | if (maxcount&3) { | 2260 | if (maxcount&3) { |
@@ -2114,8 +2279,7 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r | |||
2114 | if (resp->xbuf->page_len) | 2279 | if (resp->xbuf->page_len) |
2115 | return nfserr_resource; | 2280 | return nfserr_resource; |
2116 | 2281 | ||
2117 | svc_take_page(resp->rqstp); | 2282 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); |
2118 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2119 | 2283 | ||
2120 | maxcount = PAGE_SIZE; | 2284 | maxcount = PAGE_SIZE; |
2121 | RESERVE_SPACE(4); | 2285 | RESERVE_SPACE(4); |
@@ -2139,7 +2303,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r | |||
2139 | resp->xbuf->page_len = maxcount; | 2303 | resp->xbuf->page_len = maxcount; |
2140 | 2304 | ||
2141 | /* Use rest of head for padding and remaining ops: */ | 2305 | /* Use rest of head for padding and remaining ops: */ |
2142 | resp->rqstp->rq_restailpage = 0; | ||
2143 | resp->xbuf->tail[0].iov_base = p; | 2306 | resp->xbuf->tail[0].iov_base = p; |
2144 | resp->xbuf->tail[0].iov_len = 0; | 2307 | resp->xbuf->tail[0].iov_len = 0; |
2145 | if (maxcount&3) { | 2308 | if (maxcount&3) { |
@@ -2190,8 +2353,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2190 | goto err_no_verf; | 2353 | goto err_no_verf; |
2191 | } | 2354 | } |
2192 | 2355 | ||
2193 | svc_take_page(resp->rqstp); | 2356 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); |
2194 | page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2195 | readdir->common.err = 0; | 2357 | readdir->common.err = 0; |
2196 | readdir->buflen = maxcount; | 2358 | readdir->buflen = maxcount; |
2197 | readdir->buffer = page; | 2359 | readdir->buffer = page; |
@@ -2216,10 +2378,10 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re | |||
2216 | p = readdir->buffer; | 2378 | p = readdir->buffer; |
2217 | *p++ = 0; /* no more entries */ | 2379 | *p++ = 0; /* no more entries */ |
2218 | *p++ = htonl(readdir->common.err == nfserr_eof); | 2380 | *p++ = htonl(readdir->common.err == nfserr_eof); |
2219 | resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | 2381 | resp->xbuf->page_len = ((char*)p) - (char*)page_address( |
2382 | resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); | ||
2220 | 2383 | ||
2221 | /* Use rest of head for padding and remaining ops: */ | 2384 | /* Use rest of head for padding and remaining ops: */ |
2222 | resp->rqstp->rq_restailpage = 0; | ||
2223 | resp->xbuf->tail[0].iov_base = tailbase; | 2385 | resp->xbuf->tail[0].iov_base = tailbase; |
2224 | resp->xbuf->tail[0].iov_len = 0; | 2386 | resp->xbuf->tail[0].iov_len = 0; |
2225 | resp->p = resp->xbuf->tail[0].iov_base; | 2387 | resp->p = resp->xbuf->tail[0].iov_base; |