Date: Sun, 1 Sep 2019 04:57:58 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r351652 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver Message-ID: <201909010457.x814vwjS092517@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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, };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909010457.x814vwjS092517>