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.c324
1 files changed, 156 insertions, 168 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fd548d155088..0dc11586682f 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -53,6 +53,7 @@
53#include "vfs.h" 53#include "vfs.h"
54#include "state.h" 54#include "state.h"
55#include "cache.h" 55#include "cache.h"
56#include "netns.h"
56 57
57#define NFSDDBG_FACILITY NFSDDBG_XDR 58#define NFSDDBG_FACILITY NFSDDBG_XDR
58 59
@@ -65,17 +66,17 @@
65#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL 66#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL
66 67
67static __be32 68static __be32
68check_filename(char *str, int len, __be32 err) 69check_filename(char *str, int len)
69{ 70{
70 int i; 71 int i;
71 72
72 if (len == 0) 73 if (len == 0)
73 return nfserr_inval; 74 return nfserr_inval;
74 if (isdotent(str, len)) 75 if (isdotent(str, len))
75 return err; 76 return nfserr_badname;
76 for (i = 0; i < len; i++) 77 for (i = 0; i < len; i++)
77 if (str[i] == '/') 78 if (str[i] == '/')
78 return err; 79 return nfserr_badname;
79 return 0; 80 return 0;
80} 81}
81 82
@@ -422,6 +423,86 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
422 DECODE_TAIL; 423 DECODE_TAIL;
423} 424}
424 425
426static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
427{
428 DECODE_HEAD;
429 u32 dummy, uid, gid;
430 char *machine_name;
431 int i;
432 int nr_secflavs;
433
434 /* callback_sec_params4 */
435 READ_BUF(4);
436 READ32(nr_secflavs);
437 cbs->flavor = (u32)(-1);
438 for (i = 0; i < nr_secflavs; ++i) {
439 READ_BUF(4);
440 READ32(dummy);
441 switch (dummy) {
442 case RPC_AUTH_NULL:
443 /* Nothing to read */
444 if (cbs->flavor == (u32)(-1))
445 cbs->flavor = RPC_AUTH_NULL;
446 break;
447 case RPC_AUTH_UNIX:
448 READ_BUF(8);
449 /* stamp */
450 READ32(dummy);
451
452 /* machine name */
453 READ32(dummy);
454 READ_BUF(dummy);
455 SAVEMEM(machine_name, dummy);
456
457 /* uid, gid */
458 READ_BUF(8);
459 READ32(uid);
460 READ32(gid);
461
462 /* more gids */
463 READ_BUF(4);
464 READ32(dummy);
465 READ_BUF(dummy * 4);
466 if (cbs->flavor == (u32)(-1)) {
467 cbs->uid = uid;
468 cbs->gid = gid;
469 cbs->flavor = RPC_AUTH_UNIX;
470 }
471 break;
472 case RPC_AUTH_GSS:
473 dprintk("RPC_AUTH_GSS callback secflavor "
474 "not supported!\n");
475 READ_BUF(8);
476 /* gcbp_service */
477 READ32(dummy);
478 /* gcbp_handle_from_server */
479 READ32(dummy);
480 READ_BUF(dummy);
481 p += XDR_QUADLEN(dummy);
482 /* gcbp_handle_from_client */
483 READ_BUF(4);
484 READ32(dummy);
485 READ_BUF(dummy);
486 break;
487 default:
488 dprintk("Illegal callback secflavor\n");
489 return nfserr_inval;
490 }
491 }
492 DECODE_TAIL;
493}
494
495static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
496{
497 DECODE_HEAD;
498
499 READ_BUF(4);
500 READ32(bc->bc_cb_program);
501 nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
502
503 DECODE_TAIL;
504}
505
425static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts) 506static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
426{ 507{
427 DECODE_HEAD; 508 DECODE_HEAD;
@@ -490,7 +571,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
490 READ32(create->cr_namelen); 571 READ32(create->cr_namelen);
491 READ_BUF(create->cr_namelen); 572 READ_BUF(create->cr_namelen);
492 SAVEMEM(create->cr_name, create->cr_namelen); 573 SAVEMEM(create->cr_name, create->cr_namelen);
493 if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval))) 574 if ((status = check_filename(create->cr_name, create->cr_namelen)))
494 return status; 575 return status;
495 576
496 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, 577 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
@@ -522,7 +603,7 @@ nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
522 READ32(link->li_namelen); 603 READ32(link->li_namelen);
523 READ_BUF(link->li_namelen); 604 READ_BUF(link->li_namelen);
524 SAVEMEM(link->li_name, link->li_namelen); 605 SAVEMEM(link->li_name, link->li_namelen);
525 if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval))) 606 if ((status = check_filename(link->li_name, link->li_namelen)))
526 return status; 607 return status;
527 608
528 DECODE_TAIL; 609 DECODE_TAIL;
@@ -616,7 +697,7 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
616 READ32(lookup->lo_len); 697 READ32(lookup->lo_len);
617 READ_BUF(lookup->lo_len); 698 READ_BUF(lookup->lo_len);
618 SAVEMEM(lookup->lo_name, lookup->lo_len); 699 SAVEMEM(lookup->lo_name, lookup->lo_len);
619 if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent))) 700 if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
620 return status; 701 return status;
621 702
622 DECODE_TAIL; 703 DECODE_TAIL;
@@ -780,7 +861,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
780 READ32(open->op_fname.len); 861 READ32(open->op_fname.len);
781 READ_BUF(open->op_fname.len); 862 READ_BUF(open->op_fname.len);
782 SAVEMEM(open->op_fname.data, open->op_fname.len); 863 SAVEMEM(open->op_fname.data, open->op_fname.len);
783 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval))) 864 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
784 return status; 865 return status;
785 break; 866 break;
786 case NFS4_OPEN_CLAIM_PREVIOUS: 867 case NFS4_OPEN_CLAIM_PREVIOUS:
@@ -795,7 +876,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
795 READ32(open->op_fname.len); 876 READ32(open->op_fname.len);
796 READ_BUF(open->op_fname.len); 877 READ_BUF(open->op_fname.len);
797 SAVEMEM(open->op_fname.data, open->op_fname.len); 878 SAVEMEM(open->op_fname.data, open->op_fname.len);
798 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval))) 879 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
799 return status; 880 return status;
800 break; 881 break;
801 case NFS4_OPEN_CLAIM_FH: 882 case NFS4_OPEN_CLAIM_FH:
@@ -907,7 +988,7 @@ nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove
907 READ32(remove->rm_namelen); 988 READ32(remove->rm_namelen);
908 READ_BUF(remove->rm_namelen); 989 READ_BUF(remove->rm_namelen);
909 SAVEMEM(remove->rm_name, remove->rm_namelen); 990 SAVEMEM(remove->rm_name, remove->rm_namelen);
910 if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent))) 991 if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
911 return status; 992 return status;
912 993
913 DECODE_TAIL; 994 DECODE_TAIL;
@@ -925,9 +1006,9 @@ nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename
925 READ32(rename->rn_tnamelen); 1006 READ32(rename->rn_tnamelen);
926 READ_BUF(rename->rn_tnamelen); 1007 READ_BUF(rename->rn_tnamelen);
927 SAVEMEM(rename->rn_tname, rename->rn_tnamelen); 1008 SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
928 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent))) 1009 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
929 return status; 1010 return status;
930 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval))) 1011 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
931 return status; 1012 return status;
932 1013
933 DECODE_TAIL; 1014 DECODE_TAIL;
@@ -954,8 +1035,7 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
954 READ32(secinfo->si_namelen); 1035 READ32(secinfo->si_namelen);
955 READ_BUF(secinfo->si_namelen); 1036 READ_BUF(secinfo->si_namelen);
956 SAVEMEM(secinfo->si_name, secinfo->si_namelen); 1037 SAVEMEM(secinfo->si_name, secinfo->si_namelen);
957 status = check_filename(secinfo->si_name, secinfo->si_namelen, 1038 status = check_filename(secinfo->si_name, secinfo->si_namelen);
958 nfserr_noent);
959 if (status) 1039 if (status)
960 return status; 1040 return status;
961 DECODE_TAIL; 1041 DECODE_TAIL;
@@ -1026,31 +1106,14 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
1026static __be32 1106static __be32
1027nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify) 1107nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
1028{ 1108{
1029#if 0
1030 struct nfsd4_compoundargs save = {
1031 .p = argp->p,
1032 .end = argp->end,
1033 .rqstp = argp->rqstp,
1034 };
1035 u32 ve_bmval[2];
1036 struct iattr ve_iattr; /* request */
1037 struct nfs4_acl *ve_acl; /* request */
1038#endif
1039 DECODE_HEAD; 1109 DECODE_HEAD;
1040 1110
1041 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval))) 1111 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
1042 goto out; 1112 goto out;
1043 1113
1044 /* For convenience's sake, we compare raw xdr'd attributes in 1114 /* For convenience's sake, we compare raw xdr'd attributes in
1045 * nfsd4_proc_verify; however we still decode here just to return 1115 * nfsd4_proc_verify */
1046 * correct error in case of bad xdr. */ 1116
1047#if 0
1048 status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
1049 if (status == nfserr_inval) {
1050 status = nfserrno(status);
1051 goto out;
1052 }
1053#endif
1054 READ_BUF(4); 1117 READ_BUF(4);
1055 READ32(verify->ve_attrlen); 1118 READ32(verify->ve_attrlen);
1056 READ_BUF(verify->ve_attrlen); 1119 READ_BUF(verify->ve_attrlen);
@@ -1063,7 +1126,6 @@ static __be32
1063nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) 1126nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1064{ 1127{
1065 int avail; 1128 int avail;
1066 int v;
1067 int len; 1129 int len;
1068 DECODE_HEAD; 1130 DECODE_HEAD;
1069 1131
@@ -1087,27 +1149,26 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1087 __FILE__, __LINE__); 1149 __FILE__, __LINE__);
1088 goto xdr_error; 1150 goto xdr_error;
1089 } 1151 }
1090 argp->rqstp->rq_vec[0].iov_base = p; 1152 write->wr_head.iov_base = p;
1091 argp->rqstp->rq_vec[0].iov_len = avail; 1153 write->wr_head.iov_len = avail;
1092 v = 0; 1154 WARN_ON(avail != (XDR_QUADLEN(avail) << 2));
1093 len = write->wr_buflen; 1155 write->wr_pagelist = argp->pagelist;
1094 while (len > argp->rqstp->rq_vec[v].iov_len) { 1156
1095 len -= argp->rqstp->rq_vec[v].iov_len; 1157 len = XDR_QUADLEN(write->wr_buflen) << 2;
1096 v++; 1158 if (len >= avail) {
1097 argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]); 1159 int pages;
1098 argp->pagelist++; 1160
1099 if (argp->pagelen >= PAGE_SIZE) { 1161 len -= avail;
1100 argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE; 1162
1101 argp->pagelen -= PAGE_SIZE; 1163 pages = len >> PAGE_SHIFT;
1102 } else { 1164 argp->pagelist += pages;
1103 argp->rqstp->rq_vec[v].iov_len = argp->pagelen; 1165 argp->pagelen -= pages * PAGE_SIZE;
1104 argp->pagelen -= len; 1166 len -= pages * PAGE_SIZE;
1105 } 1167
1168 argp->p = (__be32 *)page_address(argp->pagelist[0]);
1169 argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
1106 } 1170 }
1107 argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); 1171 argp->p += XDR_QUADLEN(len);
1108 argp->p = (__be32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
1109 argp->rqstp->rq_vec[v].iov_len = len;
1110 write->wr_vlen = v+1;
1111 1172
1112 DECODE_TAIL; 1173 DECODE_TAIL;
1113} 1174}
@@ -1237,11 +1298,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1237 struct nfsd4_create_session *sess) 1298 struct nfsd4_create_session *sess)
1238{ 1299{
1239 DECODE_HEAD; 1300 DECODE_HEAD;
1240
1241 u32 dummy; 1301 u32 dummy;
1242 char *machine_name;
1243 int i;
1244 int nr_secflavs;
1245 1302
1246 READ_BUF(16); 1303 READ_BUF(16);
1247 COPYMEM(&sess->clientid, 8); 1304 COPYMEM(&sess->clientid, 8);
@@ -1282,58 +1339,9 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1282 goto xdr_error; 1339 goto xdr_error;
1283 } 1340 }
1284 1341
1285 READ_BUF(8); 1342 READ_BUF(4);
1286 READ32(sess->callback_prog); 1343 READ32(sess->callback_prog);
1287 1344 nfsd4_decode_cb_sec(argp, &sess->cb_sec);
1288 /* callback_sec_params4 */
1289 READ32(nr_secflavs);
1290 for (i = 0; i < nr_secflavs; ++i) {
1291 READ_BUF(4);
1292 READ32(dummy);
1293 switch (dummy) {
1294 case RPC_AUTH_NULL:
1295 /* Nothing to read */
1296 break;
1297 case RPC_AUTH_UNIX:
1298 READ_BUF(8);
1299 /* stamp */
1300 READ32(dummy);
1301
1302 /* machine name */
1303 READ32(dummy);
1304 READ_BUF(dummy);
1305 SAVEMEM(machine_name, dummy);
1306
1307 /* uid, gid */
1308 READ_BUF(8);
1309 READ32(sess->uid);
1310 READ32(sess->gid);
1311
1312 /* more gids */
1313 READ_BUF(4);
1314 READ32(dummy);
1315 READ_BUF(dummy * 4);
1316 break;
1317 case RPC_AUTH_GSS:
1318 dprintk("RPC_AUTH_GSS callback secflavor "
1319 "not supported!\n");
1320 READ_BUF(8);
1321 /* gcbp_service */
1322 READ32(dummy);
1323 /* gcbp_handle_from_server */
1324 READ32(dummy);
1325 READ_BUF(dummy);
1326 p += XDR_QUADLEN(dummy);
1327 /* gcbp_handle_from_client */
1328 READ_BUF(4);
1329 READ32(dummy);
1330 READ_BUF(dummy);
1331 break;
1332 default:
1333 dprintk("Illegal callback secflavor\n");
1334 return nfserr_inval;
1335 }
1336 }
1337 DECODE_TAIL; 1345 DECODE_TAIL;
1338} 1346}
1339 1347
@@ -1528,7 +1536,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
1528 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp, 1536 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp,
1529 1537
1530 /* new operations for NFSv4.1 */ 1538 /* new operations for NFSv4.1 */
1531 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, 1539 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
1532 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session, 1540 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
1533 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, 1541 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1534 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, 1542 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
@@ -1568,12 +1576,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1568 bool cachethis = false; 1576 bool cachethis = false;
1569 int i; 1577 int i;
1570 1578
1571 /*
1572 * XXX: According to spec, we should check the tag
1573 * for UTF-8 compliance. I'm postponing this for
1574 * now because it seems that some clients do use
1575 * binary tags.
1576 */
1577 READ_BUF(4); 1579 READ_BUF(4);
1578 READ32(argp->taglen); 1580 READ32(argp->taglen);
1579 READ_BUF(argp->taglen + 8); 1581 READ_BUF(argp->taglen + 8);
@@ -1603,38 +1605,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1603 op = &argp->ops[i]; 1605 op = &argp->ops[i];
1604 op->replay = NULL; 1606 op->replay = NULL;
1605 1607
1606 /* 1608 READ_BUF(4);
1607 * We can't use READ_BUF() here because we need to handle 1609 READ32(op->opnum);
1608 * a missing opcode as an OP_WRITE + 1. So we need to check
1609 * to see if we're truly at the end of our buffer or if there
1610 * is another page we need to flip to.
1611 */
1612
1613 if (argp->p == argp->end) {
1614 if (argp->pagelen < 4) {
1615 /* There isn't an opcode still on the wire */
1616 op->opnum = OP_WRITE + 1;
1617 op->status = nfserr_bad_xdr;
1618 argp->opcnt = i+1;
1619 break;
1620 }
1621
1622 /*
1623 * False alarm. We just hit a page boundary, but there
1624 * is still data available. Move pointer across page
1625 * boundary. *snip from READ_BUF*
1626 */
1627 argp->p = page_address(argp->pagelist[0]);
1628 argp->pagelist++;
1629 if (argp->pagelen < PAGE_SIZE) {
1630 argp->end = argp->p + (argp->pagelen>>2);
1631 argp->pagelen = 0;
1632 } else {
1633 argp->end = argp->p + (PAGE_SIZE>>2);
1634 argp->pagelen -= PAGE_SIZE;
1635 }
1636 }
1637 op->opnum = ntohl(*argp->p++);
1638 1610
1639 if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP) 1611 if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
1640 op->status = ops->decoders[op->opnum](argp, &op->u); 1612 op->status = ops->decoders[op->opnum](argp, &op->u);
@@ -2014,6 +1986,22 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
2014 return 0; 1986 return 0;
2015} 1987}
2016 1988
1989
1990static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
1991{
1992 struct path path = exp->ex_path;
1993 int err;
1994
1995 path_get(&path);
1996 while (follow_up(&path)) {
1997 if (path.dentry != path.mnt->mnt_root)
1998 break;
1999 }
2000 err = vfs_getattr(path.mnt, path.dentry, stat);
2001 path_put(&path);
2002 return err;
2003}
2004
2017/* 2005/*
2018 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 2006 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
2019 * ourselves. 2007 * ourselves.
@@ -2048,6 +2036,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2048 .mnt = exp->ex_path.mnt, 2036 .mnt = exp->ex_path.mnt,
2049 .dentry = dentry, 2037 .dentry = dentry,
2050 }; 2038 };
2039 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2051 2040
2052 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); 2041 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
2053 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion)); 2042 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
@@ -2208,7 +2197,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2208 if (bmval0 & FATTR4_WORD0_LEASE_TIME) { 2197 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
2209 if ((buflen -= 4) < 0) 2198 if ((buflen -= 4) < 0)
2210 goto out_resource; 2199 goto out_resource;
2211 WRITE32(nfsd4_lease); 2200 WRITE32(nn->nfsd4_lease);
2212 } 2201 }
2213 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 2202 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
2214 if ((buflen -= 4) < 0) 2203 if ((buflen -= 4) < 0)
@@ -2430,18 +2419,8 @@ out_acl:
2430 * and this is the root of a cross-mounted filesystem. 2419 * and this is the root of a cross-mounted filesystem.
2431 */ 2420 */
2432 if (ignore_crossmnt == 0 && 2421 if (ignore_crossmnt == 0 &&
2433 dentry == exp->ex_path.mnt->mnt_root) { 2422 dentry == exp->ex_path.mnt->mnt_root)
2434 struct path path = exp->ex_path; 2423 get_parent_attributes(exp, &stat);
2435 path_get(&path);
2436 while (follow_up(&path)) {
2437 if (path.dentry != path.mnt->mnt_root)
2438 break;
2439 }
2440 err = vfs_getattr(path.mnt, path.dentry, &stat);
2441 path_put(&path);
2442 if (err)
2443 goto out_nfserr;
2444 }
2445 WRITE64(stat.ino); 2424 WRITE64(stat.ino);
2446 } 2425 }
2447 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2426 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
@@ -2927,7 +2906,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2927 struct nfsd4_read *read) 2906 struct nfsd4_read *read)
2928{ 2907{
2929 u32 eof; 2908 u32 eof;
2930 int v, pn; 2909 int v;
2910 struct page *page;
2931 unsigned long maxcount; 2911 unsigned long maxcount;
2932 long len; 2912 long len;
2933 __be32 *p; 2913 __be32 *p;
@@ -2946,11 +2926,15 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2946 len = maxcount; 2926 len = maxcount;
2947 v = 0; 2927 v = 0;
2948 while (len > 0) { 2928 while (len > 0) {
2949 pn = resp->rqstp->rq_resused++; 2929 page = *(resp->rqstp->rq_next_page);
2950 resp->rqstp->rq_vec[v].iov_base = 2930 if (!page) { /* ran out of pages */
2951 page_address(resp->rqstp->rq_respages[pn]); 2931 maxcount -= len;
2932 break;
2933 }
2934 resp->rqstp->rq_vec[v].iov_base = page_address(page);
2952 resp->rqstp->rq_vec[v].iov_len = 2935 resp->rqstp->rq_vec[v].iov_len =
2953 len < PAGE_SIZE ? len : PAGE_SIZE; 2936 len < PAGE_SIZE ? len : PAGE_SIZE;
2937 resp->rqstp->rq_next_page++;
2954 v++; 2938 v++;
2955 len -= PAGE_SIZE; 2939 len -= PAGE_SIZE;
2956 } 2940 }
@@ -2996,8 +2980,10 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd
2996 return nfserr; 2980 return nfserr;
2997 if (resp->xbuf->page_len) 2981 if (resp->xbuf->page_len)
2998 return nfserr_resource; 2982 return nfserr_resource;
2983 if (!*resp->rqstp->rq_next_page)
2984 return nfserr_resource;
2999 2985
3000 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 2986 page = page_address(*(resp->rqstp->rq_next_page++));
3001 2987
3002 maxcount = PAGE_SIZE; 2988 maxcount = PAGE_SIZE;
3003 RESERVE_SPACE(4); 2989 RESERVE_SPACE(4);
@@ -3045,6 +3031,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3045 return nfserr; 3031 return nfserr;
3046 if (resp->xbuf->page_len) 3032 if (resp->xbuf->page_len)
3047 return nfserr_resource; 3033 return nfserr_resource;
3034 if (!*resp->rqstp->rq_next_page)
3035 return nfserr_resource;
3048 3036
3049 RESERVE_SPACE(NFS4_VERIFIER_SIZE); 3037 RESERVE_SPACE(NFS4_VERIFIER_SIZE);
3050 savep = p; 3038 savep = p;
@@ -3071,7 +3059,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3071 goto err_no_verf; 3059 goto err_no_verf;
3072 } 3060 }
3073 3061
3074 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 3062 page = page_address(*(resp->rqstp->rq_next_page++));
3075 readdir->common.err = 0; 3063 readdir->common.err = 0;
3076 readdir->buflen = maxcount; 3064 readdir->buflen = maxcount;
3077 readdir->buffer = page; 3065 readdir->buffer = page;
@@ -3094,8 +3082,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3094 p = readdir->buffer; 3082 p = readdir->buffer;
3095 *p++ = 0; /* no more entries */ 3083 *p++ = 0; /* no more entries */
3096 *p++ = htonl(readdir->common.err == nfserr_eof); 3084 *p++ = htonl(readdir->common.err == nfserr_eof);
3097 resp->xbuf->page_len = ((char*)p) - (char*)page_address( 3085 resp->xbuf->page_len = ((char*)p) -
3098 resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); 3086 (char*)page_address(*(resp->rqstp->rq_next_page-1));
3099 3087
3100 /* Use rest of head for padding and remaining ops: */ 3088 /* Use rest of head for padding and remaining ops: */
3101 resp->xbuf->tail[0].iov_base = tailbase; 3089 resp->xbuf->tail[0].iov_base = tailbase;