HAMMER 60H/Many: Stabilization pass
authorMatthew Dillon <dillon@dragonflybsd.org>
Tue, 8 Jul 2008 04:34:41 +0000 (04:34 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Tue, 8 Jul 2008 04:34:41 +0000 (04:34 +0000)
* Fix races in the in-memory/B-Tree scanning code introduced by the
  mirror_tid update code.  This fixes two assertion panics.

* Remove compile-time reminder #warning that no longer applies.
  (Sascha will be happy).

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_btree.c
sys/vfs/hammer/hammer_cursor.c
sys/vfs/hammer/hammer_object.c

index 667a0cc..b5c1161 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.106 2008/07/07 22:42:35 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.107 2008/07/08 04:34:41 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -862,9 +862,10 @@ 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_unlock_cursor(hammer_cursor_t cursor, int also_ip);
+int    hammer_lock_cursor(hammer_cursor_t cursor, int also_ip);
+hammer_cursor_t        hammer_push_cursor(hammer_cursor_t ocursor);
+void   hammer_pop_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 3982437..8713a4c 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.66 2008/07/07 22:42:35 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_btree.c,v 1.67 2008/07/08 04:34:41 dillon Exp $
  */
 
 /*
@@ -2163,13 +2163,10 @@ hammer_btree_do_propagation(hammer_cursor_t cursor, hammer_inode_t ip,
         */
        mirror_tid = cursor->node->ondisk->mirror_tid;
        KKASSERT(mirror_tid != 0);
-       ncursor = kmalloc(sizeof(*ncursor), M_HAMMER, M_WAITOK | M_ZERO);
-       hammer_dup_cursor(cursor, ncursor);
+       ncursor = hammer_push_cursor(cursor);
        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 */
+       hammer_pop_cursor(cursor, ncursor);
 }
 
 
index 06faeaa..45d26fc 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.39 2008/07/07 22:42:35 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_cursor.c,v 1.40 2008/07/08 04:34:41 dillon Exp $
  */
 
 /*
@@ -169,15 +169,15 @@ hammer_done_cursor(hammer_cursor_t cursor)
                 cursor->data_buffer = NULL;
         }
        if ((ip = cursor->ip) != NULL) {
-               if (cursor->iprec) {
-                       hammer_rel_mem_record(cursor->iprec);
-                       cursor->iprec = NULL;
-               }
                 KKASSERT(ip->cursor_ip_refs > 0);
                 --ip->cursor_ip_refs;
                hammer_unlock(&ip->lock);
                 cursor->ip = NULL;
         }
+       if (cursor->iprec) {
+               hammer_rel_mem_record(cursor->iprec);
+               cursor->iprec = NULL;
+       }
 
        /*
         * If we deadlocked this node will be referenced.  Do a quick
@@ -487,7 +487,7 @@ hammer_cursor_down(hammer_cursor_t cursor)
  * operations.
  */
 void
-hammer_unlock_cursor(hammer_cursor_t cursor)
+hammer_unlock_cursor(hammer_cursor_t cursor, int also_ip)
 {
        hammer_node_t node;
        hammer_inode_t ip;
@@ -509,7 +509,7 @@ hammer_unlock_cursor(hammer_cursor_t cursor)
        TAILQ_INSERT_TAIL(&node->cursor_list, cursor, deadlk_entry);
        hammer_unlock(&node->lock);
 
-       if ((ip = cursor->ip) != NULL)
+       if (also_ip && (ip = cursor->ip) != NULL)
                hammer_unlock(&ip->lock);
 }
 
@@ -522,7 +522,7 @@ hammer_unlock_cursor(hammer_cursor_t cursor)
  * the element after it.
  */
 int
-hammer_lock_cursor(hammer_cursor_t cursor)
+hammer_lock_cursor(hammer_cursor_t cursor, int also_ip)
 {
        hammer_inode_t ip;
        hammer_node_t node;
@@ -533,7 +533,7 @@ hammer_lock_cursor(hammer_cursor_t cursor)
        /*
         * Relock the inode
         */
-       if ((ip = cursor->ip) != NULL) {
+       if (also_ip && (ip = cursor->ip) != NULL) {
                if (cursor->trans->type == HAMMER_TRANS_FLS)
                        hammer_lock_ex(&ip->lock);
                else
@@ -579,7 +579,7 @@ hammer_recover_cursor(hammer_cursor_t cursor)
 {
        int error;
 
-       hammer_unlock_cursor(cursor);
+       hammer_unlock_cursor(cursor, 0);
 
        /*
         * Wait for the deadlock to clear
@@ -596,7 +596,7 @@ hammer_recover_cursor(hammer_cursor_t cursor)
                cursor->deadlk_rec = NULL;
        }
 
-       error = hammer_lock_cursor(cursor);
+       error = hammer_lock_cursor(cursor, 0);
        return(error);
 }
 
@@ -608,12 +608,14 @@ hammer_recover_cursor(hammer_cursor_t cursor)
  * 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_cursor_t
+hammer_push_cursor(hammer_cursor_t ocursor)
 {
+       hammer_cursor_t ncursor;
        hammer_inode_t ip;
        hammer_node_t node;
 
+       ncursor = kmalloc(sizeof(*ncursor), M_HAMMER, M_WAITOK | M_ZERO);
        bcopy(ocursor, ncursor, sizeof(*ocursor));
 
        node = ocursor->node;
@@ -634,6 +636,29 @@ hammer_dup_cursor(hammer_cursor_t ocursor, hammer_cursor_t ncursor)
        }
        if (ncursor->iprec)
                hammer_ref(&ncursor->iprec->lock);
+       return(ncursor);
+}
+
+/*
+ * Destroy ncursor and restore ocursor
+ *
+ * This is a temporary hack for the release.  We can't afford to lose
+ * the IP lock until the IP object scan code is able to deal with it,
+ * so have ocursor inherit it back.
+ */
+void
+hammer_pop_cursor(hammer_cursor_t ocursor, hammer_cursor_t ncursor)
+{
+       hammer_inode_t ip;
+
+       ip = ncursor->ip;
+       ncursor->ip = NULL;
+       if (ip)
+                --ip->cursor_ip_refs;
+       hammer_done_cursor(ncursor);
+       kfree(ncursor, M_HAMMER);
+       KKASSERT(ocursor->ip == ip);
+       hammer_lock_cursor(ocursor, 0);
 }
 
 /*
index c454e75..ec72df5 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.83 2008/07/07 22:42:35 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.84 2008/07/08 04:34:41 dillon Exp $
  */
 
 #include "hammer.h"
@@ -474,18 +474,11 @@ hammer_rec_scan_callback(hammer_record_t rec, void *data)
         }
 
        /*
-        * If the record is queued to the flusher we have to block until
-        * it isn't.  Otherwise we may see duplication between our memory
-        * cache and the media.
+        * ref the record.  The record is protected from backend B-Tree
+        * interactions by virtue of the cursor's IP lock.
         */
        hammer_ref(&rec->lock);
 
-#warning "This deadlocks"
-#if 0
-       if (rec->flush_state == HAMMER_FST_FLUSH)
-               hammer_wait_mem_record(rec);
-#endif
-
        /*
         * The record may have been deleted while we were blocked.
         */
@@ -1387,9 +1380,7 @@ next_btree:
 
 next_memory:
        /*
-        * Get the next in-memory record.  The record can be ripped out
-        * of the RB tree so we maintain a scan_info structure to track
-        * the next node.
+        * Get the next in-memory record.
         *
         * hammer_rec_scan_cmp:  Is the record still in our general range,
         *                       (non-inclusive of snapshot exclusions)?
@@ -1499,7 +1490,7 @@ next_memory:
                                }
                                /* fall through to memory entry */
                        } else {
-                               panic("hammer_ip_next: duplicate mem/b-tree entry");
+                               panic("hammer_ip_next: duplicate mem/b-tree entry %p %d %08x", cursor->iprec, cursor->iprec->type, cursor->iprec->flags);
                                cursor->flags |= HAMMER_CURSOR_ATEMEM;
                                goto next_memory;
                        }
@@ -1520,7 +1511,7 @@ next_memory:
                 */
                if (cursor->iprec->type == HAMMER_MEM_RECORD_DEL &&
                    (cursor->flags & HAMMER_CURSOR_DELETE_VISIBILITY) == 0) {
-                       panic("hammer_ip_next: del-on-disk with no b-tree entry");
+                       panic("hammer_ip_next: del-on-disk with no b-tree entry iprec %p flags %08x", cursor->iprec, cursor->iprec->flags);
                }
                break;
        case HAMMER_CURSOR_ATEMEM: