hammer2 - flush sequencing part 8 - stabilization pass
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 13 May 2013 03:44:32 +0000 (20:44 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 13 May 2013 03:44:32 +0000 (20:44 -0700)
* On this commit it appears that the cpdup / test is fully validating
  on remount and chain memory leaks are gone.

* Remove a hack when creating a hardlink.  The original directory entry
  is duplicated to create the invisible hardlink target in the common
  parent directory, but the original directory entry is then not deleted.
  Instead I was modifying it (which generally did not cause a delete/duplicate
  sequence) and then changing the inode type to HARDLINK and setting
  the OPFLAG_DIRECTDATA flag.

  The problem with this is that the inode's core RBTREE was left intact,
  but as a DIRECTDATA inode the flusher ignores it.  This prevented the
  flusher from clearing the MOVED but on the children and resulted in the
  memory leak.

  What I do now is delete/duplicate the original inode, give the duplicate
  a fresh core, and then modify the duplicate instead of the original to be
  the special HARDLINK type w/OPFLAG_DIRECTDATA.  This removes the special
  case.

sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_chain.c
sys/vfs/hammer2/hammer2_flush.c
sys/vfs/hammer2/hammer2_inode.c

index 4d65d5d..52e6815 100644 (file)
@@ -212,6 +212,11 @@ RB_PROTOTYPE(hammer2_chain_tree, hammer2_chain, rbnode, hammer2_chain_cmp);
 #define HAMMER2_RESOLVE_NOREF          0x20
 
 /*
+ * Flags passed to hammer2_chain_delete_duplicate()
+ */
+#define HAMMER2_DELDUP_RECORE          0x0001
+
+/*
  * Cluster different types of storage together for allocations
  */
 #define HAMMER2_FREECACHE_INODE                0
@@ -602,7 +607,7 @@ int hammer2_chain_snapshot(hammer2_trans_t *trans, hammer2_inode_t *ip,
                                hammer2_ioc_pfs_t *pfs);
 void hammer2_chain_delete(hammer2_trans_t *trans, hammer2_chain_t *chain);
 void hammer2_chain_delete_duplicate(hammer2_trans_t *trans,
-                               hammer2_chain_t **chainp);
+                               hammer2_chain_t **chainp, int flags);
 void hammer2_chain_flush(hammer2_trans_t *trans, hammer2_chain_t *chain);
 void hammer2_chain_commit(hammer2_trans_t *trans, hammer2_chain_t *chain);
 void hammer2_chain_setsubmod(hammer2_trans_t *trans, hammer2_chain_t *chain);
index 92331a2..1b419f9 100644 (file)
@@ -899,7 +899,7 @@ hammer2_chain_resize(hammer2_trans_t *trans, hammer2_inode_t *ip,
         *       duplication code will simply reuse the existing chain
         *       structure.
         */
-       hammer2_chain_delete_duplicate(trans, &chain);
+       hammer2_chain_delete_duplicate(trans, &chain, 0);
 
        /*
         * Set MODIFIED and add a chain ref to prevent destruction.  Both
@@ -1015,7 +1015,7 @@ hammer2_chain_modify(hammer2_trans_t *trans, hammer2_chain_t **chainp,
                         * requires delete-duplicate.
                         */
                        KKASSERT((flags & HAMMER2_MODIFY_ASSERTNOCOPY) == 0);
-                       hammer2_chain_delete_duplicate(trans, chainp);
+                       hammer2_chain_delete_duplicate(trans, chainp, 0);
                        chain = *chainp;
                        /* fall through using duplicate */
                } else {
@@ -2370,14 +2370,13 @@ hammer2_chain_duplicate(hammer2_trans_t *trans, hammer2_chain_t *parent, int i,
  * order to ensure that lookups do not race us.
  */
 void
-hammer2_chain_delete_duplicate(hammer2_trans_t *trans,
-                              hammer2_chain_t **chainp)
+hammer2_chain_delete_duplicate(hammer2_trans_t *trans, hammer2_chain_t **chainp,
+                              int flags)
 {
        hammer2_mount_t *hmp = trans->hmp;
        hammer2_chain_t *ochain;
        hammer2_chain_t *nchain;
        hammer2_chain_core_t *above;
-       hammer2_chain_core_t *core;
        size_t bytes;
 
        /*
@@ -2388,13 +2387,12 @@ hammer2_chain_delete_duplicate(hammer2_trans_t *trans,
         */
        ochain = *chainp;
        nchain = hammer2_chain_alloc(hmp, trans, &ochain->bref);    /* 1 ref */
-       hammer2_chain_core_alloc(nchain, ochain->core);
-       core = ochain->core;
+       if (flags & HAMMER2_DELDUP_RECORE)
+               hammer2_chain_core_alloc(nchain, NULL);
+       else
+               hammer2_chain_core_alloc(nchain, ochain->core);
        above = ochain->above;
 
-       kprintf("delete_duplicate %p.%d(%d)\n",
-               ochain, ochain->bref.type, ochain->refs);
-
        bytes = (hammer2_off_t)1 <<
                (int)(ochain->bref.data_off & HAMMER2_OFF_MASK_RADIX);
        nchain->bytes = bytes;
@@ -2511,9 +2509,6 @@ hammer2_chain_delete_duplicate(hammer2_trans_t *trans,
 
        nchain->index = ochain->index;
 
-       kprintf("duplicate ochain %p(%d) nchain %p(%d) %08x\n",
-               ochain, ochain->refs, nchain, nchain->refs, nchain->flags);
-
        spin_lock(&above->cst.spin);
        atomic_set_int(&nchain->flags, HAMMER2_CHAIN_ONRBTREE);
        ochain->delete_tid = trans->sync_tid;
index 751b71e..4741596 100644 (file)
@@ -888,6 +888,7 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data)
         * skipped right now before we start messing with a non-existant
         * block table.
         */
+#if 0
        if (parent->bref.type == HAMMER2_BREF_TYPE_INODE &&
            (parent->data->ipdata.op_flags & HAMMER2_OPFLAG_DIRECTDATA)) {
 #if FLUSH_DEBUG
@@ -895,6 +896,7 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data)
 #endif
                goto finalize;
        }
+#endif
 
        /*
         * Ignore children created after our flush point, treating them as
@@ -981,10 +983,13 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data)
                KKASSERT((parent->data->ipdata.op_flags &
                          HAMMER2_OPFLAG_DIRECTDATA) == 0);
 #endif
+#if 0
                if (parent->data->ipdata.op_flags &
                    HAMMER2_OPFLAG_DIRECTDATA) {
                        base = NULL;
-               } else {
+               } else
+#endif
+               {
                        base = &parent->data->ipdata.u.blockset.blockref[0];
                        count = HAMMER2_SET_COUNT;
                }
@@ -1061,6 +1066,18 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data)
                for (scan = above->first_parent;
                     scan;
                     scan = scan->next_parent) {
+                       /*
+                        * XXX weird code also checked at the top of scan2,
+                        *     I would like to fix this by detaching the core
+                        *     on initial hardlink consolidation (1->2 nlinks).
+                        */
+#if 0
+                       if (scan->bref.type == HAMMER2_BREF_TYPE_INODE &&
+                           (scan->data->ipdata.op_flags &
+                            HAMMER2_OPFLAG_DIRECTDATA)) {
+                               continue;
+                       }
+#endif
                        if (scan->flags & HAMMER2_CHAIN_SUBMODIFIED) {
                                ok = 0;
                                break;
index a4eff73..1f022f4 100644 (file)
@@ -1329,6 +1329,8 @@ hammer2_hardlink_consolidate(hammer2_trans_t *trans, hammer2_inode_t *ip,
                         * file is extended afterwords.
                         */
                        hammer2_chain_modify(trans, &chain, 0);
+                       hammer2_chain_delete_duplicate(trans, &chain,
+                                                      HAMMER2_DELDUP_RECORE);
                        ipdata = &chain->data->ipdata;
                        ipdata->target_type = ipdata->type;
                        ipdata->type = HAMMER2_OBJTYPE_HARDLINK;
@@ -1360,7 +1362,6 @@ hammer2_hardlink_consolidate(hammer2_trans_t *trans, hammer2_inode_t *ip,
                        bzero(&ipdata->u, sizeof(ipdata->u));
                        /* XXX transaction ids */
                } else {
-                       kprintf("DELETE INVISIBLE %p\n", chain);
                        hammer2_chain_delete(trans, chain);
                }