Date: Thu, 27 Apr 2017 23:46:00 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r317534 - projects/pnfs-planb-server/sys/fs/nfsserver Message-ID: <201704272346.v3RNk08p033118@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rmacklem Date: Thu Apr 27 23:46:00 2017 New Revision: 317534 URL: https://svnweb.freebsd.org/changeset/base/317534 Log: Update nfs_nfsdserv.c to include the pNFS server code. Modified: projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c Modified: projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c ============================================================================== --- projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c Thu Apr 27 23:31:38 2017 (r317533) +++ projects/pnfs-planb-server/sys/fs/nfsserver/nfs_nfsdserv.c Thu Apr 27 23:46:00 2017 (r317534) @@ -54,6 +54,11 @@ extern struct timeval nfsboottime; extern int nfs_rootfhset; extern int nfsrv_enable_crossmntpt; extern int nfsrv_statehashsize; +extern int nfsrv_layouthashsize; +extern time_t nfsdev_time; +extern struct nfsdevicehead nfsrv_devidhead; +extern int nfsd_debuglevel; +extern u_long sb_max_adj; #endif /* !APPLEKEXT */ static int nfs_async = 0; @@ -151,7 +156,7 @@ nfsrvd_access(struct nfsrv_descript *nd, } nfsmode &= supported; if (nd->nd_flag & ND_NFSV3) { - getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &nva, nd, p, 1); nfsrv_postopattr(nd, getret, &nva); } vput(vp); @@ -235,14 +240,14 @@ nfsrvd_getattr(struct nfsrv_descript *nd } } if (!nd->nd_repstat) - nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1); if (!nd->nd_repstat) { if (nd->nd_flag & ND_NFSV4) { if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_FILEHANDLE)) nd->nd_repstat = nfsvno_getfh(vp, &fh, p); if (!nd->nd_repstat) nd->nd_repstat = nfsrv_checkgetattr(nd, vp, - &nva, &attrbits, nd->nd_cred, p); + &nva, &attrbits, p); if (nd->nd_repstat == 0) { supports_nfsv4acls = nfs_supportsnfsv4acls(vp); mp = vp->v_mount; @@ -307,6 +312,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd struct nfsvattr nva, nva2; u_int32_t *tl; int preat_ret = 1, postat_ret = 1, gcheck = 0, error = 0; + int gotproxystateid; struct timespec guard = { 0, 0 }; nfsattrbit_t attrbits, retbits; nfsv4stateid_t stateid; @@ -320,17 +326,25 @@ nfsrvd_setattr(struct nfsrv_descript *nd aclp = acl_alloc(M_WAITOK); aclp->acl_cnt = 0; #endif + gotproxystateid = 0; NFSVNO_ATTRINIT(&nva); NFSZERO_ATTRBIT(&retbits); if (nd->nd_flag & ND_NFSV4) { NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); - NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER); + stateid.other[0] = *tl++; + stateid.other[1] = *tl++; + stateid.other[2] = *tl; + if (stateid.other[0] == 0x55555555 && + stateid.other[1] == 0x55555555 && + stateid.other[2] == 0x55555555 && + stateid.seqid == 0xffffffff) + gotproxystateid = 1; } error = nfsrv_sattr(nd, vp, &nva, &attrbits, aclp, p); if (error) goto nfsmout; - preat_ret = nfsvno_getattr(vp, &nva2, nd->nd_cred, p, 1); + preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1); if (!nd->nd_repstat) nd->nd_repstat = preat_ret; if (nd->nd_flag & ND_NFSV3) { @@ -376,7 +390,12 @@ nfsrvd_setattr(struct nfsrv_descript *nd NFSACCCHK_VPISLOCKED, NULL); } } - if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) + /* + * Proxy operations from the MDS are allowed via the all 0s special + * stateid. + */ + if (nd->nd_repstat == 0 && (nd->nd_flag & ND_NFSV4) != 0 && + gotproxystateid == 0) nd->nd_repstat = nfsrv_checksetattr(vp, nd, &stateid, &nva, &attrbits, exp, p); @@ -450,7 +469,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd exp); } if (nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) { - postat_ret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + postat_ret = nfsvno_getattr(vp, &nva, nd, p, 1); if (!nd->nd_repstat) nd->nd_repstat = postat_ret; } @@ -534,8 +553,8 @@ nfsrvd_lookup(struct nfsrv_descript *nd, if (nd->nd_repstat) { if (dirp) { if (nd->nd_flag & ND_NFSV3) - dattr_ret = nfsvno_getattr(dirp, &dattr, - nd->nd_cred, p, 0); + dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p, + 0); vrele(dirp); } if (nd->nd_flag & ND_NFSV3) @@ -556,15 +575,14 @@ nfsrvd_lookup(struct nfsrv_descript *nd, if (nd->nd_repstat == 0) nd->nd_repstat = nfsvno_getfh(vp, fhp, p); if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) - nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1); if (vpp != NULL && nd->nd_repstat == 0) *vpp = vp; else vput(vp); if (dirp) { if (nd->nd_flag & ND_NFSV3) - dattr_ret = nfsvno_getattr(dirp, &dattr, nd->nd_cred, - p, 0); + dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p, 0); vrele(dirp); } if (nd->nd_repstat) { @@ -612,7 +630,7 @@ nfsrvd_readlink(struct nfsrv_descript *n nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, p, &mp, &mpend, &len); if (nd->nd_flag & ND_NFSV3) - getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &nva, nd, p, 1); vput(vp); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &nva); @@ -637,7 +655,7 @@ nfsrvd_read(struct nfsrv_descript *nd, _ vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) { u_int32_t *tl; - int error = 0, cnt, getret = 1, reqlen, eof = 0; + int error = 0, cnt, getret = 1, gotproxystateid, reqlen, eof = 0; mbuf_t m2, m3; struct nfsvattr nva; off_t off = 0x0; @@ -669,6 +687,7 @@ nfsrvd_read(struct nfsrv_descript *nd, _ error = EBADRPC; goto nfsmout; } + gotproxystateid = 0; if (nd->nd_flag & ND_NFSV4) { stp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS); lop->lo_flags = NFSLCK_READ; @@ -690,6 +709,24 @@ nfsrvd_read(struct nfsrv_descript *nd, _ nd->nd_clientid.qval = clientid.qval; } stp->ls_stateid.other[2] = *tl++; + /* + * Don't allow the client to use a special stateid for a DS op. + */ + if ((nd->nd_flag & ND_DSSERVER) != 0 && + ((stp->ls_stateid.other[0] == 0x0 && + stp->ls_stateid.other[1] == 0x0 && + stp->ls_stateid.other[2] == 0x0) || + (stp->ls_stateid.other[0] == 0xffffffff && + stp->ls_stateid.other[1] == 0xffffffff && + stp->ls_stateid.other[2] == 0xffffffff) || + stp->ls_stateid.seqid != 0)) + nd->nd_repstat = NFSERR_BADSTATEID; + /* However, allow the proxy stateid. */ + if (stp->ls_stateid.seqid == 0xffffffff && + stp->ls_stateid.other[0] == 0x55555555 && + stp->ls_stateid.other[1] == 0x55555555 && + stp->ls_stateid.other[2] == 0x55555555) + gotproxystateid = 1; off = fxdr_hyper(tl); lop->lo_first = off; tl += 2; @@ -707,7 +744,7 @@ nfsrvd_read(struct nfsrv_descript *nd, _ nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR : EINVAL; } - getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &nva, nd, p, 1); if (!nd->nd_repstat) nd->nd_repstat = getret; if (!nd->nd_repstat && @@ -721,7 +758,12 @@ nfsrvd_read(struct nfsrv_descript *nd, _ nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); } - if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) + /* + * DS reads are marked by ND_DSSERVER or use the proxy special + * stateid. + */ + if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) == + ND_NFSV4 && gotproxystateid == 0) nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, &stateid, exp, nd, p); if (nd->nd_repstat) { @@ -745,7 +787,7 @@ nfsrvd_read(struct nfsrv_descript *nd, _ nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, p, &m3, &m2); if (!(nd->nd_flag & ND_NFSV4)) { - getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &nva, nd, p, 1); if (!nd->nd_repstat) nd->nd_repstat = getret; } @@ -802,7 +844,7 @@ nfsrvd_write(struct nfsrv_descript *nd, mbuf_t mp; struct nfsvattr nva, forat; int aftat_ret = 1, retlen, len, error = 0, forat_ret = 1; - int stable = NFSWRITE_FILESYNC; + int gotproxystateid, stable = NFSWRITE_FILESYNC; off_t off; struct nfsstate st, *stp = &st; struct nfslock lo, *lop = &lo; @@ -813,6 +855,7 @@ nfsrvd_write(struct nfsrv_descript *nd, nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); goto out; } + gotproxystateid = 0; if (nd->nd_flag & ND_NFSV2) { NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); off = (off_t)fxdr_unsigned(u_int32_t, *++tl); @@ -846,6 +889,24 @@ nfsrvd_write(struct nfsrv_descript *nd, nd->nd_clientid.qval = clientid.qval; } stp->ls_stateid.other[2] = *tl++; + /* + * Don't allow the client to use a special stateid for a DS op. + */ + if ((nd->nd_flag & ND_DSSERVER) != 0 && + ((stp->ls_stateid.other[0] == 0x0 && + stp->ls_stateid.other[1] == 0x0 && + stp->ls_stateid.other[2] == 0x0) || + (stp->ls_stateid.other[0] == 0xffffffff && + stp->ls_stateid.other[1] == 0xffffffff && + stp->ls_stateid.other[2] == 0xffffffff) || + stp->ls_stateid.seqid != 0)) + nd->nd_repstat = NFSERR_BADSTATEID; + /* However, allow the proxy stateid. */ + if (stp->ls_stateid.seqid == 0xffffffff && + stp->ls_stateid.other[0] == 0x55555555 && + stp->ls_stateid.other[1] == 0x55555555 && + stp->ls_stateid.other[2] == 0x55555555) + gotproxystateid = 1; off = fxdr_hyper(tl); lop->lo_first = off; tl += 2; @@ -891,7 +952,7 @@ nfsrvd_write(struct nfsrv_descript *nd, nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR : EINVAL; } - forat_ret = nfsvno_getattr(vp, &forat, nd->nd_cred, p, 1); + forat_ret = nfsvno_getattr(vp, &forat, nd, p, 1); if (!nd->nd_repstat) nd->nd_repstat = forat_ret; if (!nd->nd_repstat && @@ -900,10 +961,14 @@ nfsrvd_write(struct nfsrv_descript *nd, nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); - if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { + /* + * DS reads are marked by ND_DSSERVER or use the proxy special + * stateid. + */ + if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) == + ND_NFSV4 && gotproxystateid == 0) nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, &stateid, exp, nd, p); - } if (nd->nd_repstat) { vput(vp); if (nd->nd_flag & ND_NFSV3) @@ -917,7 +982,7 @@ nfsrvd_write(struct nfsrv_descript *nd, * which is to return ok so long as there are no permission problems. */ if (retlen > 0) { - nd->nd_repstat = nfsvno_write(vp, off, retlen, cnt, stable, + nd->nd_repstat = nfsvno_write(vp, off, retlen, cnt, &stable, nd->nd_md, nd->nd_dpos, nd->nd_cred, p); error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1); if (error) @@ -926,7 +991,7 @@ nfsrvd_write(struct nfsrv_descript *nd, if (nd->nd_flag & ND_NFSV4) aftat_ret = 0; else - aftat_ret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + aftat_ret = nfsvno_getattr(vp, &nva, nd, p, 1); vput(vp); if (!nd->nd_repstat) nd->nd_repstat = aftat_ret; @@ -1048,8 +1113,7 @@ nfsrvd_create(struct nfsrv_descript *nd, if (nd->nd_repstat) { nfsvno_relpathbuf(&named); if (nd->nd_flag & ND_NFSV3) { - dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred, - p, 1); + dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 1); nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); } @@ -1063,8 +1127,7 @@ nfsrvd_create(struct nfsrv_descript *nd, vrele(dirp); dirp = NULL; } else { - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, - p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); } } if (nd->nd_repstat) { @@ -1102,8 +1165,7 @@ nfsrvd_create(struct nfsrv_descript *nd, if (!nd->nd_repstat) { nd->nd_repstat = nfsvno_getfh(vp, &fh, p); if (!nd->nd_repstat) - nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, - p, 1); + nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1); vput(vp); if (!nd->nd_repstat) { tverf[0] = nva.na_atime.tv_sec; @@ -1119,7 +1181,7 @@ nfsrvd_create(struct nfsrv_descript *nd, if (exclusive_flag && !nd->nd_repstat && (cverf[0] != tverf[0] || cverf[1] != tverf[1])) nd->nd_repstat = EEXIST; - diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); + diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0); vrele(dirp); if (!nd->nd_repstat) { (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 1); @@ -1229,7 +1291,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, } } - dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 0); if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) { if (!dirfor_ret && NFSVNO_ISSETGID(&nva) && dirfor.na_gid == nva.na_gid) @@ -1267,8 +1329,8 @@ nfsrvd_mknod(struct nfsrv_descript *nd, if (nd->nd_repstat) { if (dirp) { if (nd->nd_flag & ND_NFSV3) - dirfor_ret = nfsvno_getattr(dirp, &dirfor, - nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, + p, 0); vrele(dirp); } #ifdef NFS4_ACL_EXTATTR_NAME @@ -1280,7 +1342,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, goto out; } if (dirp) - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) { if (vtyp == VDIR) { @@ -1309,8 +1371,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp); nd->nd_repstat = nfsvno_getfh(vp, fhp, p); if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat) - nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, - p, 1); + nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1); if (vpp != NULL && nd->nd_repstat == 0) { NFSVOPUNLOCK(vp, 0); *vpp = vp; @@ -1318,7 +1379,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, vput(vp); } - diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); + diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0); vrele(dirp); if (!nd->nd_repstat) { if (nd->nd_flag & ND_NFSV3) { @@ -1392,8 +1453,7 @@ nfsrvd_remove(struct nfsrv_descript *nd, } if (dirp) { if (!(nd->nd_flag & ND_NFSV2)) { - dirfor_ret = nfsvno_getattr(dirp, &dirfor, - nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); } else { vrele(dirp); dirp = NULL; @@ -1417,8 +1477,7 @@ nfsrvd_remove(struct nfsrv_descript *nd, } if (!(nd->nd_flag & ND_NFSV2)) { if (dirp) { - diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, - p, 0); + diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0); vrele(dirp); } if (nd->nd_flag & ND_NFSV3) { @@ -1464,7 +1523,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, goto out; } if (!(nd->nd_flag & ND_NFSV2)) - fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd->nd_cred, p, 1); + fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd, p, 1); tond.ni_cnd.cn_nameiop = 0; tond.ni_startdir = NULL; NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT | SAVESTART); @@ -1487,11 +1546,10 @@ nfsrvd_rename(struct nfsrv_descript *nd, tnes = *toexp; if (dp != tdp) { NFSVOPUNLOCK(dp, 0); - tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, - p, 0); /* Might lock tdp. */ + /* Might lock tdp. */ + tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 0); } else { - tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, - p, 1); + tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1); NFSVOPUNLOCK(dp, 0); } } else { @@ -1512,8 +1570,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, VREF(dp); tdp = dp; tnes = *exp; - tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, - p, 1); + tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1); NFSVOPUNLOCK(dp, 0); } else { NFSVOPUNLOCK(dp, 0); @@ -1521,8 +1578,8 @@ nfsrvd_rename(struct nfsrv_descript *nd, nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 0, p); /* Locks tdp. */ if (tdp) { - tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, - nd->nd_cred, p, 1); + tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, + p, 1); NFSVOPUNLOCK(tdp, 0); } } @@ -1579,11 +1636,9 @@ nfsrvd_rename(struct nfsrv_descript *nd, nd->nd_repstat = nfsvno_rename(&fromnd, &tond, nd->nd_repstat, nd->nd_flag, nd->nd_cred, p); if (fdirp) - fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd->nd_cred, p, - 0); + fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd, p, 0); if (tdirp) - tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd->nd_cred, p, - 0); + tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd, p, 0); if (fdirp) vrele(fdirp); if (tdirp) @@ -1684,16 +1739,15 @@ nfsrvd_link(struct nfsrv_descript *nd, i vrele(dirp); dirp = NULL; } else { - dirfor_ret = nfsvno_getattr(dirp, &dirfor, - nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); } } if (!nd->nd_repstat) nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp); if (nd->nd_flag & ND_NFSV3) - getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 0); + getret = nfsvno_getattr(vp, &at, nd, p, 0); if (dirp) { - diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); + diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0); vrele(dirp); } vrele(vp); @@ -1763,13 +1817,12 @@ nfsrvd_symlink(struct nfsrv_descript *nd */ if (!nd->nd_repstat) { if (dirp != NULL) - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, - p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp, pathcp, pathlen); } else if (dirp != NULL) { - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); vrele(dirp); } if (pathcp) @@ -1809,7 +1862,7 @@ nfsrvd_symlinksub(struct nfsrv_descript nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p); if (!nd->nd_repstat) nd->nd_repstat = nfsvno_getattr(ndp->ni_vp, - nvap, nd->nd_cred, p, 1); + nvap, nd, p, 1); } if (vpp != NULL && nd->nd_repstat == 0) { NFSVOPUNLOCK(ndp->ni_vp, 0); @@ -1818,7 +1871,7 @@ nfsrvd_symlinksub(struct nfsrv_descript vput(ndp->ni_vp); } if (dirp) { - *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0); + *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0); vrele(dirp); } if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { @@ -1882,8 +1935,7 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, } if (nd->nd_repstat) { if (dirp != NULL) { - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, - p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); vrele(dirp); } if (nd->nd_flag & ND_NFSV3) @@ -1892,7 +1944,7 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, goto out; } if (dirp != NULL) - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0); /* * Call nfsrvd_mkdirsub() for the code common to V4 as well. @@ -1942,8 +1994,7 @@ nfsrvd_mkdirsub(struct nfsrv_descript *n nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp); nd->nd_repstat = nfsvno_getfh(vp, fhp, p); if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) - nd->nd_repstat = nfsvno_getattr(vp, nvap, nd->nd_cred, - p, 1); + nd->nd_repstat = nfsvno_getattr(vp, nvap, nd, p, 1); if (vpp && !nd->nd_repstat) { NFSVOPUNLOCK(vp, 0); *vpp = vp; @@ -1952,7 +2003,7 @@ nfsrvd_mkdirsub(struct nfsrv_descript *n } } if (dirp) { - *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0); + *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0); vrele(dirp); } if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { @@ -2002,10 +2053,10 @@ nfsrvd_commit(struct nfsrv_descript *nd, tl += 2; cnt = fxdr_unsigned(int, *tl); if (nd->nd_flag & ND_NFSV3) - for_ret = nfsvno_getattr(vp, &bfor, nd->nd_cred, p, 1); + for_ret = nfsvno_getattr(vp, &bfor, nd, p, 1); nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p); if (nd->nd_flag & ND_NFSV3) { - aft_ret = nfsvno_getattr(vp, &aft, nd->nd_cred, p, 1); + aft_ret = nfsvno_getattr(vp, &aft, nd, p, 1); nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft); } vput(vp); @@ -2044,7 +2095,7 @@ nfsrvd_statfs(struct nfsrv_descript *nd, } sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); nd->nd_repstat = nfsvno_statfs(vp, sf); - getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &at, nd, p, 1); vput(vp); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &at); @@ -2099,7 +2150,7 @@ nfsrvd_fsinfo(struct nfsrv_descript *nd, nfsrv_postopattr(nd, getret, &at); goto out; } - getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &at, nd, p, 1); nfsvno_getfs(&fs, isdgram); vput(vp); nfsrv_postopattr(nd, getret, &at); @@ -2149,7 +2200,7 @@ nfsrvd_pathconf(struct nfsrv_descript *n if (!nd->nd_repstat) nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, ¬runc, nd->nd_cred, p); - getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); + getret = nfsvno_getattr(vp, &at, nd, p, 1); vput(vp); nfsrv_postopattr(nd, getret, &at); if (!nd->nd_repstat) { @@ -2232,6 +2283,25 @@ nfsrvd_lock(struct nfsrv_descript *nd, _ NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, NFSX_STATEIDOTHER); tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + + /* + * For the special stateid of other all 0s and seqid == 1, set + * the stateid to the current stateid, if it is set. + */ + if ((nd->nd_flag & ND_NFSV41) != 0 && + stp->ls_stateid.seqid == 1 && + stp->ls_stateid.other[0] == 0 && + stp->ls_stateid.other[1] == 0 && + stp->ls_stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) { + stp->ls_stateid = nd->nd_curstateid; + stp->ls_stateid.seqid = 0; + } else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + stp->ls_opentolockseq = fxdr_unsigned(int, *tl++); clientid.lval[0] = *tl++; clientid.lval[1] = *tl++; @@ -2259,6 +2329,25 @@ nfsrvd_lock(struct nfsrv_descript *nd, _ NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, NFSX_STATEIDOTHER); tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + + /* + * For the special stateid of other all 0s and seqid == 1, set + * the stateid to the current stateid, if it is set. + */ + if ((nd->nd_flag & ND_NFSV41) != 0 && + stp->ls_stateid.seqid == 1 && + stp->ls_stateid.other[0] == 0 && + stp->ls_stateid.other[1] == 0 && + stp->ls_stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) { + stp->ls_stateid = nd->nd_curstateid; + stp->ls_stateid.seqid = 0; + } else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + stp->ls_seq = fxdr_unsigned(int, *tl); clientid.lval[0] = stp->ls_stateid.other[0]; clientid.lval[1] = stp->ls_stateid.other[1]; @@ -2325,6 +2414,11 @@ nfsrvd_lock(struct nfsrv_descript *nd, _ if (stp) FREE((caddr_t)stp, M_NFSDSTATE); if (!nd->nd_repstat) { + /* For NFSv4.1, set the Current StateID. */ + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_curstateid = stateid; + nd->nd_flag |= ND_CURSTATEID; + } NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); *tl++ = txdr_unsigned(stateid.seqid); NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); @@ -2518,6 +2612,23 @@ nfsrvd_locku(struct nfsrv_descript *nd, NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, NFSX_STATEIDOTHER); tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + + /* + * For the special stateid of other all 0s and seqid == 1, set the + * stateid to the current stateid, if it is set. + */ + if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 && + stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 && + stp->ls_stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) { + stp->ls_stateid = nd->nd_curstateid; + stp->ls_stateid.seqid = 0; + } else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + lop->lo_first = fxdr_hyper(tl); tl += 2; len = fxdr_hyper(tl); @@ -2697,7 +2808,7 @@ nfsrvd_open(struct nfsrv_descript *nd, _ NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); create = fxdr_unsigned(int, *tl); if (!nd->nd_repstat) - nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0); + nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd, p, 0); if (create == NFSV4OPEN_CREATE) { nva.na_type = VREG; nva.na_mode = 0; @@ -2896,7 +3007,7 @@ nfsrvd_open(struct nfsrv_descript *nd, _ } if (!nd->nd_repstat) { - nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1); if (!nd->nd_repstat) { tverf[0] = nva.na_atime.tv_sec; tverf[1] = nva.na_atime.tv_nsec; @@ -2922,9 +3033,13 @@ nfsrvd_open(struct nfsrv_descript *nd, _ if (stp) FREE((caddr_t)stp, M_NFSDSTATE); if (!nd->nd_repstat && dirp) - nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, - 0); + nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd, p, 0); if (!nd->nd_repstat) { + /* For NFSv4.1, set the Current StateID. */ + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_curstateid = stateid; + nd->nd_flag |= ND_CURSTATEID; + } NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED); *tl++ = txdr_unsigned(stateid.seqid); NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); @@ -3036,6 +3151,22 @@ nfsrvd_close(struct nfsrv_descript *nd, stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, NFSX_STATEIDOTHER); + + /* + * For the special stateid of other all 0s and seqid == 1, set the + * stateid to the current stateid, if it is set. + */ + if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 && + stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 && + stp->ls_stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) + stp->ls_stateid = nd->nd_curstateid; + else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + stp->ls_flags = NFSLCK_CLOSE; clientid.lval[0] = stp->ls_stateid.other[0]; clientid.lval[1] = stp->ls_stateid.other[1]; @@ -3053,6 +3184,15 @@ nfsrvd_close(struct nfsrv_descript *nd, nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p); vput(vp); if (!nd->nd_repstat) { + /* + * If the stateid that has been closed is the current stateid, + * unset it. + */ + if ((nd->nd_flag & ND_CURSTATEID) != 0 && + stateid.other[0] == nd->nd_curstateid.other[0] && + stateid.other[1] == nd->nd_curstateid.other[1] && + stateid.other[2] == nd->nd_curstateid.other[2]) + nd->nd_flag &= ~ND_CURSTATEID; NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); *tl++ = txdr_unsigned(stateid.seqid); NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); @@ -3233,6 +3373,22 @@ nfsrvd_opendowngrade(struct nfsrv_descri NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, NFSX_STATEIDOTHER); tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + + /* + * For the special stateid of other all 0s and seqid == 1, set the + * stateid to the current stateid, if it is set. + */ + if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 && + stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 && + stp->ls_stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) + stp->ls_stateid = nd->nd_curstateid; + else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); i = fxdr_unsigned(int, *tl++); switch (i) { @@ -3283,6 +3439,11 @@ nfsrvd_opendowngrade(struct nfsrv_descri nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p); if (!nd->nd_repstat) { + /* For NFSv4.1, set the Current StateID. */ + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_curstateid = stateid; + nd->nd_flag |= ND_CURSTATEID; + } NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); *tl++ = txdr_unsigned(stateid.seqid); NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); @@ -3609,7 +3770,7 @@ nfsrvd_verify(struct nfsrv_descript *nd, fhandle_t fh; sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); - nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); + nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1); if (!nd->nd_repstat) nd->nd_repstat = nfsvno_statfs(vp, sf); if (!nd->nd_repstat) @@ -3787,7 +3948,10 @@ nfsrvd_exchangeid(struct nfsrv_descript confirm.lval[1] = 1; else confirm.lval[1] = 0; - v41flags = NFSV4EXCH_USENONPNFS; + if (TAILQ_EMPTY(&nfsrv_devidhead)) + v41flags = NFSV4EXCH_USENONPNFS | NFSV4EXCH_USEPNFSDS; + else + v41flags = NFSV4EXCH_USEPNFSMDS; sp4type = fxdr_unsigned(uint32_t, *tl); if (sp4type != NFSV4EXCH_SP4NONE) { nd->nd_repstat = NFSERR_NOTSUPP; @@ -3878,7 +4042,15 @@ nfsrvd_createsession(struct nfsrv_descri NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); tl++; /* Header pad always 0. */ sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++); + if (sep->sess_maxreq > sb_max_adj - NFS_MAXXDR) { + sep->sess_maxreq = sb_max_adj - NFS_MAXXDR; + printf("Consider increasing kern.ipc.maxsockbuf\n"); + } sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++); + if (sep->sess_maxresp > sb_max_adj - NFS_MAXXDR) { + sep->sess_maxresp = sb_max_adj - NFS_MAXXDR; + printf("Consider increasing kern.ipc.maxsockbuf\n"); + } sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++); sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++); sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++); @@ -4080,7 +4252,361 @@ nfsrvd_freestateid(struct nfsrv_descript NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID); stateid.seqid = fxdr_unsigned(uint32_t, *tl++); NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); + + /* + * For the special stateid of other all 0s and seqid == 1, set the + * stateid to the current stateid, if it is set. + */ + if (stateid.seqid == 1 && stateid.other[0] == 0 && + stateid.other[1] == 0 && stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) { + stateid = nd->nd_curstateid; + stateid.seqid = 0; + } else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p); + + /* If the current stateid has been free'd, unset it. */ + if (nd->nd_repstat == 0 && (nd->nd_flag & ND_CURSTATEID) != 0 && + stateid.other[0] == nd->nd_curstateid.other[0] && + stateid.other[1] == nd->nd_curstateid.other[1] && + stateid.other[2] == nd->nd_curstateid.other[2]) + nd->nd_flag &= ~ND_CURSTATEID; +nfsmout: + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 layoutget service + */ +APPLESTATIC int +nfsrvd_layoutget(struct nfsrv_descript *nd, __unused int isdgram, + vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) +{ + uint32_t *tl; + nfsv4stateid_t stateid; + int error = 0, layoutlen, layouttype, iomode, maxcnt, retonclose; + uint64_t offset, len, minlen; + char *layp = NULL; + + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER + + NFSX_STATEID); + tl++; /* Signal layout available. Ignore for now. */ + layouttype = fxdr_unsigned(int, *tl++); + iomode = fxdr_unsigned(int, *tl++); + offset = fxdr_hyper(tl); tl += 2; + len = fxdr_hyper(tl); tl += 2; + minlen = fxdr_hyper(tl); tl += 2; + stateid.seqid = fxdr_unsigned(uint32_t, *tl++); + NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); + tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + maxcnt = fxdr_unsigned(int, tl); + NFSD_DEBUG(4, "layoutget ltyp=%d iom=%d off=%ju len=%ju mlen=%ju\n", + layouttype, iomode, (uintmax_t)offset, (uintmax_t)len, + (uintmax_t)minlen); + if (len < minlen || + (minlen != UINT64_MAX && offset + minlen < offset) || + (len != UINT64_MAX && offset + len < offset)) { + nd->nd_repstat = NFSERR_INVAL; + goto nfsmout; + } + + /* + * For the special stateid of other all 0s and seqid == 1, set the + * stateid to the current stateid, if it is set. + */ + if (stateid.seqid == 1 && stateid.other[0] == 0 && + stateid.other[1] == 0 && stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) { + stateid = nd->nd_curstateid; + stateid.seqid = 0; + } else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + + if (layouttype == NFSLAYOUT_NFSV4_1_FILES) + layp = malloc(NFSX_V4FILELAYOUT, M_TEMP, M_WAITOK); + else + layp = malloc(NFSX_V4MAXLAYOUT, M_TEMP, M_WAITOK); + nd->nd_repstat = nfsrv_layoutget(nd, vp, exp, layouttype, &iomode, + &offset, &len, minlen, &stateid, maxcnt, &retonclose, &layoutlen, + layp, nd->nd_cred, p); + NFSD_DEBUG(4, "nfsrv_layoutget stat=%u layoutlen=%d\n", nd->nd_repstat, + layoutlen); + if (nd->nd_repstat == 0) { + /* For NFSv4.1, set the Current StateID. */ + if ((nd->nd_flag & ND_NFSV41) != 0) { + nd->nd_curstateid = stateid; + nd->nd_flag |= ND_CURSTATEID; + } + NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_STATEID + + 2 * NFSX_HYPER); + *tl++ = txdr_unsigned(retonclose); + *tl++ = txdr_unsigned(stateid.seqid); + NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER); + tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + *tl++ = txdr_unsigned(1); /* Only returns one layout. */ + txdr_hyper(offset, tl); tl += 2; + txdr_hyper(len, tl); tl += 2; + *tl++ = txdr_unsigned(iomode); + *tl = txdr_unsigned(layouttype); + nfsm_strtom(nd, layp, layoutlen); + } else if (nd->nd_repstat == NFSERR_LAYOUTTRYLATER) { + NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); + *tl = newnfs_false; + } + free(layp, M_TEMP); +nfsmout: + vput(vp); + NFSEXITCODE2(error, nd); + return (error); +} + +/* + * nfsv4 layoutcommit service + */ +APPLESTATIC int +nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram, + vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) +{ + uint32_t *tl; + nfsv4stateid_t stateid; + int error = 0, hasnewoff, hasnewmtime, layouttype, maxcnt, reclaim; + int hasnewsize; + uint64_t offset, len, newoff, newsize; + struct timespec newmtime; + char *layp; + + layp = NULL; + if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { + nd->nd_repstat = NFSERR_WRONGSEC; + goto nfsmout; + } + NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + 2 * NFSX_HYPER + + NFSX_STATEID); + offset = fxdr_hyper(tl); tl += 2; + len = fxdr_hyper(tl); tl += 2; + reclaim = fxdr_unsigned(int, *tl++); + stateid.seqid = fxdr_unsigned(uint32_t, *tl++); + NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); + tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); + /* + * For the special stateid of other all 0s and seqid == 1, set the + * stateid to the current stateid, if it is set. + */ + if (stateid.seqid == 1 && stateid.other[0] == 0 && + stateid.other[1] == 0 && stateid.other[2] == 0) { + if ((nd->nd_flag & ND_CURSTATEID) != 0) { + stateid = nd->nd_curstateid; + stateid.seqid = 0; + } else { + nd->nd_repstat = NFSERR_BADSTATEID; + goto nfsmout; + } + } + + hasnewoff = fxdr_unsigned(int, *tl); + if (hasnewoff != 0) { + NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED); + newoff = fxdr_hyper(tl); tl += 2; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704272346.v3RNk08p033118>