From 177935c8d6bd5c7d5edf8352dab4ae58748a8f9c Mon Sep 17 00:00:00 2001 From: David Schultz Date: Fri, 13 Jun 2003 08:59:37 +0000 Subject: [PATCH] Plug a serious memory leak. The -STABLE equivalent of this patch has been tested extensively, but -CURRENT testing has been hampered by a number of panics that also occur without the patch. Since the destabilizing changes between 4.X and 5.X are external to unionfs, I believe this patch applies equally well to both. Thanks to scrappy for assistance testing these and other changes. MFC after: 4 days --- sys/fs/unionfs/union_subr.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index 643e1504fe88..077726834e6f 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -1246,12 +1246,14 @@ union_dircache(vp, td) int cnt; struct vnode *nvp; struct vnode **vpp; - struct vnode **dircache; + struct vnode **dircache, **newdircache; struct union_node *un; int error; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - dircache = VTOUNION(vp)->un_dircache; + un = VTOUNION(vp); + dircache = un->un_dircache; + newdircache = NULL; nvp = NULLVP; @@ -1259,8 +1261,8 @@ union_dircache(vp, td) cnt = 0; union_dircache_r(vp, 0, &cnt); cnt++; - dircache = malloc(cnt * sizeof(struct vnode *), - M_TEMP, M_WAITOK); + newdircache = dircache = malloc(cnt * sizeof(struct vnode *), + M_TEMP, M_WAITOK); vpp = dircache; union_dircache_r(vp, &vpp, &cnt); *vpp = NULLVP; @@ -1268,7 +1270,7 @@ union_dircache(vp, td) } else { vpp = dircache; do { - if (*vpp++ == VTOUNION(vp)->un_uppervp) + if (*vpp++ == un->un_uppervp) break; } while (*vpp != NULLVP); } @@ -1284,11 +1286,21 @@ union_dircache(vp, td) if (error) goto out; - VTOUNION(vp)->un_dircache = 0; - un = VTOUNION(nvp); - un->un_dircache = dircache; + un->un_dircache = NULL; + VTOUNION(nvp)->un_dircache = dircache; + newdircache = NULL; out: + /* + * If we allocated a new dircache and couldn't attach + * it to a new vp, free the resources we allocated. + */ + if (newdircache) { + for (vpp = newdircache; *vpp != NULLVP; vpp++) + vrele(*vpp); + free(newdircache, M_TEMP); + } + VOP_UNLOCK(vp, 0, td); return (nvp); }