Date: Fri, 6 Sep 2019 02:52:21 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r351922 - in projects/nfsv42/sys/fs: nfs nfsclient nfsserver Message-ID: <201909060252.x862qLFB065615@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909060252.x862qLFB065615>