Module Name: src
Committed By: hannken
Date: Sat Dec 13 15:59:30 UTC 2014
Modified Files:
src/sys/coda: cnode.h coda_subr.c coda_vfsops.c coda_vfsops.h
coda_vnops.c
Log Message:
Change coda from hashlist to vcache.
- Replace all hash list crawlers with vfs_vnode_iterator.
To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/coda/cnode.h
cvs rdiff -u -r1.29 -r1.30 src/sys/coda/coda_subr.c
cvs rdiff -u -r1.83 -r1.84 src/sys/coda/coda_vfsops.c
cvs rdiff -u -r1.18 -r1.19 src/sys/coda/coda_vfsops.h
cvs rdiff -u -r1.100 -r1.101 src/sys/coda/coda_vnops.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/coda/cnode.h
diff -u src/sys/coda/cnode.h:1.19 src/sys/coda/cnode.h:1.20
--- src/sys/coda/cnode.h:1.19 Sat Dec 13 15:58:13 2014
+++ src/sys/coda/cnode.h Sat Dec 13 15:59:30 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: cnode.h,v 1.19 2014/12/13 15:58:13 hannken Exp $ */
+/* $NetBSD: cnode.h,v 1.20 2014/12/13 15:59:30 hannken Exp $ */
/*
*
@@ -106,7 +106,7 @@ struct cnode {
u_short c_symlen; /* length of symbolic link */
dev_t c_device; /* associated vnode device */
ino_t c_inode; /* associated vnode inode */
- struct cnode *c_next; /* links if on NetBSD machine */
+ kmutex_t c_lock;
};
#define VTOC(vp) ((struct cnode *)(vp)->v_data)
#define SET_VTOC(vp) ((vp)->v_data)
Index: src/sys/coda/coda_subr.c
diff -u src/sys/coda/coda_subr.c:1.29 src/sys/coda/coda_subr.c:1.30
--- src/sys/coda/coda_subr.c:1.29 Sat Dec 13 15:58:39 2014
+++ src/sys/coda/coda_subr.c Sat Dec 13 15:59:30 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: coda_subr.c,v 1.29 2014/12/13 15:58:39 hannken Exp $ */
+/* $NetBSD: coda_subr.c,v 1.30 2014/12/13 15:59:30 hannken Exp $ */
/*
*
@@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: coda_subr.c,v 1.29 2014/12/13 15:58:39 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: coda_subr.c,v 1.30 2014/12/13 15:59:30 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -70,22 +70,11 @@ __KERNEL_RCSID(0, "$NetBSD: coda_subr.c,
#include <coda/coda_subr.h>
#include <coda/coda_namecache.h>
-
-int coda_active = 0;
-int coda_reuse = 0;
-int coda_new = 0;
-
-struct cnode *coda_freelist = NULL;
-struct cnode *coda_cache[CODA_CACHESIZE];
-MALLOC_DEFINE(M_CODA, "coda", "Coda file system structures and tables");
-
int codadebug = 0;
int coda_printf_delay = 0; /* in microseconds */
int coda_vnop_print_entry = 0;
int coda_vfsop_print_entry = 0;
-#define CNODE_NEXT(cp) ((cp)->c_next)
-
#ifdef CODA_COMPAT_5
#define coda_hash(fid) \
(((fid)->Volume + (fid)->Vnode) & (CODA_CACHESIZE-1))
@@ -99,99 +88,56 @@ int coda_vfsop_print_entry = 0;
struct vnode *coda_ctlvp;
/*
- * Allocate a cnode.
+ * Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it.
+ * The cnode is returned locked with the vnode referenced.
*/
struct cnode *
-coda_alloc(void)
+coda_find(CodaFid *fid)
{
- struct cnode *cp;
-
- if (coda_freelist) {
- cp = coda_freelist;
- coda_freelist = CNODE_NEXT(cp);
- coda_reuse++;
- }
- else {
- CODA_ALLOC(cp, struct cnode *, sizeof(struct cnode));
- /* NetBSD vnodes don't have any Pager info in them ('cause there are
- no external pagers, duh!) */
-#define VNODE_VM_INFO_INIT(vp) /* MT */
- VNODE_VM_INFO_INIT(CTOV(cp));
- coda_new++;
- }
- memset(cp, 0, sizeof (struct cnode));
+ int i;
+ struct vnode *vp;
+ struct cnode *cp;
- return(cp);
-}
+ for (i = 0; i < NVCODA; i++) {
+ if (!coda_mnttbl[i].mi_started)
+ continue;
+ if (vcache_get(coda_mnttbl[i].mi_vfsp,
+ fid, sizeof(CodaFid), &vp) != 0)
+ continue;
+ mutex_enter(vp->v_interlock);
+ cp = VTOC(vp);
+ if (vp->v_type == VNON || cp == NULL || IS_UNMOUNTING(cp)) {
+ mutex_exit(vp->v_interlock);
+ vrele(vp);
+ continue;
+ }
+ mutex_enter(&cp->c_lock);
+ mutex_exit(vp->v_interlock);
-/*
- * Deallocate a cnode.
- */
-void
-coda_free(struct cnode *cp)
-{
+ return cp;
+ }
- CNODE_NEXT(cp) = coda_freelist;
- coda_freelist = cp;
+ return NULL;
}
/*
- * Put a cnode in the hash table
+ * Iterate over all nodes attached to coda mounts.
*/
-void
-coda_save(struct cnode *cp)
+static void
+coda_iterate(bool (*f)(void *, struct vnode *), void *cl)
{
- CNODE_NEXT(cp) = coda_cache[coda_hash(&cp->c_fid)];
- coda_cache[coda_hash(&cp->c_fid)] = cp;
-}
-
-/*
- * Remove a cnode from the hash table
- */
-void
-coda_unsave(struct cnode *cp)
-{
- struct cnode *ptr;
- struct cnode *ptrprev = NULL;
-
- ptr = coda_cache[coda_hash(&cp->c_fid)];
- while (ptr != NULL) {
- if (ptr == cp) {
- if (ptrprev == NULL) {
- coda_cache[coda_hash(&cp->c_fid)]
- = CNODE_NEXT(ptr);
- } else {
- CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr);
- }
- CNODE_NEXT(cp) = NULL;
+ int i;
+ struct vnode_iterator *marker;
+ struct vnode *vp;
- return;
+ for (i = 0; i < NVCODA; i++) {
+ if (coda_mnttbl[i].mi_vfsp == NULL)
+ continue;
+ vfs_vnode_iterator_init(coda_mnttbl[i].mi_vfsp, &marker);
+ while ((vp = vfs_vnode_iterator_next(marker, f, cl)) != NULL)
+ vrele(vp);
+ vfs_vnode_iterator_destroy(marker);
}
- ptrprev = ptr;
- ptr = CNODE_NEXT(ptr);
- }
-}
-
-/*
- * Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it.
- * NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95
- */
-struct cnode *
-coda_find(CodaFid *fid)
-{
- struct cnode *cp;
-
- cp = coda_cache[coda_hash(fid)];
- while (cp) {
- if (coda_fid_eq(&(cp->c_fid), fid) &&
- (!IS_UNMOUNTING(cp)))
- {
- coda_active++;
- return(cp);
- }
- cp = CNODE_NEXT(cp);
- }
- return(NULL);
}
/*
@@ -203,19 +149,25 @@ coda_find(CodaFid *fid)
* running, only kill the cnodes for a particular entry in the
* coda_mnttbl. -- DCS 12/1/94 */
+static bool
+coda_kill_selector(void *cl, struct vnode *vp)
+{
+ int *count = cl;
+
+ (*count)++;
+
+ return false;
+}
+
int
coda_kill(struct mount *whoIam, enum dc_status dcstat)
{
- int hash, count = 0;
- struct cnode *cp;
+ int count = 0;
+ struct vnode_iterator *marker;
/*
* Algorithm is as follows:
* Second, flush whatever vnodes we can from the name cache.
- *
- * Finally, step through whatever is left and mark them dying.
- * This prevents any operation at all.
-
*/
/* This is slightly overkill, but should work. Eventually it'd be
@@ -223,23 +175,11 @@ coda_kill(struct mount *whoIam, enum dc_
* reference a vnode in this vfs. */
coda_nc_flush(dcstat);
- for (hash = 0; hash < CODA_CACHESIZE; hash++) {
- for (cp = coda_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
- if (IS_CTL_VP(CTOV(cp)))
- continue;
- if (CTOV(cp)->v_mount == whoIam) {
-#ifdef DEBUG
- printf("coda_kill: vp %p, cp %p\n", CTOV(cp), cp);
-#endif
- count++;
- CODADEBUG(CODA_FLUSH,
- myprintf(("Live cnode fid %s flags %d count %d\n",
- coda_f2s(&cp->c_fid),
- cp->c_flags,
- CTOV(cp)->v_usecount)); );
- }
- }
- }
+
+ vfs_vnode_iterator_init(whoIam, &marker);
+ vfs_vnode_iterator_next(marker, coda_kill_selector, &count);
+ vfs_vnode_iterator_destroy(marker);
+
return count;
}
@@ -247,43 +187,48 @@ coda_kill(struct mount *whoIam, enum dc_
* There are two reasons why a cnode may be in use, it may be in the
* name cache or it may be executing.
*/
+static bool
+coda_flush_selector(void *cl, struct vnode *vp)
+{
+ struct cnode *cp = VTOC(vp);
+
+ if (cp != NULL && !IS_DIR(cp->c_fid)) /* only files can be executed */
+ coda_vmflush(cp);
+
+ return false;
+}
void
coda_flush(enum dc_status dcstat)
{
- int hash;
- struct cnode *cp;
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_FLUSH]++;
coda_nc_flush(dcstat); /* flush files from the name cache */
- for (hash = 0; hash < CODA_CACHESIZE; hash++) {
- for (cp = coda_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
- if (!IS_DIR(cp->c_fid)) /* only files can be executed */
- coda_vmflush(cp);
- }
- }
+ coda_iterate(coda_flush_selector, NULL);
}
/*
* As a debugging measure, print out any cnodes that lived through a
* name cache flush.
*/
+static bool
+coda_testflush_selector(void *cl, struct vnode *vp)
+{
+ struct cnode *cp = VTOC(vp);
+
+ if (cp != NULL)
+ myprintf(("Live cnode fid %s count %d\n",
+ coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount));
+
+ return false;
+}
void
coda_testflush(void)
{
- int hash;
- struct cnode *cp;
- for (hash = 0; hash < CODA_CACHESIZE; hash++) {
- for (cp = coda_cache[hash];
- cp != NULL;
- cp = CNODE_NEXT(cp)) {
- myprintf(("Live cnode fid %s count %d\n",
- coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount));
- }
- }
+ coda_iterate(coda_testflush_selector, NULL);
}
/*
@@ -292,62 +237,66 @@ coda_testflush(void)
* is dead, which would be a bad thing.
*
*/
+static bool
+coda_unmounting_selector(void *cl, struct vnode *vp)
+{
+ struct cnode *cp = VTOC(vp);
+
+ if (cp)
+ cp->c_flags |= C_UNMOUNTING;
+
+ return false;
+}
void
coda_unmounting(struct mount *whoIam)
{
- int hash;
- struct cnode *cp;
+ struct vnode_iterator *marker;
- for (hash = 0; hash < CODA_CACHESIZE; hash++) {
- for (cp = coda_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
- if (CTOV(cp)->v_mount == whoIam) {
- cp->c_flags |= C_UNMOUNTING;
- }
- }
- }
+ vfs_vnode_iterator_init(whoIam, &marker);
+ vfs_vnode_iterator_next(marker, coda_unmounting_selector, NULL);
+ vfs_vnode_iterator_destroy(marker);
}
#ifdef DEBUG
+static bool
+coda_checkunmounting_selector(void *cl, struct vnode *vp)
+{
+ struct cnode *cp = VTOC(vp);
+
+ if (cp && !(cp->c_flags & C_UNMOUNTING)) {
+ printf("vp %p, cp %p missed\n", vp, cp);
+ cp->c_flags |= C_UNMOUNTING;
+ }
+
+ return false;
+}
void
coda_checkunmounting(struct mount *mp)
{
- struct vnode *vp;
- struct cnode *cp;
- int count = 0, bad = 0;
-loop:
- TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
- if (vp->v_mount != mp)
- goto loop;
- cp = VTOC(vp);
- count++;
- if (!(cp->c_flags & C_UNMOUNTING)) {
- bad++;
- printf("vp %p, cp %p missed\n", vp, cp);
- cp->c_flags |= C_UNMOUNTING;
- }
- }
+ struct vnode_iterator *marker;
+
+ vfs_vnode_iterator_init(mp, &marker);
+ vfs_vnode_iterator_next(marker, coda_checkunmounting_selector, NULL);
+ vfs_vnode_iterator_destroy(marker);
}
void
coda_cacheprint(struct mount *whoIam)
{
- int hash;
- struct cnode *cp;
+ struct vnode *vp;
+ struct vnode_iterator *marker;
int count = 0;
printf("coda_cacheprint: coda_ctlvp %p, cp %p", coda_ctlvp, VTOC(coda_ctlvp));
coda_nc_name(VTOC(coda_ctlvp));
printf("\n");
- for (hash = 0; hash < CODA_CACHESIZE; hash++) {
- for (cp = coda_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
- if (CTOV(cp)->v_mount == whoIam) {
- printf("coda_cacheprint: vp %p, cp %p", CTOV(cp), cp);
- coda_nc_name(cp);
- printf("\n");
- count++;
- }
- }
+ vfs_vnode_iterator_init(whoIam, &marker);
+ while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL)) != NULL) {
+ printf("coda_cacheprint: vp %p, cp %p", vp, VTOC(vp));
+ coda_nc_name(VTOC(vp));
+ printf("\n");
+ count++;
}
printf("coda_cacheprint: count %d\n", count);
}
@@ -414,8 +363,6 @@ int handleDownCall(int opcode, union out
cp = coda_find(&out->coda_zapfile.Fid);
if (cp != NULL) {
- vref(CTOV(cp));
-
cp->c_flags &= ~C_VATTR;
if (CTOV(cp)->v_iflag & VI_TEXT)
error = coda_vmflush(cp);
@@ -425,6 +372,7 @@ int handleDownCall(int opcode, union out
if (CTOV(cp)->v_usecount == 1) {
cp->c_flags |= C_PURGING;
}
+ mutex_exit(&cp->c_lock);
vrele(CTOV(cp));
}
@@ -439,8 +387,6 @@ int handleDownCall(int opcode, union out
cp = coda_find(&out->coda_zapdir.Fid);
if (cp != NULL) {
- vref(CTOV(cp));
-
cp->c_flags &= ~C_VATTR;
coda_nc_zapParentfid(&out->coda_zapdir.Fid, IS_DOWNCALL);
@@ -450,6 +396,7 @@ int handleDownCall(int opcode, union out
if (CTOV(cp)->v_usecount == 1) {
cp->c_flags |= C_PURGING;
}
+ mutex_exit(&cp->c_lock);
vrele(CTOV(cp));
}
@@ -465,7 +412,6 @@ int handleDownCall(int opcode, union out
cp = coda_find(&out->coda_purgefid.Fid);
if (cp != NULL) {
- vref(CTOV(cp));
if (IS_DIR(out->coda_purgefid.Fid)) { /* Vnode is a directory */
coda_nc_zapParentfid(&out->coda_purgefid.Fid,
IS_DOWNCALL);
@@ -483,6 +429,7 @@ int handleDownCall(int opcode, union out
if (CTOV(cp)->v_usecount == 1) {
cp->c_flags |= C_PURGING;
}
+ mutex_exit(&cp->c_lock);
vrele(CTOV(cp));
}
return(error);
@@ -496,16 +443,24 @@ int handleDownCall(int opcode, union out
cp = coda_find(&out->coda_replace.OldFid);
if (cp != NULL) {
- /* remove the cnode from the hash table, replace the fid, and reinsert */
- vref(CTOV(cp));
- coda_unsave(cp);
+ error = vcache_rekey_enter(CTOV(cp)->v_mount, CTOV(cp),
+ &out->coda_replace.OldFid, sizeof(CodaFid),
+ &out->coda_replace.NewFid, sizeof(CodaFid));
+ if (error) {
+ mutex_exit(&cp->c_lock);
+ vrele(CTOV(cp));
+ return error;
+ }
cp->c_fid = out->coda_replace.NewFid;
- coda_save(cp);
+ vcache_rekey_exit(CTOV(cp)->v_mount, CTOV(cp),
+ &out->coda_replace.OldFid, sizeof(CodaFid),
+ &cp->c_fid, sizeof(CodaFid));
CODADEBUG(CODA_REPLACE, myprintf((
"replace: oldfid = %s, newfid = %s, cp = %p\n",
coda_f2s(&out->coda_replace.OldFid),
coda_f2s(&cp->c_fid), cp));)
+ mutex_exit(&cp->c_lock);
vrele(CTOV(cp));
}
return (0);
Index: src/sys/coda/coda_vfsops.c
diff -u src/sys/coda/coda_vfsops.c:1.83 src/sys/coda/coda_vfsops.c:1.84
--- src/sys/coda/coda_vfsops.c:1.83 Sat Dec 13 15:58:39 2014
+++ src/sys/coda/coda_vfsops.c Sat Dec 13 15:59:30 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: coda_vfsops.c,v 1.83 2014/12/13 15:58:39 hannken Exp $ */
+/* $NetBSD: coda_vfsops.c,v 1.84 2014/12/13 15:59:30 hannken Exp $ */
/*
*
@@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: coda_vfsops.c,v 1.83 2014/12/13 15:58:39 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: coda_vfsops.c,v 1.84 2014/12/13 15:59:30 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -106,6 +106,7 @@ struct vfsops coda_vfsops = {
.vfs_statvfs = coda_nb_statvfs,
.vfs_sync = coda_sync,
.vfs_vget = coda_vget,
+ .vfs_loadvnode = coda_loadvnode,
.vfs_fhtovp = (void *)eopnotsupp,
.vfs_vptofh = (void *)eopnotsupp,
.vfs_init = coda_init,
@@ -371,13 +372,19 @@ coda_root(struct mount *vfsp, struct vno
error = venus_root(vftomi(vfsp), l->l_cred, l->l_proc, &VFid);
if (!error) {
+ struct cnode *cp = VTOC(mi->mi_rootvp);
+
/*
- * Save the new rootfid in the cnode, and rehash the cnode into the
- * cnode hash with the new fid key.
+ * Save the new rootfid in the cnode, and rekey the cnode
+ * with the new fid key.
*/
- coda_unsave(VTOC(mi->mi_rootvp));
- VTOC(mi->mi_rootvp)->c_fid = VFid;
- coda_save(VTOC(mi->mi_rootvp));
+ error = vcache_rekey_enter(vfsp, mi->mi_rootvp,
+ &invalfid, sizeof(CodaFid), &VFid, sizeof(CodaFid));
+ if (error)
+ goto exit;
+ cp->c_fid = VFid;
+ vcache_rekey_exit(vfsp, mi->mi_rootvp,
+ &invalfid, sizeof(CodaFid), &cp->c_fid, sizeof(CodaFid));
*vpp = mi->mi_rootvp;
vref(*vpp);
@@ -475,6 +482,31 @@ coda_vget(struct mount *vfsp, ino_t ino,
return (EOPNOTSUPP);
}
+int
+coda_loadvnode(struct mount *mp, struct vnode *vp,
+ const void *key, size_t key_len, const void **new_key)
+{
+ CodaFid fid;
+ struct cnode *cp;
+ extern int (**coda_vnodeop_p)(void *);
+
+ KASSERT(key_len == sizeof(CodaFid));
+ memcpy(&fid, key, key_len);
+
+ cp = kmem_zalloc(sizeof(*cp), KM_SLEEP);
+ mutex_init(&cp->c_lock, MUTEX_DEFAULT, IPL_NONE);
+ cp->c_fid = fid;
+ cp->c_vnode = vp;
+ vp->v_op = coda_vnodeop_p;
+ vp->v_tag = VT_CODA;
+ vp->v_type = VNON;
+ vp->v_data = cp;
+
+ *new_key = &cp->c_fid;
+
+ return 0;
+}
+
/*
* fhtovp is now what vget used to be in 4.3-derived systems. For
* some silly reason, vget is now keyed by a 32 bit ino_t, rather than
Index: src/sys/coda/coda_vfsops.h
diff -u src/sys/coda/coda_vfsops.h:1.18 src/sys/coda/coda_vfsops.h:1.19
--- src/sys/coda/coda_vfsops.h:1.18 Mon Nov 26 19:01:28 2007
+++ src/sys/coda/coda_vfsops.h Sat Dec 13 15:59:30 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: coda_vfsops.h,v 1.18 2007/11/26 19:01:28 pooka Exp $ */
+/* $NetBSD: coda_vfsops.h,v 1.19 2014/12/13 15:59:30 hannken Exp $ */
/*
*
@@ -53,6 +53,8 @@ int coda_root(struct mount *, struct vno
int coda_nb_statvfs(struct mount *, struct statvfs *);
int coda_sync(struct mount *, int, kauth_cred_t);
int coda_vget(struct mount *, ino_t, struct vnode **);
+int coda_loadvnode(struct mount *, struct vnode *, const void *, size_t,
+ const void **);
int coda_fhtovp(struct mount *, struct fid *, struct mbuf *, struct vnode **,
int *, kauth_cred_t *);
int coda_vptofh(struct vnode *, struct fid *);
Index: src/sys/coda/coda_vnops.c
diff -u src/sys/coda/coda_vnops.c:1.100 src/sys/coda/coda_vnops.c:1.101
--- src/sys/coda/coda_vnops.c:1.100 Sat Dec 13 15:59:03 2014
+++ src/sys/coda/coda_vnops.c Sat Dec 13 15:59:30 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: coda_vnops.c,v 1.100 2014/12/13 15:59:03 hannken Exp $ */
+/* $NetBSD: coda_vnops.c,v 1.101 2014/12/13 15:59:30 hannken Exp $ */
/*
*
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: coda_vnops.c,v 1.100 2014/12/13 15:59:03 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: coda_vnops.c,v 1.101 2014/12/13 15:59:30 hannken Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -793,8 +793,8 @@ coda_fsync(void *v)
return(ENODEV);
}
- /* Check for fsync of control object. */
- if (IS_CTL_VP(vp)) {
+ /* Check for fsync of control object or unitialized cnode. */
+ if (IS_CTL_VP(vp) || vp->v_type == VNON) {
MARK_INT_SAT(CODA_FSYNC_STATS);
return(0);
}
@@ -1675,9 +1675,16 @@ coda_reclaim(void *v)
}
/* Remove it from the table so it can't be found. */
- coda_unsave(cp);
- coda_free(VTOC(vp));
+ vcache_remove(vp->v_mount, &cp->c_fid, sizeof(CodaFid));
+
+ mutex_enter(vp->v_interlock);
+ mutex_enter(&cp->c_lock);
SET_VTOC(vp) = NULL;
+ mutex_exit(&cp->c_lock);
+ mutex_exit(vp->v_interlock);
+ mutex_destroy(&cp->c_lock);
+ kmem_free(cp, sizeof(*cp));
+
return (0);
}
@@ -1830,32 +1837,30 @@ coda_print_vattr(struct vattr *attr)
struct cnode *
make_coda_node(CodaFid *fid, struct mount *fvsp, short type)
{
- struct cnode *cp;
- int error;
-
- if ((cp = coda_find(fid)) == NULL) {
- vnode_t *vp;
-
- cp = coda_alloc();
- cp->c_fid = *fid;
-
- error = getnewvnode(VT_CODA, fvsp, coda_vnodeop_p, NULL, &vp);
- if (error) {
- panic("%s: getnewvnode returned error %d", __func__, error);
+ int error __diagused;
+ struct vnode *vp;
+ struct cnode *cp;
+
+ error = vcache_get(fvsp, fid, sizeof(CodaFid), &vp);
+ KASSERT(error == 0);
+
+ mutex_enter(vp->v_interlock);
+ cp = VTOC(vp);
+ KASSERT(cp != NULL);
+ mutex_enter(&cp->c_lock);
+ mutex_exit(vp->v_interlock);
+
+ if (vp->v_type != type) {
+ if (vp->v_type == VCHR || vp->v_type == VBLK)
+ spec_node_destroy(vp);
+ vp->v_type = type;
+ if (type == VCHR || type == VBLK)
+ spec_node_init(vp, NODEV);
+ uvm_vnp_setsize(vp, 0);
}
- vp->v_data = cp;
- vp->v_type = type;
- cp->c_vnode = vp;
- if (type == VCHR || type == VBLK)
- spec_node_init(vp, NODEV);
- uvm_vnp_setsize(vp, 0);
- coda_save(cp);
-
- } else {
- vref(CTOV(cp));
- }
+ mutex_exit(&cp->c_lock);
- return cp;
+ return cp;
}
/*