Module Name:    src
Committed By:   ttoth
Date:           Fri Aug 10 09:26:58 UTC 2012

Modified Files:
        src/sys/ufs/chfs: chfs.h chfs_build.c chfs_gc.c chfs_malloc.c
            chfs_nodeops.c chfs_readinode.c chfs_scan.c chfs_subr.c
            chfs_vfsops.c chfs_vnode.c chfs_vnode_cache.c chfs_vnops.c
            chfs_write.c ebh.c

Log Message:
chfs bugfix [node was obsoleted twice]


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/ufs/chfs/chfs.h
cvs rdiff -u -r1.3 -r1.4 src/sys/ufs/chfs/chfs_build.c \
    src/sys/ufs/chfs/chfs_write.c
cvs rdiff -u -r1.2 -r1.3 src/sys/ufs/chfs/chfs_gc.c \
    src/sys/ufs/chfs/chfs_malloc.c src/sys/ufs/chfs/chfs_readinode.c \
    src/sys/ufs/chfs/chfs_scan.c src/sys/ufs/chfs/ebh.c
cvs rdiff -u -r1.1 -r1.2 src/sys/ufs/chfs/chfs_nodeops.c \
    src/sys/ufs/chfs/chfs_vnode_cache.c
cvs rdiff -u -r1.4 -r1.5 src/sys/ufs/chfs/chfs_subr.c \
    src/sys/ufs/chfs/chfs_vfsops.c
cvs rdiff -u -r1.5 -r1.6 src/sys/ufs/chfs/chfs_vnode.c
cvs rdiff -u -r1.8 -r1.9 src/sys/ufs/chfs/chfs_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/ufs/chfs/chfs.h
diff -u src/sys/ufs/chfs/chfs.h:1.6 src/sys/ufs/chfs/chfs.h:1.7
--- src/sys/ufs/chfs/chfs.h:1.6	Fri Apr 13 14:50:35 2012
+++ src/sys/ufs/chfs/chfs.h	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs.h,v 1.6 2012/04/13 14:50:35 ttoth Exp $	*/
+/*	$NetBSD: chfs.h,v 1.7 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -494,6 +494,10 @@ int chfs_update_eb_dirty(struct chfs_mou
     struct chfs_eraseblock *, uint32_t);
 void chfs_add_node_to_list(struct chfs_mount *, struct chfs_vnode_cache *,
     struct chfs_node_ref *, struct chfs_node_ref **);
+void chfs_remove_node_from_list(struct chfs_mount *, struct chfs_vnode_cache *,
+    struct chfs_node_ref *, struct chfs_node_ref **);
+void chfs_remove_and_obsolete(struct chfs_mount *, struct chfs_vnode_cache *,
+    struct chfs_node_ref *, struct chfs_node_ref **);
 void chfs_add_fd_to_inode(struct chfs_mount *,
     struct chfs_inode *, struct chfs_dirent *);
 void chfs_add_vnode_ref_to_vc(struct chfs_mount *, struct chfs_vnode_cache *,
@@ -522,7 +526,6 @@ chfs_nref_to_vc(struct chfs_node_ref *nr
 			dbg("Empty!\n");
 		}
 	}
-	//dbg("vno: %llu\n", ((struct chfs_vnode_cache *)(nref))->vno);
 
 	//dbg("NREF_TO_VC: GET IT\n");
 	//dbg("nref_next: %p, lnr: %u, ofs: %u\n", nref->nref_next, nref->nref_lnr, nref->nref_offset);
@@ -564,7 +567,9 @@ void chfs_free_tmp_dnode_info(struct chf
 /* chfs_readinode.c */
 int chfs_read_inode(struct chfs_mount *, struct chfs_inode *);
 int chfs_read_inode_internal(struct chfs_mount *, struct chfs_inode *);
-void chfs_kill_fragtree(struct rb_tree *);
+void chfs_remove_frags_of_node(struct chfs_mount *, struct rb_tree *,
+	struct chfs_node_ref *);
+void chfs_kill_fragtree(struct chfs_mount *, struct rb_tree *);
 uint32_t chfs_truncate_fragtree(struct chfs_mount *,
 	struct rb_tree *, uint32_t);
 int chfs_add_full_dnode_to_inode(struct chfs_mount *,
@@ -653,8 +658,6 @@ void chfs_change_size_wasted(struct chfs
 /* chfs_vnode_cache.c */
 struct chfs_vnode_cache **chfs_vnocache_hash_init(void);
 void chfs_vnocache_hash_destroy(struct chfs_vnode_cache **);
-void chfs_vnode_cache_set_state(struct chfs_mount *,
-    struct chfs_vnode_cache *, int);
 struct chfs_vnode_cache* chfs_vnode_cache_get(struct chfs_mount *, ino_t);
 void chfs_vnode_cache_add(struct chfs_mount *, struct chfs_vnode_cache *);
 void chfs_vnode_cache_remove(struct chfs_mount *, struct chfs_vnode_cache *);

Index: src/sys/ufs/chfs/chfs_build.c
diff -u src/sys/ufs/chfs/chfs_build.c:1.3 src/sys/ufs/chfs/chfs_build.c:1.4
--- src/sys/ufs/chfs/chfs_build.c:1.3	Thu Apr 12 15:31:01 2012
+++ src/sys/ufs/chfs/chfs_build.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_build.c,v 1.3 2012/04/12 15:31:01 ttoth Exp $	*/
+/*	$NetBSD: chfs_build.c,v 1.4 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -67,11 +67,11 @@ void
 chfs_build_set_vnodecache_nlink(struct chfs_mount *chmp,
     struct chfs_vnode_cache *vc)
 {
-	struct chfs_dirent *fd;
+	struct chfs_dirent *fd, *tmpfd;
 	//dbg("set nlink\n");
 
 //	for (fd = vc->scan_dirents; fd; fd = fd->next) {
-	TAILQ_FOREACH(fd, &vc->scan_dirents, fds) {
+	TAILQ_FOREACH_SAFE(fd, &vc->scan_dirents, fds, tmpfd) {
 		struct chfs_vnode_cache *child_vc;
 
 		if (!fd->vno)
@@ -82,6 +82,7 @@ chfs_build_set_vnodecache_nlink(struct c
 		mutex_exit(&chmp->chm_lock_vnocache);
 		if (!child_vc) {
 			chfs_mark_node_obsolete(chmp, fd->nref);
+			TAILQ_REMOVE(&vc->scan_dirents, fd, fds);
 			continue;
 		}
 		if (fd->type == CHT_DIR) {
@@ -122,8 +123,8 @@ chfs_build_remove_unlinked_vnode(struct 
 	dbg("START\n");
 	dbg("vno: %llu\n", (unsigned long long)vc->vno);
 
-	nref = vc->dnode;
 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
+	nref = vc->dnode;
 	// The vnode cache is at the end of the data node's chain
 	while (nref != (struct chfs_node_ref *)vc) {
 		struct chfs_node_ref *next = nref->nref_next;
@@ -131,6 +132,7 @@ chfs_build_remove_unlinked_vnode(struct 
 		chfs_mark_node_obsolete(chmp, nref);
 		nref = next;
 	}
+	vc->dnode = (struct chfs_node_ref *)vc;
 	nref = vc->dirents;
 	// The vnode cache is at the end of the dirent node's chain
 	while (nref != (struct chfs_node_ref *)vc) {
@@ -139,6 +141,7 @@ chfs_build_remove_unlinked_vnode(struct 
 		chfs_mark_node_obsolete(chmp, nref);
 		nref = next;
 	}
+	vc->dirents = (struct chfs_node_ref *)vc;
 	if (!TAILQ_EMPTY(&vc->scan_dirents)) {
 		TAILQ_FOREACH_SAFE(fd, &vc->scan_dirents, fds, tmpfd) {
 //		while (vc->scan_dirents) {
@@ -189,14 +192,14 @@ chfs_build_remove_unlinked_vnode(struct 
 
 	nref = vc->v;
 	while ((struct chfs_vnode_cache *)nref != vc) {
-		if (!CHFS_REF_OBSOLETE(nref))
-			chfs_mark_node_obsolete(chmp, nref);
+		chfs_mark_node_obsolete(chmp, nref);
 		nref = nref->nref_next;
 	}
+	vc->v = (struct chfs_node_ref *)vc;
 
 	mutex_enter(&chmp->chm_lock_vnocache);
 	if (vc->vno != CHFS_ROOTINO)
-		chfs_vnode_cache_set_state(chmp, vc, VNO_STATE_UNCHECKED);
+		vc->state = VNO_STATE_UNCHECKED;
 	mutex_exit(&chmp->chm_lock_vnocache);
 	dbg("END\n");
 }
@@ -375,11 +378,8 @@ chfs_build_filesystem(struct chfs_mount 
 				} else if (fd->type == CHT_DIR) {
 					//set state every non-VREG file's vc
 					mutex_enter(&chmp->chm_lock_vnocache);
-					notregvc =
-					    chfs_vnode_cache_get(chmp,
-						fd->vno);
-					chfs_vnode_cache_set_state(chmp,
-					    notregvc, VNO_STATE_PRESENT);
+					notregvc = chfs_vnode_cache_get(chmp, fd->vno);
+					notregvc->state = VNO_STATE_PRESENT;
 					mutex_exit(&chmp->chm_lock_vnocache);
 				}
 				chfs_free_dirent(fd);
Index: src/sys/ufs/chfs/chfs_write.c
diff -u src/sys/ufs/chfs/chfs_write.c:1.3 src/sys/ufs/chfs/chfs_write.c:1.4
--- src/sys/ufs/chfs/chfs_write.c:1.3	Thu Apr 12 15:31:01 2012
+++ src/sys/ufs/chfs/chfs_write.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_write.c,v 1.3 2012/04/12 15:31:01 ttoth Exp $	*/
+/*	$NetBSD: chfs_write.c,v 1.4 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -139,7 +139,9 @@ retry:
 	    &chmp->chm_blocks[nref->nref_lnr], CHFS_PAD(size));
 	mutex_exit(&chmp->chm_lock_sizes);
 	
+	mutex_enter(&chmp->chm_lock_vnocache);
 	chfs_add_vnode_ref_to_vc(chmp, chvc, nref);
+	mutex_exit(&chmp->chm_lock_vnocache);
 	KASSERT(chmp->chm_blocks[nref->nref_lnr].used_size <= chmp->chm_ebh->eb_size);
 out:
 	chfs_free_flash_vnode(fvnode);
@@ -248,10 +250,13 @@ retry:
 	    &chmp->chm_blocks[nref->nref_lnr], CHFS_PAD(size));
 	mutex_exit(&chmp->chm_lock_sizes);
 	KASSERT(chmp->chm_blocks[nref->nref_lnr].used_size <= chmp->chm_ebh->eb_size);
+
 	fd->nref = nref;
 	if (prio != ALLOC_DELETION) {
+		mutex_enter(&chmp->chm_lock_vnocache);
 		chfs_add_node_to_list(chmp,
 			pdir->chvc, nref, &pdir->chvc->dirents);
+		mutex_exit(&chmp->chm_lock_vnocache);
 	}
 out:
 	chfs_free_flash_dirent(fdirent);
@@ -324,7 +329,6 @@ chfs_write_flash_dnode(struct chfs_mount
 	vec[1].iov_base = tmpbuf;
 	vec[1].iov_len = CHFS_PAD(size) - sizeof(*dnode);
 
-	fd->frags = 0;
 	fd->ofs = ofs;
 	fd->size = len;
 
@@ -382,9 +386,16 @@ retry:
 	    &chmp->chm_blocks[nref->nref_lnr], CHFS_PAD(size));
 	mutex_exit(&chmp->chm_lock_sizes);
 
+	mutex_enter(&chmp->chm_lock_vnocache);
+	if (fd->nref != NULL) {
+		chfs_remove_frags_of_node(chmp, &ip->fragtree, fd->nref);
+		chfs_remove_and_obsolete(chmp, ip->chvc, fd->nref, &ip->chvc->dnode);
+	}
+
 	KASSERT(chmp->chm_blocks[nref->nref_lnr].used_size <= chmp->chm_ebh->eb_size);
 	fd->nref = nref;
 	chfs_add_node_to_list(chmp, ip->chvc, nref, &ip->chvc->dnode);
+	mutex_exit(&chmp->chm_lock_vnocache);
 out:
 	chfs_free_flash_dnode(dnode);
 	if (CHFS_PAD(size) - sizeof(*dnode)) {
@@ -488,6 +499,9 @@ chfs_do_unlink(struct chfs_inode *ip,
 		if (fd->vno == ip->ino &&
 		    fd->nsize == namelen &&
 		    !memcmp(fd->name, name, fd->nsize)) {
+
+			chfs_kill_fragtree(chmp, &ip->fragtree);
+
 			if (fd->type == CHT_DIR && ip->chvc->nlink == 2)
 				ip->chvc->nlink = 0;
 			else
@@ -497,45 +511,41 @@ chfs_do_unlink(struct chfs_inode *ip,
 
 			TAILQ_REMOVE(&parent->dents, fd, fds);
 
-			/* remove nref from dirents list */
-			nref = parent->chvc->dirents;
-			if (nref == fd->nref) {
-				nref->nref_next = fd->nref->nref_next;
-			} else {
-				while (nref->nref_next && nref->nref_next != fd->nref)
-					nref = nref->nref_next;
-				if (nref->nref_next)
-					nref->nref_next = fd->nref->nref_next;
-			}
+			mutex_enter(&chmp->chm_lock_vnocache);
 
-			//dbg("FD->NREF vno: %llu, lnr: %u, ofs: %u\n",
-			//    fd->vno, fd->nref->nref_lnr, fd->nref->nref_offset);
-			chfs_mark_node_obsolete(chmp, fd->nref);
+			dbg("FD->NREF vno: %llu, lnr: %u, ofs: %u\n",
+			    fd->vno, fd->nref->nref_lnr, fd->nref->nref_offset);
+			chfs_remove_and_obsolete(chmp, parent->chvc, fd->nref,
+				&parent->chvc->dirents);
 
 			error = chfs_write_flash_dirent(chmp,
 			    parent, ip, fd, 0, ALLOC_DELETION);
 
-			//dbg("FD->NREF vno: %llu, lnr: %u, ofs: %u\n",
-			//    fd->vno, fd->nref->nref_lnr, fd->nref->nref_offset);
-			chfs_mark_node_obsolete(chmp, fd->nref);
-
-			nref = ip->chvc->dnode;
-			while (nref != (struct chfs_node_ref *)ip->chvc) {
-				//dbg("DATA NREF\n");
-				chfs_mark_node_obsolete(chmp, nref);
-				nref = nref->nref_next;
+			dbg("FD->NREF vno: %llu, lnr: %u, ofs: %u\n",
+			    fd->vno, fd->nref->nref_lnr, fd->nref->nref_offset);
+			// set nref_next field
+			chfs_add_node_to_list(chmp, parent->chvc, fd->nref,
+				&parent->chvc->dirents);
+			// remove from the list
+			chfs_remove_and_obsolete(chmp, parent->chvc, fd->nref,
+				&parent->chvc->dirents);
+
+			// clean dnode list
+			while (ip->chvc->dnode != (struct chfs_node_ref *)ip->chvc) {
+				nref = ip->chvc->dnode;
+				chfs_remove_frags_of_node(chmp, &ip->fragtree, nref);
+				chfs_remove_and_obsolete(chmp, ip->chvc, nref, &ip->chvc->dnode);
 			}
-			ip->chvc->dnode = (struct chfs_node_ref *)ip->chvc;
 
-			nref = ip->chvc->v;
-			while (nref != (struct chfs_node_ref *)ip->chvc) {
-				//dbg("V NREF\n");
-				chfs_mark_node_obsolete(chmp, nref);
-				nref = nref->nref_next;
+			// clean v list
+			while (ip->chvc->v != (struct chfs_node_ref *)ip->chvc) {
+				nref = ip->chvc->v;
+				chfs_remove_and_obsolete(chmp, ip->chvc, nref, &ip->chvc->v);
 			}
-			ip->chvc->v = ip->chvc->v->nref_next;
 
 			parent->chvc->nlink--;
+
+			mutex_exit(&chmp->chm_lock_vnocache);
 			//TODO: if error
 		}
 	}

Index: src/sys/ufs/chfs/chfs_gc.c
diff -u src/sys/ufs/chfs/chfs_gc.c:1.2 src/sys/ufs/chfs/chfs_gc.c:1.3
--- src/sys/ufs/chfs/chfs_gc.c:1.2	Thu Nov 24 21:09:37 2011
+++ src/sys/ufs/chfs/chfs_gc.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_gc.c,v 1.2 2011/11/24 21:09:37 agc Exp $	*/
+/*	$NetBSD: chfs_gc.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -92,6 +92,7 @@ chfs_gc_thread(void *data)
 		if (chfs_gc_thread_should_wake(chmp)) {
 //			mutex_exit(&chmp->chm_lock_mountfields);
 			if (chfs_gcollect_pass(chmp) == ENOSPC) {
+				mutex_exit(&chmp->chm_lock_mountfields);
 				dbg_gc("No space for garbage collection\n");
 				panic("No space for garbage collection\n");
 				/* XXX why break here? i have added a panic
@@ -100,7 +101,7 @@ chfs_gc_thread(void *data)
 				break;
 			}
 			/* XXX gcollect_pass drops the mutex */
-			mutex_enter(&chmp->chm_lock_mountfields);
+			//mutex_enter(&chmp->chm_lock_mountfields);
 		}
 
 		cv_timedwait_sig(&gc->gcth_wakeup,
@@ -254,6 +255,8 @@ extern rb_tree_ops_t frag_rbtree_ops;
 int
 chfs_check(struct chfs_mount *chmp, struct  chfs_vnode_cache *chvc)
 {
+	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
+
 	struct chfs_inode *ip;
 	struct vnode *vp;
 	int ret;
@@ -273,7 +276,9 @@ chfs_check(struct chfs_mount *chmp, stru
 	rb_tree_init(&ip->fragtree, &frag_rbtree_ops);
 	TAILQ_INIT(&ip->dents);
 
+	mutex_exit(&chmp->chm_lock_vnocache);
 	ret = chfs_read_inode_internal(chmp, ip);
+	mutex_enter(&chmp->chm_lock_vnocache);
 	if (!ret) {
 		chfs_clear_inode(chmp, ip);
 	}
@@ -286,52 +291,39 @@ chfs_check(struct chfs_mount *chmp, stru
 void
 chfs_clear_inode(struct chfs_mount *chmp, struct chfs_inode *ip)
 {
+	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
+
 	struct chfs_dirent *fd, *tmpfd;
 	struct chfs_vnode_cache *chvc;
+	struct chfs_node_ref *nref;
 
-
-	/* XXX not sure if this is the correct locking */
-//	mutex_enter(&chmp->chm_lock_vnocache);
 	chvc = ip->chvc;
 	/* shouldnt this be: */
 	//bool deleted = (chvc && !(chvc->pvno || chvc->nlink));
 	int deleted = (chvc && !(chvc->pvno | chvc->nlink));
 
 	if (chvc && chvc->state != VNO_STATE_CHECKING) {
-//		chfs_vnode_cache_state_set(chmp, chvc, VNO_STATE_CLEARING);
 		chvc->state = VNO_STATE_CLEARING;
 	}
 
-	if (chvc->v && ((struct  chfs_vnode_cache *)chvc->v != chvc)) {
-		if (deleted)
-			chfs_mark_node_obsolete(chmp, chvc->v);
-		//chfs_free_refblock(chvc->v);
-	}
-//	mutex_enter(&chmp->chm_lock_vnocache);
-
-	chfs_kill_fragtree(&ip->fragtree);
-/*
-	fd = TAILQ_FIRST(&ip->dents);
-	while (fd) {
-		TAILQ_REMOVE(&ip->dents, fd, fds);
-		chfs_free_dirent(fd);
-		fd = TAILQ_FIRST(&ip->dents);
+	while (deleted && chvc->v != (struct chfs_node_ref *)chvc) {
+		nref = chvc->v;
+		chfs_remove_and_obsolete(chmp, chvc, nref, &chvc->v);
 	}
-*/
+
+	chfs_kill_fragtree(chmp, &ip->fragtree);
 
 	TAILQ_FOREACH_SAFE(fd, &ip->dents, fds, tmpfd) {
 		chfs_free_dirent(fd);
 	}
 
 	if (chvc && chvc->state == VNO_STATE_CHECKING) {
-		chfs_vnode_cache_set_state(chmp,
-		    chvc, VNO_STATE_CHECKEDABSENT);
+		chvc->state = VNO_STATE_CHECKEDABSENT;
 		if ((struct chfs_vnode_cache *)chvc->v == chvc &&
 		    (struct chfs_vnode_cache *)chvc->dirents == chvc &&
 		    (struct chfs_vnode_cache *)chvc->dnode == chvc)
 			chfs_vnode_cache_remove(chmp, chvc);
 	}
-
 }
 
 struct chfs_eraseblock *
@@ -427,7 +419,6 @@ chfs_gcollect_pass(struct chfs_mount *ch
 
 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
 
-//	mutex_enter(&chmp->chm_lock_mountfields);
 	for (;;) {
 		mutex_enter(&chmp->chm_lock_sizes);
 
@@ -437,7 +428,6 @@ chfs_gcollect_pass(struct chfs_mount *ch
 
 		if (chmp->chm_checked_vno > chmp->chm_max_vno) {
 			mutex_exit(&chmp->chm_lock_sizes);
-			mutex_exit(&chmp->chm_lock_mountfields);
 			dbg_gc("checked_vno (#%llu) > max_vno (#%llu)\n",
 			    (unsigned long long)chmp->chm_checked_vno,
 			    (unsigned long long)chmp->chm_max_vno);
@@ -474,7 +464,6 @@ chfs_gcollect_pass(struct chfs_mount *ch
 		case VNO_STATE_GC:
 		case VNO_STATE_CHECKING:
 			mutex_exit(&chmp->chm_lock_vnocache);
-			mutex_exit(&chmp->chm_lock_mountfields);
 			dbg_gc("VNO_STATE GC or CHECKING\n");
 			panic("CHFS BUG - vc state gc or checking\n");
 
@@ -486,12 +475,10 @@ chfs_gcollect_pass(struct chfs_mount *ch
 
 //			sleep_on_spinunlock(&chmp->chm_lock_vnocache);
 //			KASSERT(!mutex_owned(&chmp->chm_lock_vnocache));
-			mutex_exit(&chmp->chm_lock_mountfields);
 			return 0;
 
 		default:
 			mutex_exit(&chmp->chm_lock_vnocache);
-			mutex_exit(&chmp->chm_lock_mountfields);
 			dbg_gc("default\n");
 			panic("CHFS BUG - vc state is other what we"
 			    " checked\n");
@@ -500,19 +487,16 @@ chfs_gcollect_pass(struct chfs_mount *ch
 			;
 		}
 
-		chfs_vnode_cache_set_state(chmp, vc, VNO_STATE_CHECKING);
+		vc->state = VNO_STATE_CHECKING;
 
 		/* XXX check if this is too heavy to call under
 		 * chm_lock_vnocache
 		 */
 		ret = chfs_check(chmp, vc);
 		dbg_gc("set state\n");
-		chfs_vnode_cache_set_state(chmp,
-		    vc, VNO_STATE_CHECKEDABSENT);
+		vc->state = VNO_STATE_CHECKEDABSENT;
 
 		mutex_exit(&chmp->chm_lock_vnocache);
-		mutex_exit(&chmp->chm_lock_mountfields);
-
 		return ret;
 	}
 
@@ -527,11 +511,9 @@ chfs_gcollect_pass(struct chfs_mount *ch
 		dbg_gc("!eb\n");
 		if (!TAILQ_EMPTY(&chmp->chm_erase_pending_queue)) {
 			mutex_exit(&chmp->chm_lock_sizes);
-			mutex_exit(&chmp->chm_lock_mountfields);
 			return EAGAIN;
 		}
 		mutex_exit(&chmp->chm_lock_sizes);
-		mutex_exit(&chmp->chm_lock_mountfields);
 		return EIO;
 	}
 
@@ -557,7 +539,6 @@ chfs_gcollect_pass(struct chfs_mount *ch
 			//dbg_gc("!nref\n");
 			eb->gc_node = nref;
 			mutex_exit(&chmp->chm_lock_sizes);
-			mutex_exit(&chmp->chm_lock_mountfields);
 			panic("CHFS BUG - nref is NULL)\n");
 		}
 	}
@@ -576,19 +557,19 @@ chfs_gcollect_pass(struct chfs_mount *ch
 		goto lock_size;
 	}
 
-	dbg_gc("nref lnr: %u - offset: %u\n", nref->nref_lnr, nref->nref_offset);
-	vc = chfs_nref_to_vc(nref);
-
 	mutex_exit(&chmp->chm_lock_sizes);
 
 	//dbg_gc("enter vnocache lock on #%llu\n", vc->vno);
 	mutex_enter(&chmp->chm_lock_vnocache);
 
+	dbg_gc("nref lnr: %u - offset: %u\n", nref->nref_lnr, nref->nref_offset);
+	vc = chfs_nref_to_vc(nref);
+
 	dbg_gc("switch\n");
 	switch(vc->state) {
         case VNO_STATE_CHECKEDABSENT:
 		if (CHFS_REF_FLAGS(nref) == CHFS_PRISTINE_NODE_MASK) {
-			chfs_vnode_cache_set_state(chmp, vc, VNO_STATE_GC);
+			vc->state = VNO_STATE_GC;
 		}
 		break;
 
@@ -599,7 +580,6 @@ chfs_gcollect_pass(struct chfs_mount *ch
         case VNO_STATE_CHECKING:
         case VNO_STATE_GC:
 		mutex_exit(&chmp->chm_lock_vnocache);
-		mutex_exit(&chmp->chm_lock_mountfields);
 		panic("CHFS BUG - vc state unchecked,"
 		    " checking or gc (vno #%llu, num #%d)\n",
 		    (unsigned long long)vc->vno, vc->state);
@@ -611,19 +591,15 @@ chfs_gcollect_pass(struct chfs_mount *ch
 
 //		sleep_on_spinunlock(&chmp->chm_lock_vnocache);
 //		KASSERT(!mutex_owned(&chmp->chm_lock_vnocache));
-		mutex_exit(&chmp->chm_lock_mountfields);
 		return 0;
 	}
 
 	if (vc->state == VNO_STATE_GC) {
 		dbg_gc("vc->state == VNO_STATE_GC\n");
+		vc->state = VNO_STATE_CHECKEDABSENT;
 		mutex_exit(&chmp->chm_lock_vnocache);
 		ret = chfs_gcollect_pristine(chmp, eb, NULL, nref);
 
-//		chfs_vnode_cache_state_set(chmp,
-//		    vc, VNO_STATE_CHECKEDABSENT);
-		/* XXX locking? */
-		vc->state = VNO_STATE_CHECKEDABSENT;
 		//TODO wake_up(&chmp->chm_vnocache_wq);
 		if (ret != EBADF)
 			goto test_gcnode;
@@ -691,7 +667,6 @@ eraseit:
 	}
 
 	mutex_exit(&chmp->chm_lock_sizes);
-	mutex_exit(&chmp->chm_lock_mountfields);
 	dbg_gc("return\n");
 	return ret;
 }
@@ -814,8 +789,10 @@ retry:
 
 	mutex_exit(&chmp->chm_lock_sizes);
 	//TODO should we set free_size?
-	chfs_mark_node_obsolete(chmp, nref);
+	//chfs_mark_node_obsolete(chmp, nref);
+	mutex_enter(&chmp->chm_lock_vnocache);
 	chfs_add_vnode_ref_to_vc(chmp, chvc, newnref);
+	mutex_exit(&chmp->chm_lock_vnocache);
 	return 0;
 }
 
@@ -881,7 +858,7 @@ chfs_gcollect_live(struct chfs_mount *ch
 	}
 
 
-	/* It's a dirent? */
+	/* Is it a dirent? */
 	dbg_gc("find full dirent\n");
 	is_dirent = false;
 	TAILQ_FOREACH(fd, &ip->dents, fds) {
@@ -928,7 +905,6 @@ chfs_gcollect_dirent(struct chfs_mount *
 {
 	struct vnode *vnode = NULL;
 	struct chfs_inode *ip;
-	struct chfs_node_ref *prev;
 	dbg_gc("gcollect_dirent\n");
 
 	vnode = chfs_vnode_lookup(chmp, fd->vno);
@@ -940,23 +916,11 @@ chfs_gcollect_dirent(struct chfs_mount *
 
 	ip = VTOI(vnode);
 
-	prev = parent->chvc->dirents;
-	if (prev == fd->nref) {
-		parent->chvc->dirents = prev->nref_next;
-		dbg_gc("fd nref removed from dirents list\n");
-		prev = NULL;
-	}
-	while (prev) {
-		if (prev->nref_next == fd->nref) {
-			prev->nref_next = fd->nref->nref_next;
-			dbg_gc("fd nref removed from dirents list\n");
-			break;
-		}
-		prev = prev->nref_next;
-	}
+	mutex_enter(&chmp->chm_lock_vnocache);
+	chfs_remove_and_obsolete(chmp, parent->chvc, fd->nref,
+		&parent->chvc->dirents);
+	mutex_exit(&chmp->chm_lock_vnocache);
 
-	prev = fd->nref;
-	chfs_mark_node_obsolete(chmp, fd->nref);
 	return chfs_write_flash_dirent(chmp,
 	    parent, ip, fd, fd->vno, ALLOC_GC);
 }
@@ -1048,7 +1012,11 @@ chfs_gcollect_deletion_dirent(struct chf
 
 //		kmem_free(chfdn, nref_len);
 
-		chfs_mark_node_obsolete(chmp, fd->nref);
+		mutex_enter(&chmp->chm_lock_vnocache);
+		chfs_remove_and_obsolete(chmp, parent->chvc, fd->nref,
+			&parent->chvc->dirents);
+		mutex_exit(&chmp->chm_lock_vnocache);
+		//chfs_mark_node_obsolete(chmp, fd->nref);
 		return chfs_write_flash_dirent(chmp,
 		    parent, NULL, fd, fd->vno, ALLOC_GC);
 	}
@@ -1065,7 +1033,8 @@ chfs_gcollect_dnode(struct chfs_mount *c
     struct chfs_eraseblock *orig_cheb, struct chfs_inode *ip,
     struct chfs_full_dnode *fn, uint32_t orig_start, uint32_t orig_end)
 {
-	struct chfs_node_ref *nref, *prev;
+	struct chfs_node_ref *nref;
+	//struct chfs_node_ref *prev;
 	struct chfs_full_dnode *newfn;
 	struct chfs_flash_data_node *fdnode;
 	int ret = 0, retries = 0;
@@ -1211,26 +1180,16 @@ retry:
 	newfn->nref = nref;
 	newfn->ofs = fn->ofs;
 	newfn->size = fn->size;
-	newfn->frags = fn->frags;
+	newfn->frags = 0;
 
-	//TODO should we remove fd from dnode list?
-
-	prev = ip->chvc->dnode;
-	if (prev == fn->nref) {
-		ip->chvc->dnode = prev->nref_next;
-		prev = NULL;
-	}
-	while (prev) {
-		if (prev->nref_next == fn->nref) {
-			prev->nref_next = fn->nref->nref_next;
-			break;
-		}
-		prev = prev->nref_next;
-	}
+	mutex_enter(&chmp->chm_lock_vnocache);
+	chfs_remove_frags_of_node(chmp, &ip->fragtree, fn->nref);
+	chfs_remove_and_obsolete(chmp, ip->chvc, fn->nref, &ip->chvc->dnode);
 
 	chfs_add_full_dnode_to_inode(chmp, ip, newfn);
 	chfs_add_node_to_list(chmp,
 	    ip->chvc, newfn->nref, &ip->chvc->dnode);
+	mutex_exit(&chmp->chm_lock_vnocache);
 
 out:
 	kmem_free(data, totlen);
Index: src/sys/ufs/chfs/chfs_malloc.c
diff -u src/sys/ufs/chfs/chfs_malloc.c:1.2 src/sys/ufs/chfs/chfs_malloc.c:1.3
--- src/sys/ufs/chfs/chfs_malloc.c:1.2	Tue Feb 28 02:48:39 2012
+++ src/sys/ufs/chfs/chfs_malloc.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_malloc.c,v 1.2 2012/02/28 02:48:39 christos Exp $	*/
+/*	$NetBSD: chfs_malloc.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -297,6 +297,8 @@ chfs_alloc_full_dnode(void)
 {
 	struct chfs_full_dnode *ret;
 	ret = kmem_alloc(sizeof(struct chfs_full_dnode), KM_SLEEP);
+	ret->nref = NULL;
+	ret->frags = 0;
 	return ret;
 }
 
Index: src/sys/ufs/chfs/chfs_readinode.c
diff -u src/sys/ufs/chfs/chfs_readinode.c:1.2 src/sys/ufs/chfs/chfs_readinode.c:1.3
--- src/sys/ufs/chfs/chfs_readinode.c:1.2	Thu Nov 24 21:09:37 2011
+++ src/sys/ufs/chfs/chfs_readinode.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_readinode.c,v 1.2 2011/11/24 21:09:37 agc Exp $	*/
+/*	$NetBSD: chfs_readinode.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -201,7 +201,7 @@ chfs_check_td_data(struct chfs_mount *ch
 		return 1;
 	}
 
-	nref->nref_offset = CHFS_GET_OFS(nref->nref_offset) | CHFS_NORMAL_NODE_MASK;
+	CHFS_MARK_REF_NORMAL(nref);
 	totlen = CHFS_PAD(sizeof(struct chfs_flash_data_node) + len);
 
 	mutex_enter(&chmp->chm_lock_sizes);
@@ -225,9 +225,6 @@ chfs_check_td_node(struct chfs_mount *ch
 		return 0;
 
 	ret = chfs_check_td_data(chmp, td);
-	if (ret == 1) {
-		chfs_mark_node_obsolete(chmp, td->node->nref);
-	}
 	return ret;
 }
 
@@ -289,9 +286,12 @@ static void
 chfs_kill_td(struct chfs_mount *chmp,
     struct chfs_tmp_dnode *td)
 {
-	/* check if we need to mark as obsolete, to avoid double mark */
-	if (!CHFS_REF_OBSOLETE(td->node->nref)) {
-		chfs_mark_node_obsolete(chmp, td->node->nref);
+	struct chfs_vnode_cache *vc;
+	if (td->node) {
+		mutex_enter(&chmp->chm_lock_vnocache);
+		vc = chfs_nref_to_vc(td->node->nref);
+		chfs_remove_and_obsolete(chmp, vc, td->node->nref, &vc->dnode);	
+		mutex_exit(&chmp->chm_lock_vnocache);
 	}
 
 	chfs_free_tmp_dnode(td);
@@ -422,8 +422,8 @@ chfs_add_tmp_dnode_to_tree(struct chfs_m
 	   obsoleted by an earlier node. Insert into the tree */
 	struct chfs_tmp_dnode_info *tmp_tdi = rb_tree_insert_node(&rii->tdi_root, newtdi);
 	if (tmp_tdi != newtdi) {
+		chfs_remove_tmp_dnode_from_tdi(newtdi, newtd);
 		chfs_add_tmp_dnode_to_tdi(tmp_tdi, newtd);
-		newtdi->tmpnode = NULL;
 		chfs_kill_tdi(chmp, newtdi);
 	}
 
@@ -473,6 +473,9 @@ new_fragment(struct chfs_full_dnode *fdn
 		newfrag->ofs = ofs;
 		newfrag->size = size;
 		newfrag->node = fdn;
+		if (newfrag->node) {
+			newfrag->node->frags++;
+		}
 	} else {
 		chfs_err("cannot allocate a chfs_node_frag object\n");
 	}
@@ -544,8 +547,6 @@ chfs_add_frag_to_fragtree(struct chfs_mo
 			    this->ofs + this->size - newfrag->ofs - newfrag->size);
 			if (!newfrag2)
 				return ENOMEM;
-			if (this->node)
-				this->node->frags++;
 
 			this->size = newfrag->ofs - this->ofs;
 
@@ -597,17 +598,34 @@ chfs_add_frag_to_fragtree(struct chfs_mo
 }
 
 void
-chfs_kill_fragtree(struct rb_tree *fragtree)
+chfs_remove_frags_of_node(struct chfs_mount *chmp, struct rb_tree *fragtree,
+	struct chfs_node_ref *nref)
+{
+	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
+	struct chfs_node_frag *this, *next;
+
+	this = (struct chfs_node_frag *)RB_TREE_MIN(fragtree);
+	while (this) {
+		next = frag_next(fragtree, this);
+		if (this->node->nref == nref) {
+			rb_tree_remove_node(fragtree, this);
+		}
+		this = next;
+	}
+}
+
+void
+chfs_kill_fragtree(struct chfs_mount *chmp, struct rb_tree *fragtree)
 {
+	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
 	struct chfs_node_frag *this, *next;
 	//dbg("start\n");
 
 	this = (struct chfs_node_frag *)RB_TREE_MIN(fragtree);
 	while (this) {
-		//for (this = (struct chfs_node_frag *)RB_TREE_MIN(&fragtree); this != NULL; this = (struct chfs_node_frag *)rb_tree_iterate(&fragtree, &this->rb_node, RB_DIR_RIGHT)) {
 		next = frag_next(fragtree, this);
 		rb_tree_remove_node(fragtree, this);
-		chfs_free_node_frag(this);
+		chfs_obsolete_node_frag(chmp, this);
 		//dbg("one frag killed\n");
 		this = next;
 	}
@@ -618,8 +636,8 @@ uint32_t
 chfs_truncate_fragtree(struct chfs_mount *chmp,
 	struct rb_tree *fragtree, uint32_t size)
 {
-	struct chfs_node_frag *frag;
 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
+	struct chfs_node_frag *frag;
 
 	dbg("truncate to size: %u\n", size);
 
@@ -658,7 +676,8 @@ chfs_truncate_fragtree(struct chfs_mount
 
 	/* FIXME Should we check the postion of the last node? (PAGE_CACHE size, etc.) */
 	if (frag->node && (frag->ofs & (PAGE_SIZE - 1)) == 0) {
-		frag->node->nref->nref_offset = CHFS_GET_OFS(frag->node->nref->nref_offset) | CHFS_PRISTINE_NODE_MASK;
+		frag->node->nref->nref_offset =
+			CHFS_GET_OFS(frag->node->nref->nref_offset) | CHFS_PRISTINE_NODE_MASK;
 	}
 
 	return size;
@@ -668,27 +687,21 @@ void
 chfs_obsolete_node_frag(struct chfs_mount *chmp,
     struct chfs_node_frag *this)
 {
+	struct chfs_vnode_cache *vc;
 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
 	if (this->node) {
+		KASSERT(this->node->frags != 0);
 		this->node->frags--;
-		if (!this->node->frags) {
-			struct chfs_vnode_cache *vc = chfs_nref_to_vc(this->node->nref);
-			chfs_mark_node_obsolete(chmp, this->node->nref);
-			
-			if (vc->dnode == this->node->nref) {
-				vc->dnode = this->node->nref->nref_next;
-			} else {
-				struct chfs_node_ref *tmp = vc->dnode;
-				while (tmp->nref_next != (struct chfs_node_ref*) vc 
-						&& tmp->nref_next != this->node->nref) {
-					tmp = tmp->nref_next;
-				}
-				if (tmp->nref_next == this->node->nref) {
-					tmp->nref_next = this->node->nref->nref_next;
-				}
-				// FIXME should we free here the this->node->nref?
-			}
-			
+		if (this->node->frags == 0) {
+			KASSERT(!CHFS_REF_OBSOLETE(this->node->nref));
+			mutex_enter(&chmp->chm_lock_vnocache);
+			vc = chfs_nref_to_vc(this->node->nref);
+			dbg("[MARK] lnr: %u ofs: %u\n", this->node->nref->nref_lnr, 
+				this->node->nref->nref_offset);
+
+			chfs_remove_and_obsolete(chmp, vc, this->node->nref, &vc->dnode);	
+			mutex_exit(&chmp->chm_lock_vnocache);
+
 			chfs_free_full_dnode(this->node);
 		} else {
 			CHFS_MARK_REF_NORMAL(this->node->nref);
@@ -713,8 +726,6 @@ chfs_add_full_dnode_to_inode(struct chfs
 	if (unlikely(!newfrag))
 		return ENOMEM;
 
-	newfrag->node->frags = 1;
-
 	ret = chfs_add_frag_to_fragtree(chmp, &ip->fragtree, newfrag);
 	if (ret)
 		return ret;
@@ -815,6 +826,7 @@ chfs_get_data_nodes(struct chfs_mount *c
 		td->data_crc = le32toh(dnode->data_crc);
 		td->node->nref = nref;
 		td->node->size = le32toh(dnode->data_length);
+		td->node->frags = 1;
 		td->overlapped = 0;
 
 		if (td->version > rii->highest_version) {
@@ -892,6 +904,7 @@ chfs_build_fragtree(struct chfs_mount *c
 				if (chfs_check_td_node(chmp, tmp_td)) {
 					if (next_td) {
 						chfs_remove_tmp_dnode_from_tdi(this, tmp_td);
+						chfs_kill_td(chmp, tmp_td);
 					} else {
 						break;
 					}
@@ -908,13 +921,10 @@ chfs_build_fragtree(struct chfs_mount *c
 							vers_next = (struct chfs_tmp_dnode_info *)rb_tree_iterate(&ver_tree, this, RB_DIR_LEFT);
 							while (tmp_td) {
 								next_td = tmp_td->next;
-								if (chfs_check_td_node(chmp, tmp_td) > 1) {
-									chfs_mark_node_obsolete(chmp,
-										tmp_td->node->nref);
-								}
+
 								chfs_free_full_dnode(tmp_td->node);
 								chfs_remove_tmp_dnode_from_tdi(this, tmp_td);
-								chfs_free_tmp_dnode(tmp_td);
+								chfs_kill_td(chmp, tmp_td);
 								tmp_td = next_td;
 							}
 							chfs_free_tmp_dnode_info(this);
@@ -922,12 +932,15 @@ chfs_build_fragtree(struct chfs_mount *c
 							if (!this)
 								break;
 							rb_tree_remove_node(&ver_tree, vers_next);
+							chfs_kill_tdi(chmp, vers_next);
 						}
 						return ret;
 					}
 
 					chfs_remove_tmp_dnode_from_tdi(this, tmp_td);
 					chfs_free_tmp_dnode(tmp_td);
+					// shouldn't obsolete tmp_td here,
+					// because tmp_td->node was added to the inode
 				}
 				tmp_td = next_td;
 			}
@@ -946,16 +959,15 @@ int chfs_read_inode(struct chfs_mount *c
 	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
 
 retry:
-	/* XXX locking */
-	//mutex_enter(&chmp->chm_lock_vnocache);
+	mutex_enter(&chmp->chm_lock_vnocache);
 	switch (vc->state) {
 	case VNO_STATE_UNCHECKED:
 	case VNO_STATE_CHECKEDABSENT:
-//		chfs_vnode_cache_set_state(chmp, vc, VNO_STATE_READING);
 		vc->state = VNO_STATE_READING;
 		break;
 	case VNO_STATE_CHECKING:
 	case VNO_STATE_GC:
+		mutex_exit(&chmp->chm_lock_vnocache);
 		//sleep_on_spinunlock(&chmp->chm_lock_vnocache);
 		//KASSERT(!mutex_owned(&chmp->chm_lock_vnocache));
 		goto retry;
@@ -970,7 +982,7 @@ retry:
 	default:
 		panic("BUG() Bad vno cache state.");
 	}
-	//mutex_exit(&chmp->chm_lock_vnocache);
+	mutex_exit(&chmp->chm_lock_vnocache);
 
 	return chfs_read_inode_internal(chmp, ip);
 }
Index: src/sys/ufs/chfs/chfs_scan.c
diff -u src/sys/ufs/chfs/chfs_scan.c:1.2 src/sys/ufs/chfs/chfs_scan.c:1.3
--- src/sys/ufs/chfs/chfs_scan.c:1.2	Thu Nov 24 21:09:37 2011
+++ src/sys/ufs/chfs/chfs_scan.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_scan.c,v 1.2 2011/11/24 21:09:37 agc Exp $	*/
+/*	$NetBSD: chfs_scan.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -64,17 +64,12 @@ chfs_scan_make_vnode_cache(struct chfs_m
 
 	vc = chfs_vnode_cache_alloc(vno);
 
-	//mutex_enter(&chmp->chm_lock_vnocache);
-
 	chfs_vnode_cache_add(chmp, vc);
 
-	//mutex_exit(&chmp->chm_lock_vnocache);
-
 	if (vno == CHFS_ROOTINO) {
 		vc->nlink = 2;
 		vc->pvno = CHFS_ROOTINO;
-		chfs_vnode_cache_set_state(chmp,
-		    vc, VNO_STATE_CHECKEDABSENT);
+		vc->state = VNO_STATE_CHECKEDABSENT;
 	}
 
 	return vc;
@@ -152,7 +147,6 @@ chfs_scan_check_vnode(struct chfs_mount 
 			return ENOMEM;
 		}
 	}
-	mutex_exit(&chmp->chm_lock_vnocache);
 
 	nref = chfs_alloc_node_ref(cheb);
 
@@ -179,6 +173,7 @@ chfs_scan_check_vnode(struct chfs_mount 
 		*vc->vno_version = le64toh(vnode->version);
 		chfs_add_vnode_ref_to_vc(chmp, vc, nref);
 	}
+	mutex_exit(&chmp->chm_lock_vnocache);
 
 	mutex_enter(&chmp->chm_lock_sizes);
 	//dbg("B:lnr: %d |free_size: %d node's size: %d\n", cheb->lnr, cheb->free_size, le32toh(vnode->length));
@@ -228,15 +223,15 @@ chfs_scan_mark_dirent_obsolete(struct ch
 	if (prev && prev == nref) {
 		vc->dirents = prev->nref_next;
 	} else if (prev && prev != (void *)vc) {
-		while (prev->nref_next && prev->nref_next !=
-		    (void *)vc && prev->nref_next != nref) {
+		while (prev->nref_next && prev->nref_next != (void *)vc) {
+			if (prev->nref_next == nref) {
+				prev->nref_next = nref->nref_next;
+				break;
+			}
 			prev = prev->nref_next;
 		}
-
-		if (prev->nref_next == nref) {
-			prev->nref_next = nref->nref_next;
-		}
 	}
+
 	/*dbg("XXX - start\n");
 	//nref = vc->dirents;
 	struct chfs_dirent *tmp;
@@ -366,7 +361,7 @@ chfs_scan_check_dirent_node(struct chfs_
 	int err, namelen;
 	uint32_t crc;
 	struct chfs_dirent *fd;
-	struct chfs_vnode_cache *vc;
+	struct chfs_vnode_cache *parentvc;
 	struct chfs_flash_dirent_node *dirent = buf;
 
 	//struct chfs_node_ref *tmp;
@@ -406,17 +401,17 @@ chfs_scan_check_dirent_node(struct chfs_
 
 	/* Check vnode_cache of parent node */
 	mutex_enter(&chmp->chm_lock_vnocache);
-	vc = chfs_scan_make_vnode_cache(chmp, le64toh(dirent->pvno));
-	mutex_exit(&chmp->chm_lock_vnocache);
-	if (!vc) {
+	parentvc = chfs_scan_make_vnode_cache(chmp, le64toh(dirent->pvno));
+	if (!parentvc) {
 		chfs_free_dirent(fd);
 		return ENOMEM;
 	}
 
 	fd->nref->nref_offset = ofs;
 
-	dbg("add dirent to #%llu\n", (unsigned long long)vc->vno);
-	chfs_add_node_to_list(chmp, vc, fd->nref, &vc->dirents);
+	dbg("add dirent to #%llu\n", (unsigned long long)parentvc->vno);
+	chfs_add_node_to_list(chmp, parentvc, fd->nref, &parentvc->dirents);
+	mutex_exit(&chmp->chm_lock_vnocache);
 	/*tmp = vc->dirents;
 	  dbg("START|vno: %d dirents dump\n", vc->vno);
 	  while (tmp) {
@@ -440,7 +435,7 @@ chfs_scan_check_dirent_node(struct chfs_
 	  dbg(" ->name:    %s\n", fd->name);
 	  dbg(" ->type:    %d\n", fd->type);*/
 
-	chfs_add_fd_to_list(chmp, fd, vc);
+	chfs_add_fd_to_list(chmp, fd, parentvc);
 
 	/*struct chfs_node_ref *tmp;
 	  tmp = vc->dirents;
@@ -503,7 +498,7 @@ chfs_scan_check_data_node(struct chfs_mo
 	if (!nref)
 		return ENOMEM;
 
-	nref->nref_offset = ofs | CHFS_UNCHECKED_NODE_MASK;
+	nref->nref_offset = CHFS_GET_OFS(ofs) | CHFS_UNCHECKED_NODE_MASK;
 
 	KASSERT(nref->nref_lnr == cheb->lnr);
 
@@ -515,8 +510,8 @@ chfs_scan_check_data_node(struct chfs_mo
 		if (!vc)
 			return ENOMEM;
 	}
-	mutex_exit(&chmp->chm_lock_vnocache);
 	chfs_add_node_to_list(chmp, vc, nref, &vc->dnode);
+	mutex_exit(&chmp->chm_lock_vnocache);
 
 	dbg("chmpfree: %u, chebfree: %u, dnode: %u\n", chmp->chm_free_size, cheb->free_size, dnode->length);
 
Index: src/sys/ufs/chfs/ebh.c
diff -u src/sys/ufs/chfs/ebh.c:1.2 src/sys/ufs/chfs/ebh.c:1.3
--- src/sys/ufs/chfs/ebh.c:1.2	Fri Nov 25 11:15:24 2011
+++ src/sys/ufs/chfs/ebh.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ebh.c,v 1.2 2011/11/25 11:15:24 ahoka Exp $	*/
+/*	$NetBSD: ebh.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -1730,6 +1730,7 @@ ebh_read_leb(struct chfs_ebh *ebh, int l
 	err = leb_read_lock(ebh, lnr);
 	if (err)
 		return err;
+
 	pebnr = ebh->lmap[lnr];
 	/* If PEB is not mapped the buffer is filled with 0xFF */
 	if (EBH_LEB_UNMAPPED == pebnr) {
@@ -1747,9 +1748,6 @@ ebh_read_leb(struct chfs_ebh *ebh, int l
 
 	KASSERT(len == *retlen);
 
-	leb_read_unlock(ebh, lnr);
-	return err;
-
 out_free:
 	leb_read_unlock(ebh, lnr);
 	return err;

Index: src/sys/ufs/chfs/chfs_nodeops.c
diff -u src/sys/ufs/chfs/chfs_nodeops.c:1.1 src/sys/ufs/chfs/chfs_nodeops.c:1.2
--- src/sys/ufs/chfs/chfs_nodeops.c:1.1	Thu Nov 24 15:51:31 2011
+++ src/sys/ufs/chfs/chfs_nodeops.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_nodeops.c,v 1.1 2011/11/24 15:51:31 ahoka Exp $	*/
+/*	$NetBSD: chfs_nodeops.c,v 1.2 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -80,6 +80,8 @@ chfs_add_node_to_list(struct chfs_mount 
     struct chfs_vnode_cache *vc,
     struct chfs_node_ref *new, struct chfs_node_ref **list)
 {
+	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
+
 	struct chfs_node_ref *nextref = *list;
 	struct chfs_node_ref *prevref = NULL;
 
@@ -104,10 +106,13 @@ chfs_add_node_to_list(struct chfs_mount 
 	    CHFS_GET_OFS(nextref->nref_offset) ==
 	    CHFS_GET_OFS(new->nref_offset)) {
 		new->nref_next = nextref->nref_next;
+		chfs_mark_node_obsolete(chmp, nextref);
 	} else {
 		new->nref_next = nextref;
 	}
 
+	KASSERT(new->nref_next != NULL);
+
 	if (prevref) {
 		prevref->nref_next = new;
 	} else {
@@ -115,6 +120,60 @@ chfs_add_node_to_list(struct chfs_mount 
 	}
 }
 
+/*
+ * Removes a node from a list. Usually used for removing data nodes.
+ */
+void
+chfs_remove_node_from_list(struct chfs_mount *chmp,
+	struct chfs_vnode_cache *vc,
+	struct chfs_node_ref *old_nref, struct chfs_node_ref **list)
+{
+	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
+	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
+
+	struct chfs_node_ref *tmpnref;
+
+	if (*list == (struct chfs_node_ref *)vc) {
+		return;
+	}
+
+	KASSERT(old_nref->nref_next != NULL);
+
+	if (*list == old_nref) {
+		*list = old_nref->nref_next;
+	} else {
+		tmpnref = *list;
+		while (tmpnref->nref_next &&
+			tmpnref->nref_next != (struct chfs_node_ref *)vc) {
+			if (tmpnref->nref_next == old_nref) {
+				tmpnref->nref_next = old_nref->nref_next;
+				break;
+			}
+			tmpnref = tmpnref->nref_next;
+		}
+	}
+}
+
+/*
+ * Removes a node from a list and obsoletes the nref.
+ * We should use this function carefully on data nodes, 
+ * because removing a frag will obsolete the node ref.
+ */
+void
+chfs_remove_and_obsolete(struct chfs_mount *chmp,
+	struct chfs_vnode_cache *vc,
+	struct chfs_node_ref *old_nref, struct chfs_node_ref **list)
+{
+	KASSERT(mutex_owned(&chmp->chm_lock_mountfields));
+	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
+
+	chfs_remove_node_from_list(chmp, vc, old_nref, list);
+
+	dbg("[MARK] vno: %llu lnr: %u ofs: %u\n", vc->vno, old_nref->nref_lnr,
+		old_nref->nref_offset);
+	chfs_mark_node_obsolete(chmp, old_nref);
+}
+
 void
 chfs_add_fd_to_inode(struct chfs_mount *chmp,
     struct chfs_inode *parent, struct chfs_dirent *new)
@@ -140,8 +199,10 @@ chfs_add_fd_to_inode(struct chfs_mount *
 				TAILQ_INSERT_BEFORE(fd, new, fds);
 				TAILQ_REMOVE(&parent->dents, fd, fds);
 				if (fd->nref) {
-					chfs_mark_node_obsolete(chmp,
-					    fd->nref);
+					mutex_enter(&chmp->chm_lock_vnocache);
+					chfs_remove_and_obsolete(chmp, parent->chvc, fd->nref,
+						&parent->chvc->dirents);
+					mutex_exit(&chmp->chm_lock_vnocache);
 				}
 				chfs_free_dirent(fd);
 //				*prev = new;//XXX
@@ -186,12 +247,15 @@ void
 chfs_add_vnode_ref_to_vc(struct chfs_mount *chmp,
     struct chfs_vnode_cache *vc, struct chfs_node_ref *new)
 {
-	if ((struct chfs_vnode_cache*)(vc->v) != vc) {
-		chfs_mark_node_obsolete(chmp, vc->v);
-		new->nref_next = vc->v->nref_next;
-	} else {
-		new->nref_next = vc->v;
+	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
+	struct chfs_node_ref *nref;
+
+	while (vc->v != (struct chfs_node_ref *)vc) {
+		nref = vc->v;
+		chfs_remove_and_obsolete(chmp, vc, nref, &vc->v);
 	}
+
+	new->nref_next = (struct chfs_node_ref *)vc;
 	vc->v = new;
 }
 
@@ -456,8 +520,6 @@ chfs_reserve_space_normal(struct chfs_mo
 
 		mutex_exit(&chmp->chm_lock_sizes);
 		ret = chfs_gcollect_pass(chmp);
-		/* gcollect_pass exits chm_lock_mountfields */
-		mutex_enter(&chmp->chm_lock_mountfields);
 		mutex_enter(&chmp->chm_lock_sizes);
 
 		if (chmp->chm_nr_erasable_blocks ||
Index: src/sys/ufs/chfs/chfs_vnode_cache.c
diff -u src/sys/ufs/chfs/chfs_vnode_cache.c:1.1 src/sys/ufs/chfs/chfs_vnode_cache.c:1.2
--- src/sys/ufs/chfs/chfs_vnode_cache.c:1.1	Thu Nov 24 15:51:32 2011
+++ src/sys/ufs/chfs/chfs_vnode_cache.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_vnode_cache.c,v 1.1 2011/11/24 15:51:32 ahoka Exp $	*/
+/*	$NetBSD: chfs_vnode_cache.c,v 1.2 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -43,21 +43,6 @@ chfs_vnocache_hash_init(void)
 }
 
 /**
- * chfs_set_vnode_cache_state - set state of a vnode_cache
- * @chmp: fs super block info
- * @vc: vnode_cache
- * @state: new state
- */
-void
-chfs_vnode_cache_set_state(struct chfs_mount *chmp,
-    struct chfs_vnode_cache* vc, int state)
-{
-	/* XXX do we really need locking here? */
-	KASSERT(mutex_owned(&chmp->chm_lock_vnocache));
-	vc->state = state;
-}
-
-/**
  * chfs_get_vnode_cache - get a vnode_cache from the vnocache_hash
  * @chmp: fs super block info
  * @ino: inode for search

Index: src/sys/ufs/chfs/chfs_subr.c
diff -u src/sys/ufs/chfs/chfs_subr.c:1.4 src/sys/ufs/chfs/chfs_subr.c:1.5
--- src/sys/ufs/chfs/chfs_subr.c:1.4	Thu Apr 12 15:31:01 2012
+++ src/sys/ufs/chfs/chfs_subr.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_subr.c,v 1.4 2012/04/12 15:31:01 ttoth Exp $	*/
+/*	$NetBSD: chfs_subr.c,v 1.5 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -295,7 +295,12 @@ chfs_chsize(struct vnode *vp, u_quad_t s
 
 		struct chfs_node_frag *lastfrag = frag_last(&ip->fragtree);
 		fd = lastfrag->node;
-		chfs_mark_node_obsolete(chmp, fd->nref);
+
+		// remove from the list
+		mutex_enter(&chmp->chm_lock_vnocache);
+		chfs_remove_frags_of_node(chmp, &ip->fragtree, fd->nref);
+		chfs_remove_and_obsolete(chmp, ip->chvc, fd->nref, &ip->chvc->dnode);
+		mutex_exit(&chmp->chm_lock_vnocache);
 
 		blknum = lastfrag->ofs / PAGE_SIZE;
 		lastfrag->size = append > PAGE_SIZE ? PAGE_SIZE : size % PAGE_SIZE;
Index: src/sys/ufs/chfs/chfs_vfsops.c
diff -u src/sys/ufs/chfs/chfs_vfsops.c:1.4 src/sys/ufs/chfs/chfs_vfsops.c:1.5
--- src/sys/ufs/chfs/chfs_vfsops.c:1.4	Mon Apr 30 22:51:28 2012
+++ src/sys/ufs/chfs/chfs_vfsops.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_vfsops.c,v 1.4 2012/04/30 22:51:28 rmind Exp $	*/
+/*	$NetBSD: chfs_vfsops.c,v 1.5 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -539,8 +539,7 @@ retry:
 		if (ino == CHFS_ROOTINO) {
 			chvc->nlink = 2;
 			chvc->pvno = CHFS_ROOTINO;
-			chfs_vnode_cache_set_state(chmp,
-			    chvc, VNO_STATE_CHECKEDABSENT);
+			chvc->state = VNO_STATE_CHECKEDABSENT;
 		}
 		chfs_vnode_cache_add(chmp, chvc);
 		mutex_exit(&chmp->chm_lock_vnocache);

Index: src/sys/ufs/chfs/chfs_vnode.c
diff -u src/sys/ufs/chfs/chfs_vnode.c:1.5 src/sys/ufs/chfs/chfs_vnode.c:1.6
--- src/sys/ufs/chfs/chfs_vnode.c:1.5	Fri Apr 13 14:50:35 2012
+++ src/sys/ufs/chfs/chfs_vnode.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_vnode.c,v 1.5 2012/04/13 14:50:35 ttoth Exp $	*/
+/*	$NetBSD: chfs_vnode.c,v 1.6 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -211,7 +211,6 @@ chfs_makeinode(int mode, struct vnode *d
 
 	mutex_enter(&chmp->chm_lock_vnocache);
 	chvc = chfs_vnode_cache_get(chmp, vno);
-	mutex_exit(&chmp->chm_lock_vnocache);
 
 	chvc->pvno = pdir->ino;
 	chvc->vno_version = kmem_alloc(sizeof(uint64_t), KM_SLEEP);
@@ -220,8 +219,8 @@ chfs_makeinode(int mode, struct vnode *d
 		chvc->nlink = 1;
 	else
 		chvc->nlink = 2;
-//	chfs_vnode_cache_set_state(chmp, chvc, VNO_STATE_CHECKEDABSENT);
 	chvc->state = VNO_STATE_CHECKEDABSENT;
+	mutex_exit(&chmp->chm_lock_vnocache);
 
 	ip = VTOI(vp);
 	ip->ino = vno;

Index: src/sys/ufs/chfs/chfs_vnops.c
diff -u src/sys/ufs/chfs/chfs_vnops.c:1.8 src/sys/ufs/chfs/chfs_vnops.c:1.9
--- src/sys/ufs/chfs/chfs_vnops.c:1.8	Sun Jul 22 00:53:22 2012
+++ src/sys/ufs/chfs/chfs_vnops.c	Fri Aug 10 09:26:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_vnops.c,v 1.8 2012/07/22 00:53:22 rmind Exp $	*/
+/*	$NetBSD: chfs_vnops.c,v 1.9 2012/08/10 09:26:58 ttoth Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -661,7 +661,6 @@ chfs_read(void *v)
 		goto out;
 	}
 
-
 	dbg("start reading\n");
 	for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
 		bytesinfile = ip->size - uio->uio_offset;
@@ -706,10 +705,14 @@ chfs_read(void *v)
 			break;
 		brelse(bp, 0);
 	}
+
 	if (bp != NULL)
 		brelse(bp, 0);
 
 out:
+	// FIXME HACK
+	ip->ino = ip->chvc->vno;
+
 	if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
 		ip->iflag |= IN_ACCESS;
 		if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) {
@@ -725,6 +728,7 @@ out:
 
 	dbg("[END]\n");
 	fstrans_done(vp->v_mount);
+
 	return (error);
 }
 
@@ -989,7 +993,7 @@ out:
 	} else if (resid > uio->uio_resid && (ioflag & IO_SYNC) == IO_SYNC)
 		error = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
 
-	//XXX hack, i write the next line after i know ip->i_size and vp->v_size don't equal
+	//FIXME HACK
 	chfs_set_vnode_size(vp, vp->v_size);
 
 
@@ -1492,22 +1496,18 @@ chfs_reclaim(void *v)
 
 	//dbg("reclaim() | ino: %llu\n", (unsigned long long)ip->ino);
 	//mutex_enter(&ip->inode_lock);
+	mutex_enter(&chmp->chm_lock_mountfields);
 
 	mutex_enter(&chmp->chm_lock_vnocache);
-	chfs_vnode_cache_set_state(chmp,
-	    ip->chvc, VNO_STATE_CHECKEDABSENT);
+	ip->chvc->state = VNO_STATE_CHECKEDABSENT;
 	mutex_exit(&chmp->chm_lock_vnocache);
 
 	chfs_update(vp, NULL, NULL, UPDATE_CLOSE);
 
-	if (ip->ch_type == CHT_REG || ip->ch_type == CHT_LNK ||
-		ip->ch_type == CHT_CHR || ip->ch_type == CHT_BLK || 
-		ip->ch_type == CHT_FIFO || ip->ch_type == CHT_SOCK) {
-		chfs_kill_fragtree(&ip->fragtree);
-	}
+	chfs_kill_fragtree(chmp, &ip->fragtree);
 
 	fd = TAILQ_FIRST(&ip->dents);
-	while(fd) {
+	while (fd) {
 		TAILQ_REMOVE(&ip->dents, fd, fds);
 		chfs_free_dirent(fd);
 		fd = TAILQ_FIRST(&ip->dents);
@@ -1525,6 +1525,9 @@ chfs_reclaim(void *v)
 	genfs_node_destroy(vp);
 	pool_put(&chfs_inode_pool, vp->v_data);
 	vp->v_data = NULL;
+
+	mutex_exit(&chmp->chm_lock_mountfields);
+
 	return (0);
 }
 
@@ -1570,16 +1573,17 @@ chfs_strategy(void *v)
 	if (read) {
 		err = chfs_read_data(chmp, vp, bp);
 	} else {
-		fd = chfs_alloc_full_dnode();
-
 		mutex_enter(&chmp->chm_lock_mountfields);
 
+		fd = chfs_alloc_full_dnode();
+
 		err = chfs_write_flash_dnode(chmp, vp, bp, fd);
 		if (err) {
 			mutex_exit(&chmp->chm_lock_mountfields);
 			goto out;
 		}
 
+		ip = VTOI(vp);
 		err = chfs_add_full_dnode_to_inode(chmp, ip, fd);
 		/*if (err) {
 			mutex_exit(&chmp->chm_lock_mountfields);

Reply via email to