HAMMER 60E/Many: Mirroring, bug fixes
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 7 Jul 2008 00:24:31 +0000 (00:24 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 7 Jul 2008 00:24:31 +0000 (00:24 +0000)
* Work on the mirror_tid propagation code.  The code now retries on
  EDEADLK so propagation is guaranteed to reach the root.

* Get most of the mirror_write code working.

* Add PFS support for NFS exports.  Change fid_reserved to fid_ext and use
  it to store the localization parameter that selects the PFS.  This isn't
  well tested yet.

* BUGFIX: Fix a bug in vol0_last_tid updates.  Flush sequences might
  not always update the field, creating issues with mirroring and snapshots.

* BUGFIX: Properly update the volume header CRC.

* CLEANUP: Fix some obj_id's that were u_int64_t's. They should be int64_t's.

* CLEANUP: #if 0 out unused code, remove other bits of unused code.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_cursor.c
sys/vfs/hammer/hammer_cursor.h
sys/vfs/hammer/hammer_disk.h
sys/vfs/hammer/hammer_flusher.c
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_ioctl.h
sys/vfs/hammer/hammer_mirror.c
sys/vfs/hammer/hammer_vfsops.c
sys/vfs/hammer/hammer_vnops.c

index f38936e..ed5f47f 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.103 2008/07/05 18:59:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.104 2008/07/07 00:24:31 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -248,7 +248,7 @@ struct hammer_inode {
        int                     flush_group;
        TAILQ_ENTRY(hammer_inode) flush_entry;
        struct hammer_record_list target_list;  /* target of dependant recs */
-       u_int64_t               obj_id;         /* (key) object identifier */
+       int64_t                 obj_id;         /* (key) object identifier */
        hammer_tid_t            obj_asof;       /* (key) snapshot or 0 */
        u_int32_t               obj_localization; /* (key) pseudo-fs */
        struct hammer_mount     *hmp;
@@ -778,7 +778,7 @@ int hammer_vop_inactive(struct vop_inactive_args *);
 int    hammer_vop_reclaim(struct vop_reclaim_args *);
 int    hammer_get_vnode(struct hammer_inode *ip, struct vnode **vpp);
 struct hammer_inode *hammer_get_inode(hammer_transaction_t trans,
-                       hammer_inode_t dip, u_int64_t obj_id,
+                       hammer_inode_t dip, int64_t obj_id,
                        hammer_tid_t asof, u_int32_t localization,
                        int flags, int *errorp);
 void   hammer_scan_inode_snapshots(hammer_mount_t hmp,
@@ -862,6 +862,9 @@ int hammer_init_cursor(hammer_transaction_t trans, hammer_cursor_t cursor,
 void   hammer_normalize_cursor(hammer_cursor_t cursor);
 void   hammer_done_cursor(hammer_cursor_t cursor);
 int    hammer_recover_cursor(hammer_cursor_t cursor);
+void   hammer_unlock_cursor(hammer_cursor_t cursor);
+int    hammer_lock_cursor(hammer_cursor_t cursor);
+void   hammer_dup_cursor(hammer_cursor_t ocursor, hammer_cursor_t ncursor);
 
 void   hammer_cursor_replaced_node(hammer_node_t onode, hammer_node_t nnode);
 void   hammer_cursor_removed_node(hammer_node_t onode, hammer_node_t parent,
index 06896c2..25ee834 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.63 2008/07/05 18:59:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.64 2008/07/07 00:24:31 dillon Exp $
  */
 
 /*
@@ -87,8 +87,8 @@ static int btree_split_internal(hammer_cursor_t cursor);
 static int btree_split_leaf(hammer_cursor_t cursor);
 static int btree_remove(hammer_cursor_t cursor);
 static int btree_node_is_full(hammer_node_ondisk_t node);
-static int hammer_btree_mirror_propagate(hammer_transaction_t trans,
-                       hammer_node_t node, int index, hammer_tid_t mirror_tid);
+static int hammer_btree_mirror_propagate(hammer_cursor_t cursor,       
+                       hammer_tid_t mirror_tid);
 static void hammer_make_separator(hammer_base_elm_t key1,
                        hammer_base_elm_t key2, hammer_base_elm_t dest);
 
@@ -1777,6 +1777,8 @@ done:
        return (error);
 }
 
+#if 0
+
 /*
  * Recursively correct the right-hand boundary's create_tid to (tid) as
  * long as the rest of the key matches.  We have to recurse upward in
@@ -1997,6 +1999,8 @@ hammer_btree_correct_lhb(hammer_cursor_t cursor, hammer_tid_t tid)
        return (error);
 }
 
+#endif
+
 /*
  * Attempt to remove the locked, empty or want-to-be-empty B-Tree node at
  * (cursor->node).  Returns 0 on success, EDEADLK if we could not complete
@@ -2121,6 +2125,8 @@ hammer_btree_do_propagation(hammer_cursor_t cursor, hammer_inode_t ip,
                            hammer_btree_leaf_elm_t leaf)
 {
        hammer_pseudofs_inmem_t pfsm;
+       hammer_cursor_t ncursor;
+       hammer_tid_t mirror_tid;
        int error;
 
        /*
@@ -2134,10 +2140,28 @@ hammer_btree_do_propagation(hammer_cursor_t cursor, hammer_inode_t ip,
                return;
        }
 
-       error = hammer_btree_mirror_propagate(cursor->trans,
-                                       cursor->parent, cursor->parent_index,
-                                       cursor->node->ondisk->mirror_tid);
-       /* XXX */
+       /*
+        * This is a bit of a hack because we cannot deadlock or return
+        * EDEADLK here.  The related operation has already completed and
+        * we must propagate the mirror_tid now regardless.
+        *
+        * Generate a new cursor which inherits the original's locks and
+        * unlock the original.  Use the new cursor to propagate the
+        * mirror_tid.  Then clean up the new cursor and reacquire locks
+        * on the original.
+        *
+        * hammer_dup_cursor() cannot dup locks.  The dup inherits the
+        * original's locks and the original is tracked and must be
+        * re-locked.
+        */
+       mirror_tid = cursor->node->ondisk->mirror_tid;
+       ncursor = kmalloc(sizeof(*ncursor), M_HAMMER, M_WAITOK | M_ZERO);
+       hammer_dup_cursor(cursor, ncursor);
+       error = hammer_btree_mirror_propagate(ncursor, mirror_tid);
+       KKASSERT(error == 0);
+       hammer_done_cursor(ncursor);
+       kfree(ncursor, M_HAMMER);
+       hammer_lock_cursor(cursor);     /* shared-lock */
 }
 
 
@@ -2151,47 +2175,47 @@ hammer_btree_do_propagation(hammer_cursor_t cursor, hammer_inode_t ip,
  * adjusts the node's aggregation mirror_tid, and then recurses upwards.
  */
 static int
-hammer_btree_mirror_propagate(hammer_transaction_t trans, hammer_node_t node,
-                             int index, hammer_tid_t mirror_tid)
+hammer_btree_mirror_propagate(hammer_cursor_t cursor, hammer_tid_t mirror_tid)
 {
        hammer_btree_internal_elm_t elm;
-       hammer_node_t parent;
-       int parent_index;
+       hammer_node_t node;
        int error;
 
-       KKASSERT (node->ondisk->type == HAMMER_BTREE_TYPE_INTERNAL);
-
-       /*
-        * Adjust the node's element
-        */
-       elm = &node->ondisk->elms[index].internal;
-       if (elm->mirror_tid >= mirror_tid)
-               return(0);
-       hammer_modify_node(trans, node, &elm->mirror_tid,
-                          sizeof(elm->mirror_tid));
-       elm->mirror_tid = mirror_tid;
-       hammer_modify_node_done(node);
+       for (;;) {
+               error = hammer_cursor_up(cursor);
+               if (error == 0)
+                       error = hammer_cursor_upgrade(cursor);
+               while (error == EDEADLK) {
+                       hammer_recover_cursor(cursor);
+                       error = hammer_cursor_upgrade(cursor);
+               }
+               if (error)
+                       break;
+               node = cursor->node;
+               KKASSERT (node->ondisk->type == HAMMER_BTREE_TYPE_INTERNAL);
 
-       /*
-        * Adjust the node's mirror_tid aggregator
-        */
-       if (node->ondisk->mirror_tid >= mirror_tid)
-               return(0);
-       hammer_modify_node_field(trans, node, mirror_tid);
-       node->ondisk->mirror_tid = mirror_tid;
-       hammer_modify_node_done(node);
+               /*
+                * Adjust the node's element
+                */
+               elm = &node->ondisk->elms[cursor->index].internal;
+               if (elm->mirror_tid >= mirror_tid)
+                       break;
+               hammer_modify_node(cursor->trans, node, &elm->mirror_tid,
+                                  sizeof(elm->mirror_tid));
+               elm->mirror_tid = mirror_tid;
+               hammer_modify_node_done(node);
 
-       error = 0;
-       if (node->ondisk->parent) {
-               parent = hammer_btree_get_parent(node, &parent_index,
-                                                &error, 1);
-               if (parent) {
-                       hammer_btree_mirror_propagate(trans, parent,
-                                                     parent_index, mirror_tid);
-                       hammer_unlock(&parent->lock);
-                       hammer_rel_node(parent);
-               }
+               /*
+                * Adjust the node's mirror_tid aggregator
+                */
+               if (node->ondisk->mirror_tid >= mirror_tid)
+                       return(0);
+               hammer_modify_node_field(cursor->trans, node, mirror_tid);
+               node->ondisk->mirror_tid = mirror_tid;
+               hammer_modify_node_done(node);
        }
+       if (error == ENOENT)
+               error = 0;
        return(error);
 }
 
index b7f795d..32e328e 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.37 2008/07/05 18:59:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.38 2008/07/07 00:24:31 dillon Exp $
  */
 
 /*
@@ -153,6 +153,7 @@ hammer_done_cursor(hammer_cursor_t cursor)
 {
        hammer_inode_t ip;
 
+       KKASSERT((cursor->flags & HAMMER_CURSOR_TRACKED) == 0);
        if (cursor->parent) {
                hammer_unlock(&cursor->parent->lock);
                hammer_rel_node(cursor->parent);
@@ -167,10 +168,6 @@ hammer_done_cursor(hammer_cursor_t cursor)
                 hammer_rel_buffer(cursor->data_buffer, 0);
                 cursor->data_buffer = NULL;
         }
-        if (cursor->record_buffer) {
-                hammer_rel_buffer(cursor->record_buffer, 0);
-                cursor->record_buffer = NULL;
-        }
        if ((ip = cursor->ip) != NULL) {
                if (cursor->iprec) {
                        hammer_rel_mem_record(cursor->iprec);
@@ -489,22 +486,13 @@ hammer_cursor_down(hammer_cursor_t cursor)
  * ultimately the intention is to use them for all deadlock recovery
  * operations.
  */
-
-/*
- * Recover from a deadlocked cursor, tracking any node removals or
- * replacements.  If the cursor's current node is removed by another
- * thread (via btree_remove()) the cursor will be seeked upwards.
- */
-int
-hammer_recover_cursor(hammer_cursor_t cursor)
+void
+hammer_unlock_cursor(hammer_cursor_t cursor)
 {
-       hammer_inode_t ip;
        hammer_node_t node;
-       int status;
-       int error;
+       hammer_inode_t ip;
 
-again:
-       KKASSERT((cursor->flags & HAMMER_CURSOR_DEADLK_RECOVER) == 0);
+       KKASSERT((cursor->flags & HAMMER_CURSOR_TRACKED) == 0);
        KKASSERT(cursor->node);
        /*
         * Release the cursor's locks and track B-Tree operations on node.
@@ -517,13 +505,81 @@ again:
                cursor->parent = NULL;
        }
        node = cursor->node;
-       cursor->flags |= HAMMER_CURSOR_DEADLK_RECOVER;
+       cursor->flags |= HAMMER_CURSOR_TRACKED;
        TAILQ_INSERT_TAIL(&node->cursor_list, cursor, deadlk_entry);
-       status = hammer_lock_status(&node->lock);
        hammer_unlock(&node->lock);
 
        if ((ip = cursor->ip) != NULL)
                hammer_unlock(&ip->lock);
+}
+
+/*
+ * Get the cursor heated up again.  The cursor's node may have
+ * changed and we might have to locate the new parent.
+ *
+ * If the exact element we were on got deleted RIPOUT will be
+ * set and we must clear ATEDISK so an iteration does not skip
+ * the element after it.
+ */
+int
+hammer_lock_cursor(hammer_cursor_t cursor)
+{
+       hammer_inode_t ip;
+       hammer_node_t node;
+       int error;
+
+       KKASSERT(cursor->flags & HAMMER_CURSOR_TRACKED);
+
+       /*
+        * Relock the inode
+        */
+       if ((ip = cursor->ip) != NULL) {
+               if (cursor->trans->type == HAMMER_TRANS_FLS)
+                       hammer_lock_ex(&ip->lock);
+               else
+                       hammer_lock_sh(&ip->lock);
+       }
+
+       /*
+        * Relock the node
+        */
+       for (;;) {
+               node = cursor->node;
+               hammer_ref_node(node);
+               hammer_lock_sh(&node->lock);
+               if (cursor->node == node) {
+                       hammer_rel_node(node);
+                       break;
+               }
+               hammer_unlock(&node->lock);
+               hammer_rel_node(node);
+       }
+
+       /*
+        * Untrack the cursor, clean up, and re-establish the parent node.
+        */
+       TAILQ_REMOVE(&node->cursor_list, cursor, deadlk_entry);
+       cursor->flags &= ~HAMMER_CURSOR_TRACKED;
+
+       if (cursor->flags & HAMMER_CURSOR_TRACKED_RIPOUT) {
+               cursor->flags &= ~HAMMER_CURSOR_TRACKED_RIPOUT;
+               cursor->flags &= ~HAMMER_CURSOR_ATEDISK;
+       }
+       error = hammer_load_cursor_parent(cursor, 0);
+       return(error);
+}
+
+/*
+ * Recover from a deadlocked cursor, tracking any node removals or
+ * replacements.  If the cursor's current node is removed by another
+ * thread (via btree_remove()) the cursor will be seeked upwards.
+ */
+int
+hammer_recover_cursor(hammer_cursor_t cursor)
+{
+       int error;
+
+       hammer_unlock_cursor(cursor);
 
        /*
         * Wait for the deadlock to clear
@@ -540,34 +596,44 @@ again:
                cursor->deadlk_rec = NULL;
        }
 
-       /*
-        * Get the cursor heated up again.  The cursor's node may have
-        * changed and we might have to locate the new parent.
-        *
-        * If the exact element we were on got deleted RIPOUT will be
-        * set and we must clear ATEDISK so an iteration does not skip
-        * the element after it.
-        */
-       KKASSERT(cursor->flags & HAMMER_CURSOR_DEADLK_RECOVER);
-       node = cursor->node;
-       TAILQ_REMOVE(&node->cursor_list, cursor, deadlk_entry);
-       cursor->flags &= ~HAMMER_CURSOR_DEADLK_RECOVER;
-       if (cursor->flags & HAMMER_CURSOR_DEADLK_RIPOUT) {
-               cursor->flags &= ~HAMMER_CURSOR_DEADLK_RIPOUT;
-               cursor->flags &= ~HAMMER_CURSOR_ATEDISK;
+       error = hammer_lock_cursor(cursor);
+       return(error);
+}
+
+/*
+ * Dup ocursor to ncursor.  ncursor inherits ocursor's locks and ocursor
+ * is effectively unlocked and becomes tracked.  If ocursor was not locked
+ * then ncursor also inherits the tracking.
+ *
+ * After the caller finishes working with ncursor it must be cleaned up
+ * with hammer_done_cursor(), and the caller must re-lock ocursor.
+ */
+void
+hammer_dup_cursor(hammer_cursor_t ocursor, hammer_cursor_t ncursor)
+{
+       hammer_inode_t ip;
+       hammer_node_t node;
+
+       bcopy(ocursor, ncursor, sizeof(*ocursor));
+
+       node = ocursor->node;
+       hammer_ref_node(node);
+       if ((ocursor->flags & HAMMER_CURSOR_TRACKED) == 0) {
+               ocursor->flags |= HAMMER_CURSOR_TRACKED;
+               TAILQ_INSERT_TAIL(&node->cursor_list, ocursor, deadlk_entry);
        }
-       hammer_lock_sh(&node->lock);
-       error = hammer_load_cursor_parent(cursor, 0);
-       if (error == 0) {
-               if (status > 0) {
-                       error = hammer_cursor_upgrade(cursor);
-                       if (error == EDEADLK) {
-                               kprintf("r");
-                               goto again;
-                       }
-               }
+       if (ncursor->parent)
+               ocursor->parent = NULL;
+       ocursor->data_buffer = NULL;
+       ocursor->leaf = NULL;
+       ocursor->data = NULL;
+       if (ncursor->flags & HAMMER_CURSOR_TRACKED)
+               TAILQ_INSERT_TAIL(&node->cursor_list, ncursor, deadlk_entry);
+       if ((ip = ncursor->ip) != NULL) {
+                ++ip->cursor_ip_refs;
        }
-       return(error);
+       if (ncursor->iprec)
+               hammer_ref(&ncursor->iprec->lock);
 }
 
 /*
@@ -603,7 +669,7 @@ hammer_cursor_removed_node(hammer_node_t node, hammer_node_t parent, int index)
                KKASSERT(cursor->index == 0);
                TAILQ_REMOVE(&node->cursor_list, cursor, deadlk_entry);
                TAILQ_INSERT_TAIL(&parent->cursor_list, cursor, deadlk_entry);
-               cursor->flags |= HAMMER_CURSOR_DEADLK_RIPOUT;
+               cursor->flags |= HAMMER_CURSOR_TRACKED_RIPOUT;
                cursor->node = parent;
                cursor->index = index;
                hammer_ref_node(parent);
@@ -647,7 +713,7 @@ hammer_cursor_deleted_element(hammer_node_t node, int index)
        TAILQ_FOREACH(cursor, &node->cursor_list, deadlk_entry) {
                KKASSERT(cursor->node == node);
                if (cursor->index == index) {
-                       cursor->flags |= HAMMER_CURSOR_DEADLK_RIPOUT;
+                       cursor->flags |= HAMMER_CURSOR_TRACKED_RIPOUT;
                } else if (cursor->index > index) {
                        --cursor->index;
                }
index e7b815a..c96c1ee 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.h,v 1.23 2008/07/05 18:59:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_cursor.h,v 1.24 2008/07/07 00:24:31 dillon Exp $
  */
 
 /*
@@ -97,7 +97,6 @@ struct hammer_cursor {
         * can be NULL when data and/or record is not, typically indicating
         * information referenced via an in-memory record.
         */
-       struct hammer_buffer *record_buffer;    /* record (+ built-in data) */
        struct hammer_buffer *data_buffer;      /* extended data */
        struct hammer_btree_leaf_elm *leaf;
        union hammer_data_ondisk *data;
@@ -135,8 +134,8 @@ typedef struct hammer_cursor *hammer_cursor_t;
 
 #define HAMMER_CURSOR_PRUNING          0x00010000
 #define HAMMER_CURSOR_REBLOCKING       0x00020000
-#define HAMMER_CURSOR_DEADLK_RECOVER   0x00040000
-#define HAMMER_CURSOR_DEADLK_RIPOUT    0x00080000
+#define HAMMER_CURSOR_TRACKED          0x00040000
+#define HAMMER_CURSOR_TRACKED_RIPOUT   0x00080000
 
 /*
  * Flags we can clear when reusing a cursor (we can clear all of them)
index 86dd1a1..fc1696a 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_disk.h,v 1.45 2008/07/05 18:59:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_disk.h,v 1.46 2008/07/07 00:24:31 dillon Exp $
  */
 
 #ifndef VFS_HAMMER_DISK_H_
@@ -583,7 +583,7 @@ struct hammer_inode_data {
        u_int32_t rmajor;       /* used by device nodes */
        u_int32_t rminor;       /* used by device nodes */
        u_int64_t ctime;
-       u_int64_t parent_obj_id;/* parent directory obj_id */
+       int64_t parent_obj_id;  /* parent directory obj_id */
        uuid_t    uid;
        uuid_t    gid;
 
@@ -637,7 +637,7 @@ struct hammer_inode_data {
  * NOTE: den_name / the filename data reference is NOT terminated with \0.
  */
 struct hammer_entry_data {
-       u_int64_t obj_id;               /* object being referenced */
+       int64_t obj_id;                 /* object being referenced */
        u_int32_t localization;         /* identify pseudo-filesystem */
        u_int32_t reserved02;
        char    name[16];               /* name (extended) */
index 5df004c..653d539 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_flusher.c,v 1.32 2008/06/30 02:45:30 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_flusher.c,v 1.33 2008/07/07 00:24:31 dillon Exp $
  */
 /*
  * HAMMER dependancy flusher thread
@@ -520,13 +520,15 @@ hammer_flusher_finalize(hammer_transaction_t trans, int final)
                dundomap->first_offset = cundomap->first_offset;
                dundomap->next_offset = cundomap->next_offset;
                hammer_crc_set_blockmap(dundomap);
-               hammer_crc_set_volume(root_volume->ondisk);
-               if (root_volume->ondisk->vol0_next_tid < trans->tid)
-                       root_volume->ondisk->vol0_next_tid = trans->tid;
                hammer_modify_volume_done(root_volume);
        }
 
        if (root_volume->io.modified) {
+               hammer_modify_volume(NULL, root_volume, NULL, 0);
+               if (root_volume->ondisk->vol0_next_tid < trans->tid)
+                       root_volume->ondisk->vol0_next_tid = trans->tid;
+               hammer_crc_set_volume(root_volume->ondisk);
+               hammer_modify_volume_done(root_volume);
                hammer_io_flush(&root_volume->io);
        }
 
index de0407c..d4b42b8 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.93 2008/07/04 07:25:36 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.94 2008/07/07 00:24:31 dillon Exp $
  */
 
 #include "hammer.h"
@@ -324,7 +324,7 @@ hammer_scan_inode_snapshots(hammer_mount_t hmp, hammer_inode_info_t iinfo,
  */
 struct hammer_inode *
 hammer_get_inode(hammer_transaction_t trans, hammer_inode_t dip,
-                u_int64_t obj_id, hammer_tid_t asof, u_int32_t localization,
+                int64_t obj_id, hammer_tid_t asof, u_int32_t localization,
                 int flags, int *errorp)
 {
        hammer_mount_t hmp = trans->hmp;
index 218f743..3c7ce15 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_ioctl.h,v 1.16 2008/07/02 21:57:54 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ioctl.h,v 1.17 2008/07/07 00:24:31 dillon Exp $
  */
 /*
  * HAMMER ioctl's.  This file can be #included from userland
@@ -250,6 +250,7 @@ typedef struct hammer_ioc_mrecord {
 #define HAMMER_MREC_TYPE_REC           1
 #define HAMMER_MREC_TYPE_PFSD          2
 #define HAMMER_MREC_TYPE_UPDATE                3
+#define HAMMER_MREC_TYPE_SYNC          4
 
 #define HAMMER_MREC_CRCOFF     (offsetof(struct hammer_ioc_mrecord, rec_size))
 #define HAMMER_MREC_HEADSIZE   sizeof(struct hammer_ioc_mrecord)
index ea112e3..a9dbe9e 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_mirror.c,v 1.6 2008/07/04 07:25:36 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_mirror.c,v 1.7 2008/07/07 00:24:31 dillon Exp $
  */
 /*
  * HAMMER mirroring ioctls - serialize and deserialize modifications made
@@ -287,19 +287,24 @@ retry:
                        error = hammer_mirror_write(&cursor, &mrec, ip,
                                                    uptr + head_size);
                        hammer_sync_unlock(trans);
+               } else if (error == ENOENT) {
+                       error = 0;
                }
 
                /*
-                * Setup for loop
+                * Clean for loop.  It is ok if the record already exists
+                * on the target.
                 */
                if (error == EDEADLK) {
                        hammer_done_cursor(&cursor);
                        error = hammer_init_cursor(trans, &cursor, NULL, NULL);
                        goto retry;
                }
-               if (error == 0) {
+
+               if (error == EALREADY)
+                       error = 0;
+               if (error == 0)
                        mirror->count += mrec.rec_size;
-               }
        }
        hammer_done_cursor(&cursor);
        return(0);
@@ -332,9 +337,11 @@ static
 int
 hammer_mirror_update(hammer_cursor_t cursor, struct hammer_ioc_mrecord *mrec)
 {
+       hammer_transaction_t trans;
        hammer_btree_leaf_elm_t elm;
 
        elm = cursor->leaf;
+       trans = cursor->trans;
 
        if (mrec->leaf.base.delete_tid == 0) {
                kprintf("mirror_write: object %016llx:%016llx deleted on "
@@ -344,38 +351,65 @@ hammer_mirror_update(hammer_cursor_t cursor, struct hammer_ioc_mrecord *mrec)
        }
 
        KKASSERT(elm->base.create_tid < mrec->leaf.base.delete_tid);
-       hammer_modify_node(cursor->trans, cursor->node, elm, sizeof(*elm));
+       hammer_modify_node(trans, cursor->node, elm, sizeof(*elm));
        elm->base.delete_tid = mrec->leaf.base.delete_tid;
        elm->delete_ts = mrec->leaf.delete_ts;
        hammer_modify_node_done(cursor->node);
+
+       /*
+        * Track a count of active inodes.
+        */
+       if (elm->base.obj_type == HAMMER_RECTYPE_INODE) {
+               hammer_modify_volume_field(trans,
+                                          trans->rootvol,
+                                          vol0_stat_inodes);
+               --trans->hmp->rootvol->ondisk->vol0_stat_inodes;
+               hammer_modify_volume_done(trans->rootvol);
+       }
+
        return(0);
 }
 
 /*
  * Write out a new record.
- *
- * XXX this is messy.
  */
 static
 int
 hammer_mirror_write(hammer_cursor_t cursor, struct hammer_ioc_mrecord *mrec,
                    hammer_inode_t ip, char *udata)
 {
-       hammer_buffer_t data_buffer = NULL;
+       hammer_transaction_t trans;
+       hammer_buffer_t data_buffer;
        hammer_off_t ndata_offset;
        void *ndata;
        int error;
        int doprop;
-       int wanted_skip = 0;
 
+       /*
+        * Skip records related to the root inode other then
+        * directory entries.
+        */
+       if (mrec->leaf.base.obj_id == HAMMER_OBJID_ROOT) {
+               if (mrec->leaf.base.rec_type == HAMMER_RECTYPE_INODE ||
+                   mrec->leaf.base.rec_type == HAMMER_RECTYPE_FIX) {
+                       return(0);
+               }
+       }
+
+       trans = cursor->trans;
+       data_buffer = NULL;
+
+       /*
+        * Allocate and adjust data
+        */
        if (mrec->leaf.data_len && mrec->leaf.data_offset) {
-               ndata = hammer_alloc_data(cursor->trans, mrec->leaf.data_len,
+               ndata = hammer_alloc_data(trans, mrec->leaf.data_len,
                                          mrec->leaf.base.rec_type,
                                          &ndata_offset, &data_buffer, &error);
                if (ndata == NULL)
                        return(error);
                mrec->leaf.data_offset = ndata_offset;
-               hammer_modify_buffer(cursor->trans, data_buffer, NULL, 0);
+               hammer_modify_buffer(trans, data_buffer, NULL, 0);
                error = copyin(udata, ndata, mrec->leaf.data_len);
                if (error == 0) {
                        if (hammer_crc_test_leaf(ndata, &mrec->leaf) == 0) {
@@ -384,8 +418,6 @@ hammer_mirror_write(hammer_cursor_t cursor, struct hammer_ioc_mrecord *mrec,
                        } else {
                                error = hammer_mirror_localize_data(
                                                        ndata, &mrec->leaf);
-                               if (error)
-                                       wanted_skip = 1;
                        }
                }
                hammer_modify_buffer_done(data_buffer);
@@ -396,6 +428,10 @@ hammer_mirror_write(hammer_cursor_t cursor, struct hammer_ioc_mrecord *mrec,
        }
        if (error)
                goto failed;
+
+       /*
+        * Do the insertion
+        */
        cursor->flags |= HAMMER_CURSOR_INSERT;
        error = hammer_btree_lookup(cursor);
        if (error != ENOENT) {
@@ -405,10 +441,19 @@ hammer_mirror_write(hammer_cursor_t cursor, struct hammer_ioc_mrecord *mrec,
        }
        error = 0;
 
+       error = hammer_btree_insert(cursor, &mrec->leaf, &doprop);
+
        /*
-        * Physical insertion
+        * Track a count of active inodes.
         */
-       error = hammer_btree_insert(cursor, &mrec->leaf, &doprop);
+       if (error == 0 && mrec->leaf.base.delete_tid == 0 &&
+           mrec->leaf.base.obj_type == HAMMER_RECTYPE_INODE) {
+               hammer_modify_volume_field(trans,
+                                          trans->rootvol,
+                                          vol0_stat_inodes);
+               ++trans->hmp->rootvol->ondisk->vol0_stat_inodes;
+               hammer_modify_volume_done(trans->rootvol);
+       }
        if (error == 0 && doprop)
                hammer_btree_do_propagation(cursor, ip, &mrec->leaf);
 
@@ -423,8 +468,6 @@ failed:
        }
        if (data_buffer)
                hammer_rel_buffer(data_buffer, 0);
-       if (wanted_skip)
-               error = 0;
        return(error);
 }
 
@@ -432,43 +475,26 @@ failed:
  * Localize the data payload.  Directory entries may need their
  * localization adjusted.
  *
- * Pseudo-fs directory entries must be skipped entirely (EBADF).
- *
- * The root inode must be skipped, it will exist on the target with a
- * different create_tid so updating it would result in a duplicate.  This
- * also prevents inode updates on the root directory (aka mtime, ctime, etc)
- * from mirroring, which is ok.
- *
- * XXX Root directory inode updates - parent_obj_localization is broken.
+ * PFS directory entries must be skipped entirely (return EALREADY).
  */
 static
 int
 hammer_mirror_localize_data(hammer_data_ondisk_t data,
                            hammer_btree_leaf_elm_t leaf)
 {
-       int modified = 0;
-       int error = 0;
        u_int32_t localization;
 
        if (leaf->base.rec_type == HAMMER_RECTYPE_DIRENTRY) {
+               if (data->entry.obj_id == HAMMER_OBJID_ROOT)
+                       return(EALREADY);
                localization = leaf->base.localization &
                               HAMMER_LOCALIZE_PSEUDOFS_MASK;
                if (data->entry.localization != localization) {
                        data->entry.localization = localization;
-                       modified = 1;
+                       hammer_crc_set_leaf(data, leaf);
                }
-               if (data->entry.obj_id == 1)
-                       error = EBADF;
        }
-       if (leaf->base.obj_id == HAMMER_OBJID_ROOT) {
-               if (leaf->base.rec_type == HAMMER_RECTYPE_INODE ||
-                   leaf->base.rec_type == HAMMER_RECTYPE_FIX) {
-                       error = EBADF;
-               }
-       }
-       if (modified)
-               hammer_crc_set_leaf(data, leaf);
-       return(error);
+       return(0);
 }
 
 /*
index a31384f..1a3a504 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_vfsops.c,v 1.59 2008/07/03 04:24:51 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.60 2008/07/07 00:24:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -449,7 +449,9 @@ hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data,
        }
 
        /*
-        * Finish setup now that we have a good root volume
+        * Finish setup now that we have a good root volume.
+        *
+        * The top 16 bits of fsid.val[1] is a pfs id.
         */
        ksnprintf(mp->mnt_stat.f_mntfromname,
                  sizeof(mp->mnt_stat.f_mntfromname), "%s",
@@ -458,6 +460,7 @@ hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data,
                crc32((char *)&rootvol->ondisk->vol_fsid + 0, 8);
        mp->mnt_stat.f_fsid.val[1] =
                crc32((char *)&rootvol->ondisk->vol_fsid + 8, 8);
+       mp->mnt_stat.f_fsid.val[1] &= 0x0000FFFF;
 
        mp->mnt_vstat.f_fsid_uuid = rootvol->ondisk->vol_fsid;
        mp->mnt_vstat.f_fsid = crc32(&mp->mnt_vstat.f_fsid_uuid,
@@ -727,7 +730,7 @@ hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp)
        KKASSERT(MAXFIDSZ >= 16);
        ip = VTOI(vp);
        fhp->fid_len = offsetof(struct fid, fid_data[16]);
-       fhp->fid_reserved = 0;
+       fhp->fid_ext = ip->obj_localization >> 16;
        bcopy(&ip->obj_id, fhp->fid_data + 0, sizeof(ip->obj_id));
        bcopy(&ip->obj_asof, fhp->fid_data + 8, sizeof(ip->obj_asof));
        return(0);
@@ -744,9 +747,11 @@ hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
        struct hammer_inode *ip;
        struct hammer_inode_info info;
        int error;
+       u_int32_t localization;
 
        bcopy(fhp->fid_data + 0, &info.obj_id, sizeof(info.obj_id));
        bcopy(fhp->fid_data + 8, &info.obj_asof, sizeof(info.obj_asof));
+       localization = (u_int32_t)fhp->fid_ext << 16;
 
        hammer_simple_transaction(&trans, (void *)mp->mnt_data);
 
@@ -755,9 +760,9 @@ hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
         * unlocked while we manipulate the related vnode to avoid a
         * deadlock.
         */
+       kprintf("localization %08x\n", localization);
        ip = hammer_get_inode(&trans, NULL, info.obj_id,
-                             info.obj_asof, HAMMER_DEF_LOCALIZATION,
-                             0, &error);
+                             info.obj_asof, localization, 0, &error);
        if (ip == NULL) {
                *vpp = NULL;
                return(error);
index a02015b..00183a5 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.80 2008/07/03 04:24:51 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.81 2008/07/07 00:24:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -733,7 +733,7 @@ hammer_vop_nresolve(struct vop_nresolve_args *ap)
        int i;
        int nlen;
        int flags;
-       u_int64_t obj_id;
+       int64_t obj_id;
        u_int32_t localization;
 
        /*