diff options
author | daichi <daichi@FreeBSD.org> | 2008-05-07 05:32:55 +0000 |
---|---|---|
committer | daichi <daichi@FreeBSD.org> | 2008-05-07 05:32:55 +0000 |
commit | 8f6931899ec11c0dcf6e9bf7de562cc5dc2c7cbc (patch) | |
tree | 29be23f9d0bdd5565d782ce4a3e1344286c6a36e | |
parent | 2d9de442ad04fb80f0f066a70e8634a5d566ce1e (diff) | |
download | FreeBSD-src-8f6931899ec11c0dcf6e9bf7de562cc5dc2c7cbc.zip FreeBSD-src-8f6931899ec11c0dcf6e9bf7de562cc5dc2c7cbc.tar.gz |
- change function name from *_vdir to *_vnode because
VSOCK has been added as cache target. Now they process
not only VDIR but also VSOCK.
- fixed panic issue caused by cache incorrect free process
by "umount -f"
Submitted by: Masanori OZAWA <ozawa@ongs.co.jp>
MFC after: 1 week
-rw-r--r-- | sys/fs/unionfs/union_subr.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index b3b5811..fb30537 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -103,10 +103,10 @@ unionfs_get_hashhead(struct vnode *dvp, char *path) } /* - * Get the cached vnode. (only VDIR) + * Get the cached vnode. */ static struct vnode * -unionfs_get_cached_vdir(struct vnode *uvp, struct vnode *lvp, +unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp, struct vnode *dvp, char *path) { struct unionfs_node_hashhead *hd; @@ -114,9 +114,9 @@ unionfs_get_cached_vdir(struct vnode *uvp, struct vnode *lvp, struct vnode *vp; KASSERT((uvp == NULLVP || uvp->v_type == VDIR || uvp->v_type == VSOCK), - ("unionfs_get_cached_vdir: v_type != VDIR/VSOCK")); + ("unionfs_get_cached_vnode: v_type != VDIR/VSOCK")); KASSERT((lvp == NULLVP || lvp->v_type == VDIR || lvp->v_type == VSOCK), - ("unionfs_get_cached_vdir: v_type != VDIR/VSOCK")); + ("unionfs_get_cached_vnode: v_type != VDIR/VSOCK")); VI_LOCK(dvp); hd = unionfs_get_hashhead(dvp, path); @@ -140,10 +140,10 @@ unionfs_get_cached_vdir(struct vnode *uvp, struct vnode *lvp, } /* - * Add the new vnode into cache. (only VDIR) + * Add the new vnode into cache. */ static struct vnode * -unionfs_ins_cached_vdir(struct unionfs_node *uncp, +unionfs_ins_cached_vnode(struct unionfs_node *uncp, struct vnode *dvp, char *path) { struct unionfs_node_hashhead *hd; @@ -152,10 +152,10 @@ unionfs_ins_cached_vdir(struct unionfs_node *uncp, KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR || uncp->un_uppervp->v_type==VSOCK), - ("unionfs_ins_cached_vdir: v_type != VDIR/VSOCK")); + ("unionfs_ins_cached_vnode: v_type != VDIR/VSOCK")); KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR || uncp->un_lowervp->v_type==VSOCK), - ("unionfs_ins_cached_vdir: v_type != VDIR/VSOCK")); + ("unionfs_ins_cached_vnode: v_type != VDIR/VSOCK")); VI_LOCK(dvp); hd = unionfs_get_hashhead(dvp, path); @@ -182,19 +182,21 @@ unionfs_ins_cached_vdir(struct unionfs_node *uncp, } /* - * Remove the vnode. (only VDIR) + * Remove the vnode. */ static void -unionfs_rem_cached_vdir(struct unionfs_node *unp, struct vnode *dvp) +unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp) { - KASSERT((unp != NULL), ("unionfs_rem_cached_vdir: null node")); + KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node")); KASSERT((dvp != NULLVP), - ("unionfs_rem_cached_vdir: null parent vnode")); + ("unionfs_rem_cached_vnode: null parent vnode")); KASSERT((unp->un_hash.le_prev != NULL), - ("unionfs_rem_cached_vdir: null hash")); + ("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; VI_UNLOCK(dvp); } @@ -233,9 +235,9 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp, if (cnp && !(cnp->cn_flags & ISLASTCN)) path = NULL; - /* check the vdir cache */ + /* check the cache */ if (path != NULL && dvp != NULLVP && (vt == VDIR || vt == VSOCK)) { - vp = unionfs_get_cached_vdir(uppervp, lowervp, dvp, path); + vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp, path); if (vp != NULLVP) { vref(vp); *vpp = vp; @@ -313,7 +315,7 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp, vp->v_vflag |= VV_ROOT; if (path != NULL && dvp != NULLVP && (vt == VDIR || vt == VSOCK)) - *vpp = unionfs_ins_cached_vdir(unp, dvp, path); + *vpp = unionfs_ins_cached_vnode(unp, dvp, path); if ((*vpp) != NULLVP) { if (dvp != NULLVP) vrele(dvp); @@ -345,7 +347,9 @@ void unionfs_noderem(struct vnode *vp, struct thread *td) { int vfslocked; - struct unionfs_node *unp; + int count; + struct unionfs_node *unp, *unp_t1, *unp_t2; + struct unionfs_node_hashhead *hd; struct unionfs_node_status *unsp, *unsp_tmp; struct vnode *lvp; struct vnode *uvp; @@ -371,9 +375,8 @@ unionfs_noderem(struct vnode *vp, struct thread *td) VOP_UNLOCK(uvp, 0); vp->v_object = NULL; - if (unp->un_path != NULL && dvp != NULLVP && - (vp->v_type == VDIR || vp->v_type == VSOCK)) - unionfs_rem_cached_vdir(unp, dvp); + if (dvp != NULLVP && unp->un_hash.le_prev != NULL) + unionfs_rem_cached_vnode(unp, dvp); if (lvp != NULLVP) { vfslocked = VFS_LOCK_GIANT(lvp->v_mount); @@ -396,8 +399,17 @@ unionfs_noderem(struct vnode *vp, struct thread *td) unp->un_path = NULL; } - if (unp->un_hashtbl != NULL) + if (unp->un_hashtbl != NULL) { + for (count = 0; count <= unp->un_hashmask; count++) { + hd = unp->un_hashtbl + count; + LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) { + LIST_REMOVE(unp_t1, un_hash); + unp_t1->un_hash.le_next = NULL; + unp_t1->un_hash.le_prev = NULL; + } + } hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask); + } LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) { LIST_REMOVE(unsp, uns_list); |