svn commit: r351646 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Sat Aug 31 16:10:50 UTC 2019
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,
More information about the svn-src-projects
mailing list