Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Aug 2019 16:10:48 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r351646 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver
Message-ID:  <201908311610.x7VGAmb9097196@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Aug 31 16:10:48 2019
New Revision: 351646
URL: https://svnweb.freebsd.org/changeset/base/351646

Log:
  Add support for the Get extended attribute operation.
  
  RFC-8276 defines an optional extension to NFSv4.2 to handle extended
  attributes. This patch adds the first of the four of these operations.

Modified:
  projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
  projects/nfsv42/sys/fs/nfs/nfsport.h
  projects/nfsv42/sys/fs/nfs/nfsproto.h
  projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
  projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c
  projects/nfsv42/sys/fs/nfsclient/nfsmount.h
  projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c
  projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
  projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c

Modified: projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c	Sat Aug 31 16:10:48 2019	(r351646)
@@ -107,7 +107,7 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsmirror, CTLFLAG_RD,
  * non-idempotent Ops.
  * Define it here, since it is used by both the client and server.
  */
-struct nfsv4_opflag nfsv4_opflag[NFSV4N_NOPS] = {
+struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* undef */
 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* undef */
 	{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },		/* undef */

Modified: projects/nfsv42/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsport.h	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfs/nfsport.h	Sat Aug 31 16:10:48 2019	(r351646)
@@ -277,11 +277,6 @@
 #define	NFSV4OP_WRITESAME	70
 #define	NFSV4OP_CLONE		71
 
-/*
- * Must be one more than the last NFSv4.2 op#.
- */
-#define	NFSV42_NOPS		72
-
 /* and the optional Extended attribute operations (RFC-8276). */
 #define	NFSV4OP_GETXATTR	72
 #define	NFSV4OP_SETXATTR	73
@@ -289,9 +284,9 @@
 #define	NFSV4OP_REMOVEXATTR	75
 
 /*
- * Must be one more that the last op#.
+ * Must be one more than the last NFSv4.2 op#.
  */
-#define	NFSV4N_NOPS		76
+#define	NFSV42_NOPS		76
 
 /* Quirky case if the illegal op code */
 #define	NFSV4OP_OPILLEGAL	10044

Modified: projects/nfsv42/sys/fs/nfs/nfsproto.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsproto.h	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfs/nfsproto.h	Sat Aug 31 16:10:48 2019	(r351646)
@@ -407,10 +407,10 @@
 
 /*
  * NFSPROC_NOOP is a fake op# that can't be the same as any V2/3/4 Procedure
- * or Operation#. Since the NFS V4 Op #s go higher, use NFSV4N_NOPS, which
+ * or Operation#. Since the NFS V4 Op #s go higher, use NFSV42_NOPS, which
  * is one greater than the highest Op#.
  */
-#define	NFSPROC_NOOP		NFSV4N_NOPS
+#define	NFSPROC_NOOP		NFSV42_NOPS
 
 /* Actual Version 2 procedure numbers */
 #define	NFSV2PROC_NULL		0

Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c	Sat Aug 31 16:10:48 2019	(r351646)
@@ -8240,3 +8240,73 @@ nfsmout:
 	return (error);
 }
 
+/*
+ * The getextattr RPC.
+ */
+APPLESTATIC int
+nfsrpc_getextattr(vnode_t vp, const char *name, struct uio *uiop, ssize_t *lenp,
+    struct nfsvattr *nap, int *attrflagp, struct ucred *cred, NFSPROC_T *p)
+{
+	uint32_t *tl;
+	int error;
+	struct nfsrv_descript nfsd;
+	struct nfsrv_descript *nd = &nfsd;
+	nfsattrbit_t attrbits;
+	uint32_t len, len2;
+
+	*attrflagp = 0;
+	NFSCL_REQSTART(nd, NFSPROC_GETEXTATTR, vp);
+	nfsm_strtom(nd, name, strlen(name));
+	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+	*tl = txdr_unsigned(NFSV4OP_GETATTR);
+	NFSGETATTR_ATTRBIT(&attrbits);
+	nfsrv_putattrbit(nd, &attrbits);
+	error = nfscl_request(nd, vp, p, cred, NULL);
+	if (error != 0)
+		return (error);
+	if (nd->nd_repstat == 0) {
+		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+		len = fxdr_unsigned(uint32_t, *tl);
+		/* Sanity check lengths. */
+		if (uiop != NULL && len > 0 && len <= IOSIZE_MAX &&
+		    uiop->uio_resid <= UINT32_MAX) {
+			len2 = uiop->uio_resid;
+			if (len2 >= len)
+				error = nfsm_mbufuio(nd, uiop, len);
+			else {
+				error = nfsm_mbufuio(nd, uiop, len2);
+				if (error == 0) {
+					/*
+					 * nfsm_mbufuio() advances to a multiple
+					 * of 4, so advance len2 as well.  Then
+					 * we need to advance over the rest of
+					 * the data.
+					 */
+					len2 = NFSM_RNDUP(len2);
+					len2 = NFSM_RNDUP(len - len2);
+					if (len2 > 0)
+						error = nfsm_advance(nd, len2,
+						    -1);
+				}
+			}
+		} else if (uiop == NULL && len > 0) {
+			/* Just wants the length and not the data. */
+			error = nfsm_advance(nd, len, -1);
+		} else
+			error = ENOATTR;
+		if (error != 0)
+			goto nfsmout;
+		*lenp = len;
+		/* Just skip over Getattr op status. */
+		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+		error = nfsm_loadattr(nd, nap);
+		if (error == 0)
+			*attrflagp = 1;
+	}
+	if (error == 0)
+		error = nd->nd_repstat;
+nfsmout:
+	mbuf_freem(nd->nd_mrep);
+	return (error);
+}
+

Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c	Sat Aug 31 16:10:48 2019	(r351646)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mount.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
+#include <sys/extattr.h>
 #include <sys/filio.h>
 #include <sys/jail.h>
 #include <sys/malloc.h>
@@ -147,6 +148,7 @@ static vop_advise_t nfs_advise;
 static vop_allocate_t nfs_allocate;
 static vop_copy_file_range_t nfs_copy_file_range;
 static vop_ioctl_t nfs_ioctl;
+static vop_getextattr_t nfs_getextattr;
 
 /*
  * Global vfs data structures for nfs
@@ -188,6 +190,7 @@ static struct vop_vector newnfs_vnodeops_nosig = {
 	.vop_allocate =		nfs_allocate,
 	.vop_copy_file_range =	nfs_copy_file_range,
 	.vop_ioctl =		nfs_ioctl,
+	.vop_getextattr =	nfs_getextattr,
 };
 
 static int
@@ -3742,6 +3745,65 @@ nfs_ioctl(struct vop_ioctl_args *ap)
 
 	if (error != 0)
 		error = ENXIO;
+	return (error);
+}
+
+/*
+ * nfs getextattr call
+ */
+static int
+nfs_getextattr(struct vop_getextattr_args *ap)
+{
+	struct vnode *vp = ap->a_vp;
+	struct nfsmount *nmp;
+	struct ucred *cred;
+	struct thread *td = ap->a_td;
+	struct nfsvattr nfsva;
+	ssize_t len;
+	int attrflag, error, ret;
+
+	nmp = VFSTONFS(vp->v_mount);
+	mtx_lock(&nmp->nm_mtx);
+	if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION ||
+	    (nmp->nm_privflag & NFSMNTP_NOXATTR) != 0 ||
+	    ap->a_attrnamespace != EXTATTR_NAMESPACE_USER) {
+		mtx_unlock(&nmp->nm_mtx);
+		return (EOPNOTSUPP);
+	}
+	mtx_unlock(&nmp->nm_mtx);
+
+	cred = ap->a_cred;
+	if (cred == NULL)
+		cred = td->td_ucred;
+	/* Do the actual NFSv4.2 Optional Extended Attribute (RFC-8276) RPC. */
+	attrflag = 0;
+	error = nfsrpc_getextattr(vp, ap->a_name, ap->a_uio, &len, &nfsva,
+	    &attrflag, cred, td);
+	if (attrflag != 0) {
+		ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
+		if (error == 0 && ret != 0)
+			error = ret;
+	}
+	if (error == 0 && ap->a_size != NULL)
+		*ap->a_size = len;
+
+	switch (error) {
+	case NFSERR_NOTSUPP:
+	case NFSERR_OPILLEGAL:
+	case NFSERR_MINORVERMISMATCH:
+		mtx_lock(&nmp->nm_mtx);
+		nmp->nm_privflag |= NFSMNTP_NOXATTR;
+		mtx_unlock(&nmp->nm_mtx);
+		error = EOPNOTSUPP;
+		break;
+	case NFSERR_NOXATTR:
+	case NFSERR_XATTR2BIG:
+		error = ENOATTR;
+		break;
+	default:
+		error = nfscl_maperr(td, error, 0, 0);
+		break;
+	}
 	return (error);
 }
 

Modified: projects/nfsv42/sys/fs/nfsclient/nfsmount.h
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfsmount.h	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfsclient/nfsmount.h	Sat Aug 31 16:10:48 2019	(r351646)
@@ -110,6 +110,7 @@ struct	nfsmount {
 #define	NFSMNTP_NOCONSECUTIVE	0x00000010
 #define	NFSMNTP_SEEK		0x00000020
 #define	NFSMNTP_SEEKTESTED	0x00000040
+#define	NFSMNTP_NOXATTR		0x00000080
 
 #define	NFSMNT_DIRPATH(m)	(&((m)->nm_name[(m)->nm_krbnamelen + 1]))
 #define	NFSMNT_SRVKRBNAME(m)						\

Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c	Sat Aug 31 16:10:48 2019	(r351646)
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
  */
 
 #include <fs/nfs/nfsport.h>
+#include <security/mac/mac_framework.h>
 #include <sys/filio.h>
 #include <sys/hash.h>
 #include <sys/sysctl.h>
@@ -5862,6 +5863,86 @@ nfsvno_seek(struct nfsrv_descript *nd, struct vnode *v
 		if (ret != 0 && error == 0)
 			error = ret;
 	}
+	NFSEXITCODE(error);
+	return (error);
+}
+
+/*
+ * Get Extended Atribute vnode op into an mbuf list.
+ */
+int
+nfsvno_getxattr(struct vnode *vp, char *name, struct ucred *cred,
+    struct thread *p, struct mbuf **mpp, struct mbuf **mpendp, int *lenp)
+{
+	struct iovec *ivp, *ivp2;
+	struct uio io, *uiop = &io;
+	struct mbuf *mp, *mp2 = NULL, *mp3 = NULL;
+	int alen, error, i, len, maxiov, tlen;
+	size_t siz;
+
+	maxiov = (NFS_SRVMAXIO + MCLBYTES - 1) / MCLBYTES;
+	if (maxiov < 1)
+		maxiov = 1;
+	ivp2 = ivp = mallocarray(maxiov, sizeof(*ivp), M_TEMP, M_WAITOK);
+	len = 0;
+	i = 0;
+	while (i < maxiov) {
+		NFSMGET(mp);
+		MCLGET(mp, M_WAITOK);
+		mp->m_len = M_SIZE(mp);
+		if (len == 0) {
+			mp3 = mp2 = mp;
+		} else {
+			mp2->m_next = mp;
+			mp2 = mp;
+		}
+		len += mp->m_len;
+		ivp->iov_base = mtod(mp, caddr_t);
+		ivp->iov_len = mp->m_len;
+		i++;
+		ivp++;
+	}
+	uiop->uio_iov = ivp2;
+	uiop->uio_iovcnt = i;
+	uiop->uio_offset = 0;
+	uiop->uio_resid = len;
+	uiop->uio_rw = UIO_READ;
+	uiop->uio_segflg = UIO_SYSSPACE;
+	uiop->uio_td = p;
+#ifdef MAC
+	error = mac_vnode_check_getextattr(cred, vp, EXTATTR_NAMESPACE_USER,
+	    name);
+	if (error != 0)
+		goto out;
+#endif
+
+	error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop, NULL,
+	    cred, p);
+	if (error != 0)
+		goto out;
+	if (uiop->uio_resid > 0) {
+		alen = len;
+		len -= uiop->uio_resid;
+		tlen = NFSM_RNDUP(len);
+		nfsrv_adj(mp3, alen - tlen, tlen - len);
+	} else {
+		error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
+		    &siz, cred, p);
+		if (error == 0 && len < siz)
+			error = NFSERR_XATTR2BIG;
+	}
+	if (error == 0) {
+		*lenp = len;
+		*mpp = mp3;
+		*mpendp = mp;
+	}
+
+out:
+	if (error != 0) {
+		m_freem(mp3);
+		*lenp = 0;
+	}
+	free(ivp2, M_TEMP);
 	NFSEXITCODE(error);
 	return (error);
 }

Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c	Sat Aug 31 16:10:48 2019	(r351646)
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
 
 #ifndef APPLEKEXT
 #include <fs/nfs/nfsport.h>
+#include <sys/extattr.h>
 #include <sys/filio.h>
 
 /* Global vars */
@@ -5472,6 +5473,60 @@ nfsmout:
 	vput(vp);
 	NFSEXITCODE2(error, nd);
 	return (error);
+}
+
+/*
+ * nfs get extended attribute service
+ */
+APPLESTATIC int
+nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram,
+    vnode_t vp, __unused struct nfsexstuff *exp)
+{
+	uint32_t *tl;
+	mbuf_t mp = NULL, mpend = NULL;
+	int error, len;
+	char *name;
+	struct thread *p = curthread;
+
+	error = 0;
+	if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+		nd->nd_repstat = NFSERR_WRONGSEC;
+		goto nfsmout;
+	}
+	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+	len = fxdr_unsigned(int, *tl);
+	if (len <= 0) {
+		nd->nd_repstat = NFSERR_BADXDR;
+		goto nfsmout;
+	}
+	if (len > EXTATTR_MAXNAMELEN) {
+		nd->nd_repstat = NFSERR_NOXATTR;
+		goto nfsmout;
+	}
+	name = malloc(len + 1, M_TEMP, M_WAITOK);
+	nd->nd_repstat = nfsrv_mtostr(nd, name, len);
+	if (nd->nd_repstat == 0)
+		nd->nd_repstat = nfsvno_getxattr(vp, name, nd->nd_cred, p,
+		    &mp, &mpend, &len);
+	if (nd->nd_repstat == ENOATTR)
+		nd->nd_repstat = NFSERR_NOXATTR;
+	else if (nd->nd_repstat == EOPNOTSUPP)
+		nd->nd_repstat = NFSERR_NOTSUPP;
+	if (nd->nd_repstat == 0) {
+		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+		*tl = txdr_unsigned(len);
+		mbuf_setnext(nd->nd_mb, mp);
+		nd->nd_mb = mpend;
+		nd->nd_bpos = NFSMTOD(mpend, caddr_t) + mbuf_len(mpend);
+	}
+	free(name, M_TEMP);
+
+nfsmout:
+	if (nd->nd_repstat == 0)
+		nd->nd_repstat = error;
+	vput(vp);
+	NFSEXITCODE2(0, nd);
+	return (0);
 }
 
 /*

Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c	Sat Aug 31 15:17:22 2019	(r351645)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c	Sat Aug 31 16:10:48 2019	(r351646)
@@ -209,6 +209,10 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript 
 	nfsrvd_seek,
 	nfsrvd_notsupp,
 	nfsrvd_notsupp,
+	nfsrvd_getxattr,
+	nfsrvd_notsupp,
+	nfsrvd_notsupp,
+	nfsrvd_notsupp,
 };
 
 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
@@ -285,6 +289,10 @@ int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript 
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
 };
 
 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
@@ -350,6 +358,10 @@ int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript 
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
 	nfsrvd_copy_file_range,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
+	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908311610.x7VGAmb9097196>