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);