Module Name: src Committed By: snj Date: Mon Apr 13 21:06:50 UTC 2009
Modified Files: src/sys/nfs [netbsd-5]: nfs_serv.c nfsm_subs.h Log Message: Pull up following revision(s) (requested by ad in ticket #700): sys/nfs/nfs_serv.c: revision 1.144 sys/nfs/nfsm_subs.h: revision 1.51 PR kern/41158: nfs_rename() locking against myself nfsrv_rename() can exit without calling genfs_renamelock_exit() because the nfsm_reply() can do return (0) on error. Change nfsm_reply to use 'error = 0; goto nfsmout' instead. Fix a few place so it's safe to goto nfsmout from nfsm_reply, or other macros calling it. As a side effect it could fix a missing vrele(dirp) in various place where nfsm_reply could return(0). To generate a diff of this commit: cvs rdiff -u -r1.138 -r1.138.16.1 src/sys/nfs/nfs_serv.c cvs rdiff -u -r1.50 -r1.50.52.1 src/sys/nfs/nfsm_subs.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.138 src/sys/nfs/nfs_serv.c:1.138.16.1 --- src/sys/nfs/nfs_serv.c:1.138 Fri Mar 28 05:02:08 2008 +++ src/sys/nfs/nfs_serv.c Mon Apr 13 21:06:50 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_serv.c,v 1.138 2008/03/28 05:02:08 dholland Exp $ */ +/* $NetBSD: nfs_serv.c,v 1.138.16.1 2009/04/13 21:06:50 snj Exp $ */ /* * Copyright (c) 1989, 1993 @@ -55,7 +55,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.138 2008/03/28 05:02:08 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.138.16.1 2009/04/13 21:06:50 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1383,7 +1383,7 @@ int32_t t1; char *bpos; int error = 0, cache = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1; - int rdev = 0; + int rdev = 0, abort = 0; int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0; char *cp2; struct mbuf *mb, *mreq; @@ -1410,6 +1410,7 @@ vrele(dirp); return (0); } + abort = 1; VATTR_NULL(&va); if (v3) { va.va_mode = 0; @@ -1485,6 +1486,7 @@ KAUTH_SYSTEM_MKNOD, 0, NULL, NULL, NULL))) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); vput(nd.ni_dvp); + abort = 0; nfsm_reply(0); return (error); } else @@ -1500,12 +1502,14 @@ vrele(nd.ni_dvp); VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); error = EINVAL; + abort = 0; nfsm_reply(0); } } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); vput(nd.ni_dvp); error = ENXIO; + abort = 0; } vp = nd.ni_vp; } else { @@ -1515,6 +1519,7 @@ vrele(nd.ni_dvp); else vput(nd.ni_dvp); + abort = 0; if (!error && va.va_size != -1) { error = nfsrv_access(vp, VWRITE, cred, (nd.ni_cnd.cn_flags & RDONLY), lwp, 0); @@ -1552,7 +1557,9 @@ } if (dirp) { vrele(dirp); + dirp = NULL; } + abort = 0; nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { if (!error) { @@ -1569,13 +1576,15 @@ nfsmout: if (dirp) vrele(dirp); - VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - if (nd.ni_vp) - vput(nd.ni_vp); + if (abort) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + if (nd.ni_vp) + vput(nd.ni_vp); + } return (error); } @@ -1599,6 +1608,7 @@ int32_t t1; char *bpos; int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; + int abort = 0; u_int32_t major, minor; enum vtype vtyp; char *cp2; @@ -1624,6 +1634,7 @@ vrele(dirp); return (0); } + abort = 1; nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); vtyp = nfsv3tov_type(*tl); if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { @@ -1695,7 +1706,9 @@ if (dirp) { diraft_ret = VOP_GETATTR(dirp, &diraft, cred); vrele(dirp); + dirp = NULL; } + abort = 0; nfsm_reply(NFSX_SRVFH(&nsfh, true) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1)); if (!error) { @@ -1705,13 +1718,15 @@ nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); return (0); nfsmout: - VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - if (nd.ni_vp) - vput(nd.ni_vp); + if (abort) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + if (nd.ni_vp) + vput(nd.ni_vp); + } if (dirp) vrele(dirp); return (error); @@ -2009,21 +2024,26 @@ } vrele(tond.ni_startdir); PNBUF_PUT(tond.ni_cnd.cn_pnbuf); + tond.ni_cnd.cn_nameiop = 0; out1: if (fdirp) { if (v3) { fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred); } vrele(fdirp); + fdirp = NULL; } if (tdirp) { if (v3) { tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred); } vrele(tdirp); + tdirp = NULL; } vrele(fromnd.ni_startdir); PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf); + fromnd.ni_cnd.cn_nameiop = 0; + localfs = NULL; nfsm_reply(2 * NFSX_WCCDATA(v3)); if (v3) { nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); @@ -2170,7 +2190,7 @@ char *bpos, *pathcp = NULL, *cp2; struct uio io; struct iovec iv; - int error = 0, cache = 0, dirfor_ret = 1, diraft_ret = 1; + int error = 0, cache = 0, dirfor_ret = 1, diraft_ret = 1, abort = 0; uint32_t len, len2; int v3 = (nfsd->nd_flag & ND_NFSV3); struct mbuf *mb, *mreq; @@ -2191,6 +2211,7 @@ } if (error) goto out; + abort = 1; VATTR_NULL(&va); va.va_type = VLNK; if (v3) { @@ -2255,7 +2276,9 @@ diraft_ret = VOP_GETATTR(dirp, &diraft, cred); } vrele(dirp); + dirp = NULL; } + abort = 0; nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { @@ -2267,13 +2290,15 @@ } return (0); nfsmout: - VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - if (nd.ni_vp) - vrele(nd.ni_vp); + if (abort) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); + } if (dirp) vrele(dirp); if (pathcp) @@ -2303,6 +2328,7 @@ int32_t t1; char *bpos; int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; + int abort = 0; int v3 = (nfsd->nd_flag & ND_NFSV3); char *cp2; struct mbuf *mb, *mreq; @@ -2327,6 +2353,7 @@ vrele(dirp); return (0); } + abort = 1; VATTR_NULL(&va); if (v3) { va.va_mode = 0; @@ -2362,7 +2389,9 @@ diraft_ret = VOP_GETATTR(dirp, &diraft, cred); } vrele(dirp); + dirp = NULL; } + abort = 0; nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { @@ -2378,13 +2407,15 @@ } return (0); nfsmout: - VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - if (nd.ni_vp) - vrele(nd.ni_vp); + if (abort) { + VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); + } if (dirp) vrele(dirp); return (error); @@ -3395,6 +3426,7 @@ u_quad_t frev; nfsm_reply(0); +nfsmout: return (0); } @@ -3417,6 +3449,7 @@ else error = EPROCUNAVAIL; nfsm_reply(0); +nfsmout: return (0); } Index: src/sys/nfs/nfsm_subs.h diff -u src/sys/nfs/nfsm_subs.h:1.50 src/sys/nfs/nfsm_subs.h:1.50.52.1 --- src/sys/nfs/nfsm_subs.h:1.50 Sun Mar 4 06:03:38 2007 +++ src/sys/nfs/nfsm_subs.h Mon Apr 13 21:06:50 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: nfsm_subs.h,v 1.50 2007/03/04 06:03:38 christos Exp $ */ +/* $NetBSD: nfsm_subs.h,v 1.50.52.1 2009/04/13 21:06:50 snj Exp $ */ /* * Copyright (c) 1989, 1993 @@ -444,8 +444,10 @@ } \ mreq = *mrq; \ if (error && (!(nfsd->nd_flag & ND_NFSV3) || \ - error == EBADRPC)) \ - return(0); \ + error == EBADRPC)) {\ + error = 0; \ + goto nfsmout; \ + } \ } #define nfsm_writereply(s, v3) \