svn commit: r351922 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Fri Sep 6 02:52:23 UTC 2019
Author: rmacklem
Date: Fri Sep 6 02:52:20 2019
New Revision: 351922
URL: https://svnweb.freebsd.org/changeset/base/351922
Log:
Add support for the NFSv4.2 Remove Extended Attribute operation.
This also required addditional arguments for nfsrv_checkremove(), so that
"same client" delegations could be avoided.
I think nfsrv_checkremove() should also check for grace before doing
the delegation removal. That would be a fix unrelated to the NFSv4.2
server work that I will look at for a possible commit to head.
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
projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c
Modified: projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfs/nfs_commonsubs.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -183,7 +183,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
{ 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, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Removexattr */
+ { 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 };
+ 1, 0, 0 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@@ -292,6 +292,7 @@ static struct {
{ NFSV4OP_SEEK, 1, "SeekDS", 6, },
{ NFSV4OP_GETXATTR, 2, "Getxattr", 8, },
{ NFSV4OP_SETXATTR, 2, "Setxattr", 8, },
+ { NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, },
};
/*
@@ -300,7 +301,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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
};
/*
Modified: projects/nfsv42/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfs_var.h Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfs/nfs_var.h Fri Sep 6 02:52:20 2019 (r351922)
@@ -128,7 +128,8 @@ void nfsrv_setupstable(NFSPROC_T *);
void nfsrv_updatestable(NFSPROC_T *);
void nfsrv_writestable(u_char *, int, int, NFSPROC_T *);
void nfsrv_throwawayopens(NFSPROC_T *);
-int nfsrv_checkremove(vnode_t, int, NFSPROC_T *);
+int nfsrv_checkremove(vnode_t, int, struct nfsrv_descript *, nfsquad_t,
+ NFSPROC_T *);
void nfsd_recalldelegation(vnode_t, NFSPROC_T *);
void nfsd_disabledelegation(vnode_t, NFSPROC_T *);
int nfsrv_checksetattr(vnode_t, struct nfsrv_descript *,
@@ -287,6 +288,8 @@ int nfsrvd_getxattr(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
int nfsrvd_setxattr(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
+int nfsrvd_rmxattr(struct nfsrv_descript *, int,
+ vnode_t, struct nfsexstuff *);
int nfsrvd_notsupp(struct nfsrv_descript *, int,
vnode_t, struct nfsexstuff *);
@@ -552,6 +555,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_rmextattr(vnode_t, const char *, struct nfsvattr *, int *,
+ struct ucred *, NFSPROC_T *);
/* nfs_clstate.c */
int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int,
@@ -738,6 +743,8 @@ int nfsvno_seek(struct nfsrv_descript *, struct vnode
int nfsvno_getxattr(struct vnode *, char *, 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 *);
/* nfs_commonkrpc.c */
Modified: projects/nfsv42/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/nfsv42/sys/fs/nfs/nfsport.h Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfs/nfsport.h Fri Sep 6 02:52:20 2019 (r351922)
@@ -409,11 +409,12 @@
/* and the ones for the optional Extended attribute support (RFC-8276). */
#define NFSPROC_GETEXTATTR 61
#define NFSPROC_SETEXTATTR 62
+#define NFSPROC_RMEXTATTR 63
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 63
+#define NFSV42_NPROCS 64
#endif /* NFS_V3NPROCS */
@@ -442,7 +443,7 @@ struct nfsstatsv1 {
uint64_t readlink_bios;
uint64_t biocache_readdirs;
uint64_t readdir_bios;
- uint64_t rpccnt[NFSV42_NPROCS + 6];
+ uint64_t rpccnt[NFSV42_NPROCS + 5];
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 Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfs/nfsproto.h Fri Sep 6 02:52:20 2019 (r351922)
@@ -391,11 +391,12 @@
/* and the ones for the optional Extended attribute support (RFC-8276). */
#define NFSPROC_GETEXTATTR 61
#define NFSPROC_SETEXTATTR 62
+#define NFSPROC_RMEXTATTR 63
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 63
+#define NFSV42_NPROCS 64
#endif /* NFS_V3NPROCS */
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clrpcops.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -8354,3 +8354,41 @@ nfsmout:
return (error);
}
+/*
+ * The removeextattr RPC.
+ */
+APPLESTATIC int
+nfsrpc_rmextattr(vnode_t vp, const char *name, 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_RMEXTATTR, 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) {
+ /* 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);
+}
+
Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -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_deleteextattr_t nfs_deleteextattr;
/*
* Global vfs data structures for nfs
@@ -193,6 +194,7 @@ static struct vop_vector newnfs_vnodeops_nosig = {
.vop_ioctl = nfs_ioctl,
.vop_getextattr = nfs_getextattr,
.vop_setextattr = nfs_setextattr,
+ .vop_deleteextattr = nfs_deleteextattr,
};
static int
@@ -3860,6 +3862,56 @@ nfs_setextattr(struct vop_setextattr_args *ap)
break;
default:
error = nfscl_maperr(td, error, 0, 0);
+ break;
+ }
+ return (error);
+}
+
+/*
+ * nfs setextattr call
+ */
+static int
+nfs_deleteextattr(struct vop_deleteextattr_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nfsmount *nmp;
+ 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);
+
+ /* Do the actual NFSv4.2 Optional Extended Attribute (RFC-8276) RPC. */
+ attrflag = 0;
+ error = nfsrpc_rmextattr(vp, ap->a_name, &nfsva, &attrflag, ap->a_cred,
+ ap->a_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);
+ error = EOPNOTSUPP;
+ break;
+ case NFSERR_NOXATTR:
+ case NFSERR_XATTR2BIG:
+ error = ENOATTR;
+ break;
+ default:
+ error = nfscl_maperr(ap->a_td, error, 0, 0);
break;
}
return (error);
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdport.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -1291,7 +1291,8 @@ nfsvno_removesub(struct nameidata *ndp, int is_v4, str
if (vp->v_type == VDIR)
error = NFSERR_ISDIR;
else if (is_v4)
- error = nfsrv_checkremove(vp, 1, p);
+ error = nfsrv_checkremove(vp, 1, NULL, (nfsquad_t)((u_quad_t)0),
+ p);
if (error == 0)
nfsrv_pnfsremovesetup(vp, p, dsdvp, &mirrorcnt, fname, &fh);
if (!error)
@@ -1421,12 +1422,14 @@ nfsvno_rename(struct nameidata *fromndp, struct nameid
}
if (ndflag & ND_NFSV4) {
if (NFSVOPLOCK(fvp, LK_EXCLUSIVE) == 0) {
- error = nfsrv_checkremove(fvp, 0, p);
+ error = nfsrv_checkremove(fvp, 0, NULL,
+ (nfsquad_t)((u_quad_t)0), p);
NFSVOPUNLOCK(fvp, 0);
} else
error = EPERM;
if (tvp && !error)
- error = nfsrv_checkremove(tvp, 1, p);
+ error = nfsrv_checkremove(tvp, 1, NULL,
+ (nfsquad_t)((u_quad_t)0), p);
} else {
/*
* For NFSv2 and NFSv3, try to get rid of the delegation, so
@@ -6002,6 +6005,40 @@ nfsvno_setxattr(struct vnode *vp, char *name, int len,
}
out:
+ NFSEXITCODE(error);
+ return (error);
+}
+
+/*
+ * Remove Extended attribute vnode op.
+ */
+int
+nfsvno_rmxattr(struct nfsrv_descript *nd, struct vnode *vp, char *name,
+ struct ucred *cred, struct thread *p)
+{
+ int error;
+
+ /*
+ * Get rid of any delegations. I am not sure why this is required,
+ * but RFC-8276 says so.
+ */
+ error = nfsrv_checkremove(vp, 0, nd, nd->nd_clientid, p);
+ if (error != 0)
+ goto out;
+#ifdef MAC
+ error = mac_vnode_check_deleteextattr(cred, vp, EXTATTR_NAMESPACE_USER,
+ name);
+ if (error != 0)
+ goto out;
+#endif
+
+ error = VOP_DELETEEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, cred, p);
+ if (error == EOPNOTSUPP)
+ error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
+ cred, p);
+#ifdef MAC
+out:
+#endif
NFSEXITCODE(error);
return (error);
}
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdserv.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -5604,6 +5604,75 @@ nfsmout:
}
/*
+ * nfs remove extended attribute service
+ */
+APPLESTATIC int
+nfsrvd_rmxattr(struct nfsrv_descript *nd, __unused int isdgram,
+ vnode_t vp, __unused struct nfsexstuff *exp)
+{
+ uint32_t *tl;
+ struct nfsvattr ova, nva;
+ nfsattrbit_t attrbits;
+ int error, len;
+ 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 *, 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);
+ error = nfsrv_mtostr(nd, name, len);
+ if (error != 0)
+ goto nfsmout;
+
+ if ((nd->nd_flag & ND_IMPLIEDCLID) == 0) {
+ printf("EEK! nfsrvd_rmxattr: no implied clientid\n");
+ error = NFSERR_NOXATTR;
+ goto nfsmout;
+ }
+ /*
+ * Now, do the Remove 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_rmxattr(nd, vp, name, nd->nd_cred, p);
+ if (nd->nd_repstat == ENOATTR)
+ nd->nd_repstat = NFSERR_NOXATTR;
+ }
+ 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);
+ 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 Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdsocket.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -212,7 +212,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript
nfsrvd_getxattr,
nfsrvd_setxattr,
nfsrvd_notsupp,
- nfsrvd_notsupp,
+ nfsrvd_rmxattr,
};
int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
Modified: projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Fri Sep 6 02:45:46 2019 (r351921)
+++ projects/nfsv42/sys/fs/nfsserver/nfs_nfsdstate.c Fri Sep 6 02:52:20 2019 (r351922)
@@ -5388,13 +5388,16 @@ out:
* delegations.
*/
APPLESTATIC int
-nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p)
+nfsrv_checkremove(vnode_t vp, int remove, struct nfsrv_descript *nd,
+ nfsquad_t clientid, NFSPROC_T *p)
{
+ struct nfsclient *clp;
struct nfsstate *stp;
struct nfslockfile *lfp;
int error, haslock = 0;
fhandle_t nfh;
+ clp = NULL;
/*
* First, get the lock file structure.
* (A return of -1 means no associated state, so remove ok.)
@@ -5402,6 +5405,9 @@ nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p
error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
tryagain:
NFSLOCKSTATE();
+ if (error == 0 && clientid.qval != 0)
+ error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
+ (nfsquad_t)((u_quad_t)0), 0, nd, p);
if (!error)
error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
if (error) {
@@ -5419,7 +5425,7 @@ tryagain:
/*
* Now, we must Recall any delegations.
*/
- error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p);
+ error = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
if (error) {
/*
* nfsrv_cleandeleg() unlocks state for non-zero
@@ -5556,7 +5562,8 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
starttime = NFSD_MONOSEC;
do {
if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
- error = nfsrv_checkremove(vp, 0, p);
+ error = nfsrv_checkremove(vp, 0, NULL,
+ (nfsquad_t)((u_quad_t)0), p);
NFSVOPUNLOCK(vp, 0);
} else
error = EPERM;
More information about the svn-src-projects
mailing list