Module Name: src
Committed By: hannken
Date: Mon Feb 16 10:21:25 UTC 2015
Modified Files:
src/sys/fs/union: union.h union_subr.c
Log Message:
Add reference count to union node.
To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/fs/union/union.h
cvs rdiff -u -r1.68 -r1.69 src/sys/fs/union/union_subr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/fs/union/union.h
diff -u src/sys/fs/union/union.h:1.26 src/sys/fs/union/union.h:1.27
--- src/sys/fs/union/union.h:1.26 Fri Feb 14 08:50:27 2014
+++ src/sys/fs/union/union.h Mon Feb 16 10:21:25 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: union.h,v 1.26 2014/02/14 08:50:27 hannken Exp $ */
+/* $NetBSD: union.h,v 1.27 2015/02/16 10:21:25 hannken Exp $ */
/*
* Copyright (c) 1994 The Regents of the University of California.
@@ -120,6 +120,7 @@ struct union_mount {
struct union_node {
kmutex_t un_lock;
LIST_ENTRY(union_node) un_cache; /* c: Hash chain */
+ int un_refs; /* c: Reference counter */
struct vnode *un_vnode; /* :: Back pointer */
struct vnode *un_uppervp; /* m: overlaying object */
struct vnode *un_lowervp; /* v: underlying object */
Index: src/sys/fs/union/union_subr.c
diff -u src/sys/fs/union/union_subr.c:1.68 src/sys/fs/union/union_subr.c:1.69
--- src/sys/fs/union/union_subr.c:1.68 Mon Feb 16 10:20:57 2015
+++ src/sys/fs/union/union_subr.c Mon Feb 16 10:21:25 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: union_subr.c,v 1.68 2015/02/16 10:20:57 hannken Exp $ */
+/* $NetBSD: union_subr.c,v 1.69 2015/02/16 10:21:25 hannken Exp $ */
/*
* Copyright (c) 1994
@@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.68 2015/02/16 10:20:57 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.69 2015/02/16 10:21:25 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -105,6 +105,8 @@ static u_long uhash_mask; /* size of ha
static kmutex_t uhash_lock;
void union_updatevp(struct union_node *, struct vnode *, struct vnode *);
+static void union_ref(struct union_node *);
+static void union_rele(struct union_node *);
static int union_do_lookup(struct vnode *, struct componentname *, kauth_cred_t, const char *);
int union_vn_close(struct vnode *, int, kauth_cred_t, struct lwp *);
static void union_dircache_r(struct vnode *, struct vnode ***, int *);
@@ -289,6 +291,45 @@ union_newsize(struct vnode *vp, off_t up
}
}
+static void
+union_ref(struct union_node *un)
+{
+
+ KASSERT(mutex_owned(&uhash_lock));
+ un->un_refs++;
+}
+
+static void
+union_rele(struct union_node *un)
+{
+
+ mutex_enter(&uhash_lock);
+ un->un_refs--;
+ if (un->un_refs > 0) {
+ mutex_exit(&uhash_lock);
+ return;
+ }
+ if (un->un_cflags & UN_CACHED) {
+ un->un_cflags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
+ mutex_exit(&uhash_lock);
+
+ if (un->un_pvp != NULLVP)
+ vrele(un->un_pvp);
+ if (un->un_uppervp != NULLVP)
+ vrele(un->un_uppervp);
+ if (un->un_lowervp != NULLVP)
+ vrele(un->un_lowervp);
+ if (un->un_dirvp != NULLVP)
+ vrele(un->un_dirvp);
+ if (un->un_path)
+ free(un->un_path, M_TEMP);
+ mutex_destroy(&un->un_lock);
+
+ free(un, M_TEMP);
+}
+
/*
* allocate a union_node/vnode pair. the vnode is
* referenced and unlocked. the new vnode is returned
@@ -397,9 +438,12 @@ loop:
continue;
vp = UNIONTOV(un);
+ union_ref(un);
mutex_enter(vp->v_interlock);
mutex_exit(&uhash_lock);
- if (vget(vp, 0))
+ error = vget(vp, 0);
+ union_rele(un);
+ if (error)
goto loop;
goto found;
}
@@ -517,6 +561,7 @@ found:
un = VTOUNION(*vpp);
mutex_init(&un->un_lock, MUTEX_DEFAULT, IPL_NONE);
+ un->un_refs = 1;
un->un_vnode = *vpp;
un->un_uppervp = uppervp;
un->un_lowervp = lowervp;
@@ -562,29 +607,11 @@ union_freevp(struct vnode *vp)
{
struct union_node *un = VTOUNION(vp);
- mutex_enter(&uhash_lock);
- if (un->un_cflags & UN_CACHED) {
- un->un_cflags &= ~UN_CACHED;
- LIST_REMOVE(un, un_cache);
- }
- mutex_exit(&uhash_lock);
-
- if (un->un_pvp != NULLVP)
- vrele(un->un_pvp);
- if (un->un_uppervp != NULLVP)
- vrele(un->un_uppervp);
- if (un->un_lowervp != NULLVP)
- vrele(un->un_lowervp);
- if (un->un_dirvp != NULLVP)
- vrele(un->un_dirvp);
- if (un->un_path)
- free(un->un_path, M_TEMP);
- mutex_destroy(&un->un_lock);
+ union_rele(un);
- free(vp->v_data, M_TEMP);
vp->v_data = NULL;
- return (0);
+ return 0;
}
/*