svn commit: r317534 - projects/pnfs-planb-server/sys/fs/nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Thu Apr 27 23:46:02 UTC 2017
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 ***
More information about the svn-src-projects
mailing list