Date: Sun, 11 Jun 2017 20:27:39 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r319833 - projects/pnfs-planb-server-stable11/sys/fs/nfsserver Message-ID: <201706112027.v5BKRdIG071904@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rmacklem Date: Sun Jun 11 20:27:38 2017 New Revision: 319833 URL: https://svnweb.freebsd.org/changeset/base/319833 Log: Update some NFS server files with the pNFS code. Modified: projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdserv.c projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdsocket.c projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdstate.c projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdsubs.c Modified: projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdserv.c ============================================================================== --- projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdserv.c Sun Jun 11 20:18:18 2017 (r319832) +++ projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdserv.c Sun Jun 11 20:27:38 2017 (r319833) @@ -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, __unused int } 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, NULL); nfsrv_postopattr(nd, getret, &nva); } vput(vp); @@ -235,14 +240,14 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, } } 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, &attrbits); 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, __unused int 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,19 +326,32 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int 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); + + /* For NFSv4, only va_uid is used from nva2. */ + NFSZERO_ATTRBIT(&retbits); + NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER); + preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1, &retbits); if (!nd->nd_repstat) nd->nd_repstat = preat_ret; + + NFSZERO_ATTRBIT(&retbits); if (nd->nd_flag & ND_NFSV3) { NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); gcheck = fxdr_unsigned(int, *tl); @@ -376,7 +395,12 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int 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 +474,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int 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, NULL); if (!nd->nd_repstat) nd->nd_repstat = postat_ret; } @@ -534,8 +558,8 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int 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, NULL); vrele(dirp); } if (nd->nd_flag & ND_NFSV3) @@ -556,15 +580,15 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int 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, NULL); 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, + NULL); vrele(dirp); } if (nd->nd_repstat) { @@ -612,7 +636,7 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused in 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, NULL); vput(vp); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &nva); @@ -637,7 +661,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is 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 +693,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is 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 +715,24 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is 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 +750,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is 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, NULL); if (!nd->nd_repstat) nd->nd_repstat = getret; if (!nd->nd_repstat && @@ -721,7 +764,12 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is 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 +793,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is 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, NULL); if (!nd->nd_repstat) nd->nd_repstat = getret; } @@ -802,17 +850,19 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i 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; nfsv4stateid_t stateid; nfsquad_t clientid; + nfsattrbit_t attrbits; if (nd->nd_repstat) { 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 +896,24 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i 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 +959,9 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR : EINVAL; } - forat_ret = nfsvno_getattr(vp, &forat, nd->nd_cred, p, 1); + NFSZERO_ATTRBIT(&attrbits); + NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER); + forat_ret = nfsvno_getattr(vp, &forat, nd, p, 1, &attrbits); if (!nd->nd_repstat) nd->nd_repstat = forat_ret; if (!nd->nd_repstat && @@ -900,10 +970,14 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i 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 +991,7 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i * 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 +1000,7 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i 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, NULL); vput(vp); if (!nd->nd_repstat) nd->nd_repstat = aftat_ret; @@ -1048,8 +1122,8 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int 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, + NULL); nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); } @@ -1063,8 +1137,8 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int 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, + NULL); } } if (nd->nd_repstat) { @@ -1102,8 +1176,8 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int 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, + NULL); vput(vp); if (!nd->nd_repstat) { tverf[0] = nva.na_atime.tv_sec; @@ -1119,7 +1193,7 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int 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, NULL); vrele(dirp); if (!nd->nd_repstat) { (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 1); @@ -1229,7 +1303,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int i } } - dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL); if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) { if (!dirfor_ret && NFSVNO_ISSETGID(&nva) && dirfor.na_gid == nva.na_gid) @@ -1267,8 +1341,8 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int i 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, NULL); vrele(dirp); } #ifdef NFS4_ACL_EXTATTR_NAME @@ -1280,7 +1354,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int i goto out; } if (dirp) - dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); + dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL); if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) { if (vtyp == VDIR) { @@ -1309,8 +1383,8 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int i 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, + NULL); if (vpp != NULL && nd->nd_repstat == 0) { NFSVOPUNLOCK(vp, 0); *vpp = vp; @@ -1318,7 +1392,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int i vput(vp); } - diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); + diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL); vrele(dirp); if (!nd->nd_repstat) { if (nd->nd_flag & ND_NFSV3) { @@ -1392,8 +1466,8 @@ nfsrvd_remove(struct nfsrv_descript *nd, __unused int } 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, + NULL); } else { vrele(dirp); dirp = NULL; @@ -1417,8 +1491,8 @@ nfsrvd_remove(struct nfsrv_descript *nd, __unused int } 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, + NULL); vrele(dirp); } if (nd->nd_flag & ND_NFSV3) { @@ -1464,7 +1538,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 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, NULL); tond.ni_cnd.cn_nameiop = 0; tond.ni_startdir = NULL; NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT | SAVESTART); @@ -1487,11 +1561,12 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 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, + NULL); } else { - tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, - p, 1); + tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1, + NULL); NFSVOPUNLOCK(dp, 0); } } else { @@ -1512,8 +1587,8 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 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, + NULL); NFSVOPUNLOCK(dp, 0); } else { NFSVOPUNLOCK(dp, 0); @@ -1521,8 +1596,8 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 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, NULL); NFSVOPUNLOCK(tdp, 0); } } @@ -1579,11 +1654,9 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 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, NULL); if (tdirp) - tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd->nd_cred, p, - 0); + tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd, p, 0, NULL); if (fdirp) vrele(fdirp); if (tdirp) @@ -1684,16 +1757,16 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram, 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, + NULL); } } 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, NULL); if (dirp) { - diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); + diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL); vrele(dirp); } vrele(vp); @@ -1763,13 +1836,13 @@ nfsrvd_symlink(struct nfsrv_descript *nd, __unused int */ 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, + NULL); 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, NULL); vrele(dirp); } if (pathcp) @@ -1809,7 +1882,7 @@ nfsrvd_symlinksub(struct nfsrv_descript *nd, struct na 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, NULL); } if (vpp != NULL && nd->nd_repstat == 0) { NFSVOPUNLOCK(ndp->ni_vp, 0); @@ -1818,7 +1891,7 @@ nfsrvd_symlinksub(struct nfsrv_descript *nd, struct na 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, NULL); vrele(dirp); } if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { @@ -1882,8 +1955,8 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int i } 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, + NULL); vrele(dirp); } if (nd->nd_flag & ND_NFSV3) @@ -1892,7 +1965,7 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int i 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, NULL); /* * Call nfsrvd_mkdirsub() for the code common to V4 as well. @@ -1942,8 +2015,8 @@ nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct name 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, + NULL); if (vpp && !nd->nd_repstat) { NFSVOPUNLOCK(vp, 0); *vpp = vp; @@ -1952,7 +2025,7 @@ nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct name } } if (dirp) { - *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0); + *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL); vrele(dirp); } if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { @@ -2002,10 +2075,10 @@ nfsrvd_commit(struct nfsrv_descript *nd, __unused int 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, NULL); 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, NULL); nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft); } vput(vp); @@ -2044,7 +2117,7 @@ nfsrvd_statfs(struct nfsrv_descript *nd, __unused int } 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, NULL); vput(vp); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &at); @@ -2099,7 +2172,7 @@ nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram, 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, NULL); nfsvno_getfs(&fs, isdgram); vput(vp); nfsrv_postopattr(nd, getret, &at); @@ -2149,7 +2222,7 @@ nfsrvd_pathconf(struct nfsrv_descript *nd, __unused in 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, NULL); vput(vp); nfsrv_postopattr(nd, getret, &at); if (!nd->nd_repstat) { @@ -2232,6 +2305,25 @@ nfsrvd_lock(struct nfsrv_descript *nd, __unused int is 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 +2351,25 @@ nfsrvd_lock(struct nfsrv_descript *nd, __unused int is 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 +2436,11 @@ nfsrvd_lock(struct nfsrv_descript *nd, __unused int is 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 +2634,23 @@ nfsrvd_locku(struct nfsrv_descript *nd, __unused int i 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 +2830,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int is 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, NULL); if (create == NFSV4OPEN_CREATE) { nva.na_type = VREG; nva.na_mode = 0; @@ -2896,7 +3029,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int is } 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, NULL); if (!nd->nd_repstat) { tverf[0] = nva.na_atime.tv_sec; tverf[1] = nva.na_atime.tv_nsec; @@ -2922,9 +3055,13 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int is 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, NULL); 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); @@ -3024,9 +3161,10 @@ nfsrvd_close(struct nfsrv_descript *nd, __unused int i { u_int32_t *tl; struct nfsstate st, *stp = &st; - int error = 0; + int error = 0, writeacc; nfsv4stateid_t stateid; nfsquad_t clientid; + struct nfsvattr na; NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); @@ -3036,6 +3174,22 @@ nfsrvd_close(struct nfsrv_descript *nd, __unused int i 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]; @@ -3050,9 +3204,22 @@ nfsrvd_close(struct nfsrv_descript *nd, __unused int i nd->nd_flag |= ND_IMPLIEDCLID; nd->nd_clientid.qval = clientid.qval; } - nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p); + nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p, + &writeacc); + /* For pNFS, update the attributes. */ + if (writeacc != 0) + nfsrv_updatemdsattr(vp, &na, 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); @@ -3095,7 +3262,7 @@ nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused nd->nd_clientid.qval = clientid.qval; } nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL, - NFSV4OP_DELEGPURGE, nd->nd_cred, p); + NFSV4OP_DELEGPURGE, nd->nd_cred, p, NULL); nfsmout: NFSEXITCODE2(error, nd); return (error); @@ -3109,9 +3276,10 @@ nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) { u_int32_t *tl; - int error = 0; + int error = 0, writeacc; nfsv4stateid_t stateid; nfsquad_t clientid; + struct nfsvattr na; NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); @@ -3130,7 +3298,10 @@ nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused nd->nd_clientid.qval = clientid.qval; } nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp, - NFSV4OP_DELEGRETURN, nd->nd_cred, p); + NFSV4OP_DELEGRETURN, nd->nd_cred, p, &writeacc); + /* For pNFS, update the attributes. */ + if (writeacc != 0) + nfsrv_updatemdsattr(vp, &na, p); nfsmout: vput(vp); NFSEXITCODE2(error, nd); @@ -3194,7 +3365,8 @@ nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused nd->nd_flag |= ND_IMPLIEDCLID; nd->nd_clientid.qval = clientid.qval; } - nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p); + nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p, + NULL); if (!nd->nd_repstat) { NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); *tl++ = txdr_unsigned(stateid.seqid); @@ -3233,6 +3405,22 @@ nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unus 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) { @@ -3281,8 +3469,13 @@ nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unus } if (!nd->nd_repstat) nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, - nd, p); + nd, p, NULL); 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 +3802,7 @@ nfsrvd_verify(struct nfsrv_descript *nd, int isdgram, 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, NULL); if (!nd->nd_repstat) nd->nd_repstat = nfsvno_statfs(vp, sf); if (!nd->nd_repstat) @@ -3787,7 +3980,10 @@ nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused 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 +4074,15 @@ nfsrvd_createsession(struct nfsrv_descript *nd, __unus 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 +4284,361 @@ nfsrvd_freestateid(struct nfsrv_descript *nd, __unused 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) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706112027.v5BKRdIG071904>