Page MenuHomeFreeBSD

D32533.diff
No OneTemporary

D32533.diff

diff --git a/sys/fs/unionfs/union.h b/sys/fs/unionfs/union.h
--- a/sys/fs/unionfs/union.h
+++ b/sys/fs/unionfs/union.h
@@ -96,7 +96,6 @@
STAILQ_ENTRY(unionfs_node) un_rele; /* deferred release list */
};
- u_long un_hashmask; /* bit mask */
char *un_path; /* path */
int un_pathlen; /* strlen of path */
int un_flag; /* unionfs node flag */
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -64,6 +64,7 @@
#include <fs/unionfs/union.h>
#define NUNIONFSNODECACHE 16
+#define UNIONFSHASHMASK (NUNIONFSNODECACHE - 1)
static MALLOC_DEFINE(M_UNIONFSHASH, "UNIONFS hash", "UNIONFS hash table");
MALLOC_DEFINE(M_UNIONFSNODE, "UNIONFS node", "UNIONFS vnode private part");
@@ -129,69 +130,83 @@
}
static struct unionfs_node_hashhead *
-unionfs_get_hashhead(struct vnode *dvp, char *path)
+unionfs_get_hashhead(struct vnode *dvp, struct vnode *lookup)
{
struct unionfs_node *unp;
- int count;
- char hash;
- hash = 0;
unp = VTOUNIONFS(dvp);
- if (path != NULL) {
- for (count = 0; path[count]; count++)
- hash += path[count];
- }
- return (&(unp->un_hashtbl[hash & (unp->un_hashmask)]));
+ return (&(unp->un_hashtbl[vfs_hash_index(lookup) & UNIONFSHASHMASK]));
}
/*
- * Get the cached vnode.
+ * Attempt to lookup a cached unionfs vnode by upper/lower vp
+ * from dvp, with dvp's interlock held.
*/
static struct vnode *
-unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp,
- struct vnode *dvp, char *path)
+unionfs_get_cached_vnode_locked(struct vnode *lookup, struct vnode *dvp)
{
- struct unionfs_node_hashhead *hd;
struct unionfs_node *unp;
+ struct unionfs_node_hashhead *hd;
struct vnode *vp;
- KASSERT((uvp == NULLVP || uvp->v_type == VDIR),
- ("unionfs_get_cached_vnode: v_type != VDIR"));
- KASSERT((lvp == NULLVP || lvp->v_type == VDIR),
- ("unionfs_get_cached_vnode: v_type != VDIR"));
+ hd = unionfs_get_hashhead(dvp, lookup);
- VI_LOCK(dvp);
- hd = unionfs_get_hashhead(dvp, path);
LIST_FOREACH(unp, hd, un_hash) {
- if (!strcmp(unp->un_path, path)) {
+ if ((unp->un_uppervp == lookup) ||
+ (unp->un_lowervp == lookup)) {
vp = UNIONFSTOV(unp);
VI_LOCK_FLAGS(vp, MTX_DUPOK);
- VI_UNLOCK(dvp);
vp->v_iflag &= ~VI_OWEINACT;
if (VN_IS_DOOMED(vp) ||
((vp->v_iflag & VI_DOINGINACT) != 0)) {
VI_UNLOCK(vp);
vp = NULLVP;
- } else
+ } else {
+ vrefl(vp);
VI_UNLOCK(vp);
+ }
return (vp);
}
}
- VI_UNLOCK(dvp);
return (NULLVP);
}
+
+/*
+ * Get the cached vnode.
+ */
+static struct vnode *
+unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp,
+ struct vnode *dvp)
+{
+ struct vnode *vp;
+
+ KASSERT((uvp == NULLVP || uvp->v_type == VDIR),
+ ("unionfs_get_cached_vnode: v_type != VDIR"));
+ KASSERT((lvp == NULLVP || lvp->v_type == VDIR),
+ ("unionfs_get_cached_vnode: v_type != VDIR"));
+
+ vp = NULLVP;
+ VI_LOCK(dvp);
+ if (uvp != NULLVP)
+ vp = unionfs_get_cached_vnode_locked(uvp, dvp);
+ else if (lvp != NULLVP)
+ vp = unionfs_get_cached_vnode_locked(lvp, dvp);
+ VI_UNLOCK(dvp);
+
+ return (vp);
+}
+
/*
* Add the new vnode into cache.
*/
static struct vnode *
unionfs_ins_cached_vnode(struct unionfs_node *uncp,
- struct vnode *dvp, char *path)
+ struct vnode *dvp)
{
struct unionfs_node_hashhead *hd;
- struct unionfs_node *unp;
struct vnode *vp;
KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR),
@@ -199,29 +214,20 @@
KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR),
("unionfs_ins_cached_vnode: v_type != VDIR"));
+ vp = NULLVP;
VI_LOCK(dvp);
- hd = unionfs_get_hashhead(dvp, path);
- LIST_FOREACH(unp, hd, un_hash) {
- if (!strcmp(unp->un_path, path)) {
- vp = UNIONFSTOV(unp);
- VI_LOCK_FLAGS(vp, MTX_DUPOK);
- vp->v_iflag &= ~VI_OWEINACT;
- if (VN_IS_DOOMED(vp) ||
- ((vp->v_iflag & VI_DOINGINACT) != 0)) {
- LIST_INSERT_HEAD(hd, uncp, un_hash);
- VI_UNLOCK(vp);
- vp = NULLVP;
- } else
- VI_UNLOCK(vp);
- VI_UNLOCK(dvp);
- return (vp);
- }
+ if (uncp->un_uppervp != NULL)
+ vp = unionfs_get_cached_vnode_locked(uncp->un_uppervp, dvp);
+ else if (uncp->un_lowervp != NULL)
+ vp = unionfs_get_cached_vnode_locked(uncp->un_lowervp, dvp);
+ if (vp == NULLVP) {
+ hd = unionfs_get_hashhead(dvp, (uncp->un_uppervp != NULLVP ?
+ uncp->un_uppervp : uncp->un_lowervp));
+ LIST_INSERT_HEAD(hd, uncp, un_hash);
}
-
- LIST_INSERT_HEAD(hd, uncp, un_hash);
VI_UNLOCK(dvp);
- return (NULLVP);
+ return (vp);
}
/*
@@ -233,13 +239,13 @@
KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node"));
KASSERT((dvp != NULLVP),
("unionfs_rem_cached_vnode: null parent vnode"));
- KASSERT((unp->un_hash.le_prev != NULL),
- ("unionfs_rem_cached_vnode: null hash"));
VI_LOCK(dvp);
- LIST_REMOVE(unp, un_hash);
- unp->un_hash.le_next = NULL;
- unp->un_hash.le_prev = NULL;
+ if (unp->un_hash.le_prev != NULL) {
+ LIST_REMOVE(unp, un_hash);
+ unp->un_hash.le_next = NULL;
+ unp->un_hash.le_prev = NULL;
+ }
VI_UNLOCK(dvp);
}
@@ -281,7 +287,7 @@
if (unp->un_lowervp != NULLVP)
vput(unp->un_lowervp);
if (unp->un_hashtbl != NULL)
- hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
+ hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, UNIONFSHASHMASK);
free(unp->un_path, M_UNIONFSPATH);
free(unp, M_UNIONFSNODE);
}
@@ -302,6 +308,7 @@
struct unionfs_mount *ump;
struct unionfs_node *unp;
struct vnode *vp;
+ u_long hashmask;
int error;
int lkflags;
enum vtype vt;
@@ -322,10 +329,9 @@
path = NULL;
/* check the cache */
- if (path != NULL && dvp != NULLVP && vt == VDIR) {
- vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp, path);
+ if (dvp != NULLVP && vt == VDIR) {
+ vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp);
if (vp != NULLVP) {
- vref(vp);
*vpp = vp;
goto unionfs_nodeget_out;
}
@@ -352,9 +358,12 @@
if (lowervp != NULLVP)
vref(lowervp);
- if (vt == VDIR)
+ if (vt == VDIR) {
unp->un_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH,
- &(unp->un_hashmask));
+ &hashmask);
+ KASSERT(hashmask == UNIONFSHASHMASK,
+ ("unexpected unionfs hash mask 0x%lx", hashmask));
+ }
unp->un_vnode = vp;
unp->un_uppervp = uppervp;
@@ -395,12 +404,12 @@
unionfs_nodeget_cleanup(vp, unp);
return (ENOENT);
}
- if (path != NULL && dvp != NULLVP && vt == VDIR)
- *vpp = unionfs_ins_cached_vnode(unp, dvp, path);
+
+ if (dvp != NULLVP && vt == VDIR)
+ *vpp = unionfs_ins_cached_vnode(unp, dvp);
if (*vpp != NULLVP) {
unionfs_nodeget_cleanup(vp, unp);
vp = *vpp;
- vref(vp);
} else {
if (uppervp != NULL)
VOP_UNLOCK(uppervp);
@@ -457,7 +466,7 @@
if (uvp != NULLVP)
VOP_UNLOCK(uvp);
- if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
+ if (dvp != NULLVP)
unionfs_rem_cached_vnode(unp, dvp);
if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0)
@@ -474,7 +483,7 @@
}
if (unp->un_hashtbl != NULL) {
- for (count = 0; count <= unp->un_hashmask; count++) {
+ for (count = 0; count <= UNIONFSHASHMASK; count++) {
hd = unp->un_hashtbl + count;
LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) {
LIST_REMOVE(unp_t1, un_hash);
@@ -482,7 +491,7 @@
unp_t1->un_hash.le_prev = NULL;
}
}
- hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
+ hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, UNIONFSHASHMASK);
}
LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) {
@@ -777,6 +786,7 @@
unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp,
struct thread *td)
{
+ struct unionfs_node_hashhead *hd;
struct vnode *vp;
struct vnode *lvp;
struct vnode *dvp;
@@ -799,16 +809,16 @@
vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
/*
- * cache update
+ * Re-cache the unionfs vnode against the upper vnode
*/
- if (unp->un_path != NULL && dvp != NULLVP && vp->v_type == VDIR) {
- static struct unionfs_node_hashhead *hd;
-
+ if (dvp != NULLVP && vp->v_type == VDIR) {
VI_LOCK(dvp);
- hd = unionfs_get_hashhead(dvp, unp->un_path);
- LIST_REMOVE(unp, un_hash);
- LIST_INSERT_HEAD(hd, unp, un_hash);
- VI_UNLOCK(dvp);
+ if (unp->un_hash.le_prev != NULL) {
+ LIST_REMOVE(unp, un_hash);
+ hd = unionfs_get_hashhead(dvp, uvp);
+ LIST_INSERT_HEAD(hd, unp, un_hash);
+ }
+ VI_UNLOCK(unp->un_dvp);
}
}

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 10, 7:37 PM (5 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31212049
Default Alt Text
D32533.diff (8 KB)

Event Timeline