svn commit: r351968 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Sat Sep 7 04:09:45 UTC 2019
Author: rmacklem
Date: Sat Sep 7 04:09:43 2019
New Revision: 351968
URL: https://svnweb.freebsd.org/changeset/base/351968
Log:
Add support for the List Extended Attributes RPC.
This patch also saves the maxrequest and maxreply for the session in
nd_maxreq and nd_maxresp so they can be used to limit the size of
extended attribute requests/replies.
The code for doing this on the client side still needs to be done.
Modified:
projects/nfsv42/sys/fs/nfs/nfs.h
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
projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c
Modified: projects/nfsv42/sys/fs/nfs/nfs.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs.h Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfs/nfs.h Sat Sep 7 04:09:43 2019 (r351968)
@@ -667,6 +667,8 @@ struct nfsrv_descript {
uint32_t *nd_sequence; /* Sequence Op. ptr */
nfsv4stateid_t nd_curstateid; /* Current StateID */
nfsv4stateid_t nd_savedcurstateid; /* Saved Current StateID */
+ uint32_t nd_maxreq; /* Max. request (session). */
+ uint32_t nd_maxresp; /* Max. reply (session). */
};
#define nd_princlen nd_gssnamelen
Modified: projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -182,7 +182,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
{ 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Clone */
{ 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Getxattr */
{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Setxattr */
- { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Listxattrs */
+ { 0, 1, 0, 0, LK_SHARED, 1, 1 }, /* Listxattrs */
{ 0, 1, 1, 1, LK_EXCLUSIVE, 1, 1 }, /* Removexattr */
};
#endif /* !APPLEKEXT */
@@ -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,
- 1, 0, 0 };
+ 1, 0, 0, 1 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@@ -293,6 +293,7 @@ static struct {
{ NFSV4OP_GETXATTR, 2, "Getxattr", 8, },
{ NFSV4OP_SETXATTR, 2, "Setxattr", 8, },
{ NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, },
+ { NFSV4OP_LISTXATTRS, 2, "Listxattr", 9, },
};
/*
@@ -301,7 +302,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, 1, 0
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
};
/*
@@ -4632,6 +4633,8 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_d
error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq,
sessionid);
+ nd->nd_maxreq = sep->sess_maxreq;
+ nd->nd_maxresp = sep->sess_maxresp;
/* Build the Sequence arguments. */
NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
Modified: projects/nfsv42/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_var.h Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfs/nfs_var.h Sat Sep 7 04:09:43 2019 (r351968)
@@ -290,6 +290,8 @@ int nfsrvd_setxattr(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
int nfsrvd_rmxattr(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
+int nfsrvd_listxattr(struct nfsrv_descript *, int,
+ vnode_t, struct nfsexstuff *);
int nfsrvd_notsupp(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
@@ -555,6 +557,8 @@ int nfsrpc_getextattr(vnode_t, const char *, struct ui
struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);
int nfsrpc_setextattr(vnode_t, const char *, struct uio *, struct nfsvattr *,
int *, struct ucred *, NFSPROC_T *);
+int nfsrpc_listextattr(vnode_t, uint64_t *, struct uio *, size_t *, bool *,
+ struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);
int nfsrpc_rmextattr(vnode_t, const char *, struct nfsvattr *, int *,
struct ucred *, NFSPROC_T *);
@@ -740,12 +744,14 @@ void nfsrv_killrpcs(struct nfsmount *);
int nfsrv_setacl(struct vnode *, NFSACL_T *, struct ucred *, NFSPROC_T *);
int nfsvno_seek(struct nfsrv_descript *, struct vnode *, u_long, off_t *, int,
bool *, struct ucred *, NFSPROC_T *);
-int nfsvno_getxattr(struct vnode *, char *, struct ucred *, struct thread *,
- struct mbuf **, struct mbuf **, int *);
+int nfsvno_getxattr(struct vnode *, char *, uint32_t, struct ucred *,
+ struct thread *, struct mbuf **, struct mbuf **, int *);
int nfsvno_setxattr(struct vnode *, char *, int, struct mbuf *, char *,
struct ucred *, struct thread *);
int nfsvno_rmxattr(struct nfsrv_descript *, struct vnode *, char *,
struct ucred *, struct thread *);
+int nfsvno_listxattr(struct vnode *, uint64_t, struct ucred *, struct thread *,
+ u_char **, uint32_t *, bool *);
/* nfs_commonkrpc.c */
int newnfs_nmcancelreqs(struct nfsmount *);
Modified: projects/nfsv42/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsport.h Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfs/nfsport.h Sat Sep 7 04:09:43 2019 (r351968)
@@ -410,11 +410,12 @@
#define NFSPROC_GETEXTATTR 61
#define NFSPROC_SETEXTATTR 62
#define NFSPROC_RMEXTATTR 63
+#define NFSPROC_LISTEXTATTR 64
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 64
+#define NFSV42_NPROCS 65
#endif /* NFS_V3NPROCS */
@@ -443,7 +444,7 @@ struct nfsstatsv1 {
uint64_t readlink_bios;
uint64_t biocache_readdirs;
uint64_t readdir_bios;
- uint64_t rpccnt[NFSV42_NPROCS + 5];
+ uint64_t rpccnt[NFSV42_NPROCS + 4];
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 Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfs/nfsproto.h Sat Sep 7 04:09:43 2019 (r351968)
@@ -392,11 +392,12 @@
#define NFSPROC_GETEXTATTR 61
#define NFSPROC_SETEXTATTR 62
#define NFSPROC_RMEXTATTR 63
+#define NFSPROC_LISTEXTATTR 64
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 64
+#define NFSV42_NPROCS 65
#endif /* NFS_V3NPROCS */
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <fs/nfs/nfsport.h>
#include <fs/nfsclient/nfs.h>
+#include <sys/extattr.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
@@ -8381,6 +8382,83 @@ nfsrpc_rmextattr(vnode_t vp, const char *name, struct
/* Just skip over the reply and Getattr op status. */
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + 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 listextattr RPC.
+ */
+APPLESTATIC int
+nfsrpc_listextattr(vnode_t vp, uint64_t *cookiep, struct uio *uiop,
+ size_t *lenp, bool *eofp, struct nfsvattr *nap, int *attrflagp,
+ struct ucred *cred, NFSPROC_T *p)
+{
+ uint32_t *tl;
+ int cnt, error, i, len;
+ struct nfsrv_descript nfsd;
+ struct nfsrv_descript *nd = &nfsd;
+ nfsattrbit_t attrbits;
+ u_char c;
+
+ *attrflagp = 0;
+ NFSCL_REQSTART(nd, NFSPROC_LISTEXTATTR, vp);
+ NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
+ txdr_hyper(*cookiep, tl); tl += 2;
+ *tl++ = txdr_unsigned(*lenp);
+ *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);
+ *eofp = true;
+ *lenp = 0;
+ if (nd->nd_repstat == 0) {
+ NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
+ *cookiep = fxdr_hyper(tl); tl += 2;
+ cnt = fxdr_unsigned(int, *tl);
+ if (cnt <= 0) {
+ error = EBADRPC;
+ goto nfsmout;
+ }
+ for (i = 0; i < cnt; i++) {
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ len = fxdr_unsigned(int, *tl);
+ if (len <= 0 || len > EXTATTR_MAXNAMELEN) {
+ error = EBADRPC;
+ goto nfsmout;
+ }
+ if (uiop == NULL)
+ error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
+ else if (uiop->uio_resid >= len + 1) {
+ c = len;
+ error = uiomove(&c, sizeof(c), uiop);
+ if (error == 0)
+ error = nfsm_mbufuio(nd, uiop, len);
+ } else {
+ error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
+ *eofp = false;
+ }
+ if (error != 0)
+ goto nfsmout;
+ *lenp += (len + 1);
+ }
+ /* Get the eof and skip over the Getattr op status. */
+ NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
+ /*
+ * *eofp is set false above, because it wasn't able to copy
+ * all of the reply.
+ */
+ if (*eofp && *tl == 0)
+ *eofp = false;
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 Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -150,6 +150,7 @@ 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;
+static vop_listextattr_t nfs_listextattr;
static vop_deleteextattr_t nfs_deleteextattr;
/*
@@ -194,6 +195,7 @@ static struct vop_vector newnfs_vnodeops_nosig = {
.vop_ioctl = nfs_ioctl,
.vop_getextattr = nfs_getextattr,
.vop_setextattr = nfs_setextattr,
+ .vop_listextattr = nfs_listextattr,
.vop_deleteextattr = nfs_deleteextattr,
};
@@ -3847,6 +3849,80 @@ nfs_setextattr(struct vop_setextattr_args *ap)
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);
+ error = EOPNOTSUPP;
+ break;
+ case NFSERR_NOXATTR:
+ case NFSERR_XATTR2BIG:
+ error = ENOATTR;
+ break;
+ default:
+ error = nfscl_maperr(td, error, 0, 0);
+ break;
+ }
+ return (error);
+}
+
+/*
+ * nfs listextattr call
+ */
+static int
+nfs_listextattr(struct vop_listextattr_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nfsmount *nmp;
+ struct ucred *cred;
+ struct thread *td = ap->a_td;
+ struct nfsvattr nfsva;
+ size_t len, len2;
+ uint64_t cookie;
+ int attrflag, error, ret;
+ bool eof;
+
+ 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;
+
+ /* Loop around doing List Extended Attribute RPCs. */
+ eof = false;
+ cookie = 0;
+ len2 = 0;
+ error = 0;
+ while (!eof && error == 0) {
+ len = nmp->nm_rsize;
+ attrflag = 0;
+ error = nfsrpc_listextattr(vp, &cookie, ap->a_uio, &len, &eof,
+ &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) {
+ len2 += len;
+ if (len2 > SSIZE_MAX)
+ error = ENOATTR;
+ }
+ }
+ if (error == 0 && ap->a_size != NULL)
+ *ap->a_size = len2;
switch (error) {
case NFSERR_NOTSUPP:
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -5914,8 +5914,9 @@ nfsvno_seek(struct nfsrv_descript *nd, struct vnode *v
* 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)
+nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp,
+ struct ucred *cred, struct thread *p, struct mbuf **mpp,
+ struct mbuf **mpendp, int *lenp)
{
struct iovec *iv;
struct uio io, *uiop = &io;
@@ -5928,7 +5929,7 @@ nfsvno_getxattr(struct vnode *vp, char *name, struct u
&siz, cred, p);
if (error != 0)
return (NFSERR_NOXATTR);
- if (siz > 1000000)
+ if (siz > maxresp - NFS_MAXXDR)
return (NFSERR_XATTR2BIG);
len = siz;
tlen = NFSM_RNDUP(len);
@@ -6039,6 +6040,72 @@ nfsvno_rmxattr(struct nfsrv_descript *nd, struct vnode
#ifdef MAC
out:
#endif
+ NFSEXITCODE(error);
+ return (error);
+}
+
+/*
+ * List Extended Atribute vnode op into an mbuf list.
+ */
+int
+nfsvno_listxattr(struct vnode *vp, uint64_t cookie, struct ucred *cred,
+ struct thread *p, u_char **bufp, uint32_t *lenp, bool *eofp)
+{
+ struct iovec iv;
+ struct uio io;
+ int error;
+ size_t siz;
+
+ *bufp = NULL;
+ /* First, find out the size of the extended attribute. */
+ error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, NULL, &siz, cred,
+ p);
+ if (error != 0)
+ return (NFSERR_NOXATTR);
+ if (siz <= cookie) {
+ *lenp = 0;
+ *eofp = true;
+ goto out;
+ }
+ if (siz > cookie + *lenp) {
+ siz = cookie + *lenp;
+ *eofp = false;
+ } else
+ *eofp = true;
+ /* Just choose a sanity limit of 10Mbytes for malloc(M_TEMP). */
+ if (siz > 10 * 1024 * 1024) {
+ error = NFSERR_XATTR2BIG;
+ goto out;
+ }
+ *bufp = malloc(siz, M_TEMP, M_WAITOK);
+ iv.iov_base = *bufp;
+ iv.iov_len = siz;
+ io.uio_iovcnt = 1;
+ io.uio_iov = &iv;
+ io.uio_offset = 0;
+ io.uio_resid = siz;
+ io.uio_rw = UIO_READ;
+ io.uio_segflg = UIO_SYSSPACE;
+ io.uio_td = p;
+#ifdef MAC
+ error = mac_vnode_check_listextattr(cred, vp, EXTATTR_NAMESPACE_USER);
+ if (error != 0)
+ goto out;
+#endif
+
+ error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, &io, NULL, cred,
+ p);
+ if (error != 0)
+ goto out;
+ if (io.uio_resid > 0)
+ siz -= io.uio_resid;
+ *lenp = siz;
+
+out:
+ if (error != 0) {
+ free(*bufp, M_TEMP);
+ *bufp = NULL;
+ }
NFSEXITCODE(error);
return (error);
}
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -5482,8 +5482,8 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused in
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);
+ nd->nd_repstat = nfsvno_getxattr(vp, name, nd->nd_maxresp,
+ nd->nd_cred, p, &mp, &mpend, &len);
if (nd->nd_repstat == ENOATTR)
nd->nd_repstat = NFSERR_NOXATTR;
else if (nd->nd_repstat == EOPNOTSUPP)
@@ -5513,11 +5513,11 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in
vnode_t vp, __unused struct nfsexstuff *exp)
{
uint32_t *tl;
- mbuf_t mp = NULL, mpend = NULL;
struct nfsvattr ova, nva;
nfsattrbit_t attrbits;
- int error, len, opt, retlen;
+ int error, len, opt;
char *name;
+ size_t siz;
struct thread *p = curthread;
error = 0;
@@ -5549,20 +5549,16 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in
}
switch (opt) {
case NFSV4SXATTR_CREATE:
- error = nfsvno_getxattr(vp, name, nd->nd_cred, p, &mp, &mpend,
- &retlen);
- if (error == 0)
- m_freem(mp);
+ error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
+ &siz, nd->nd_cred, p);
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
+ error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
+ &siz, nd->nd_cred, p);
+ if (error != 0)
nd->nd_repstat = NFSERR_NOXATTR;
break;
case NFSV4SXATTR_EITHER:
@@ -5665,6 +5661,118 @@ nfsrvd_rmxattr(struct nfsrv_descript *nd, __unused int
nfsmout:
free(name, M_TEMP);
+ if (nd->nd_repstat == 0)
+ nd->nd_repstat = error;
+ vput(vp);
+ NFSEXITCODE2(0, nd);
+ return (0);
+}
+
+/*
+ * nfs list extended attribute service
+ */
+APPLESTATIC int
+nfsrvd_listxattr(struct nfsrv_descript *nd, __unused int isdgram,
+ vnode_t vp, __unused struct nfsexstuff *exp)
+{
+ uint32_t cnt, *tl, len, len2, i, pos, retlen;
+ int error;
+ uint64_t cookie, cookie2;
+ u_char *buf;
+ bool eof;
+ struct thread *p = curthread;
+
+ error = 0;
+ buf = NULL;
+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
+ nd->nd_repstat = NFSERR_WRONGSEC;
+ goto nfsmout;
+ }
+ NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
+ /*
+ * The cookie doesn't need to be in net byte order, but FreeBSD
+ * does so to make it more readable in packet traces.
+ */
+ cookie = fxdr_hyper(tl); tl += 2;
+ len = fxdr_unsigned(uint32_t, *tl);
+ if (len == 0 || cookie >= IOSIZE_MAX) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ }
+ if (len > nd->nd_maxresp - NFS_MAXXDR)
+ len = nd->nd_maxresp - NFS_MAXXDR;
+ len2 = len;
+ nd->nd_repstat = nfsvno_listxattr(vp, cookie, nd->nd_cred, p, &buf,
+ &len, &eof);
+ if (nd->nd_repstat == EOPNOTSUPP)
+ nd->nd_repstat = NFSERR_NOTSUPP;
+ if (nd->nd_repstat == 0) {
+ cookie2 = cookie + len;
+ if (cookie2 < cookie)
+ nd->nd_repstat = NFSERR_BADXDR;
+ }
+ if (nd->nd_repstat == 0) {
+ /* Now copy the entries out. */
+ retlen = NFSX_HYPER + 2 * NFSX_UNSIGNED;
+ if (len == 0 && retlen <= len2) {
+ /* The cookie was at eof. */
+ NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 *
+ NFSX_UNSIGNED);
+ txdr_hyper(cookie2, tl); tl += 2;
+ *tl++ = txdr_unsigned(0);
+ *tl = newnfs_true;
+ goto nfsmout;
+ }
+
+ /* Sanity check the cookie. */
+ for (pos = 0; pos < len; pos += (i + 1)) {
+ if (pos == cookie)
+ break;
+ i = buf[pos];
+ }
+ if (pos != cookie) {
+ nd->nd_repstat = NFSERR_INVAL;
+ goto nfsmout;
+ }
+
+ /* Loop around copying the entrie(s) out. */
+ cnt = 0;
+ len -= cookie;
+ i = buf[pos];
+ while (i < len && len2 >= retlen + NFSM_RNDUP(i) +
+ NFSX_UNSIGNED) {
+ if (cnt == 0) {
+ NFSM_BUILD(tl, uint32_t *, NFSX_HYPER +
+ NFSX_UNSIGNED);
+ txdr_hyper(cookie2, tl); tl += 2;
+ }
+ retlen += nfsm_strtom(nd, &buf[pos + 1], i);
+ len -= (i + 1);
+ pos += (i + 1);
+ i = buf[pos];
+ cnt++;
+ }
+ /*
+ * eof is set true/false by nfsvno_listxattr(), but if we
+ * can't copy all entries returned by nfsvno_listxattr(),
+ * we are not at eof.
+ */
+ if (len > 0)
+ eof = false;
+ if (cnt > 0) {
+ /* *tl is set above. */
+ *tl = txdr_unsigned(cnt);
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ if (eof)
+ *tl = newnfs_true;
+ else
+ *tl = newnfs_false;
+ } else
+ nd->nd_repstat = NFSERR_TOOSMALL;
+ }
+
+nfsmout:
+ free(buf, M_TEMP);
if (nd->nd_repstat == 0)
nd->nd_repstat = error;
vput(vp);
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -211,7 +211,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript
nfsrvd_notsupp,
nfsrvd_getxattr,
nfsrvd_setxattr,
- nfsrvd_notsupp,
+ nfsrvd_listxattr,
nfsrvd_rmxattr,
};
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Sat Sep 7 03:51:26 2019 (r351967)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Sat Sep 7 04:09:43 2019 (r351968)
@@ -6209,6 +6209,10 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_
nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
nd->nd_flag |= ND_IMPLIEDCLID;
+ /* Save maximum request and reply sizes. */
+ nd->nd_maxreq = sep->sess_maxreq;
+ nd->nd_maxresp = sep->sess_maxresp;
+
/*
* If this session handles the backchannel, save the nd_xprt for this
* RPC, since this is the one being used.
More information about the svn-src-projects
mailing list