HAMMER 12/many - buffer cache sync, buffer cache interactions, misc fixes.
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 30 Dec 2007 08:49:20 +0000 (08:49 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 30 Dec 2007 08:49:20 +0000 (08:49 +0000)
As of this commit all vnops work, the filesystem remains consistent across
umount/remount, and the 'cpdup / /mnt/root' test succeeds.  There is still
a ton of work to do but this is a major milestone.

* Get sync and umount working properly.  Properly sync out in-memory records
  and inode updates, and properly release buffer cache buffers so the
  kernel can throw them away.

* Modifications to buffers backed by the buffer cache ensure that any
  asynchronous writes complete to avoid a modify-write race.

* Fix miscellanious reference counting bugs.

* Fix two insertion bugs for internal B-Tree nodes that were causing the
  code to blow up.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_cursor.c
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_io.c
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_ondisk.c
sys/vfs/hammer/hammer_spike.c
sys/vfs/hammer/hammer_subs.c
sys/vfs/hammer/hammer_transaction.c
sys/vfs/hammer/hammer_vnops.c

index e077daf..862126f 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.15 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.16 2007/12/30 08:49:20 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -87,8 +87,9 @@ typedef struct hammer_transaction *hammer_transaction_t;
  * HAMMER locks
  */
 struct hammer_lock {
-       int     refs;
-       int     lockcount;
+       int     refs;           /* active references delay writes */
+       int     modifying;      /* indicates buffer being modified */
+       int     lockcount;      /* lock count for exclusive/shared access */
        int     wanted;
        struct thread *locktd;
 };
@@ -99,6 +100,12 @@ hammer_islocked(struct hammer_lock *lock)
        return(lock->lockcount != 0);
 }
 
+static __inline int
+hammer_isactive(struct hammer_lock *lock)
+{
+       return(lock->refs != 0);
+}
+
 static __inline int
 hammer_islastref(struct hammer_lock *lock)
 {
@@ -164,6 +171,10 @@ typedef struct hammer_inode *hammer_inode_t;
 #define HAMMER_INODE_DELETED   0x0080  /* inode ready for deletion */
 #define HAMMER_INODE_DELONDISK 0x0100  /* delete synchronized to disk */
 
+#define HAMMER_INODE_MODMASK   (HAMMER_INODE_DDIRTY|HAMMER_INODE_RDIRTY| \
+                                HAMMER_INODE_ITIMES|HAMMER_INODE_FLUSH|  \
+                                HAMMER_INODE_DELETED)
+
 #define HAMMER_MAX_INODE_CURSORS       4
 
 /*
@@ -602,6 +613,8 @@ void hammer_io_release(struct hammer_io *io, int flush);
 int hammer_io_checkflush(hammer_io_t io);
 void hammer_io_notify_cluster(hammer_cluster_t cluster);
 void hammer_io_flush(struct hammer_io *io, struct hammer_sync_info *info);
+void hammer_io_intend_modify(struct hammer_io *io);
+void hammer_io_modify_done(struct hammer_io *io);
 
 #endif
 
@@ -612,18 +625,45 @@ static __inline void
 hammer_modify_volume(struct hammer_volume *volume)
 {
        volume->io.modified = 1;
+       ++volume->io.lock.modifying;
+       if (volume->io.released)
+               hammer_io_intend_modify(&volume->io);
+}
+
+static __inline void
+hammer_modify_volume_done(struct hammer_volume *volume)
+{
+       hammer_io_modify_done(&volume->io);
 }
 
 static __inline void
 hammer_modify_supercl(struct hammer_supercl *supercl)
 {
        supercl->io.modified = 1;
+       ++supercl->io.lock.modifying;
+       if (supercl->io.released)
+               hammer_io_intend_modify(&supercl->io);
+}
+
+static __inline void
+hammer_modify_supercl_done(struct hammer_supercl *supercl)
+{
+       hammer_io_modify_done(&supercl->io);
 }
 
 static __inline void
 hammer_modify_cluster(struct hammer_cluster *cluster)
 {
        cluster->io.modified = 1;
+       ++cluster->io.lock.modifying;
+       if (cluster->io.released)
+               hammer_io_intend_modify(&cluster->io);
+}
+
+static __inline void
+hammer_modify_cluster_done(struct hammer_cluster *cluster)
+{
+       hammer_io_modify_done(&cluster->io);
 }
 
 static __inline void
@@ -631,6 +671,15 @@ hammer_modify_buffer(struct hammer_buffer *buffer)
 {
        hammer_io_notify_cluster(buffer->cluster);
        buffer->io.modified = 1;
+       ++buffer->io.lock.modifying;
+       if (buffer->io.released)
+               hammer_io_intend_modify(&buffer->io);
+}
+
+static __inline void
+hammer_modify_buffer_done(struct hammer_buffer *buffer)
+{
+       hammer_io_modify_done(&buffer->io);
 }
 
 static __inline void
@@ -639,6 +688,12 @@ hammer_modify_node(struct hammer_node *node)
        hammer_modify_buffer(node->buffer);
 }
 
+static __inline void
+hammer_modify_node_done(struct hammer_node *node)
+{
+       hammer_modify_buffer_done(node->buffer);
+}
+
 /*
  * Return the cluster-relative byte offset of an element within a buffer
  */
index 1840c53..322e9dc 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.12 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.13 2007/12/30 08:49:20 dillon Exp $
  */
 
 /*
@@ -414,6 +414,7 @@ hammer_btree_insert(hammer_cursor_t cursor, hammer_btree_elm_t elm)
         * Remember that the right-hand boundary is not included in the
         * count.
         */
+       hammer_modify_node(cursor->node);
        node = cursor->node->ondisk;
        i = cursor->index;
        KKASSERT(node->type == HAMMER_BTREE_TYPE_LEAF);
@@ -424,18 +425,19 @@ hammer_btree_insert(hammer_cursor_t cursor, hammer_btree_elm_t elm)
        }
        node->elms[i] = *elm;
        ++node->count;
-       hammer_modify_node(cursor->node);
+       hammer_modify_node_done(cursor->node);
 
        /*
         * Adjust the sub-tree count in the parent.  note that the parent
         * may be in a different cluster.
         */
        if (cursor->parent) {
+               hammer_modify_node(cursor->parent);
                parent = cursor->parent->ondisk;
                i = cursor->parent_index;
                ++parent->elms[i].internal.subtree_count;
+               hammer_modify_node_done(cursor->parent);
                KKASSERT(parent->elms[i].internal.subtree_count <= node->count);
-               hammer_modify_node(cursor->parent);
        }
        return(0);
 }
@@ -485,12 +487,13 @@ hammer_btree_delete(hammer_cursor_t cursor)
        i = cursor->index;
 
        KKASSERT(ondisk->type == HAMMER_BTREE_TYPE_LEAF);
+       hammer_modify_node(node);
        if (i + 1 != ondisk->count) {
                bcopy(&ondisk->elms[i+1], &ondisk->elms[i],
                      (ondisk->count - i - 1) * sizeof(ondisk->elms[0]));
        }
        --ondisk->count;
-       hammer_modify_node(node);
+       hammer_modify_node_done(node);
        if (cursor->parent != NULL) {
                /*
                 * Adjust parent's notion of the leaf's count.  subtree_count
@@ -499,11 +502,12 @@ hammer_btree_delete(hammer_cursor_t cursor)
                 * the count below 0.
                 */
                parent = cursor->parent;
+               hammer_modify_node(parent);
                elm = &parent->ondisk->elms[cursor->parent_index];
                if (elm->internal.subtree_count)
                        --elm->internal.subtree_count;
+               hammer_modify_node_done(parent);
                KKASSERT(elm->internal.subtree_count <= ondisk->count);
-               hammer_modify_node(parent);
        }
 
        /*
@@ -725,10 +729,11 @@ btree_search(hammer_cursor_t cursor, int flags)
                                cursor->index = 0;
                                return(ENOENT);
                        }
+                       hammer_modify_node(cursor->node);
                        save = node->elms[0].subtree_type;
                        node->elms[0].base = *cursor->left_bound;
                        node->elms[0].subtree_type = save;
-                       hammer_modify_node(cursor->node);
+                       hammer_modify_node_done(cursor->node);
                } else if (i == node->count) {
                        /*
                         * Terminate early if not inserting and the key is
@@ -751,8 +756,9 @@ btree_search(hammer_cursor_t cursor, int flags)
                         */
                        if (hammer_btree_cmp(&node->elms[i].base,
                                             cursor->right_bound) != 0) {
-                               node->elms[i].base = *cursor->right_bound;
                                hammer_modify_node(cursor->node);
+                               node->elms[i].base = *cursor->right_bound;
+                               hammer_modify_node_done(cursor->node);
                        }
                        --i;
                } else {
@@ -985,6 +991,7 @@ btree_split_internal(hammer_cursor_t cursor)
                if (parent == NULL)
                        return(error);
                hammer_lock_ex(&parent->lock);
+               hammer_modify_node(parent);
                ondisk = parent->ondisk;
                ondisk->count = 1;
                ondisk->parent = 0;
@@ -995,6 +1002,7 @@ btree_split_internal(hammer_cursor_t cursor)
                ondisk->elms[1].base = node->cluster->clu_btree_end;
                made_root = 1;
                parent_index = 0;       /* index of current node in parent */
+               hammer_modify_node_done(parent);
        } else {
                made_root = 0;
                parent = cursor->parent;
@@ -1032,6 +1040,8 @@ btree_split_internal(hammer_cursor_t cursor)
         *
         * elm is the new separator.
         */
+       hammer_modify_node(new_node);
+       hammer_modify_node(node);
        ondisk = node->ondisk;
        elm = &ondisk->elms[split];
        bcopy(elm, &new_node->ondisk->elms[0],
@@ -1047,6 +1057,7 @@ btree_split_internal(hammer_cursor_t cursor)
         * a new root its parent pointer may have changed.
         */
        elm->internal.subtree_offset = 0;
+       elm->internal.rec_offset = 0;
        ondisk->count = split;
 
        /*
@@ -1056,6 +1067,7 @@ btree_split_internal(hammer_cursor_t cursor)
         *
         * Remember that base.count does not include the right-hand boundary.
         */
+       hammer_modify_node(parent);
        ondisk = parent->ondisk;
        KKASSERT(ondisk->count != HAMMER_BTREE_INT_ELMS);
        ondisk->elms[parent_index].internal.subtree_count = split;
@@ -1066,7 +1078,10 @@ btree_split_internal(hammer_cursor_t cursor)
        parent_elm->internal.subtree_offset = new_node->node_offset;
        parent_elm->internal.subtree_count = new_node->ondisk->count;
        parent_elm->internal.subtree_type = new_node->ondisk->type;
+       parent_elm->internal.subtree_vol_no = 0;
+       parent_elm->internal.rec_offset = 0;
        ++ondisk->count;
+       hammer_modify_node_done(parent);
 
        /*
         * The children of new_node need their parent pointer set to new_node.
@@ -1083,8 +1098,9 @@ btree_split_internal(hammer_cursor_t cursor)
         * The cluster's root pointer may have to be updated.
         */
        if (made_root) {
-               node->cluster->ondisk->clu_btree_root = parent->node_offset;
                hammer_modify_cluster(node->cluster);
+               node->cluster->ondisk->clu_btree_root = parent->node_offset;
+               hammer_modify_cluster_done(node->cluster);
                node->ondisk->parent = parent->node_offset;
                if (cursor->parent) {
                        hammer_unlock(&cursor->parent->lock);
@@ -1092,10 +1108,9 @@ btree_split_internal(hammer_cursor_t cursor)
                }
                cursor->parent = parent;        /* lock'd and ref'd */
        }
+       hammer_modify_node_done(new_node);
+       hammer_modify_node_done(node);
 
-       hammer_modify_node(node);
-       hammer_modify_node(new_node);
-       hammer_modify_node(parent);
 
        /*
         * Ok, now adjust the cursor depending on which element the original
@@ -1173,6 +1188,7 @@ btree_split_leaf(hammer_cursor_t cursor)
                if (parent == NULL)
                        return(error);
                hammer_lock_ex(&parent->lock);
+               hammer_modify_node(parent);
                ondisk = parent->ondisk;
                ondisk->count = 1;
                ondisk->parent = 0;
@@ -1181,6 +1197,7 @@ btree_split_leaf(hammer_cursor_t cursor)
                ondisk->elms[0].internal.subtree_type = leaf->ondisk->type;
                ondisk->elms[0].internal.subtree_offset = leaf->node_offset;
                ondisk->elms[1].base = leaf->cluster->clu_btree_end;
+               hammer_modify_node_done(parent);
                made_root = 1;
                parent_index = 0;       /* insertion point in parent */
        } else {
@@ -1217,6 +1234,8 @@ btree_split_leaf(hammer_cursor_t cursor)
         * Create the new node.  P become the left-hand boundary in the
         * new node.  Copy the right-hand boundary as well.
         */
+       hammer_modify_node(leaf);
+       hammer_modify_node(new_leaf);
        ondisk = leaf->ondisk;
        elm = &ondisk->elms[split];
        bcopy(elm, &new_leaf->ondisk->elms[0], (ondisk->count - split) * esize);
@@ -1241,6 +1260,7 @@ btree_split_leaf(hammer_cursor_t cursor)
         * Remember that base.count does not include the right-hand boundary.
         * We are copying parent_index+1 to parent_index+2, not +0 to +1.
         */
+       hammer_modify_node(parent);
        ondisk = parent->ondisk;
        KKASSERT(ondisk->count != HAMMER_BTREE_INT_ELMS);
        ondisk->elms[parent_index].internal.subtree_count = split;
@@ -1251,14 +1271,18 @@ btree_split_leaf(hammer_cursor_t cursor)
        parent_elm->internal.subtree_offset = new_leaf->node_offset;
        parent_elm->internal.subtree_count = new_leaf->ondisk->count;
        parent_elm->internal.subtree_type = new_leaf->ondisk->type;
+       parent_elm->internal.subtree_vol_no = 0;
+       parent_elm->internal.rec_offset = 0;
        ++ondisk->count;
+       hammer_modify_node_done(parent);
 
        /*
         * The cluster's root pointer may have to be updated.
         */
        if (made_root) {
-               leaf->cluster->ondisk->clu_btree_root = parent->node_offset;
                hammer_modify_cluster(leaf->cluster);
+               leaf->cluster->ondisk->clu_btree_root = parent->node_offset;
+               hammer_modify_cluster_done(leaf->cluster);
                leaf->ondisk->parent = parent->node_offset;
                if (cursor->parent) {
                        hammer_unlock(&cursor->parent->lock);
@@ -1266,10 +1290,8 @@ btree_split_leaf(hammer_cursor_t cursor)
                }
                cursor->parent = parent;        /* lock'd and ref'd */
        }
-
-       hammer_modify_node(leaf);
-       hammer_modify_node(new_leaf);
-       hammer_modify_node(parent);
+       hammer_modify_node_done(leaf);
+       hammer_modify_node_done(new_leaf);
 
        /*
         * Ok, now adjust the cursor depending on which element the original
@@ -1329,11 +1351,12 @@ btree_remove(hammer_cursor_t cursor)
         * allowed to be empty so convert it to a leaf node.
         */
        if (cursor->parent == NULL) {
+               hammer_modify_node(cursor->node);
                ondisk = cursor->node->ondisk;
                KKASSERT(ondisk->parent == 0);
                ondisk->type = HAMMER_BTREE_TYPE_LEAF;
                ondisk->count = 0;
-               hammer_modify_node(cursor->node);
+               hammer_modify_node_done(cursor->node);
                kprintf("EMPTY ROOT OF ROOT CLUSTER -> LEAF\n");
                return(0);
        }
@@ -1415,12 +1438,13 @@ btree_remove(hammer_cursor_t cursor)
 #if 0
        kprintf("BTREE_REMOVE: Removing element %d\n", cursor->index);
 #endif
+       hammer_modify_node(node);
        ondisk = node->ondisk;
        i = cursor->index;
        bcopy(&ondisk->elms[i+1], &ondisk->elms[i],
              (ondisk->count - i) * sizeof(ondisk->elms[0]));
        --ondisk->count;
-       hammer_modify_node(cursor->node);
+       hammer_modify_node_done(node);
 
        /*
         * Adjust the parent-parent's (now parent) reference to the parent
@@ -1429,13 +1453,15 @@ btree_remove(hammer_cursor_t cursor)
        if ((parent = cursor->parent) != NULL) {
                elm = &parent->ondisk->elms[cursor->parent_index];
                if (elm->internal.subtree_count != ondisk->count) {
-                       elm->internal.subtree_count = ondisk->count;
                        hammer_modify_node(parent);
+                       elm->internal.subtree_count = ondisk->count;
+                       hammer_modify_node_done(parent);
                }
                if (elm->subtree_type != HAMMER_BTREE_TYPE_CLUSTER &&
                    elm->subtree_type != ondisk->type) {
-                       elm->subtree_type = ondisk->type;
                        hammer_modify_node(parent);
+                       elm->subtree_type = ondisk->type;
+                       hammer_modify_node_done(parent);
                }
        }
                
@@ -1470,10 +1496,11 @@ btree_set_parent(hammer_node_t node, hammer_btree_elm_t elm)
                child = hammer_get_node(node->cluster,
                                        elm->internal.subtree_offset, &error);
                if (error == 0) {
+                       hammer_modify_node(child);
                        hammer_lock_ex(&child->lock);
                        child->ondisk->parent = node->node_offset;
-                       hammer_modify_node(child);
                        hammer_unlock(&child->lock);
+                       hammer_modify_node_done(child);
                        hammer_rel_node(child);
                }
                break;
@@ -1488,14 +1515,15 @@ btree_set_parent(hammer_node_t node, hammer_btree_elm_t elm)
                 hammer_rel_volume(volume, 0);
                if (error)
                        break;
+               hammer_modify_cluster(cluster);
                hammer_lock_ex(&cluster->io.lock);
                cluster->ondisk->clu_btree_parent_offset = node->node_offset;
                hammer_unlock(&cluster->io.lock);
+               hammer_modify_cluster_done(cluster);
                KKASSERT(cluster->ondisk->clu_btree_parent_clu_no ==
                         node->cluster->clu_no);
                KKASSERT(cluster->ondisk->clu_btree_parent_vol_no ==
                         node->cluster->volume->vol_no);
-               hammer_modify_cluster(cluster);
                hammer_rel_cluster(cluster, 0);
                break;
        default:
@@ -1655,10 +1683,11 @@ btree_rebalance(hammer_cursor_t cursor)
                                                        &error,
                                                        &subchild_buffer, XXX);
                                if (subchild) {
+                                       hammer_modify_buffer(subchild_buffer);
                                        subchild->base.parent =
                                            hammer_bclu_offset(child_buffer[i],
                                                                child);
-                                       hammer_modify_buffer(subchild_buffer);
+                                       hammer_modify_buffer_done(subchild_buffer);
                                }
                                /* XXX error */
                        }
index a7edbb2..ad574d3 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.7 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.8 2007/12/30 08:49:20 dillon Exp $
  */
 
 /*
@@ -67,6 +67,7 @@ hammer_init_cursor_hmp(hammer_cursor_t cursor, hammer_mount_t hmp)
        }
        if (error == 0)
                error = hammer_load_cursor_parent(cursor);
+       KKASSERT(error == 0);
        return(error);
 }
 
@@ -88,6 +89,7 @@ hammer_init_cursor_cluster(hammer_cursor_t cursor, hammer_cluster_t cluster)
                hammer_lock_ex(&cursor->node->lock);
                error = hammer_load_cursor_parent(cursor);
        }
+       KKASSERT(error == 0);
        return(error);
 }
 
@@ -116,6 +118,7 @@ hammer_init_cursor_ip(hammer_cursor_t cursor, hammer_inode_t ip)
        } else {
                error = hammer_init_cursor_hmp(cursor, ip->hmp);
        }
+       KKASSERT(error == 0);
        return(error);
 }
 
@@ -454,6 +457,7 @@ hammer_cursor_toroot(hammer_cursor_t cursor)
        cursor->node = hammer_get_node(cluster, cluster->ondisk->clu_btree_root,
                                       &error);
        cursor->index = 0;
+       hammer_lock_ex(&cursor->node->lock);
        hammer_rel_cluster(cluster, 0);
        if (error == 0)
                error = hammer_load_cursor_parent(cursor);
@@ -511,9 +515,11 @@ hammer_cursor_down(hammer_cursor_t cursor)
                clu_no = elm->internal.subtree_clu_no;
                volume = hammer_get_volume(node->cluster->volume->hmp,
                                           vol_no, &error);
+               KKASSERT(error != EINVAL);
                if (error)
                        return(error);
                cluster = hammer_get_cluster(volume, clu_no, &error, 0);
+               KKASSERT(error != EINVAL);
                hammer_rel_volume(volume, 0);
                if (error)
                        return(error);
index 27050ed..676a220 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.13 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.14 2007/12/30 08:49:20 dillon Exp $
  */
 
 #include "hammer.h"
@@ -233,8 +233,9 @@ loop:
        if (*errorp == 0) {
                ip->ino_rec = cursor.record->inode;
                ip->ino_data = cursor.data->inode;
+       } else if (cursor.node) {
+               hammer_cache_node(cursor.node, &ip->cache);
        }
-       hammer_cache_node(cursor.node, &ip->cache);
        hammer_done_cursor(&cursor);
 
        /*
@@ -413,8 +414,9 @@ retry:
                        ip->flags &= ~(HAMMER_INODE_RDIRTY|HAMMER_INODE_DDIRTY|
                                       HAMMER_INODE_DELONDISK);
                        if ((ip->flags & HAMMER_INODE_ONDISK) == 0) {
-                               ++ip->hmp->rootvol->ondisk->vol0_stat_inodes;
                                hammer_modify_volume(ip->hmp->rootvol);
+                               ++ip->hmp->rootvol->ondisk->vol0_stat_inodes;
+                               hammer_modify_volume_done(ip->hmp->rootvol);
                                ip->flags |= HAMMER_INODE_ONDISK;
                        }
                }
@@ -509,8 +511,8 @@ hammer_sync_inode_callback(hammer_record_t rec, void *data)
        }
 
        if (error) {
-               kprintf("hammer_sync_inode_callback: sync failed rec %p\n",
-                       rec);
+               kprintf("hammer_sync_inode_callback: sync failed rec %p, error %d\n",
+                       rec, error);
                hammer_drop_mem_record(rec, 0);
                return(-error);
        }
@@ -552,14 +554,14 @@ hammer_sync_inode(hammer_inode_t ip, int waitfor, int handle_delete)
                if (ip->vp)
                        vtruncbuf(ip->vp, 0, HAMMER_BUFSIZE);
                error = hammer_ip_delete_range_all(&trans, ip);
-               kprintf("delete_range_all error %d\n", error);
                KKASSERT(RB_EMPTY(&ip->rec_tree));
                ip->flags &= ~HAMMER_INODE_TID;
                ip->ino_rec.base.base.delete_tid = trans.tid;
                hammer_modify_inode(&trans, ip,
                                    HAMMER_INODE_DELETED | HAMMER_INODE_TID);
-               --ip->hmp->rootvol->ondisk->vol0_stat_inodes;
                hammer_modify_volume(ip->hmp->rootvol);
+               --ip->hmp->rootvol->ondisk->vol0_stat_inodes;
+               hammer_modify_volume_done(ip->hmp->rootvol);
        }
 
        /*
index 13e42e8..af40b27 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.8 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.9 2007/12/30 08:49:20 dillon Exp $
  */
 /*
  * IO Primitives and buffer cache management
@@ -101,9 +101,10 @@ hammer_close_cluster(hammer_cluster_t cluster)
                tsleep(cluster, 0, "hmrdep", 0);
        if (cluster->state == HAMMER_CLUSTER_OPEN) {
                cluster->state = HAMMER_CLUSTER_IDLE;
+               hammer_modify_cluster(cluster);
                cluster->ondisk->clu_flags &= ~HAMMER_CLUF_OPEN;
+               hammer_modify_cluster_done(cluster);
                kprintf("CLOSE CLUSTER\n");
-               hammer_modify_cluster(cluster);
        }
 }
 
@@ -169,6 +170,8 @@ hammer_io_new(struct vnode *devvp, struct hammer_io *io)
  * This guarentees (inasmuch as the OS can) that the cluster recovery code
  * will see a cluster marked open if a crash occured while the filesystem
  * still had dirty buffers associated with that cluster.
+ *
+ * XXX
  */
 void
 hammer_io_notify_cluster(hammer_cluster_t cluster)
@@ -180,12 +183,11 @@ hammer_io_notify_cluster(hammer_cluster_t cluster)
                if (cluster->state == HAMMER_CLUSTER_IDLE) {
                        if (io->released)
                                regetblk(io->bp);
+                       io->released = 1;
                        kprintf("MARK CLUSTER OPEN\n");
                        cluster->ondisk->clu_flags |= HAMMER_CLUF_OPEN;
                        cluster->state = HAMMER_CLUSTER_ASYNC;
-                       hammer_modify_cluster(cluster);
                        bawrite(io->bp);
-                       io->released = 1;
                        /* leave cluster marked as modified */
                }
                hammer_unlock(&cluster->io.lock);
@@ -286,45 +288,92 @@ hammer_io_flush(struct hammer_io *io, struct hammer_sync_info *info)
        struct buf *bp;
        int error;
 
+again:
        if ((bp = io->bp) == NULL)
                return;
        if (bp->b_flags & B_DELWRI)
                io->modified = 1;
-       if (io->modified == 0)
-               return;
+
+       /*
+        * We can't initiate a write while the buffer is being modified
+        * by someone.
+        */
+       while (io->lock.modifying) {
+               io->lock.wanted = 1;
+               kprintf("DELAYING IO FLUSH BP %p TYPE %d REFS %d modifying %d\n",
+                       bp, io->type, io->lock.refs, io->lock.modifying);
+               tsleep(&io->lock, 0, "hmrfls", 0);
+       }
        hammer_lock_ex(&io->lock);
+       if (io->lock.modifying || io->bp == NULL) {
+               hammer_unlock(&io->lock);
+               goto again;
+       }
 
-       if ((bp = io->bp) != NULL && io->modified) {
-               if (io->released)
-                       regetblk(bp);
-               io->released = 1;
+       /*
+        * Acquire ownership of the buffer cache buffer so we can flush it
+        * out.
+        */
+       if (io->released) {
+               if (io->modified == 0)
+                       goto done;
+               regetblk(bp);
+       }
+       io->released = 1;
 
-               /*
-                * We own the bp now
-                */
-               if (info->waitfor & MNT_WAIT) {
-                       io->modified = 0;
-                       error = bwrite(bp);
-                       if (error)
-                               info->error = error;
-               } else if (io->lock.refs == 1) {
-                       io->modified = 0;
-                       bawrite(bp);
-               } else {
-                       /*
-                        * structure is in-use, don't race the write, but
-                        * also set B_LOCKED so we know something tried to
-                        * flush it.
-                        */
-                       kprintf("DELAYING IO FLUSH BP %p TYPE %d REFS %d\n",
-                               bp, io->type, io->lock.refs);
-                       bp->b_flags |= B_LOCKED;
-                       bqrelse(bp);
-               }
+       /*
+        * Return the bp to the system, issuing I/O if necessary.  The
+        * system will issue a callback to us when it actually wants to
+        * throw the bp away.
+        */
+       if (io->modified == 0) {
+               bqrelse(bp);
+       } else if (info->waitfor & MNT_WAIT) {
+               io->modified = 0;
+               error = bwrite(bp);
+               if (error)
+                       info->error = error;
+       } else {
+               io->modified = 0;
+               bawrite(bp);
        }
+done:
        hammer_unlock(&io->lock);
 }
 
+/*
+ * Called prior to any modifications being made to ondisk data.  This
+ * forces the caller to wait for any writes to complete.  We explicitly
+ * avoid the write-modify race.
+ *
+ * This routine is only called on hammer structures which are already
+ * actively referenced.
+ */
+void
+hammer_io_intend_modify(struct hammer_io *io)
+{
+       KKASSERT(io->lock.refs != 0 && io->bp != NULL);
+       if (io->released) {
+               hammer_lock_ex(&io->lock);
+               if (io->released) {
+                       regetblk(io->bp);
+                       io->released = 0;
+                       BUF_KERNPROC(io->bp);
+               }
+               hammer_unlock(&io->lock);
+       }
+}
+
+void
+hammer_io_modify_done(struct hammer_io *io)
+{
+       KKASSERT(io->lock.modifying > 0);
+       --io->lock.modifying;
+       if (io->lock.wanted && io->lock.modifying == 0) {
+               io->lock.wanted = 0;
+               wakeup(&io->lock);
+       }
+}
 
 /*
  * HAMMER_BIOOPS
index e0db60a..ac89adc 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.11 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.12 2007/12/30 08:49:20 dillon Exp $
  */
 
 #include "hammer.h"
@@ -500,15 +500,17 @@ hammer_ip_sync_data(hammer_transaction_t trans, hammer_inode_t ip,
        /*
         * Fill everything in and insert our B-Tree node.
         */
+       hammer_modify_buffer(cursor.record_buffer);
        rec->base.base = cursor.key_beg;
        rec->base.data_crc = crc32(data, bytes);
        rec->base.rec_id = 0;   /* XXX */
        rec->base.data_offset = hammer_bclu_offset(cursor.data_buffer, bdata);
        rec->base.data_len = bytes;
-       hammer_modify_buffer(cursor.record_buffer);
+       hammer_modify_buffer_done(cursor.record_buffer);
 
-       bcopy(data, bdata, bytes);
        hammer_modify_buffer(cursor.data_buffer);
+       bcopy(data, bdata, bytes);
+       hammer_modify_buffer_done(cursor.data_buffer);
 
        elm.leaf.base = cursor.key_beg;
        elm.leaf.rec_offset = hammer_bclu_offset(cursor.record_buffer, rec);
@@ -595,6 +597,7 @@ hammer_ip_sync_record(hammer_record_t record, struct hammer_cursor **spike)
         *
         * XXX assign rec_id here
         */
+       hammer_modify_buffer(cursor.record_buffer);
        *rec = record->rec;
        if (bdata) {
                rec->base.data_crc = crc32(record->data,
@@ -614,13 +617,13 @@ hammer_ip_sync_record(hammer_record_t record, struct hammer_cursor **spike)
                         * Data separate from record
                         */
                        rec->base.data_offset = hammer_bclu_offset(cursor.data_buffer,bdata);
-                       bcopy(record->data, bdata, rec->base.data_len);
                        hammer_modify_buffer(cursor.data_buffer);
+                       bcopy(record->data, bdata, rec->base.data_len);
+                       hammer_modify_buffer_done(cursor.data_buffer);
                }
        }
        rec->base.rec_id = 0;   /* XXX */
-
-       hammer_modify_buffer(cursor.record_buffer);
+       hammer_modify_buffer_done(cursor.record_buffer);
 
        elm.leaf.base = cursor.key_beg;
        elm.leaf.rec_offset = hammer_bclu_offset(cursor.record_buffer, rec);
@@ -710,6 +713,7 @@ hammer_write_record(hammer_cursor_t cursor, hammer_record_ondisk_t orec,
         *
         * XXX assign rec_id here
         */
+       hammer_modify_buffer(cursor->record_buffer);
        *nrec = *orec;
        nrec->base.data_offset = 0;
        if (bdata) {
@@ -728,13 +732,13 @@ hammer_write_record(hammer_cursor_t cursor, hammer_record_ondisk_t orec,
                         * Data separate from record
                         */
                        nrec->base.data_offset = hammer_bclu_offset(cursor->data_buffer, bdata);
-                       bcopy(data, bdata, nrec->base.data_len);
                        hammer_modify_buffer(cursor->data_buffer);
+                       bcopy(data, bdata, nrec->base.data_len);
+                       hammer_modify_buffer_done(cursor->data_buffer);
                }
        }
        nrec->base.rec_id = 0;  /* XXX */
-
-       hammer_modify_buffer(cursor->record_buffer);
+       hammer_modify_buffer_done(cursor->record_buffer);
 
        elm.leaf.base = nrec->base.base;
        elm.leaf.rec_offset = hammer_bclu_offset(cursor->record_buffer, nrec);
@@ -1236,11 +1240,13 @@ hammer_ip_delete_record(hammer_cursor_t cursor, hammer_tid_t tid)
        hmp = cursor->node->cluster->volume->hmp;
 
        if (error == 0) {
-               elm = &cursor->node->ondisk->elms[cursor->index];
-               cursor->record->base.base.delete_tid = tid;
-               elm->leaf.base.delete_tid = tid;
                hammer_modify_buffer(cursor->record_buffer);
+               cursor->record->base.base.delete_tid = tid;
+               hammer_modify_buffer_done(cursor->record_buffer);
                hammer_modify_node(cursor->node);
+               elm = &cursor->node->ondisk->elms[cursor->index];
+               elm->leaf.base.delete_tid = tid;
+               hammer_modify_node_done(cursor->node);
        }
 
        /*
index edcad37..2428005 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.12 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.13 2007/12/30 08:49:20 dillon Exp $
  */
 /*
  * Manage HAMMER's on-disk structures.  These routines are primarily
@@ -675,8 +675,6 @@ hammer_rel_supercl(hammer_supercl_t supercl, int flush)
  *                             CLUSTERS                                *
  ************************************************************************
  *
- * Manage clusters.  Note that a cluster holds a reference to its
- * associated volume.
  */
 hammer_cluster_t
 hammer_get_cluster(hammer_volume_t volume, int32_t clu_no,
@@ -805,6 +803,7 @@ hammer_load_cluster(hammer_cluster_t cluster, int isnew)
                hammer_volume_ondisk_t voldisk;
                int32_t nbuffers;
 
+               hammer_modify_cluster(cluster);
                ondisk = cluster->ondisk;
                voldisk = volume->ondisk;
 
@@ -848,14 +847,19 @@ hammer_load_cluster(hammer_cluster_t cluster, int isnew)
                ondisk->clu_btree_parent_clu_no = -2;
                ondisk->clu_btree_parent_offset = -2;
                ondisk->clu_btree_parent_clu_gen = -2;
+               hammer_modify_cluster_done(cluster);
 
                croot = hammer_alloc_btree(cluster, &error);
                if (error == 0) {
+                       hammer_modify_node(croot);
                        bzero(croot->ondisk, sizeof(*croot->ondisk));
                        croot->ondisk->count = 0;
                        croot->ondisk->type = HAMMER_BTREE_TYPE_LEAF;
-                       ondisk->clu_btree_root = croot->node_offset;
+                       hammer_modify_node_done(croot);
                        hammer_modify_cluster(cluster);
+                       ondisk->clu_btree_root = croot->node_offset;
+                       hammer_modify_cluster_done(cluster);
+                       hammer_rel_node(croot);
                }
        }
        hammer_unlock(&cluster->io.lock);
@@ -1440,6 +1444,8 @@ hammer_flush_node(hammer_node_t node)
                        }
                }
                kfree(node, M_HAMMER);
+       } else {
+               kprintf("Cannot flush node: %p\n", node);
        }
 }
 
@@ -1500,6 +1506,7 @@ hammer_alloc_cluster(hammer_mount_t hmp, hammer_cluster_t cluster_hint,
                        clu_no = HAMMER_ALIST_BLOCK_NONE;
                        break;
                }
+               hammer_modify_volume(volume);
                if (clu_hint == -1) {
                        clu_hint = volume->clu_iterator;
                        clu_no = hammer_alist_alloc_fwd(&volume->alist, 1,
@@ -1516,10 +1523,9 @@ hammer_alloc_cluster(hammer_mount_t hmp, hammer_cluster_t cluster_hint,
                                                                1, clu_hint);
                        }
                }
-               if (clu_no != HAMMER_ALIST_BLOCK_NONE) {
-                       hammer_modify_volume(volume);
+               hammer_modify_volume_done(volume);
+               if (clu_no != HAMMER_ALIST_BLOCK_NONE)
                        break;
-               }
                hammer_rel_volume(volume, 0);
                volume = NULL;
                *errorp = ENOSPC;
@@ -1549,10 +1555,12 @@ hammer_init_cluster(hammer_cluster_t cluster, hammer_base_elm_t left_bound,
 {
        hammer_cluster_ondisk_t ondisk = cluster->ondisk;
 
+       hammer_modify_cluster(cluster);
        ondisk->clu_btree_beg = *left_bound;
        ondisk->clu_btree_end = *right_bound;
        cluster->clu_btree_beg = ondisk->clu_btree_beg;
        cluster->clu_btree_end = ondisk->clu_btree_end;
+       hammer_modify_cluster_done(cluster);
 }
 
 /*
@@ -1561,7 +1569,9 @@ hammer_init_cluster(hammer_cluster_t cluster, hammer_base_elm_t left_bound,
 void
 hammer_free_cluster(hammer_cluster_t cluster)
 {
+       hammer_modify_cluster(cluster);
        hammer_alist_free(&cluster->volume->alist, cluster->clu_no, 1);
+       hammer_modify_cluster_done(cluster);
 }
 
 /*
@@ -1591,6 +1601,7 @@ hammer_alloc_btree(hammer_cluster_t cluster, int *errorp)
        /*
         * Allocate a B-Tree element
         */
+       hammer_modify_cluster(cluster);
        buffer = NULL;
        live = &cluster->alist_btree;
        elm_no = hammer_alist_alloc_fwd(live, 1, cluster->ondisk->idx_index);
@@ -1605,13 +1616,12 @@ hammer_alloc_btree(hammer_cluster_t cluster, int *errorp)
                        *errorp = ENOSPC;
                        if (buffer)
                                hammer_rel_buffer(buffer, 0);
-                       hammer_modify_cluster(cluster);
+                       hammer_modify_cluster_done(cluster);
                        return(NULL);
                }
        }
        cluster->ondisk->idx_index = elm_no;
        KKASSERT((elm_no & HAMMER_FSBUF_BLKMASK) < HAMMER_BTREE_NODES);
-       hammer_modify_cluster(cluster);
 
        /*
         * Load and return the B-Tree element
@@ -1622,12 +1632,15 @@ hammer_alloc_btree(hammer_cluster_t cluster, int *errorp)
                               btree.nodes[elm_no & HAMMER_FSBUF_BLKMASK]);
        node = hammer_get_node(cluster, node_offset, errorp);
        if (node) {
+               hammer_modify_node(node);
                bzero(node->ondisk, sizeof(*node->ondisk));
+               hammer_modify_node_done(node);
        } else {
                hammer_alist_free(live, elm_no, 1);
                hammer_rel_node(node);
                node = NULL;
        }
+       hammer_modify_cluster_done(cluster);
        if (buffer)
                hammer_rel_buffer(buffer, 0);
        return(node);
@@ -1648,6 +1661,7 @@ hammer_alloc_data(hammer_cluster_t cluster, int32_t bytes,
         * Deal with large data blocks.  The blocksize is HAMMER_BUFSIZE
         * for these allocations.
         */
+       hammer_modify_cluster(cluster);
        if ((bytes & HAMMER_BUFMASK) == 0) {
                nblks = bytes / HAMMER_BUFSIZE;
                /* only one block allowed for now (so buffer can hold it) */
@@ -1657,10 +1671,12 @@ hammer_alloc_data(hammer_cluster_t cluster, int32_t bytes,
                                             cluster->ondisk->idx_ldata, 1);
                if (buf_no == HAMMER_ALIST_BLOCK_NONE) {
                        *errorp = ENOSPC;
+                       hammer_modify_cluster_done(cluster);
                        return(NULL);
                }
                hammer_adjust_stats(cluster, HAMMER_FSBUF_DATA, nblks);
                cluster->ondisk->idx_ldata = buf_no;
+               hammer_modify_cluster_done(cluster);
                buffer = *bufferp;
                *bufferp = hammer_get_buffer(cluster, buf_no, -1, errorp);
                if (buffer)
@@ -1686,12 +1702,12 @@ hammer_alloc_data(hammer_cluster_t cluster, int32_t bytes,
                elm_no = hammer_alist_alloc(live, nblks);
                if (elm_no == HAMMER_ALIST_BLOCK_NONE) {
                        *errorp = ENOSPC;
-                       hammer_modify_cluster(cluster);
+                       hammer_modify_cluster_done(cluster);
                        return(NULL);
                }
        }
        cluster->ondisk->idx_index = elm_no;
-       hammer_modify_cluster(cluster);
+       hammer_modify_cluster_done(cluster);
 
        /*
         * Load and return the B-Tree element
@@ -1707,8 +1723,10 @@ hammer_alloc_data(hammer_cluster_t cluster, int32_t bytes,
        }
        KKASSERT(buffer->ondisk->head.buf_type == HAMMER_FSBUF_DATA);
        KKASSERT((elm_no & HAMMER_FSBUF_BLKMASK) < HAMMER_DATA_NODES);
+       hammer_modify_buffer(buffer);
        item = &buffer->ondisk->data.data[elm_no & HAMMER_FSBUF_BLKMASK];
        bzero(item, nblks * HAMMER_DATA_BLKSIZE);
+       hammer_modify_buffer_done(buffer);
        *errorp = 0;
        return(item);
 }
@@ -1726,6 +1744,7 @@ hammer_alloc_record(hammer_cluster_t cluster,
        /*
         * Allocate a record element
         */
+       hammer_modify_cluster(cluster);
        live = &cluster->alist_record;
        elm_no = hammer_alist_alloc_rev(live, 1, cluster->ondisk->idx_record);
        if (elm_no == HAMMER_ALIST_BLOCK_NONE)
@@ -1738,15 +1757,15 @@ hammer_alloc_record(hammer_cluster_t cluster,
                kprintf("hammer_alloc_record elm again %08x\n", elm_no);
                if (elm_no == HAMMER_ALIST_BLOCK_NONE) {
                        *errorp = ENOSPC;
-                       hammer_modify_cluster(cluster);
+                       hammer_modify_cluster_done(cluster);
                        return(NULL);
                }
        }
        cluster->ondisk->idx_record = elm_no;
-       hammer_modify_cluster(cluster);
+       hammer_modify_cluster_done(cluster);
 
        /*
-        * Load and return the B-Tree element
+        * Load and return the record element
         */
        buf_no = elm_no / HAMMER_FSBUF_MAXBLKS;
        buffer = *bufferp;
@@ -1759,8 +1778,10 @@ hammer_alloc_record(hammer_cluster_t cluster,
        }
        KKASSERT(buffer->ondisk->head.buf_type == HAMMER_FSBUF_RECORDS);
        KKASSERT((elm_no & HAMMER_FSBUF_BLKMASK) < HAMMER_RECORD_NODES);
+       hammer_modify_buffer(buffer);
        item = &buffer->ondisk->record.recs[elm_no & HAMMER_FSBUF_BLKMASK];
        bzero(item, sizeof(union hammer_record_ondisk));
+       hammer_modify_buffer_done(buffer);
        *errorp = 0;
        return(item);
 }
@@ -1772,13 +1793,14 @@ hammer_free_data_ptr(hammer_buffer_t buffer, void *data, int bytes)
        int32_t nblks;
        hammer_alist_t live;
 
+       hammer_modify_cluster(buffer->cluster);
        if ((bytes & HAMMER_BUFMASK) == 0) {
                nblks = bytes / HAMMER_BUFSIZE;
                KKASSERT(nblks == 1 && data == (void *)buffer->ondisk);
                hammer_alist_free(&buffer->cluster->alist_master,
                                  buffer->buf_no, nblks);
                hammer_adjust_stats(buffer->cluster, HAMMER_FSBUF_DATA, -nblks);
-               hammer_modify_cluster(buffer->cluster);
+               hammer_modify_cluster_done(buffer->cluster);
                return;
        }
 
@@ -1790,7 +1812,7 @@ hammer_free_data_ptr(hammer_buffer_t buffer, void *data, int bytes)
        nblks /= HAMMER_DATA_BLKSIZE;
        live = &buffer->cluster->alist_mdata;
        hammer_alist_free(live, elm_no, nblks);
-       hammer_modify_cluster(buffer->cluster);
+       hammer_modify_cluster_done(buffer->cluster);
 }
 
 void
@@ -1799,12 +1821,13 @@ hammer_free_record_ptr(hammer_buffer_t buffer, union hammer_record_ondisk *rec)
        int32_t elm_no;
        hammer_alist_t live;
 
+       hammer_modify_cluster(buffer->cluster);
        elm_no = rec - &buffer->ondisk->record.recs[0];
        KKASSERT(elm_no >= 0 && elm_no < HAMMER_BTREE_NODES);
        elm_no += buffer->buf_no * HAMMER_FSBUF_MAXBLKS;
        live = &buffer->cluster->alist_record;
        hammer_alist_free(live, elm_no, 1);
-       hammer_modify_cluster(buffer->cluster);
+       hammer_modify_cluster_done(buffer->cluster);
 }
 
 void
@@ -1815,13 +1838,14 @@ hammer_free_btree(hammer_cluster_t cluster, int32_t bclu_offset)
        hammer_alist_t live;
        int32_t elm_no;
 
+       hammer_modify_cluster(cluster);
        elm_no = bclu_offset / HAMMER_BUFSIZE * HAMMER_FSBUF_MAXBLKS;
        fsbuf_offset -= offsetof(union hammer_fsbuf_ondisk, btree.nodes[0]);
        live = &cluster->alist_btree;
        KKASSERT(fsbuf_offset >= 0 && fsbuf_offset % blksize == 0);
        elm_no += fsbuf_offset / blksize;
        hammer_alist_free(live, elm_no, 1);
-       hammer_modify_cluster(cluster);
+       hammer_modify_cluster_done(cluster);
 }
 
 void
@@ -1834,13 +1858,14 @@ hammer_free_data(hammer_cluster_t cluster, int32_t bclu_offset, int32_t bytes)
        int32_t buf_no;
        int32_t nblks;
 
+       hammer_modify_cluster(cluster);
        if ((bytes & HAMMER_BUFMASK) == 0) {
                nblks = bytes / HAMMER_BUFSIZE;
                KKASSERT(nblks == 1 && (bclu_offset & HAMMER_BUFMASK) == 0);
                buf_no = bclu_offset / HAMMER_BUFSIZE;
                hammer_alist_free(&cluster->alist_master, buf_no, nblks);
                hammer_adjust_stats(cluster, HAMMER_FSBUF_DATA, -nblks);
-               hammer_modify_cluster(cluster);
+               hammer_modify_cluster_done(cluster);
                return;
        }
 
@@ -1852,7 +1877,7 @@ hammer_free_data(hammer_cluster_t cluster, int32_t bclu_offset, int32_t bytes)
        KKASSERT(fsbuf_offset >= 0 && fsbuf_offset % blksize == 0);
        elm_no += fsbuf_offset / blksize;
        hammer_alist_free(live, elm_no, nblks);
-       hammer_modify_cluster(cluster);
+       hammer_modify_cluster_done(cluster);
 }
 
 void
@@ -1863,13 +1888,14 @@ hammer_free_record(hammer_cluster_t cluster, int32_t bclu_offset)
        hammer_alist_t live;
        int32_t elm_no;
 
+       hammer_modify_cluster(cluster);
        elm_no = bclu_offset / HAMMER_BUFSIZE * HAMMER_FSBUF_MAXBLKS;
        fsbuf_offset -= offsetof(union hammer_fsbuf_ondisk, record.recs[0]);
        live = &cluster->alist_record;
        KKASSERT(fsbuf_offset >= 0 && fsbuf_offset % blksize == 0);
        elm_no += fsbuf_offset / blksize;
        hammer_alist_free(live, elm_no, 1);
-       hammer_modify_cluster(cluster);
+       hammer_modify_cluster_done(cluster);
 }
 
 
@@ -1887,26 +1913,24 @@ alloc_new_buffer(hammer_cluster_t cluster, hammer_alist_t live,
        int32_t buf_no;
        int isfwd;
 
-       start = start / HAMMER_FSBUF_MAXBLKS;   /* convert to buf_no */
+       if (*bufferp)
+               hammer_rel_buffer(*bufferp, 0);
+       *bufferp = NULL;
 
+       start = start / HAMMER_FSBUF_MAXBLKS;   /* convert to buf_no */
        isfwd = (type != HAMMER_FSBUF_RECORDS);
        buf_no = hammer_alloc_master(cluster, 1, start, isfwd);
        if (buf_no == HAMMER_ALIST_BLOCK_NONE) {
                *errorp = ENOSPC;
-               *bufferp = NULL;
                return;
        }
 
-       hammer_modify_cluster(cluster);
-
        /*
         * The new buffer must be initialized (type != 0) regardless of
         * whether we already have it cached or not, so don't try to
         * optimize the cached buffer check.  Just call hammer_get_buffer().
         */
        buffer = hammer_get_buffer(cluster, buf_no, type, errorp);
-       if (*bufferp)
-               hammer_rel_buffer(*bufferp, 0);
        *bufferp = buffer;
 
        /*
@@ -1917,8 +1941,10 @@ alloc_new_buffer(hammer_cluster_t cluster, hammer_alist_t live,
        if (buffer) {
                kprintf("alloc_new_buffer buf_no %d type %016llx nelms %d\n",
                        buf_no, type, nelements);
+               hammer_modify_buffer(buffer);  /*XXX*/
                hammer_alist_free(live, buf_no * HAMMER_FSBUF_MAXBLKS,
                                  nelements);
+               hammer_modify_buffer_done(buffer);  /*XXX*/
                hammer_adjust_stats(cluster, type, 1);
        }
 }
@@ -1927,9 +1953,9 @@ alloc_new_buffer(hammer_cluster_t cluster, hammer_alist_t live,
  * Sync dirty buffers to the media
  */
 
-/*
- * Sync the entire filesystem.
- */
+static int hammer_sync_scan1(struct mount *mp, struct vnode *vp, void *data);
+static int hammer_sync_scan2(struct mount *mp, struct vnode *vp, void *data);
+
 int
 hammer_sync_hmp(hammer_mount_t hmp, int waitfor)
 {
@@ -1938,11 +1964,48 @@ hammer_sync_hmp(hammer_mount_t hmp, int waitfor)
        info.error = 0;
        info.waitfor = waitfor;
 
+       vmntvnodescan(hmp->mp, VMSC_GETVP|VMSC_NOWAIT,
+                     hammer_sync_scan1, hammer_sync_scan2, &info);
+
        RB_SCAN(hammer_vol_rb_tree, &hmp->rb_vols_root, NULL,
                hammer_sync_volume, &info);
        return(info.error);
 }
 
+static int
+hammer_sync_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+       struct hammer_inode *ip;
+
+       ip = VTOI(vp);
+       if (vp->v_type == VNON || ((ip->flags & HAMMER_INODE_MODMASK) == 0 &&
+           RB_EMPTY(&vp->v_rbdirty_tree))) {
+               return(-1);
+       }
+       return(0);
+}
+
+static int
+hammer_sync_scan2(struct mount *mp, struct vnode *vp, void *data)
+{
+       struct hammer_sync_info *info = data;
+       struct hammer_inode *ip;
+       int error;
+
+       ip = VTOI(vp);
+       if (vp->v_type == VNON || vp->v_type == VBAD ||
+           ((ip->flags & HAMMER_INODE_MODMASK) == 0 &&
+            RB_EMPTY(&vp->v_rbdirty_tree))) {
+               return(0);
+       }
+       if (vp->v_type != VCHR) {
+               error = VOP_FSYNC(vp, info->waitfor);
+               if (error)
+                       info->error = error;
+       }
+       return(0);
+}
+
 int
 hammer_sync_volume(hammer_volume_t volume, void *data)
 {
@@ -1962,13 +2025,18 @@ hammer_sync_cluster(hammer_cluster_t cluster, void *data)
 {
        struct hammer_sync_info *info = data;
 
-       if (cluster->state != HAMMER_CLUSTER_IDLE) {
-               RB_SCAN(hammer_buf_rb_tree, &cluster->rb_bufs_root, NULL,
-                       hammer_sync_buffer, info);
+       RB_SCAN(hammer_buf_rb_tree, &cluster->rb_bufs_root, NULL,
+               hammer_sync_buffer, info);
+       switch(cluster->state) {
+       case HAMMER_CLUSTER_OPEN:
+       case HAMMER_CLUSTER_IDLE:
                if (hammer_ref_cluster(cluster) == 0) {
                        hammer_io_flush(&cluster->io, info);
                        hammer_rel_cluster(cluster, 0);
                }
+               break;
+       default:
+               break;
        }
        return(0);
 }
@@ -1988,69 +2056,6 @@ hammer_sync_buffer(hammer_buffer_t buffer, void *data)
        return(0);
 }
 
-#if 0
-
-/*
- * Flush various tracking structures to disk
- */
-
-/*
- * Flush various tracking structures to disk
- */
-void
-flush_all_volumes(void)
-{
-       hammer_volume_t vol;
-
-       for (vol = VolBase; vol; vol = vol->next)
-               flush_volume(vol);
-}
-
-void
-flush_volume(hammer_volume_t vol)
-{
-       hammer_supercl_t supercl;
-       hammer_cluster_t cl;
-
-       for (supercl = vol->supercl_base; supercl; supercl = supercl->next)
-               flush_supercl(supercl);
-       for (cl = vol->cluster_base; cl; cl = cl->next)
-               flush_cluster(cl);
-       writehammerbuf(vol, vol->ondisk, 0);
-}
-
-void
-flush_supercl(hammer_supercl_t supercl)
-{
-       int64_t supercl_offset;
-
-       supercl_offset = supercl->scl_offset;
-       writehammerbuf(supercl->volume, supercl->ondisk, supercl_offset);
-}
-
-void
-flush_cluster(hammer_cluster_t cl)
-{
-       hammer_buffer_t buf;
-       int64_t cluster_offset;
-
-       for (buf = cl->buffer_base; buf; buf = buf->next)
-               flush_buffer(buf);
-       cluster_offset = cl->clu_offset;
-       writehammerbuf(cl->volume, cl->ondisk, cluster_offset);
-}
-
-void
-flush_buffer(hammer_buffer_t buf)
-{
-       int64_t buffer_offset;
-
-       buffer_offset = buf->buf_offset + buf->cluster->clu_offset;
-       writehammerbuf(buf->volume, buf->ondisk, buffer_offset);
-}
-
-#endif
-
 /*
  * Generic buffer initialization
  */
@@ -2136,6 +2141,7 @@ hammer_alloc_master(hammer_cluster_t cluster, int nblks,
 {
        int32_t buf_no;
 
+       hammer_modify_cluster(cluster);
        if (isfwd) {
                buf_no = hammer_alist_alloc_fwd(&cluster->alist_master,
                                                nblks, start);
@@ -2151,6 +2157,7 @@ hammer_alloc_master(hammer_cluster_t cluster, int nblks,
                                                nblks, HAMMER_ALIST_BLOCK_MAX);
                }
        }
+       hammer_modify_cluster_done(cluster);
 
        /*
         * Recover space from empty record, b-tree, and data a-lists.
@@ -2165,6 +2172,10 @@ hammer_alloc_master(hammer_cluster_t cluster, int nblks,
 static void
 hammer_adjust_stats(hammer_cluster_t cluster, u_int64_t buf_type, int nblks)
 {
+       hammer_modify_cluster(cluster);
+       hammer_modify_volume(cluster->volume);
+       hammer_modify_volume(cluster->volume->hmp->rootvol);
+
        switch(buf_type) {
        case HAMMER_FSBUF_BTREE:
                cluster->ondisk->stat_idx_bufs += nblks;
@@ -2182,9 +2193,9 @@ hammer_adjust_stats(hammer_cluster_t cluster, u_int64_t buf_type, int nblks)
                cluster->volume->hmp->rootvol->ondisk->vol0_stat_rec_bufs += nblks;
                break;
        }
-       hammer_modify_cluster(cluster);
-       hammer_modify_volume(cluster->volume);
-       hammer_modify_volume(cluster->volume->hmp->rootvol);
+       hammer_modify_cluster_done(cluster);
+       hammer_modify_volume_done(cluster->volume);
+       hammer_modify_volume_done(cluster->volume->hmp->rootvol);
 }
 
 /*
@@ -2268,11 +2279,12 @@ buffer_alist_alloc_fwd(void *info, int32_t blk, int32_t radix,
        if (buffer) {
                KKASSERT(buffer->ondisk->head.buf_type != 0);
 
+               hammer_modify_buffer(buffer);
                r = hammer_alist_alloc_fwd(&buffer->alist, count, atblk - blk);
                if (r != HAMMER_ALIST_BLOCK_NONE)
                        r += blk;
+               hammer_modify_buffer_done(buffer);
                *fullp = hammer_alist_isfull(&buffer->alist);
-               hammer_modify_buffer(buffer);
                hammer_rel_buffer(buffer, 0);
        } else {
                r = HAMMER_ALIST_BLOCK_NONE;
@@ -2294,12 +2306,12 @@ buffer_alist_alloc_rev(void *info, int32_t blk, int32_t radix,
        buffer = hammer_get_buffer(cluster, buf_no, 0, &error);
        if (buffer) {
                KKASSERT(buffer->ondisk->head.buf_type != 0);
-
+               hammer_modify_buffer(buffer);
                r = hammer_alist_alloc_rev(&buffer->alist, count, atblk - blk);
                if (r != HAMMER_ALIST_BLOCK_NONE)
                        r += blk;
+               hammer_modify_buffer_done(buffer);
                *fullp = hammer_alist_isfull(&buffer->alist);
-               hammer_modify_buffer(buffer);
                hammer_rel_buffer(buffer, 0);
        } else {
                r = HAMMER_ALIST_BLOCK_NONE;
@@ -2321,10 +2333,11 @@ buffer_alist_free(void *info, int32_t blk, int32_t radix,
        buffer = hammer_get_buffer(cluster, buf_no, 0, &error);
        if (buffer) {
                KKASSERT(buffer->ondisk->head.buf_type != 0);
+               hammer_modify_buffer(buffer);
                hammer_alist_free(&buffer->alist, base_blk, count);
+               hammer_modify_buffer_done(buffer);
                *emptyp = hammer_alist_isempty(&buffer->alist);
                /* XXX don't bother updating the buffer is completely empty? */
-               hammer_modify_buffer(buffer);
                hammer_rel_buffer(buffer, 0);
        } else {
                *emptyp = 0;
@@ -2382,11 +2395,12 @@ super_alist_alloc_fwd(void *info, int32_t blk, int32_t radix,
        scl_no = blk / HAMMER_SCL_MAXCLUSTERS;
        supercl = hammer_get_supercl(volume, scl_no, &error, 0);
        if (supercl) {
+               hammer_modify_supercl(supercl);
                r = hammer_alist_alloc_fwd(&supercl->alist, count, atblk - blk);
                if (r != HAMMER_ALIST_BLOCK_NONE)
                        r += blk;
+               hammer_modify_supercl_done(supercl);
                *fullp = hammer_alist_isfull(&supercl->alist);
-               hammer_modify_supercl(supercl);
                hammer_rel_supercl(supercl, 0);
        } else {
                r = HAMMER_ALIST_BLOCK_NONE;
@@ -2408,11 +2422,12 @@ super_alist_alloc_rev(void *info, int32_t blk, int32_t radix,
        scl_no = blk / HAMMER_SCL_MAXCLUSTERS;
        supercl = hammer_get_supercl(volume, scl_no, &error, 0);
        if (supercl) {
+               hammer_modify_supercl(supercl);
                r = hammer_alist_alloc_rev(&supercl->alist, count, atblk - blk);
                if (r != HAMMER_ALIST_BLOCK_NONE)
                        r += blk;
+               hammer_modify_supercl_done(supercl);
                *fullp = hammer_alist_isfull(&supercl->alist);
-               hammer_modify_supercl(supercl);
                hammer_rel_supercl(supercl, 0);
        } else { 
                r = HAMMER_ALIST_BLOCK_NONE;
@@ -2433,9 +2448,10 @@ super_alist_free(void *info, int32_t blk, int32_t radix,
        scl_no = blk / HAMMER_SCL_MAXCLUSTERS;
        supercl = hammer_get_supercl(volume, scl_no, &error, 0);
        if (supercl) {
+               hammer_modify_supercl(supercl);
                hammer_alist_free(&supercl->alist, base_blk, count);
+               hammer_modify_supercl_done(supercl);
                *emptyp = hammer_alist_isempty(&supercl->alist);
-               hammer_modify_supercl(supercl);
                hammer_rel_supercl(supercl, 0);
        } else {
                *emptyp = 0;
index 6ee7271..7b00a34 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/Attic/hammer_spike.c,v 1.2 2007/12/29 09:01:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/Attic/hammer_spike.c,v 1.3 2007/12/30 08:49:20 dillon Exp $
  */
 
 #include "hammer.h"
@@ -155,6 +155,7 @@ hammer_spike(struct hammer_cursor **spikep)
                hammer_node_ondisk_t ondisk;
                hammer_btree_elm_t elm;
                
+               hammer_modify_node(spike->parent);
                ondisk = spike->parent->ondisk;
                elm = &ondisk->elms[spike->parent_index];
                elm->internal.subtree_type = HAMMER_BTREE_TYPE_CLUSTER;
@@ -162,18 +163,19 @@ hammer_spike(struct hammer_cursor **spikep)
                elm->internal.subtree_clu_no = ncluster->clu_no;
                elm->internal.subtree_vol_no = ncluster->volume->vol_no;
                elm->internal.subtree_count = onode->ondisk->count; /*XXX*/
-               hammer_modify_node(spike->parent);
+               hammer_modify_node_done(spike->parent);
                hammer_flush_node(onode);
        }
        {
                hammer_cluster_ondisk_t ondisk;
 
+               hammer_modify_cluster(ncluster);
                ondisk = ncluster->ondisk;
                ondisk->clu_btree_parent_vol_no = ocluster->volume->vol_no;
                ondisk->clu_btree_parent_clu_no = ocluster->clu_no;
                ondisk->clu_btree_parent_offset = spike->parent->node_offset;
                ondisk->clu_btree_parent_clu_gen = ocluster->ondisk->clu_gen;
-               hammer_modify_cluster(ncluster);
+               hammer_modify_cluster_done(ncluster);
        }
 
        /*
index 54029ac..167d78e 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_subs.c,v 1.7 2007/11/27 07:48:52 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_subs.c,v 1.8 2007/12/30 08:49:20 dillon Exp $
  */
 /*
  * HAMMER structural locking
@@ -56,6 +56,7 @@ hammer_lock_ex(struct hammer_lock *lock)
                }
                lock->locktd = td;
        }
+       KKASSERT(lock->lockcount >= 0);
        ++lock->lockcount;
        crit_exit();
 }
@@ -75,12 +76,12 @@ hammer_lock_ex_try(struct hammer_lock *lock)
                        return(EAGAIN);
                lock->locktd = td;
        }
+       KKASSERT(lock->lockcount >= 0);
        ++lock->lockcount;
        crit_exit();
        return(0);
 }
 
-
 void
 hammer_lock_sh(struct hammer_lock *lock)
 {
@@ -142,6 +143,7 @@ hammer_unlock(struct hammer_lock *lock)
 void
 hammer_ref(struct hammer_lock *lock)
 {
+       KKASSERT(lock->refs >= 0);
        crit_enter();
        ++lock->refs;
        crit_exit();
@@ -150,8 +152,8 @@ hammer_ref(struct hammer_lock *lock)
 void
 hammer_unref(struct hammer_lock *lock)
 {
-       crit_enter();
        KKASSERT(lock->refs > 0);
+       crit_enter();
        --lock->refs;
        crit_exit();
 }
index 7d004ab..5c09372 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_transaction.c,v 1.4 2007/12/29 09:01:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_transaction.c,v 1.5 2007/12/30 08:49:20 dillon Exp $
  */
 
 #include "hammer.h"
@@ -69,13 +69,14 @@ hammer_alloc_tid(hammer_transaction_t trans)
 
        getnanotime(&ts);
        tid = ts.tv_sec * 1000000000LL + ts.tv_nsec;
+       hammer_modify_volume(trans->rootvol);
        ondisk = trans->rootvol->ondisk;
        if (tid < ondisk->vol0_nexttid)
                tid = ondisk->vol0_nexttid;
        if (tid == 0xFFFFFFFFFFFFFFFFULL)
                panic("hammer_start_transaction: Ran out of TIDs!");
        ondisk->vol0_nexttid = tid + 1;
-       hammer_modify_volume(trans->rootvol);
+       hammer_modify_volume_done(trans->rootvol);
 
        return(tid);
 }
@@ -86,8 +87,9 @@ hammer_alloc_recid(hammer_transaction_t trans)
        hammer_volume_ondisk_t ondisk;
        hammer_tid_t recid;
 
+       hammer_modify_volume(trans->rootvol);
        ondisk = trans->rootvol->ondisk;
        recid = ++ondisk->vol0_recid;
-       hammer_modify_volume(trans->rootvol);
+       hammer_modify_volume_done(trans->rootvol);
        return(recid);
 }
index 3eee9cd..0341f86 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.11 2007/12/30 00:47:22 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.12 2007/12/30 08:49:20 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -428,6 +428,8 @@ hammer_vop_ncreate(struct vop_ncreate_args *ap)
         */
 
        error = hammer_create_inode(&trans, ap->a_vap, ap->a_cred, dip, &nip);
+       if (error)
+               kprintf("hammer_create_inode error %d\n", error);
        if (error) {
                hammer_abort_transaction(&trans);
                *ap->a_vpp = NULL;
@@ -439,6 +441,8 @@ hammer_vop_ncreate(struct vop_ncreate_args *ap)
         * bump the inode's link count.
         */
        error = hammer_ip_add_directory(&trans, dip, nch->ncp, nip);
+       if (error)
+               kprintf("hammer_ip_add_directory error %d\n", error);
 
        /*
         * Finish up.
@@ -591,6 +595,7 @@ hammer_vop_nresolve(struct vop_nresolve_args *ap)
         * records for the purposes of the search.
         */
        error = hammer_ip_first(&cursor, dip);
+       rec = NULL;
        while (error == 0) {
                error = hammer_ip_resolve_data(&cursor);
                if (error)
@@ -719,6 +724,8 @@ hammer_vop_nmkdir(struct vop_nmkdir_args *ap)
         * returned inode will be referenced but not locked.
         */
        error = hammer_create_inode(&trans, ap->a_vap, ap->a_cred, dip, &nip);
+       if (error)
+               kprintf("hammer_mkdir error %d\n", error);
        if (error) {
                hammer_abort_transaction(&trans);
                *ap->a_vpp = NULL;
@@ -730,6 +737,8 @@ hammer_vop_nmkdir(struct vop_nmkdir_args *ap)
         * bump the inode's link count.
         */
        error = hammer_ip_add_directory(&trans, dip, nch->ncp, nip);
+       if (error)
+               kprintf("hammer_mkdir (add) error %d\n", error);
 
        /*
         * Finish up.