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;
 }
 
 /*

Reply via email to