Module Name: src Committed By: hannken Date: Wed Apr 27 17:38:52 UTC 2022
Modified Files: src/sys/nfs: nfs_serv.c nfs_srvsubs.c nfs_var.h Log Message: As VOP_GETATTR() needs a shared lock at least move the preopattr lookup inside nfs_namei() where we may lock the start directory without violating the lock order. To generate a diff of this commit: cvs rdiff -u -r1.182 -r1.183 src/sys/nfs/nfs_serv.c cvs rdiff -u -r1.15 -r1.16 src/sys/nfs/nfs_srvsubs.c cvs rdiff -u -r1.95 -r1.96 src/sys/nfs/nfs_var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/nfs/nfs_serv.c diff -u src/sys/nfs/nfs_serv.c:1.182 src/sys/nfs/nfs_serv.c:1.183 --- src/sys/nfs/nfs_serv.c:1.182 Thu Sep 16 20:17:47 2021 +++ src/sys/nfs/nfs_serv.c Wed Apr 27 17:38:52 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_serv.c,v 1.182 2021/09/16 20:17:47 andvar Exp $ */ +/* $NetBSD: nfs_serv.c,v 1.183 2022/04/27 17:38:52 hannken Exp $ */ /* * Copyright (c) 1989, 1993 @@ -55,7 +55,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.182 2021/09/16 20:17:47 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.183 2022/04/27 17:38:52 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -422,7 +422,8 @@ nfsrv_lookup(struct nfsrv_descript *nfsd nd.ni_cnd.cn_nameiop = LOOKUP; nd.ni_cnd.cn_flags = LOCKLEAF; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), pubflag); + &dirp, NULL, NULL, + lwp, (nfsd->nd_flag & ND_KERBAUTH), pubflag); if (!error && pubflag) { if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL && @@ -1447,10 +1448,8 @@ nfsrv_create(struct nfsrv_descript *nfsd nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (dirp && v3) { - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); - } + &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) { nfsm_reply(NFSX_WCCDATA(v3)); nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); @@ -1689,9 +1688,8 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (dirp) - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); + &dirp, &dirfor_ret, &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) { nfsm_reply(NFSX_WCCDATA(1)); nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); @@ -1845,14 +1843,8 @@ nfsrv_remove(struct nfsrv_descript *nfsd nd.ni_cnd.cn_nameiop = DELETE; nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (error == 0 && dirp && v3) { - if (nd.ni_dvp == nd.ni_vp) - vn_lock(dirp, LK_SHARED | LK_RETRY); - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); - if (nd.ni_dvp == nd.ni_vp) - VOP_UNLOCK(dirp); - } + &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (!error) { vp = nd.ni_vp; if (vp->v_type == VDIR) { @@ -1944,14 +1936,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd fromnd.ni_cnd.cn_nameiop = DELETE; fromnd.ni_cnd.cn_flags = LOCKPARENT; error = nfs_namei(&fromnd, &fnsfh, len, slp, nam, &md, - &dpos, &fdirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (error == 0 && fdirp && v3) { - if (fromnd.ni_dvp == fromnd.ni_vp) - vn_lock(fdirp, LK_SHARED | LK_RETRY); - fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred); - if (fromnd.ni_dvp == fromnd.ni_vp) - VOP_UNLOCK(fdirp); - } + &dpos, &fdirp, (v3 ? &fdirfor_ret : NULL), &fdirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) { fromnd.ni_cnd.cn_nameiop = 0; nfsm_reply(2 * NFSX_WCCDATA(v3)); @@ -2021,10 +2007,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd tond.ni_cnd.cn_nameiop = RENAME; tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE; error = nfs_namei(&tond, &tnsfh, len2, slp, nam, &md, - &dpos, &tdirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (tdirp && v3) { - tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred); - } + &dpos, &tdirp, (v3 ? &tdirfor_ret : NULL), &tdirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) { VFS_RENAMELOCK_EXIT(localfs); VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); @@ -2218,10 +2202,8 @@ nfsrv_link(struct nfsrv_descript *nfsd, nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; error = nfs_namei(&nd, &dnsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (dirp && v3) { - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); - } + &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) goto out1; xp = nd.ni_vp; @@ -2310,10 +2292,8 @@ nfsrv_symlink(struct nfsrv_descript *nfs nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (dirp && v3) { - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); - } + &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) goto out; abort = 1; @@ -2455,10 +2435,8 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (dirp && v3) { - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); - } + &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) { if (nd.ni_pathbuf != NULL) { pathbuf_destroy(nd.ni_pathbuf); @@ -2579,10 +2557,8 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, nd.ni_cnd.cn_nameiop = DELETE; nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; error = nfs_namei(&nd, &nsfh, len, slp, nam, &md, &dpos, - &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), false); - if (dirp && v3) { - dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred); - } + &dirp, (v3 ? &dirfor_ret : NULL), &dirfor, + lwp, (nfsd->nd_flag & ND_KERBAUTH), false); if (error) { if (nd.ni_pathbuf != NULL) { pathbuf_destroy(nd.ni_pathbuf); Index: src/sys/nfs/nfs_srvsubs.c diff -u src/sys/nfs/nfs_srvsubs.c:1.15 src/sys/nfs/nfs_srvsubs.c:1.16 --- src/sys/nfs/nfs_srvsubs.c:1.15 Fri Jan 17 20:08:09 2020 +++ src/sys/nfs/nfs_srvsubs.c Wed Apr 27 17:38:52 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_srvsubs.c,v 1.15 2020/01/17 20:08:09 ad Exp $ */ +/* $NetBSD: nfs_srvsubs.c,v 1.16 2022/04/27 17:38:52 hannken Exp $ */ /* * Copyright (c) 1989, 1993 @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.15 2020/01/17 20:08:09 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.16 2022/04/27 17:38:52 hannken Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -116,7 +116,7 @@ __KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs. * it is not. */ int -nfs_namei(struct nameidata *ndp, nfsrvfh_t *nsfh, uint32_t len, struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp, char **dposp, struct vnode **retdirp, struct lwp *l, int kerbflag, int pubflag) +nfs_namei(struct nameidata *ndp, nfsrvfh_t *nsfh, uint32_t len, struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp, char **dposp, struct vnode **retdirp, int *dirattr_retp, struct vattr *dirattrp, struct lwp *l, int kerbflag, int pubflag) { int i, rem; struct mbuf *md; @@ -188,6 +188,11 @@ nfs_namei(struct nameidata *ndp, nfsrvfh cnp->cn_flags |= RDONLY; *retdirp = dp; + if (dirattr_retp != NULL) { + vn_lock(dp, LK_SHARED | LK_RETRY); + *dirattr_retp = VOP_GETATTR(dp, dirattrp, ndp->ni_cnd.cn_cred); + VOP_UNLOCK(dp); + } if (pubflag) { /* Index: src/sys/nfs/nfs_var.h diff -u src/sys/nfs/nfs_var.h:1.95 src/sys/nfs/nfs_var.h:1.96 --- src/sys/nfs/nfs_var.h:1.95 Fri Jun 4 10:44:58 2021 +++ src/sys/nfs/nfs_var.h Wed Apr 27 17:38:52 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_var.h,v 1.95 2021/06/04 10:44:58 hannken Exp $ */ +/* $NetBSD: nfs_var.h,v 1.96 2022/04/27 17:38:52 hannken Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -271,8 +271,8 @@ void nfs_delayedtruncate(struct vnode *) int nfs_check_wccdata(struct nfsnode *, const struct timespec *, struct timespec *, bool); int nfs_namei(struct nameidata *, nfsrvfh_t *, uint32_t, struct nfssvc_sock *, - struct mbuf *, struct mbuf **, char **, struct vnode **, struct lwp *, - int, int); + struct mbuf *, struct mbuf **, char **, struct vnode **, + int *, struct vattr *, struct lwp *, int, int); void nfs_zeropad(struct mbuf *, int, int); void nfsm_srvwcc(struct nfsrv_descript *, int, struct vattr *, int, struct vattr *, struct mbuf **, char **);