summaryrefslogtreecommitdiffstats
path: root/sys/fs/unionfs/union_subr.c
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2003-06-13 08:59:37 +0000
committerdas <das@FreeBSD.org>2003-06-13 08:59:37 +0000
commit7b9c7016940003859fcca549bd5468de9a774ac8 (patch)
tree42da53bdeef0e9c8ba2b1203a0e04b69bbd38270 /sys/fs/unionfs/union_subr.c
parent6e6f4e827010564489106d68fd31745b8712f0d0 (diff)
downloadFreeBSD-src-7b9c7016940003859fcca549bd5468de9a774ac8.zip
FreeBSD-src-7b9c7016940003859fcca549bd5468de9a774ac8.tar.gz
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
Diffstat (limited to 'sys/fs/unionfs/union_subr.c')
-rw-r--r--sys/fs/unionfs/union_subr.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index 643e150..0777268 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);
}
OpenPOWER on IntegriCloud