svn commit: r351652 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Sun Sep 1 04:58:00 UTC 2019
Author: rmacklem
Date: Sun Sep 1 04:57:58 2019
New Revision: 351652
URL: https://svnweb.freebsd.org/changeset/base/351652
Log:
Add the Set Extended attribute operation.
RFC-8276 defines optional Extended attribute operations. This patch adds
the set extended attribute operation. It also applies one fix to the
get attribute operation added yesterday.
Modified:
projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
projects/nfsv42/sys/fs/nfs/nfs_var.h
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/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 Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Sun Sep 1 04:57:58 2019 (r351652)
@@ -181,7 +181,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Write Same */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Clone */
{ 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Getxattr */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Setxattr */
+ { 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Setxattr */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Listxattrs */
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Removexattr */
};
@@ -211,7 +211,7 @@ static struct nfsrv_lughash *nfsgroupnamehash;
static int nfs_bigreply[NFSV42_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0 };
+ 0, 0 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@@ -291,6 +291,7 @@ static struct {
{ NFSV4OP_SEEK, 2, "Seek", 4, },
{ NFSV4OP_SEEK, 1, "SeekDS", 6, },
{ NFSV4OP_GETXATTR, 2, "Getxattr", 8, },
+ { NFSV4OP_SETXATTR, 2, "Setxattr", 8, },
};
/*
@@ -299,7 +300,7 @@ static struct {
static int nfs_bigrequest[NFSV42_NPROCS] = {
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
Modified: projects/nfsv42/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_var.h Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfs/nfs_var.h Sun Sep 1 04:57:58 2019 (r351652)
@@ -285,6 +285,8 @@ int nfsrvd_seek(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
int nfsrvd_getxattr(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
+int nfsrvd_setxattr(struct nfsrv_descript *, int,
+ vnode_t, struct nfsexstuff *);
int nfsrvd_notsupp(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
@@ -548,6 +550,8 @@ int nfsrpc_seek(vnode_t, off_t *, bool *, int, struct
struct nfsvattr *, int *);
int nfsrpc_getextattr(vnode_t, const char *, struct uio *, ssize_t *,
struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);
+int nfsrpc_setextattr(vnode_t, const char *, struct uio *, struct nfsvattr *,
+ int *, struct ucred *, NFSPROC_T *);
/* nfs_clstate.c */
int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int,
@@ -733,6 +737,8 @@ int nfsvno_seek(struct nfsrv_descript *, struct vnode
bool *, struct ucred *, NFSPROC_T *);
int nfsvno_getxattr(struct vnode *, char *, struct ucred *, struct thread *,
struct mbuf **, struct mbuf **, int *);
+int nfsvno_setxattr(struct vnode *, char *, struct uio *, struct ucred *,
+ struct thread *);
/* nfs_commonkrpc.c */
int newnfs_nmcancelreqs(struct nfsmount *);
Modified: projects/nfsv42/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsport.h Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfs/nfsport.h Sun Sep 1 04:57:58 2019 (r351652)
@@ -408,11 +408,12 @@
/* and the ones for the optional Extended attribute support (RFC-8276). */
#define NFSPROC_GETEXTATTR 61
+#define NFSPROC_SETEXTATTR 62
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 62
+#define NFSV42_NPROCS 63
#endif /* NFS_V3NPROCS */
@@ -441,7 +442,7 @@ struct nfsstatsv1 {
uint64_t readlink_bios;
uint64_t biocache_readdirs;
uint64_t readdir_bios;
- uint64_t rpccnt[NFSV42_NPROCS + 7];
+ uint64_t rpccnt[NFSV42_NPROCS + 6];
uint64_t rpcretries;
uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS];
uint64_t srvrpc_errs;
Modified: projects/nfsv42/sys/fs/nfs/nfsproto.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsproto.h Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfs/nfsproto.h Sun Sep 1 04:57:58 2019 (r351652)
@@ -390,11 +390,12 @@
/* and the ones for the optional Extended attribute support (RFC-8276). */
#define NFSPROC_GETEXTATTR 61
+#define NFSPROC_SETEXTATTR 62
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 62
+#define NFSV42_NPROCS 63
#endif /* NFS_V3NPROCS */
@@ -1490,5 +1491,10 @@ typedef struct nfsv4stateid nfsv4stateid_t;
/* Seek Contents. */
#define NFSV4CONTENT_DATA 0
#define NFSV4CONTENT_HOLE 1
+
+/* Options for Set Extended attribute (RFC-8276). */
+#define NFSV4SXATTR_EITHER 0
+#define NFSV4SXATTR_CREATE 1
+#define NFSV4SXATTR_REPLACE 2
#endif /* _NFS_NFSPROTO_H_ */
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Sun Sep 1 04:57:58 2019 (r351652)
@@ -8278,9 +8278,10 @@ nfsrpc_getextattr(vnode_t vp, const char *name, struct
if (error == 0) {
/*
* nfsm_mbufuio() advances to a multiple
- * of 4, so advance len2 as well. Then
+ * of 4, so round up len2 as well. Then
* we need to advance over the rest of
- * the data.
+ * the data, rounding up the remaining
+ * length.
*/
len2 = NFSM_RNDUP(len2);
len2 = NFSM_RNDUP(len - len2);
@@ -8291,7 +8292,7 @@ nfsrpc_getextattr(vnode_t vp, const char *name, struct
}
} else if (uiop == NULL && len > 0) {
/* Just wants the length and not the data. */
- error = nfsm_advance(nd, len, -1);
+ error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
} else
error = ENOATTR;
if (error != 0)
@@ -8299,6 +8300,49 @@ nfsrpc_getextattr(vnode_t vp, const char *name, struct
*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);
+}
+
+/*
+ * The setextattr RPC.
+ */
+APPLESTATIC int
+nfsrpc_setextattr(vnode_t vp, const char *name, struct uio *uiop,
+ 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;
+
+ *attrflagp = 0;
+ NFSCL_REQSTART(nd, NFSPROC_SETEXTATTR, vp);
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(NFSV4SXATTR_EITHER);
+ nfsm_strtom(nd, name, strlen(name));
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(uiop->uio_resid);
+ nfsm_uiombuf(nd, uiop, uiop->uio_resid);
+ 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) {
+ /* Just skip over the reply and Getattr op status. */
+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + 3 *
+ NFSX_UNSIGNED);
error = nfsm_loadattr(nd, nap);
if (error == 0)
*attrflagp = 1;
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Sun Sep 1 04:57:58 2019 (r351652)
@@ -149,6 +149,7 @@ 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;
+static vop_setextattr_t nfs_setextattr;
/*
* Global vfs data structures for nfs
@@ -191,6 +192,7 @@ static struct vop_vector newnfs_vnodeops_nosig = {
.vop_copy_file_range = nfs_copy_file_range,
.vop_ioctl = nfs_ioctl,
.vop_getextattr = nfs_getextattr,
+ .vop_setextattr = nfs_setextattr,
};
static int
@@ -3790,7 +3792,63 @@ nfs_getextattr(struct vop_getextattr_args *ap)
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);
+}
+
+/*
+ * nfs setextattr call
+ */
+static int
+nfs_setextattr(struct vop_setextattr_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nfsmount *nmp;
+ struct ucred *cred;
+ struct thread *td = ap->a_td;
+ struct nfsvattr nfsva;
+ 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);
+
+ if (ap->a_uio->uio_resid <= 0 || ap->a_uio->uio_resid > nmp->nm_wsize)
+ return (EINVAL);
+ 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_setextattr(vp, ap->a_name, ap->a_uio, &nfsva,
+ &attrflag, cred, td);
+ if (attrflag != 0) {
+ ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
+ if (error == 0 && ret != 0)
+ error = ret;
+ }
+
+ switch (error) {
+ case NFSERR_NOTSUPP:
+ case NFSERR_OPILLEGAL:
mtx_lock(&nmp->nm_mtx);
nmp->nm_privflag |= NFSMNTP_NOXATTR;
mtx_unlock(&nmp->nm_mtx);
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Sun Sep 1 04:57:58 2019 (r351652)
@@ -5947,6 +5947,31 @@ out:
return (error);
}
+/*
+ * Set Extended attribute vnode op from an mbuf list.
+ */
+int
+nfsvno_setxattr(struct vnode *vp, char *name, struct uio *uiop,
+ struct ucred *cred, struct thread *p)
+{
+ int error;
+
+ error = 0;
+#ifdef MAC
+ error = mac_vnode_check_setextattr(cred, vp, EXTATTR_NAMESPACE_USER,
+ name);
+#endif
+
+ if (error == 0)
+ error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop,
+ cred, p);
+ if (error == 0 && uiop->uio_resid > 0)
+ error = NFSERR_XATTR2BIG;
+
+ NFSEXITCODE(error);
+ return (error);
+}
+
extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *);
/*
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Sun Sep 1 04:57:58 2019 (r351652)
@@ -5530,6 +5530,153 @@ nfsmout:
}
/*
+ * nfs set extended attribute service
+ */
+APPLESTATIC int
+nfsrvd_setxattr(struct nfsrv_descript *nd, __unused int isdgram,
+ vnode_t vp, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ mbuf_t mp = NULL, mpend = NULL;
+ struct iovec *ivp, *iv;
+ struct uio io, *uiop = &io;
+ struct nfsvattr ova, nva;
+ nfsattrbit_t attrbits;
+ int cnt, error, i, len, opt, rem, retlen;
+ char *name;
+ struct thread *p = curthread;
+
+ error = 0;
+ name = NULL;
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+ opt = fxdr_unsigned(int, *tl++);
+ 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);
+ error = nfsrv_mtostr(nd, name, len);
+ if (error != 0)
+ goto nfsmout;
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ len = fxdr_unsigned(int, *tl);
+ if (len <= 0 || len > IOSIZE_MAX) {
+ nd->nd_repstat = NFSERR_XATTR2BIG;
+ goto nfsmout;
+ }
+ switch (opt) {
+ case NFSV4SXATTR_CREATE:
+ error = nfsvno_getxattr(vp, name, nd->nd_cred, p, &mp, &mpend,
+ &retlen);
+ if (error == 0)
+ m_freem(mp);
+ if (error != ENOATTR)
+ nd->nd_repstat = NFSERR_EXIST;
+ error = 0;
+ break;
+ case NFSV4SXATTR_REPLACE:
+ error = nfsvno_getxattr(vp, name, nd->nd_cred, p, &mp, &mpend,
+ &retlen);
+ if (error == 0)
+ m_freem(mp);
+ else
+ nd->nd_repstat = NFSERR_NOXATTR;
+ break;
+ case NFSV4SXATTR_EITHER:
+ break;
+ default:
+ nd->nd_repstat = NFSERR_BADXDR;
+ }
+ if (nd->nd_repstat != 0)
+ goto nfsmout;
+
+ /* Figure out how many iovecs are needed. */
+ cnt = 1;
+ mp = nd->nd_md;
+ i = mp->m_len - (nd->nd_dpos - mtod(mp, char *));
+ while (i < len) {
+ mp = mp->m_next;
+ if (mp == NULL) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ }
+ i += mp->m_len;
+ cnt++;
+ }
+
+ /* Now create the uio structure and iovec. */
+ ivp = mallocarray(cnt, sizeof(*ivp), M_TEMP, M_WAITOK);
+ uiop->uio_iov = iv = ivp;
+ uiop->uio_iovcnt = cnt;
+ uiop->uio_resid = len;
+ rem = NFSM_RNDUP(len) - len;
+ cnt = len;
+ mp = nd->nd_md;
+ i = mp->m_len - (nd->nd_dpos - mtod(mp, char *));
+ while (cnt > 0) {
+ if (mp == NULL)
+ panic("nfsvno_write");
+ if (i > 0) {
+ i = min(i, cnt);
+ ivp->iov_base = nd->nd_dpos;
+ ivp->iov_len = i;
+ ivp++;
+ cnt -= i;
+ if (cnt == 0)
+ nd->nd_dpos += i;
+ }
+ if (cnt > 0) {
+ mp = mp->m_next;
+ if (mp != NULL) {
+ i = mp->m_len;
+ nd->nd_dpos = mtod(mp, caddr_t);
+ }
+ }
+ }
+ if (rem > 0)
+ nd->nd_dpos += rem;
+ nd->nd_md = mp;
+
+ uiop->uio_rw = UIO_WRITE;
+ uiop->uio_segflg = UIO_SYSSPACE;
+ uiop->uio_td = p;
+ uiop->uio_offset = 0;
+ /* Now, do the Set Extended attribute, with Change before and after. */
+ NFSZERO_ATTRBIT(&attrbits);
+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
+ nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits);
+ if (nd->nd_repstat == 0)
+ nd->nd_repstat = nfsvno_setxattr(vp, name, uiop, nd->nd_cred,
+ p);
+ free(iv, M_TEMP);
+ if (nd->nd_repstat == 0)
+ nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
+ if (nd->nd_repstat == 0) {
+ NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
+ *tl++ = newnfs_true;
+ txdr_hyper(ova.na_filerev, tl); tl += 2;
+ txdr_hyper(nva.na_filerev, tl);
+ }
+
+nfsmout:
+ free(name, M_TEMP);
+ if (nd->nd_repstat == 0)
+ nd->nd_repstat = error;
+ vput(vp);
+ NFSEXITCODE2(0, nd);
+ return (0);
+}
+
+/*
* nfsv4 service not supported
*/
APPLESTATIC int
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Sun Sep 1 02:52:00 2019 (r351651)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Sun Sep 1 04:57:58 2019 (r351652)
@@ -210,7 +210,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript
nfsrvd_notsupp,
nfsrvd_notsupp,
nfsrvd_getxattr,
- nfsrvd_notsupp,
+ nfsrvd_setxattr,
nfsrvd_notsupp,
nfsrvd_notsupp,
};
More information about the svn-src-projects
mailing list