aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c234
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
63static int 71static int
64check_filename(char *str, int len, int err) 72check_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 */
1237static 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 */
1274static 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 */
1295static 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 */
1321static 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
1228static u32 nfs4_ftypes[16] = { 1348static 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
1400static 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
2042static int 2205static int
2043nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read) 2206nfsd4_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;