hammer2 - xop stabilization - part 2/many master
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 30 Jun 2015 06:37:20 +0000 (23:37 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 30 Jun 2015 06:41:48 +0000 (23:41 -0700)
* The xop mechanics do a quorum calculation, and will also do quorum
  calculations for the inode cluster (not yet in).  This calculation is
  primarily based on the bref.modify_tid.

  Each backend XOP now needs its own modify_tid to properly distinguish
  between and eventually serialize dependent backend ops.

* Implement discrete modify_tid (mtid) reservations in
  hammer2_xop_alloc().  Remove the old modify_tid reservation code that only
  incremented it on a per-flush basis.

* The flush code will acquire a unique modify_tid which is greater than all
  prior modify_tids in stage 2 (after it clears PREFLUSH).

* The hammer2_xop_alloc() code is too messy returning the union structure,
  return a void * instead so the caller can just assign it to the correct
  sub-union structure.

13 files changed:
sys/vfs/hammer2/TODO
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_bulkscan.c
sys/vfs/hammer2/hammer2_chain.c
sys/vfs/hammer2/hammer2_flush.c
sys/vfs/hammer2/hammer2_freemap.c
sys/vfs/hammer2/hammer2_inode.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_strategy.c
sys/vfs/hammer2/hammer2_thread.c
sys/vfs/hammer2/hammer2_vfsops.c
sys/vfs/hammer2/hammer2_vnops.c
sys/vfs/hammer2/hammer2_xops.c

index 486fe59..b28f708 100644 (file)
@@ -1,3 +1,6 @@
+* Need backend synchronization / serialization when the frontend detaches
+  a XOP.  modify_tid tests won't be enough, the backend may wind up executing
+  the XOP out of order after the detach.
 
 * xop_start - only start synchronized elements
 
index 905f022..6bc7e9a 100644 (file)
@@ -475,7 +475,7 @@ RB_PROTOTYPE(hammer2_chain_tree, hammer2_chain, rbnode, hammer2_chain_cmp);
  */
 #define HAMMER2_MODIFY_OPTDATA         0x00000002      /* data can be NULL */
 #define HAMMER2_MODIFY_NO_MODIFY_TID   0x00000004
-#define HAMMER2_MODIFY_KEEPMODIFY      0x00000008
+#define HAMMER2_MODIFY_UNUSED0008      0x00000008
 #define HAMMER2_MODIFY_NOREALLOC       0x00000010
 
 /*
@@ -825,6 +825,7 @@ typedef struct hammer2_xop_fifo {
 
 struct hammer2_xop_head {
        hammer2_xop_func_t      func;
+       hammer2_tid_t           mtid;
        struct hammer2_inode    *ip;
        struct hammer2_inode    *ip2;
        struct hammer2_inode    *ip3;
@@ -991,10 +992,9 @@ typedef struct hammer2_xop_group hammer2_xop_group_t;
 /*
  * flags to hammer2_xop_alloc()
  *
- * TRANS       - The frontend is in a transaction, backend operations
- *               will do per-node transactions.
+ * MODIFYING   - This is a modifying transaction, allocate a mtid.
  */
-#define HAMMER2_XOP_TRANS              0x00000001
+#define HAMMER2_XOP_MODIFYING          0x00000001
 
 /*
  * Global (per partition) management structure, represents a hard block
@@ -1332,17 +1332,20 @@ void hammer2_chain_lock(hammer2_chain_t *chain, int how);
 void hammer2_chain_load_data(hammer2_chain_t *chain);
 const hammer2_media_data_t *hammer2_chain_rdata(hammer2_chain_t *chain);
 hammer2_media_data_t *hammer2_chain_wdata(hammer2_chain_t *chain);
-int hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp);
+int hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp,
+                               hammer2_tid_t mtid);
 
 int hammer2_chain_hardlink_find(hammer2_inode_t *dip,
                                hammer2_chain_t **parentp,
                                hammer2_chain_t **chainp,
                                int flags);
-void hammer2_chain_modify(hammer2_chain_t *chain, int flags);
+void hammer2_chain_modify(hammer2_chain_t *chain,
+                               hammer2_tid_t mtid, int flags);
 void hammer2_chain_modify_ip(hammer2_inode_t *ip, hammer2_chain_t *chain,
-                               int flags);
+                               hammer2_tid_t mtid, int flags);
 void hammer2_chain_resize(hammer2_inode_t *ip, hammer2_chain_t *parent,
-                               hammer2_chain_t *chain, int nradix, int flags);
+                               hammer2_chain_t *chain,
+                               hammer2_tid_t mtid, int nradix, int flags);
 void hammer2_chain_unlock(hammer2_chain_t *chain);
 void hammer2_chain_wait(hammer2_chain_t *chain);
 hammer2_chain_t *hammer2_chain_get(hammer2_chain_t *parent, int generation,
@@ -1364,16 +1367,17 @@ hammer2_chain_t *hammer2_chain_scan(hammer2_chain_t *parent,
                                int *cache_indexp, int flags);
 
 int hammer2_chain_create(hammer2_chain_t **parentp,
-                               hammer2_chain_t **chainp,
-                               hammer2_pfs_t *pmp,
+                               hammer2_chain_t **chainp, hammer2_pfs_t *pmp,
                                hammer2_key_t key, int keybits,
-                               int type, size_t bytes, int flags);
+                               int type, size_t bytes,
+                               hammer2_tid_t mtid, int flags);
 void hammer2_chain_rename(hammer2_blockref_t *bref,
                                hammer2_chain_t **parentp,
-                               hammer2_chain_t *chain, int flags);
-void hammer2_chain_delete(hammer2_chain_t *parent,
-                               hammer2_chain_t *chain, int flags);
-void hammer2_flush(hammer2_chain_t *chain, int istop);
+                               hammer2_chain_t *chain,
+                               hammer2_tid_t mtid, int flags);
+void hammer2_chain_delete(hammer2_chain_t *parent, hammer2_chain_t *chain,
+                               hammer2_tid_t mtid, int flags);
+void hammer2_flush(hammer2_chain_t *chain, hammer2_tid_t mtid, int istop);
 void hammer2_delayed_flush(hammer2_chain_t *chain);
 void hammer2_chain_setflush(hammer2_chain_t *chain);
 void hammer2_chain_countbrefs(hammer2_chain_t *chain,
@@ -1398,6 +1402,8 @@ void hammer2_base_insert(hammer2_chain_t *chain,
  * hammer2_trans.c
  */
 void hammer2_trans_init(hammer2_pfs_t *pmp, uint32_t flags);
+hammer2_tid_t hammer2_trans_sub(hammer2_pfs_t *pmp);
+void hammer2_trans_clear_preflush(hammer2_pfs_t *pmp);
 void hammer2_trans_done(hammer2_pfs_t *pmp);
 hammer2_tid_t hammer2_trans_newinum(hammer2_pfs_t *pmp);
 void hammer2_trans_assert_strategy(hammer2_pfs_t *pmp);
@@ -1440,7 +1446,7 @@ void hammer2_io_bqrelse(hammer2_io_t **diop);
  * XOP API in hammer2_thread.c
  */
 void hammer2_xop_group_init(hammer2_pfs_t *pmp, hammer2_xop_group_t *xgrp);
-hammer2_xop_t *hammer2_xop_alloc(hammer2_inode_t *ip);
+void *hammer2_xop_alloc(hammer2_inode_t *ip, int flags);
 void hammer2_xop_setname(hammer2_xop_head_t *xop,
                                const char *name, size_t name_len);
 void hammer2_xop_setname2(hammer2_xop_head_t *xop,
index 4a9bd3c..15f2707 100644 (file)
@@ -201,6 +201,7 @@ typedef struct hammer2_bulkfree_info {
        long                    count_l0cleans;
        long                    count_linadjusts;
        hammer2_off_t           adj_free;
+       hammer2_tid_t           mtid;
        time_t                  save_time;
 } hammer2_bulkfree_info_t;
 
@@ -256,6 +257,7 @@ hammer2_bulkfree_pass(hammer2_dev_t *hmp, hammer2_ioc_bulkfree_t *bfi)
                        (intmax_t)incr / HAMMER2_FREEMAP_LEVEL1_SIZE);
 
                hammer2_trans_init(hmp->spmp, 0);
+               cbinfo.mtid = hammer2_trans_sub(hmp->spmp);
                doabort |= hammer2_bulk_scan(&hmp->vchain,
                                            h2_bulkfree_callback, &cbinfo);
 
@@ -544,7 +546,7 @@ h2_bulkfree_sync(hammer2_bulkfree_info_t *cbinfo)
                kprintf("live %016jx %04d.%04x (avail=%d)\n",
                        data_off, bmapindex, live->class, live->avail);
 
-               hammer2_chain_modify(live_chain, 0);
+               hammer2_chain_modify(live_chain, cbinfo->mtid, 0);
                h2_bulkfree_sync_adjust(cbinfo, live, bmap);
 next:
                data_off += HAMMER2_FREEMAP_LEVEL0_SIZE;
index 51e85db..9003355 100644 (file)
@@ -68,7 +68,8 @@ static int hammer2_indirect_optimize; /* XXX SYSCTL */
 
 static hammer2_chain_t *hammer2_chain_create_indirect(
                hammer2_chain_t *parent,
-               hammer2_key_t key, int keybits, int for_type, int *errorp);
+               hammer2_key_t key, int keybits,
+               hammer2_tid_t mtid, int for_type, int *errorp);
 static void hammer2_chain_drop_data(hammer2_chain_t *chain, int lastdrop);
 static hammer2_chain_t *hammer2_combined_find(
                hammer2_chain_t *parent,
@@ -996,7 +997,7 @@ hammer2_chain_countbrefs(hammer2_chain_t *chain,
 void
 hammer2_chain_resize(hammer2_inode_t *ip,
                     hammer2_chain_t *parent, hammer2_chain_t *chain,
-                    int nradix, int flags)
+                    hammer2_tid_t mtid, int nradix, int flags)
 {
        hammer2_dev_t *hmp;
        size_t obytes;
@@ -1029,7 +1030,7 @@ hammer2_chain_resize(hammer2_inode_t *ip,
         *
         * NOTE: The modify will set BMAPUPD for us if BMAPPED is set.
         */
-       hammer2_chain_modify(chain, 0);
+       hammer2_chain_modify(chain, mtid, 0);
 
        /*
         * Relocate the block, even if making it smaller (because different
@@ -1055,7 +1056,8 @@ hammer2_chain_resize(hammer2_inode_t *ip,
 }
 
 void
-hammer2_chain_modify(hammer2_chain_t *chain, int flags)
+hammer2_chain_modify(hammer2_chain_t *chain,
+                    hammer2_tid_t mtid, int flags)
 {
        hammer2_blockref_t obref;
        hammer2_dev_t *hmp;
@@ -1128,11 +1130,9 @@ hammer2_chain_modify(hammer2_chain_t *chain, int flags)
         *
         * NOTE: chain->pmp could be the device spmp.
         */
+       KKASSERT(mtid != 0);
        chain->bref.mirror_tid = hmp->voldata.mirror_tid + 1;
-       if (chain->pmp && (flags & HAMMER2_MODIFY_KEEPMODIFY) == 0) {
-               /* XXX HAMMER2_TRANS_ISFLUSH */
-               chain->bref.modify_tid = chain->pmp->modify_tid;
-       }
+       chain->bref.modify_tid = mtid;
 
        /*
         * Set BMAPUPD to tell the flush code that an existing blockmap entry
@@ -1273,10 +1273,11 @@ skip2:
  * Modify the chain associated with an inode.
  */
 void
-hammer2_chain_modify_ip(hammer2_inode_t *ip, hammer2_chain_t *chain, int flags)
+hammer2_chain_modify_ip(hammer2_inode_t *ip, hammer2_chain_t *chain,
+                       hammer2_tid_t mtid, int flags)
 {
        hammer2_inode_modify(ip);
-       hammer2_chain_modify(chain, flags);
+       hammer2_chain_modify(chain, mtid, flags);
 }
 
 /*
@@ -2219,7 +2220,7 @@ int
 hammer2_chain_create(hammer2_chain_t **parentp,
                     hammer2_chain_t **chainp, hammer2_pfs_t *pmp,
                     hammer2_key_t key, int keybits, int type, size_t bytes,
-                    int flags)
+                    hammer2_tid_t mtid, int flags)
 {
        hammer2_dev_t *hmp;
        hammer2_chain_t *chain;
@@ -2396,7 +2397,7 @@ again:
                hammer2_chain_t *nparent;
 
                nparent = hammer2_chain_create_indirect(parent, key, keybits,
-                                                       type, &error);
+                                                       mtid, type, &error);
                if (nparent == NULL) {
                        if (allocated)
                                hammer2_chain_drop(chain);
@@ -2441,7 +2442,8 @@ again:
                case HAMMER2_BREF_TYPE_DATA:
                case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
                case HAMMER2_BREF_TYPE_INODE:
-                       hammer2_chain_modify(chain, HAMMER2_MODIFY_OPTDATA);
+                       hammer2_chain_modify(chain, mtid,
+                                            HAMMER2_MODIFY_OPTDATA);
                        break;
                default:
                        /*
@@ -2513,7 +2515,7 @@ done:
 void
 hammer2_chain_rename(hammer2_blockref_t *bref,
                     hammer2_chain_t **parentp, hammer2_chain_t *chain,
-                    int flags)
+                    hammer2_tid_t mtid, int flags)
 {
        hammer2_dev_t *hmp;
        hammer2_chain_t *parent;
@@ -2559,7 +2561,7 @@ hammer2_chain_rename(hammer2_blockref_t *bref,
 
                hammer2_chain_create(parentp, &chain, chain->pmp,
                                     bref->key, bref->keybits, bref->type,
-                                    chain->bytes, flags);
+                                    chain->bytes, mtid, flags);
                KKASSERT(chain->flags & HAMMER2_CHAIN_UPDATE);
                hammer2_chain_setflush(*parentp);
        }
@@ -2575,7 +2577,7 @@ hammer2_chain_rename(hammer2_blockref_t *bref,
  */
 static void
 _hammer2_chain_delete_helper(hammer2_chain_t *parent, hammer2_chain_t *chain,
-                            int flags)
+                            hammer2_tid_t mtid, int flags)
 {
        hammer2_dev_t *hmp;
 
@@ -2596,7 +2598,7 @@ _hammer2_chain_delete_helper(hammer2_chain_t *parent, hammer2_chain_t *chain,
                KKASSERT(parent != NULL);
                KKASSERT(parent->error == 0);
                KKASSERT((parent->flags & HAMMER2_CHAIN_INITIAL) == 0);
-               hammer2_chain_modify(parent, HAMMER2_MODIFY_OPTDATA);
+               hammer2_chain_modify(parent, mtid, HAMMER2_MODIFY_OPTDATA);
 
                /*
                 * Calculate blockmap pointer
@@ -2753,7 +2755,7 @@ static
 hammer2_chain_t *
 hammer2_chain_create_indirect(hammer2_chain_t *parent,
                              hammer2_key_t create_key, int create_bits,
-                             int for_type, int *errorp)
+                             hammer2_tid_t mtid, int for_type, int *errorp)
 {
        hammer2_dev_t *hmp;
        hammer2_blockref_t *base;
@@ -2914,7 +2916,7 @@ hammer2_chain_create_indirect(hammer2_chain_t *parent,
         * OPTDATA to allow it to remain in the INITIAL state.  Otherwise
         * it won't be acted upon by the flush code.
         */
-       hammer2_chain_modify(ichain, HAMMER2_MODIFY_OPTDATA);
+       hammer2_chain_modify(ichain, mtid, HAMMER2_MODIFY_OPTDATA);
 
        /*
         * Iterate the original parent and move the matching brefs into
@@ -3026,8 +3028,8 @@ hammer2_chain_create_indirect(hammer2_chain_t *parent,
                 *          inode stats (and thus asserting if there is no
                 *          chain->data loaded).
                 */
-               hammer2_chain_delete(parent, chain, 0);
-               hammer2_chain_rename(NULL, &ichain, chain, 0);
+               hammer2_chain_delete(parent, chain, mtid, 0);
+               hammer2_chain_rename(NULL, &ichain, chain, mtid, 0);
                hammer2_chain_unlock(chain);
                hammer2_chain_drop(chain);
                KKASSERT(parent->refs > 0);
@@ -3387,7 +3389,7 @@ hammer2_chain_indkey_normal(hammer2_chain_t *parent, hammer2_key_t *keyp,
  */
 void
 hammer2_chain_delete(hammer2_chain_t *parent, hammer2_chain_t *chain,
-                    int flags)
+                    hammer2_tid_t mtid, int flags)
 {
        KKASSERT(hammer2_mtx_owned(&chain->lock));
 
@@ -3400,7 +3402,7 @@ hammer2_chain_delete(hammer2_chain_t *parent, hammer2_chain_t *chain,
        if ((chain->flags & HAMMER2_CHAIN_DELETED) == 0) {
                KKASSERT((chain->flags & HAMMER2_CHAIN_DELETED) == 0 &&
                         chain->parent == parent);
-               _hammer2_chain_delete_helper(parent, chain, flags);
+               _hammer2_chain_delete_helper(parent, chain, mtid, flags);
        }
 
        /*
@@ -4133,7 +4135,8 @@ done:
  * The ioctl code has already synced the filesystem.
  */
 int
-hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp)
+hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp,
+                      hammer2_tid_t mtid)
 {
        hammer2_dev_t *hmp;
        const hammer2_inode_data_t *ripdata;
@@ -4185,7 +4188,7 @@ hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp)
        if (nip) {
                hammer2_inode_modify(nip);
                nchain = hammer2_inode_chain(nip, 0, HAMMER2_RESOLVE_ALWAYS);
-               hammer2_chain_modify(nchain, 0);
+               hammer2_chain_modify(nchain, mtid, 0);
                wipdata = &nchain->data->ipdata;
 
                nip->meta.pfs_type = HAMMER2_PFSTYPE_MASTER;
@@ -4211,7 +4214,7 @@ hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp)
                /* XXX doesn't work with real cluster */
                wipdata->meta = nip->meta;
                wipdata->u.blockset = ripdata->u.blockset;
-               hammer2_flush(nchain, 1);
+               hammer2_flush(nchain, mtid, 1);
                hammer2_chain_unlock(nchain);
                hammer2_chain_drop(nchain);
                hammer2_inode_unlock(nip);
index b5eb675..04d08ac 100644 (file)
@@ -69,6 +69,7 @@ struct hammer2_flush_info {
        int             depth;
        int             diddeferral;
        int             cache_index;
+       hammer2_tid_t   mtid;
        struct h2_flush_list flushq;
        hammer2_chain_t *debug;
 };
@@ -140,7 +141,6 @@ hammer2_trans_init(hammer2_pfs_t *pmp, uint32_t flags)
                        } else {
                                nflags = (oflags | flags) + 1;
                        }
-                       ++pmp->modify_tid;
                } else if (flags & HAMMER2_TRANS_BUFCACHE) {
                        /*
                         * Requesting strategy transaction.  Generally
@@ -181,6 +181,31 @@ hammer2_trans_init(hammer2_pfs_t *pmp, uint32_t flags)
        }
 }
 
+/*
+ * Start a sub-transaction, there is no 'subdone' function.  This will
+ * issue a new modify_tid (mtid) for the current transaction and must
+ * be called for each XOP when multiple XOPs are run in sequence.
+ */
+hammer2_tid_t
+hammer2_trans_sub(hammer2_pfs_t *pmp)
+{
+       hammer2_tid_t mtid;
+
+       mtid = atomic_fetchadd_64(&pmp->modify_tid, 1);
+
+       return (mtid);
+}
+
+/*
+ * Clears the PREFLUSH stage, called during a flush transaction after all
+ * logical buffer I/O has completed.
+ */
+void
+hammer2_trans_clear_preflush(hammer2_pfs_t *pmp)
+{
+       atomic_clear_int(&pmp->trans.flags, HAMMER2_TRANS_PREFLUSH);
+}
+
 void
 hammer2_trans_done(hammer2_pfs_t *pmp)
 {
@@ -227,8 +252,7 @@ hammer2_trans_newinum(hammer2_pfs_t *pmp)
 {
        hammer2_tid_t tid;
 
-       KKASSERT(sizeof(long) == 8);
-       tid = atomic_fetchadd_long(&pmp->inode_tid, 1);
+       tid = atomic_fetchadd_64(&pmp->inode_tid, 1);
 
        return tid;
 }
@@ -292,7 +316,7 @@ hammer2_delayed_flush(hammer2_chain_t *chain)
  * the call if it was modified.
  */
 void
-hammer2_flush(hammer2_chain_t *chain, int istop)
+hammer2_flush(hammer2_chain_t *chain, hammer2_tid_t mtid, int istop)
 {
        hammer2_chain_t *scan;
        hammer2_flush_info_t info;
@@ -310,6 +334,7 @@ hammer2_flush(hammer2_chain_t *chain, int istop)
        bzero(&info, sizeof(info));
        TAILQ_INIT(&info.flushq);
        info.cache_index = -1;
+       info.mtid = mtid;
 
        /*
         * Calculate parent (can be NULL), if not NULL the flush core
@@ -358,7 +383,7 @@ hammer2_flush(hammer2_chain_t *chain, int istop)
                        if (hammer2_debug & 0x0040)
                                kprintf("deferred flush %p\n", scan);
                        hammer2_chain_lock(scan, HAMMER2_RESOLVE_MAYBE);
-                       hammer2_flush(scan, 0);
+                       hammer2_flush(scan, mtid, 0);
                        hammer2_chain_unlock(scan);
                        hammer2_chain_drop(scan);       /* ref from deferral */
                }
@@ -835,7 +860,7 @@ again:
                 * We are updating the parent's blockmap, the parent must
                 * be set modified.
                 */
-               hammer2_chain_modify(parent, HAMMER2_MODIFY_KEEPMODIFY);
+               hammer2_chain_modify(parent, info->mtid, 0);
                if (parent->bref.modify_tid < chain->bref.modify_tid)
                        parent->bref.modify_tid = chain->bref.modify_tid;
 
@@ -1018,7 +1043,7 @@ hammer2_inode_xop_flush(hammer2_xop_t *arg, int clindex)
        if (chain) {
                hmp = chain->hmp;
                if (chain->flags & HAMMER2_CHAIN_FLUSH_MASK) {
-                       hammer2_flush(chain, 1);
+                       hammer2_flush(chain, xop->head.mtid, 1);
                        parent = chain->parent;
                        KKASSERT(chain->pmp != parent->pmp);
                        hammer2_chain_setflush(parent);
@@ -1071,7 +1096,7 @@ hammer2_inode_xop_flush(hammer2_xop_t *arg, int clindex)
                 */
                hammer2_voldata_modify(hmp);
                chain = &hmp->fchain;
-               hammer2_flush(chain, 1);
+               hammer2_flush(chain, xop->head.mtid, 1);
                KKASSERT(chain == &hmp->fchain);
        }
        hammer2_chain_unlock(&hmp->fchain);
@@ -1082,7 +1107,7 @@ hammer2_inode_xop_flush(hammer2_xop_t *arg, int clindex)
        hammer2_chain_lock(&hmp->vchain, HAMMER2_RESOLVE_ALWAYS);
        if (hmp->vchain.flags & HAMMER2_CHAIN_FLUSH_MASK) {
                chain = &hmp->vchain;
-               hammer2_flush(chain, 1);
+               hammer2_flush(chain, xop->head.mtid, 1);
                KKASSERT(chain == &hmp->vchain);
        }
        hammer2_chain_unlock(&hmp->vchain);
index f784dae..d2a654e 100644 (file)
@@ -56,8 +56,8 @@ struct hammer2_fiterate {
 typedef struct hammer2_fiterate hammer2_fiterate_t;
 
 static int hammer2_freemap_try_alloc(hammer2_chain_t **parentp,
-                       hammer2_blockref_t *bref,
-                       int radix, hammer2_fiterate_t *iter);
+                       hammer2_blockref_t *bref, int radix,
+                       hammer2_fiterate_t *iter, hammer2_tid_t mtid);
 static void hammer2_freemap_init(hammer2_dev_t *hmp,
                        hammer2_key_t key, hammer2_chain_t *chain);
 static int hammer2_bmap_alloc(hammer2_dev_t *hmp,
@@ -199,11 +199,14 @@ hammer2_freemap_alloc(hammer2_chain_t *chain, size_t bytes)
        hammer2_dev_t *hmp = chain->hmp;
        hammer2_blockref_t *bref = &chain->bref;
        hammer2_chain_t *parent;
+       hammer2_tid_t mtid;
        int radix;
        int error;
        unsigned int hindex;
        hammer2_fiterate_t iter;
 
+       mtid = hammer2_trans_sub(hmp->spmp);
+
        /*
         * Validate the allocation size.  It must be a power of 2.
         *
@@ -280,7 +283,8 @@ hammer2_freemap_alloc(hammer2_chain_t *chain, size_t bytes)
        iter.loops = 0;
 
        while (error == EAGAIN) {
-               error = hammer2_freemap_try_alloc(&parent, bref, radix, &iter);
+               error = hammer2_freemap_try_alloc(&parent, bref, radix,
+                                                 &iter, mtid);
        }
        hmp->heur_freemap[hindex] = iter.bnext;
        hammer2_chain_unlock(parent);
@@ -292,7 +296,7 @@ hammer2_freemap_alloc(hammer2_chain_t *chain, size_t bytes)
 static int
 hammer2_freemap_try_alloc(hammer2_chain_t **parentp,
                          hammer2_blockref_t *bref, int radix,
-                         hammer2_fiterate_t *iter)
+                         hammer2_fiterate_t *iter, hammer2_tid_t mtid)
 {
        hammer2_dev_t *hmp = (*parentp)->hmp;
        hammer2_off_t l0size;
@@ -346,10 +350,10 @@ hammer2_freemap_try_alloc(hammer2_chain_t **parentp,
                                     key, HAMMER2_FREEMAP_LEVEL1_RADIX,
                                     HAMMER2_BREF_TYPE_FREEMAP_LEAF,
                                     HAMMER2_FREEMAP_LEVELN_PSIZE,
-                                    0);
+                                    mtid, 0);
                KKASSERT(error == 0);
                if (error == 0) {
-                       hammer2_chain_modify(chain, 0);
+                       hammer2_chain_modify(chain, mtid, 0);
                        bzero(&chain->data->bmdata[0],
                              HAMMER2_FREEMAP_LEVELN_PSIZE);
                        chain->bref.check.freemap.bigmask = (uint32_t)-1;
@@ -376,7 +380,7 @@ hammer2_freemap_try_alloc(hammer2_chain_t **parentp,
                /*
                 * Modify existing chain to setup for adjustment.
                 */
-               hammer2_chain_modify(chain, 0);
+               hammer2_chain_modify(chain, mtid, 0);
        }
 
        /*
@@ -393,7 +397,7 @@ hammer2_freemap_try_alloc(hammer2_chain_t **parentp,
                start = (int)((iter->bnext - key) >>
                              HAMMER2_FREEMAP_LEVEL0_RADIX);
                KKASSERT(start >= 0 && start < HAMMER2_FREEMAP_COUNT);
-               hammer2_chain_modify(chain, 0);
+               hammer2_chain_modify(chain, mtid, 0);
 
                error = ENOSPC;
                for (count = 0; count < HAMMER2_FREEMAP_COUNT; ++count) {
@@ -812,7 +816,8 @@ hammer2_freemap_iterate(hammer2_chain_t **parentp, hammer2_chain_t **chainp,
  * and to do the actual free.
  */
 void
-hammer2_freemap_adjust(hammer2_dev_t *hmp, hammer2_blockref_t *bref, int how)
+hammer2_freemap_adjust(hammer2_dev_t *hmp, hammer2_blockref_t *bref,
+                      int how)
 {
        hammer2_off_t data_off = bref->data_off;
        hammer2_chain_t *chain;
@@ -823,6 +828,7 @@ hammer2_freemap_adjust(hammer2_dev_t *hmp, hammer2_blockref_t *bref, int how)
        hammer2_off_t l0size;
        hammer2_off_t l1size;
        hammer2_off_t l1mask;
+       hammer2_tid_t mtid;
        hammer2_bitmap_t *bitmap;
        const hammer2_bitmap_t bmmask00 = 0;
        hammer2_bitmap_t bmmask01;
@@ -839,6 +845,8 @@ hammer2_freemap_adjust(hammer2_dev_t *hmp, hammer2_blockref_t *bref, int how)
 
        KKASSERT(how == HAMMER2_FREEMAP_DORECOVER);
 
+       mtid = hammer2_trans_sub(hmp->spmp);
+
        radix = (int)data_off & HAMMER2_OFF_MASK_RADIX;
        data_off &= ~HAMMER2_OFF_MASK_RADIX;
        KKASSERT(radix <= HAMMER2_RADIX_MAX);
@@ -901,7 +909,7 @@ hammer2_freemap_adjust(hammer2_dev_t *hmp, hammer2_blockref_t *bref, int how)
                                     key, HAMMER2_FREEMAP_LEVEL1_RADIX,
                                     HAMMER2_BREF_TYPE_FREEMAP_LEAF,
                                     HAMMER2_FREEMAP_LEVELN_PSIZE,
-                                    0);
+                                    mtid, 0);
 
                if (hammer2_debug & 0x0040) {
                        kprintf("fixup create chain %p %016jx:%d\n",
@@ -909,7 +917,7 @@ hammer2_freemap_adjust(hammer2_dev_t *hmp, hammer2_blockref_t *bref, int how)
                }
 
                if (error == 0) {
-                       hammer2_chain_modify(chain, 0);
+                       hammer2_chain_modify(chain, mtid, 0);
                        bzero(&chain->data->bmdata[0],
                              HAMMER2_FREEMAP_LEVELN_PSIZE);
                        chain->bref.check.freemap.bigmask = (uint32_t)-1;
@@ -970,7 +978,7 @@ again:
                         */
                        if ((*bitmap & bmmask11) != bmmask11) {
                                if (modified == 0) {
-                                       hammer2_chain_modify(chain, 0);
+                                       hammer2_chain_modify(chain, mtid, 0);
                                        modified = 1;
                                        goto again;
                                }
index 3ff3bab..0c4840b 100644 (file)
@@ -681,7 +681,7 @@ hammer2_inode_create(hammer2_inode_t *dip,
                hammer2_key_t lhcbase;
 
                lhcbase = lhc;
-               sxop = &hammer2_xop_alloc(dip)->xop_scanlhc;
+               sxop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
                sxop->lhc = lhc;
                hammer2_xop_start(&sxop->head, hammer2_xop_scanlhc);
                while ((error = hammer2_xop_collect(&sxop->head, 0)) == 0) {
@@ -706,7 +706,7 @@ hammer2_inode_create(hammer2_inode_t *dip,
        /*
         * Create the inode with the lhc as the key.
         */
-       xop = &hammer2_xop_alloc(dip)->xop_create;
+       xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
        xop->lhc = lhc;
        xop->flags = flags;
        bzero(&xop->meta, sizeof(xop->meta));
@@ -846,7 +846,7 @@ hammer2_inode_connect(hammer2_inode_t *dip, hammer2_inode_t *ip,
         */
        if (name) {
                lhc = lhcbase = hammer2_dirhash(name, name_len);
-               sxop = &hammer2_xop_alloc(dip)->xop_scanlhc;
+               sxop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
                sxop->lhc = lhc;
                hammer2_xop_start(&sxop->head, hammer2_xop_scanlhc);
                while ((error = hammer2_xop_collect(&sxop->head, 0)) == 0) {
@@ -885,7 +885,7 @@ hammer2_inode_connect(hammer2_inode_t *dip, hammer2_inode_t *ip,
        /*
         * Connect her up
         */
-       xop = &hammer2_xop_alloc(dip)->xop_connect;
+       xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
        if (name)
                hammer2_xop_setname(&xop->head, name, name_len);
        hammer2_xop_setip2(&xop->head, ip);
@@ -1151,7 +1151,7 @@ hammer2_inode_install_hidden(hammer2_pfs_t *pmp)
        {
                hammer2_xop_lookup_t *xop;
 
-               xop = &hammer2_xop_alloc(pmp->iroot)->xop_lookup;
+               xop = hammer2_xop_alloc(pmp->iroot, HAMMER2_XOP_MODIFYING);
                xop->lhc = HAMMER2_INODE_HIDDENDIR;
                hammer2_xop_start(&xop->head, hammer2_xop_lookup);
                error = hammer2_xop_collect(&xop->head, 0);
@@ -1199,7 +1199,7 @@ hammer2_inode_install_hidden(hammer2_pfs_t *pmp)
                hammer2_xop_unlinkall_t *xop;
 
                hammer2_inode_lock(pmp->ihidden, 0);
-               xop = &hammer2_xop_alloc(pmp->ihidden)->xop_unlinkall;
+               xop = hammer2_xop_alloc(pmp->ihidden, HAMMER2_XOP_MODIFYING);
                xop->key_beg = HAMMER2_KEY_MIN;
                xop->key_end = HAMMER2_KEY_MAX;
                hammer2_xop_start(&xop->head, hammer2_inode_xop_unlinkall);
@@ -1265,13 +1265,12 @@ hammer2_inode_common_parent(hammer2_inode_t *fdip, hammer2_inode_t *tdip)
 }
 
 /*
- * Set an inode's cluster modified, marking the related chains RW and
- * duplicating them if necessary.
+ * Mark an inode as being modified, meaning that the caller will modify
+ * ip->meta.
  *
- * The passed-in chain is a localized copy of the chain previously acquired
- * when the inode was locked (and possilby replaced in the mean time), and
- * must also be updated.  In fact, we update it first and then synchronize
- * the inode's cluster cache.
+ * NOTE: No mtid (modify_tid) is passed into this routine.  The caller is
+ *      only modifying the in-memory inode.  A modify_tid is synchronized
+ *      later when the inode gets flushed.
  */
 void
 hammer2_inode_modify(hammer2_inode_t *ip)
@@ -1294,7 +1293,7 @@ hammer2_inode_fsync(hammer2_inode_t *ip)
                hammer2_xop_fsync_t *xop;
                int error;
 
-               xop = &hammer2_xop_alloc(ip)->xop_fsync;
+               xop = hammer2_xop_alloc(ip, HAMMER2_XOP_MODIFYING);
                xop->clear_directdata = 0;
                if (ip->flags & HAMMER2_INODE_RESIZED) {
                        if ((ip->meta.op_flags & HAMMER2_OPFLAG_DIRECTDATA) &&
@@ -1356,7 +1355,7 @@ hammer2_inode_run_unlinkq(hammer2_pfs_t *pmp)
                kfree(ipul, pmp->minode);
 
                hammer2_inode_lock(ip, 0);
-               xop = &hammer2_xop_alloc(ip)->xop_destroy;
+               xop = hammer2_xop_alloc(ip, HAMMER2_XOP_MODIFYING);
                hammer2_xop_start(&xop->head, hammer2_inode_xop_destroy);
                error = hammer2_xop_collect(&xop->head, 0);
                hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
@@ -1414,9 +1413,9 @@ hammer2_inode_xop_create(hammer2_xop_t *arg, int clindex)
                                     xop->lhc, 0,
                                     HAMMER2_BREF_TYPE_INODE,
                                     HAMMER2_INODE_BYTES,
-                                    xop->flags);
+                                    xop->head.mtid, xop->flags);
        if (error == 0) {
-               hammer2_chain_modify(chain, 0);
+               hammer2_chain_modify(chain, xop->head.mtid, 0);
                chain->data->ipdata.meta = xop->meta;
                if (xop->head.name) {
                        bcopy(xop->head.name,
@@ -1473,7 +1472,7 @@ hammer2_inode_xop_destroy(hammer2_xop_t *arg, int clindex)
                error = EIO;
                goto done;
        }
-       hammer2_chain_delete(parent, chain, 0);
+       hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
        error = 0;
 done:
        hammer2_xop_feed(&xop->head, NULL, clindex, error);
@@ -1511,7 +1510,8 @@ hammer2_inode_xop_unlinkall(hammer2_xop_t *arg, int clindex)
                                     &cache_index,
                                     HAMMER2_LOOKUP_ALWAYS);
        while (chain) {
-               hammer2_chain_delete(parent, chain, HAMMER2_DELETE_PERMANENT);
+               hammer2_chain_delete(parent, chain,
+                                    xop->head.mtid, HAMMER2_DELETE_PERMANENT);
                hammer2_chain_unlock(chain);
                hammer2_chain_lock(chain, HAMMER2_RESOLVE_ALWAYS |
                                          HAMMER2_RESOLVE_SHARED);
@@ -1577,7 +1577,7 @@ hammer2_inode_xop_connect(hammer2_xop_t *arg, int clindex)
         */
        chain = hammer2_inode_chain(xop->head.ip2, clindex,
                                    HAMMER2_RESOLVE_ALWAYS);
-       hammer2_chain_modify(chain, 0);
+       hammer2_chain_modify(chain, xop->head.mtid, 0);
        wipdata = &chain->data->ipdata;
 
        hammer2_inode_modify(xop->head.ip2);
@@ -1595,7 +1595,7 @@ hammer2_inode_xop_connect(hammer2_xop_t *arg, int clindex)
                                     xop->lhc, 0,
                                     HAMMER2_BREF_TYPE_INODE,
                                     HAMMER2_INODE_BYTES,
-                                    0);
+                                    xop->head.mtid, 0);
 
        /*
         * Feed result back.
@@ -1662,6 +1662,7 @@ hammer2_inode_xop_fsync(hammer2_xop_t *arg, int clindex)
                                break;
                        case HAMMER2_BREF_TYPE_DATA:
                                hammer2_chain_delete(parent, chain,
+                                                    xop->head.mtid,
                                                     HAMMER2_DELETE_PERMANENT);
                                break;
                        }
@@ -1677,7 +1678,7 @@ hammer2_inode_xop_fsync(hammer2_xop_t *arg, int clindex)
         * Sync the inode meta-data, potentially clear the blockset area
         * of direct data so it can be used for blockrefs.
         */
-       hammer2_chain_modify(parent, 0);
+       hammer2_chain_modify(parent, xop->head.mtid, 0);
        parent->data->ipdata.meta = xop->meta;
        if (xop->clear_directdata) {
                bzero(&parent->data->ipdata.u.blockset,
index c8db9c0..3196016 100644 (file)
@@ -588,6 +588,7 @@ hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
        hammer2_dev_t *hmp;
        hammer2_ioc_pfs_t *pfs;
        hammer2_inode_t *nip;
+       hammer2_tid_t mtid;
        int error;
 
        hmp = ip->pmp->pfs_hmps[0];
@@ -605,15 +606,15 @@ hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
                return(EEXIST);
 
        hammer2_trans_init(hmp->spmp, 0);
+       mtid = hammer2_trans_sub(hmp->spmp);
        nip = hammer2_inode_create(hmp->spmp->iroot, NULL, NULL,
                                   pfs->name, strlen(pfs->name), 0,
                                   1, HAMMER2_OBJTYPE_DIRECTORY, 0,
                                   HAMMER2_INSERT_PFSROOT, &error);
-       kprintf("E %p %d\n", nip, error);
        if (error == 0) {
                hammer2_inode_modify(nip);
                nchain = hammer2_inode_chain(nip, 0, HAMMER2_RESOLVE_ALWAYS);
-               hammer2_chain_modify(nchain, 0);
+               hammer2_chain_modify(nchain, mtid, 0);
                nipdata = &nchain->data->ipdata;
 
                nip->meta.pfs_type = pfs->pfs_type;
@@ -687,7 +688,7 @@ hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data)
        hammer2_trans_init(spmp, 0);
        hammer2_inode_lock(dip, 0);
 
-       xop = &hammer2_xop_alloc(dip)->xop_unlink;
+       xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
        hammer2_xop_setname(&xop->head, pfs->name, strlen(pfs->name));
        xop->isdir = 2;
        xop->dopermanent = 1;
@@ -707,6 +708,7 @@ hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data)
        hammer2_ioc_pfs_t *pfs = data;
        hammer2_dev_t   *hmp;
        hammer2_chain_t *chain;
+       hammer2_tid_t   mtid;
        int error;
 
        if (pfs->name[0] == 0)
@@ -721,10 +723,11 @@ hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data)
        hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT);
 
        hammer2_trans_init(ip->pmp, HAMMER2_TRANS_ISFLUSH);
+       mtid = hammer2_trans_sub(ip->pmp);
        hammer2_inode_lock(ip, 0);
 
        chain = hammer2_inode_chain(ip, 0, HAMMER2_RESOLVE_ALWAYS);
-       error = hammer2_chain_snapshot(chain, pfs);
+       error = hammer2_chain_snapshot(chain, pfs, mtid);
        hammer2_chain_unlock(chain);
        hammer2_chain_drop(chain);
 
index 4aa645d..e1e2ecb 100644 (file)
@@ -249,7 +249,7 @@ hammer2_strategy_read(struct vop_strategy_args *ap)
        lbase = bio->bio_offset;
        KKASSERT(((int)lbase & HAMMER2_PBUFMASK) == 0);
 
-       xop = &hammer2_xop_alloc(ip)->xop_strategy;
+       xop = hammer2_xop_alloc(ip, 0);
        xop->finished = 0;
        xop->bio = bio;
        xop->lbase = lbase;
@@ -419,24 +419,25 @@ hammer2_strategy_read_completion(hammer2_chain_t *chain, char *data,
 static void hammer2_write_file_core(struct buf *bp, hammer2_inode_t *ip,
                                hammer2_chain_t **parentp,
                                hammer2_key_t lbase, int ioflag, int pblksize,
-                               int *errorp);
+                               hammer2_tid_t mtid, int *errorp);
 static void hammer2_compress_and_write(struct buf *bp, hammer2_inode_t *ip,
                                hammer2_chain_t **parentp,
-                               hammer2_key_t lbase, int ioflag,
-                               int pblksize, int *errorp,
+                               hammer2_key_t lbase, int ioflag, int pblksize,
+                               hammer2_tid_t mtid, int *errorp,
                                int comp_algo, int check_algo);
 static void hammer2_zero_check_and_write(struct buf *bp, hammer2_inode_t *ip,
                                hammer2_chain_t **parentp,
-                               hammer2_key_t lbase,
-                               int ioflag, int pblksize, int *errorp,
+                               hammer2_key_t lbase, int ioflag, int pblksize,
+                               hammer2_tid_t mtid, int *errorp,
                                int check_algo);
 static int test_block_zeros(const char *buf, size_t bytes);
 static void zero_write(struct buf *bp, hammer2_inode_t *ip,
                                hammer2_chain_t **parentp,
                                hammer2_key_t lbase,
-                               int *errorp);
+                               hammer2_tid_t mtid, int *errorp);
 static void hammer2_write_bp(hammer2_chain_t *chain, struct buf *bp,
-                               int ioflag, int pblksize, int *errorp,
+                               int ioflag, int pblksize,
+                               hammer2_tid_t mtid, int *errorp,
                                int check_algo);
 
 static
@@ -457,7 +458,7 @@ hammer2_strategy_write(struct vop_strategy_args *ap)
        hammer2_lwinprog_ref(pmp);
        hammer2_trans_assert_strategy(pmp);
 
-       xop = &hammer2_xop_alloc(ip)->xop_strategy;
+       xop = hammer2_xop_alloc(ip, HAMMER2_XOP_MODIFYING);
        xop->finished = 0;
        xop->bio = bio;
        xop->lbase = bio->bio_offset;
@@ -497,8 +498,8 @@ hammer2_strategy_xop_write(hammer2_xop_t *arg, int clindex)
        pblksize = hammer2_calc_physical(ip, lbase);
        parent = hammer2_inode_chain(ip, clindex, HAMMER2_RESOLVE_ALWAYS);
        hammer2_write_file_core(bp, ip, &parent,
-                               lbase, IO_ASYNC,
-                               pblksize, &error);
+                               lbase, IO_ASYNC, pblksize,
+                               xop->head.mtid, &error);
        if (parent) {
                hammer2_chain_unlock(parent);
                hammer2_chain_drop(parent);
@@ -571,7 +572,8 @@ hammer2_bioq_sync(hammer2_pfs_t *pmp)
 static
 hammer2_chain_t *
 hammer2_assign_physical(hammer2_inode_t *ip, hammer2_chain_t **parentp,
-                       hammer2_key_t lbase, int pblksize, int *errorp)
+                       hammer2_key_t lbase, int pblksize,
+                       hammer2_tid_t mtid, int *errorp)
 {
        hammer2_chain_t *chain;
        hammer2_key_t key_dummy;
@@ -601,7 +603,8 @@ retry:
                *errorp = hammer2_chain_create(parentp, &chain, ip->pmp,
                                               lbase, HAMMER2_PBUFRADIX,
                                               HAMMER2_BREF_TYPE_DATA,
-                                              pblksize, 0);
+                                              pblksize,
+                                              mtid, 0);
                if (chain == NULL) {
                        panic("hammer2_chain_create: par=%p error=%d\n",
                              *parentp, *errorp);
@@ -615,12 +618,12 @@ retry:
                         * The data is embedded in the inode, which requires
                         * a bit more finess.
                         */
-                       hammer2_chain_modify_ip(ip, chain, 0);
+                       hammer2_chain_modify_ip(ip, chain, mtid, 0);
                        break;
                case HAMMER2_BREF_TYPE_DATA:
                        if (chain->bytes != pblksize) {
                                hammer2_chain_resize(ip, *parentp, chain,
-                                                    pradix,
+                                                    mtid, pradix,
                                                     HAMMER2_MODIFY_OPTDATA);
                        }
 
@@ -631,7 +634,8 @@ retry:
                         * after resizing in case this is an encrypted or
                         * compressed buffer.
                         */
-                       hammer2_chain_modify(chain, HAMMER2_MODIFY_OPTDATA);
+                       hammer2_chain_modify(chain, mtid,
+                                            HAMMER2_MODIFY_OPTDATA);
                        break;
                default:
                        panic("hammer2_assign_physical: bad type");
@@ -655,7 +659,7 @@ void
 hammer2_write_file_core(struct buf *bp, hammer2_inode_t *ip,
                        hammer2_chain_t **parentp,
                        hammer2_key_t lbase, int ioflag, int pblksize,
-                       int *errorp)
+                       hammer2_tid_t mtid, int *errorp)
 {
        hammer2_chain_t *chain;
 
@@ -669,8 +673,8 @@ hammer2_write_file_core(struct buf *bp, hammer2_inode_t *ip,
                 * This can return NOOFFSET for inode-embedded data.
                 * The strategy code will take care of it in that case.
                 */
-               chain = hammer2_assign_physical(ip, parentp,
-                                               lbase, pblksize, errorp);
+               chain = hammer2_assign_physical(ip, parentp, lbase, pblksize,
+                                               mtid, errorp);
                if (chain->bref.type == HAMMER2_BREF_TYPE_INODE) {
                        hammer2_inode_data_t *wipdata;
 
@@ -682,7 +686,7 @@ hammer2_write_file_core(struct buf *bp, hammer2_inode_t *ip,
                              HAMMER2_EMBEDDED_BYTES);
                } else {
                        hammer2_write_bp(chain, bp, ioflag, pblksize,
-                                        errorp, ip->meta.check_algo);
+                                        mtid, errorp, ip->meta.check_algo);
                }
                if (chain) {
                        hammer2_chain_unlock(chain);
@@ -694,8 +698,8 @@ hammer2_write_file_core(struct buf *bp, hammer2_inode_t *ip,
                 * Check for zero-fill only
                 */
                hammer2_zero_check_and_write(bp, ip, parentp,
-                                            lbase, ioflag,
-                                            pblksize, errorp,
+                                            lbase, ioflag, pblksize,
+                                            mtid, errorp,
                                             ip->meta.check_algo);
                break;
        case HAMMER2_COMP_LZ4:
@@ -705,8 +709,8 @@ hammer2_write_file_core(struct buf *bp, hammer2_inode_t *ip,
                 * Check for zero-fill and attempt compression.
                 */
                hammer2_compress_and_write(bp, ip, parentp,
-                                          lbase, ioflag,
-                                          pblksize, errorp,
+                                          lbase, ioflag, pblksize,
+                                          mtid, errorp,
                                           ip->meta.comp_algo,
                                           ip->meta.check_algo);
                break;
@@ -725,7 +729,7 @@ void
 hammer2_compress_and_write(struct buf *bp, hammer2_inode_t *ip,
        hammer2_chain_t **parentp,
        hammer2_key_t lbase, int ioflag, int pblksize,
-       int *errorp, int comp_algo, int check_algo)
+       hammer2_tid_t mtid, int *errorp, int comp_algo, int check_algo)
 {
        hammer2_chain_t *chain;
        int comp_size;
@@ -733,7 +737,7 @@ hammer2_compress_and_write(struct buf *bp, hammer2_inode_t *ip,
        char *comp_buffer;
 
        if (test_block_zeros(bp->b_data, pblksize)) {
-               zero_write(bp, ip, parentp, lbase, errorp);
+               zero_write(bp, ip, parentp, lbase, mtid, errorp);
                return;
        }
 
@@ -833,8 +837,8 @@ hammer2_compress_and_write(struct buf *bp, hammer2_inode_t *ip,
                }
        }
 
-       chain = hammer2_assign_physical(ip, parentp, lbase,
-                                       comp_block_size, errorp);
+       chain = hammer2_assign_physical(ip, parentp, lbase, comp_block_size,
+                                       mtid, errorp);
        if (*errorp) {
                kprintf("WRITE PATH: An error occurred while "
                        "assigning physical space.\n");
@@ -845,7 +849,7 @@ hammer2_compress_and_write(struct buf *bp, hammer2_inode_t *ip,
        if (chain->bref.type == HAMMER2_BREF_TYPE_INODE) {
                hammer2_inode_data_t *wipdata;
 
-               hammer2_chain_modify_ip(ip, chain, 0);
+               hammer2_chain_modify_ip(ip, chain, mtid, 0);
                wipdata = &chain->data->ipdata;
                KKASSERT(wipdata->meta.op_flags & HAMMER2_OPFLAG_DIRECTDATA);
                KKASSERT(bp->b_loffset == 0);
@@ -956,18 +960,19 @@ static
 void
 hammer2_zero_check_and_write(struct buf *bp, hammer2_inode_t *ip,
        hammer2_chain_t **parentp,
-       hammer2_key_t lbase, int ioflag, int pblksize, int *errorp,
+       hammer2_key_t lbase, int ioflag, int pblksize,
+       hammer2_tid_t mtid, int *errorp,
        int check_algo)
 {
        hammer2_chain_t *chain;
 
        if (test_block_zeros(bp->b_data, pblksize)) {
-               zero_write(bp, ip, parentp, lbase, errorp);
+               zero_write(bp, ip, parentp, lbase, mtid, errorp);
        } else {
-               chain = hammer2_assign_physical(ip, parentp, lbase,
-                                               pblksize, errorp);
+               chain = hammer2_assign_physical(ip, parentp, lbase, pblksize,
+                                               mtid, errorp);
                hammer2_write_bp(chain, bp, ioflag, pblksize,
-                                errorp, check_algo);
+                                mtid, errorp, check_algo);
                if (chain) {
                        hammer2_chain_unlock(chain);
                        hammer2_chain_drop(chain);
@@ -1003,7 +1008,7 @@ static
 void
 zero_write(struct buf *bp, hammer2_inode_t *ip,
           hammer2_chain_t **parentp,
-          hammer2_key_t lbase, int *errorp __unused)
+          hammer2_key_t lbase, hammer2_tid_t mtid, int *errorp __unused)
 {
        hammer2_chain_t *chain;
        hammer2_key_t key_dummy;
@@ -1017,7 +1022,7 @@ zero_write(struct buf *bp, hammer2_inode_t *ip,
                if (chain->bref.type == HAMMER2_BREF_TYPE_INODE) {
                        hammer2_inode_data_t *wipdata;
 
-                       hammer2_chain_modify_ip(ip, chain, 0);
+                       hammer2_chain_modify_ip(ip, chain, mtid, 0);
                        wipdata = &chain->data->ipdata;
                        KKASSERT(wipdata->meta.op_flags &
                                 HAMMER2_OPFLAG_DIRECTDATA);
@@ -1025,7 +1030,7 @@ zero_write(struct buf *bp, hammer2_inode_t *ip,
                        bzero(wipdata->u.data, HAMMER2_EMBEDDED_BYTES);
                } else {
                        hammer2_chain_delete(*parentp, chain,
-                                            HAMMER2_DELETE_PERMANENT);
+                                            mtid, HAMMER2_DELETE_PERMANENT);
                }
                hammer2_chain_unlock(chain);
                hammer2_chain_drop(chain);
@@ -1042,7 +1047,8 @@ zero_write(struct buf *bp, hammer2_inode_t *ip,
 static
 void
 hammer2_write_bp(hammer2_chain_t *chain, struct buf *bp, int ioflag,
-                int pblksize, int *errorp, int check_algo)
+                int pblksize,
+                hammer2_tid_t mtid, int *errorp, int check_algo)
 {
        hammer2_inode_data_t *wipdata;
        hammer2_io_t *dio;
index cc812aa..1d0a110 100644 (file)
@@ -64,10 +64,10 @@ static int hammer2_sync_insert(hammer2_thread_t *thr,
                        hammer2_chain_t *focus);
 static int hammer2_sync_destroy(hammer2_thread_t *thr,
                        hammer2_chain_t **parentp, hammer2_chain_t **chainp,
-                       int idx);
+                       hammer2_tid_t mtid, int idx);
 static int hammer2_sync_replace(hammer2_thread_t *thr,
                        hammer2_chain_t *parent, hammer2_chain_t *chain,
-                       hammer2_tid_t modify_tid, int idx,
+                       hammer2_tid_t mtid, int idx,
                        hammer2_chain_t *focus);
 
 /****************************************************************************
@@ -448,7 +448,7 @@ hammer2_sync_slaves(hammer2_thread_t *thr, hammer2_inode_t *ip,
         * against it.
         */
        hammer2_inode_lock(ip, HAMMER2_RESOLVE_SHARED);
-       xop = &hammer2_xop_alloc(ip)->xop_scanall;
+       xop = hammer2_xop_alloc(ip, HAMMER2_XOP_MODIFYING);
        xop->key_beg = HAMMER2_KEY_MIN;
        xop->key_end = HAMMER2_KEY_MAX;
        hammer2_xop_start_except(&xop->head, hammer2_xop_scanall, idx);
@@ -527,7 +527,7 @@ hammer2_sync_slaves(hammer2_thread_t *thr, hammer2_inode_t *ip,
                         * automatically advance the chain.
                         */
                        nerror = hammer2_sync_destroy(thr, &parent, &chain,
-                                                     idx);
+                                                     0, idx);
                } else if (n == 0 && chain->bref.modify_tid !=
                                     focus->bref.modify_tid) {
                        /*
@@ -672,7 +672,7 @@ hammer2_sync_slaves(hammer2_thread_t *thr, hammer2_inode_t *ip,
                hammer2_xop_ipcluster_t *xop2;
                hammer2_chain_t *focus;
 
-               xop2 = &hammer2_xop_alloc(ip)->xop_ipcluster;
+               xop2 = hammer2_xop_alloc(ip, HAMMER2_XOP_MODIFYING);
                hammer2_xop_start_except(&xop2->head, hammer2_xop_ipcluster,
                                         idx);
                error = hammer2_xop_collect(&xop2->head, 0);
@@ -714,8 +714,7 @@ static
 int
 hammer2_sync_insert(hammer2_thread_t *thr,
                    hammer2_chain_t **parentp, hammer2_chain_t **chainp,
-                   hammer2_tid_t modify_tid, int idx,
-                   hammer2_chain_t *focus)
+                   hammer2_tid_t mtid, int idx, hammer2_chain_t *focus)
 {
        hammer2_chain_t *chain;
 
@@ -726,7 +725,7 @@ hammer2_sync_insert(hammer2_thread_t *thr,
                (*parentp)->bref.type,
                (*parentp)->bref.key,
                idx,
-               focus->bref.type, focus->bref.key, modify_tid);
+               focus->bref.type, focus->bref.key, mtid);
 #endif
 
        /*
@@ -744,8 +743,8 @@ hammer2_sync_insert(hammer2_thread_t *thr,
        hammer2_chain_create(parentp, &chain, thr->pmp,
                             focus->bref.key, focus->bref.keybits,
                             focus->bref.type, focus->bytes,
-                            0);
-       hammer2_chain_modify(chain, HAMMER2_MODIFY_KEEPMODIFY);
+                            mtid, 0);
+       hammer2_chain_modify(chain, mtid, 0);
 
        /*
         * Copy focus to new chain
@@ -756,7 +755,7 @@ hammer2_sync_insert(hammer2_thread_t *thr,
        /* keybits already set */
        chain->bref.vradix = focus->bref.vradix;
        /* mirror_tid set by flush */
-       chain->bref.modify_tid = modify_tid;
+       KKASSERT(chain->bref.modify_tid == mtid);
        chain->bref.flags = focus->bref.flags;
        /* key already present */
        /* check code will be recalculated */
@@ -811,7 +810,7 @@ static
 int
 hammer2_sync_destroy(hammer2_thread_t *thr,
                     hammer2_chain_t **parentp, hammer2_chain_t **chainp,
-                    int idx)
+                    hammer2_tid_t mtid, int idx)
 {
        hammer2_chain_t *chain;
        hammer2_chain_t *parent;
@@ -843,7 +842,7 @@ hammer2_sync_destroy(hammer2_thread_t *thr,
        hammer2_chain_lock(*parentp, HAMMER2_RESOLVE_ALWAYS);
        hammer2_chain_lock(chain, HAMMER2_RESOLVE_NEVER);
 
-       hammer2_chain_delete(*parentp, chain, HAMMER2_DELETE_PERMANENT);
+       hammer2_chain_delete(*parentp, chain, mtid, HAMMER2_DELETE_PERMANENT);
        hammer2_chain_unlock(chain);
        hammer2_chain_drop(chain);
        chain = NULL;                   /* safety */
@@ -868,7 +867,7 @@ static
 int
 hammer2_sync_replace(hammer2_thread_t *thr,
                     hammer2_chain_t *parent, hammer2_chain_t *chain,
-                    hammer2_tid_t modify_tid, int idx,
+                    hammer2_tid_t mtid, int idx,
                     hammer2_chain_t *focus)
 {
        int nradix;
@@ -879,23 +878,24 @@ hammer2_sync_replace(hammer2_thread_t *thr,
        kprintf("replace rec %p slave %d %d.%016jx mod=%016jx\n",
                chain,
                idx,
-               focus->bref.type, focus->bref.key, modify_tid);
+               focus->bref.type, focus->bref.key, mtid);
 #endif
        hammer2_chain_unlock(chain);
        hammer2_chain_lock(chain, HAMMER2_RESOLVE_ALWAYS);
        if (chain->bytes != focus->bytes) {
                /* XXX what if compressed? */
                nradix = hammer2_getradix(chain->bytes);
-               hammer2_chain_resize(NULL, parent, chain, nradix, 0);
+               hammer2_chain_resize(NULL, parent, chain,
+                                    mtid, nradix, 0);
        }
-       hammer2_chain_modify(chain, HAMMER2_MODIFY_KEEPMODIFY);
+       hammer2_chain_modify(chain, mtid, 0);
        otype = chain->bref.type;
        chain->bref.type = focus->bref.type;
        chain->bref.methods = focus->bref.methods;
        chain->bref.keybits = focus->bref.keybits;
        chain->bref.vradix = focus->bref.vradix;
        /* mirror_tid updated by flush */
-       chain->bref.modify_tid = modify_tid;
+       KKASSERT(chain->bref.modify_tid == mtid);
        chain->bref.flags = focus->bref.flags;
        /* key already present */
        /* check code will be recalculated */
@@ -962,8 +962,8 @@ hammer2_xop_group_init(hammer2_pfs_t *pmp, hammer2_xop_group_t *xgrp)
  *
  * NOTE: Fifo indices might not be zero but ri == wi on objcache_get().
  */
-hammer2_xop_t *
-hammer2_xop_alloc(hammer2_inode_t *ip)
+void *
+hammer2_xop_alloc(hammer2_inode_t *ip, int flags)
 {
        hammer2_xop_t *xop;
 
@@ -974,6 +974,10 @@ hammer2_xop_alloc(hammer2_inode_t *ip)
        xop->head.state = 0;
        xop->head.error = 0;
        xop->head.collect_key = 0;
+       if (flags & HAMMER2_XOP_MODIFYING)
+               xop->head.mtid = hammer2_trans_sub(ip->pmp);
+       else
+               xop->head.mtid = 0;
 
        xop->head.cluster.nchains = ip->cluster.nchains;
        xop->head.cluster.pmp = ip->pmp;
index b437241..f826e61 100644 (file)
@@ -1524,7 +1524,7 @@ hammer2_vfs_root(struct mount *mp, struct vnode **vpp)
                hammer2_xop_ipcluster_t *xop;
                hammer2_inode_meta_t *meta;
 
-               xop = &hammer2_xop_alloc(pmp->iroot)->xop_ipcluster;
+               xop = hammer2_xop_alloc(pmp->iroot, HAMMER2_XOP_MODIFYING);
                hammer2_xop_start(&xop->head, hammer2_xop_ipcluster);
                error = hammer2_xop_collect(&xop->head, 0);
 
@@ -1702,6 +1702,7 @@ TAILQ_HEAD(hammer2_recovery_list, hammer2_recovery_elm);
 
 struct hammer2_recovery_info {
        struct hammer2_recovery_list list;
+       hammer2_tid_t   mtid;
        int     depth;
 };
 
@@ -1865,7 +1866,7 @@ hammer2_recovery_scan(hammer2_dev_t *hmp, hammer2_chain_t *parent,
                 */
                if ((chain->bref.flags & HAMMER2_BREF_FLAG_PFSROOT) &&
                    (chain->flags & HAMMER2_CHAIN_ONFLUSH)) {
-                       hammer2_flush(chain, 1);
+                       hammer2_flush(chain, info->mtid, 1);
                }
                chain = hammer2_chain_scan(parent, chain, &cache_index,
                                           HAMMER2_LOOKUP_NODATA);
@@ -1934,7 +1935,7 @@ hammer2_vfs_sync(struct mount *mp, int waitfor)
         * to be instantiated during this sequence.
         */
        hammer2_trans_init(pmp, HAMMER2_TRANS_ISFLUSH |
-                               HAMMER2_TRANS_PREFLUSH);
+                               HAMMER2_TRANS_PREFLUSH);
        hammer2_inode_run_unlinkq(pmp);
 
        info.error = 0;
@@ -1949,7 +1950,7 @@ hammer2_vfs_sync(struct mount *mp, int waitfor)
         * are not affected.
         */
        hammer2_bioq_sync(pmp);
-       atomic_clear_int(&pmp->trans.flags, HAMMER2_TRANS_PREFLUSH);
+       hammer2_trans_clear_preflush(pmp);
 
        /*
         * Use the XOP interface to concurrently flush all nodes to
@@ -1962,7 +1963,7 @@ hammer2_vfs_sync(struct mount *mp, int waitfor)
         * XXX For now wait for all flushes to complete.
         */
        if (iroot) {
-               xop = &hammer2_xop_alloc(iroot)->xop_flush;
+               xop = hammer2_xop_alloc(iroot, HAMMER2_XOP_MODIFYING);
                hammer2_xop_start(&xop->head, hammer2_inode_xop_flush);
                error = hammer2_xop_collect(&xop->head,
                                            HAMMER2_XOP_COLLECT_WAITALL);
@@ -1978,6 +1979,10 @@ hammer2_vfs_sync(struct mount *mp, int waitfor)
 
 /*
  * Sync passes.
+ *
+ * Note that we ignore the tranasction mtid we got above.  Instead,
+ * each vfsync below will ultimately get its own via TRANS_BUFCACHE
+ * transactions.
  */
 static int
 hammer2_sync_scan2(struct mount *mp, struct vnode *vp, void *data)
index bec1332..ff943f3 100644 (file)
@@ -558,7 +558,7 @@ hammer2_vop_readdir(struct vop_readdir_args *ap)
         * parent is the inode cluster, already locked for us.  Don't
         * double lock shared locks as this will screw up upgrades.
         */
-       xop = &hammer2_xop_alloc(ip)->xop_readdir;
+       xop = hammer2_xop_alloc(ip, 0);
        xop->lkey = lkey;
        hammer2_xop_start(&xop->head, hammer2_xop_readdir);
 
@@ -1079,7 +1079,7 @@ hammer2_vop_nresolve(struct vop_nresolve_args *ap)
 
        LOCKSTART;
        dip = VTOI(ap->a_dvp);
-       xop = &hammer2_xop_alloc(dip)->xop_nresolve;
+       xop = hammer2_xop_alloc(dip, 0);
 
        ncp = ap->a_nch->ncp;
        hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen);
@@ -1303,7 +1303,7 @@ hammer2_vop_nlink(struct vop_nlink_args *ap)
         * If fdip != cdip we must shift the inode to cdip.
         */
        if (fdip != cdip || (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE)) {
-               xop1 = &hammer2_xop_alloc(fdip)->xop_nlink;
+               xop1 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING);
                hammer2_xop_setip2(&xop1->head, ip);
                hammer2_xop_setip3(&xop1->head, cdip);
 
@@ -1561,7 +1561,7 @@ hammer2_vop_nremove(struct vop_nremove_args *ap)
         * locates and returns the cluster associated with the real inode.
         * We have to handle nlinks here on the frontend.
         */
-       xop = &hammer2_xop_alloc(dip)->xop_unlink;
+       xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
        hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen);
        isopen = cache_isopen(ap->a_nch);
        xop->isdir = 0;
@@ -1620,7 +1620,7 @@ hammer2_vop_nrmdir(struct vop_nrmdir_args *ap)
        hammer2_trans_init(dip->pmp, 0);
        hammer2_inode_lock(dip, 0);
 
-       xop = &hammer2_xop_alloc(dip)->xop_unlink;
+       xop = hammer2_xop_alloc(dip, HAMMER2_XOP_MODIFYING);
 
        ncp = ap->a_nch->ncp;
        hammer2_xop_setname(&xop->head, ncp->nc_name, ncp->nc_nlen);
@@ -1724,7 +1724,7 @@ hammer2_vop_nrename(struct vop_nrename_args *ap)
            (ip->meta.name_key & HAMMER2_DIRHASH_VISIBLE) == 0) {
                hammer2_xop_nlink_t *xop1;
 
-               xop1 = &hammer2_xop_alloc(fdip)->xop_nlink;
+               xop1 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING);
                hammer2_xop_setip2(&xop1->head, ip);
                hammer2_xop_setip3(&xop1->head, cdip);
 
@@ -1746,7 +1746,7 @@ hammer2_vop_nrename(struct vop_nrename_args *ap)
                 * locates and returns the cluster associated with the real
                 * inode.  We have to handle nlinks here on the frontend.
                 */
-               xop2 = &hammer2_xop_alloc(tdip)->xop_unlink;
+               xop2 = hammer2_xop_alloc(tdip, HAMMER2_XOP_MODIFYING);
                hammer2_xop_setname(&xop2->head, tname, tname_len);
                isopen = cache_isopen(ap->a_tnch);
                xop2->isdir = -1;
@@ -1791,7 +1791,7 @@ hammer2_vop_nrename(struct vop_nrename_args *ap)
 
                tlhc = hammer2_dirhash(tname, tname_len);
                lhcbase = tlhc;
-               sxop = &hammer2_xop_alloc(tdip)->xop_scanlhc;
+               sxop = hammer2_xop_alloc(tdip, HAMMER2_XOP_MODIFYING);
                sxop->lhc = tlhc;
                hammer2_xop_start(&sxop->head, hammer2_xop_scanlhc);
                while ((error = hammer2_xop_collect(&sxop->head, 0)) == 0) {
@@ -1826,7 +1826,7 @@ hammer2_vop_nrename(struct vop_nrename_args *ap)
        if (error == 0) {
                hammer2_xop_nrename_t *xop4;
 
-               xop4 = &hammer2_xop_alloc(fdip)->xop_nrename;
+               xop4 = hammer2_xop_alloc(fdip, HAMMER2_XOP_MODIFYING);
                xop4->lhc = tlhc;
                xop4->ip_key = ip->meta.name_key;
                hammer2_xop_setip2(&xop4->head, ip);
index 631d5e0..fce37f2 100644 (file)
@@ -316,7 +316,8 @@ hammer2_xop_unlink(hammer2_xop_t *arg, int clindex)
                    xop->isdir >= 1) {
                        error = EISDIR;
                } else {
-                       hammer2_chain_delete(parent, chain, xop->dopermanent);
+                       hammer2_chain_delete(parent, chain,
+                                            xop->head.mtid, xop->dopermanent);
                }
        }
 
@@ -334,6 +335,7 @@ hammer2_xop_unlink(hammer2_xop_t *arg, int clindex)
                        if (chain &&
                            (int64_t)chain->data->ipdata.meta.nlinks <= 1) {
                                hammer2_chain_delete(parent, chain,
+                                                    xop->head.mtid,
                                                     xop->dopermanent);
                        }
                }
@@ -400,7 +402,7 @@ hammer2_xop_nlink(hammer2_xop_t *arg, int clindex)
                error = EIO;
                goto done;
        }
-       hammer2_chain_delete(parent, chain, 0);
+       hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
 
        /*
         * Replace the namespace with a hardlink pointer if the chain being
@@ -412,10 +414,10 @@ hammer2_xop_nlink(hammer2_xop_t *arg, int clindex)
                                             chain->bref.key, 0,
                                             HAMMER2_BREF_TYPE_INODE,
                                             HAMMER2_INODE_BYTES,
-                                            0);
+                                            xop->head.mtid, 0);
                if (error)
                        goto done;
-               hammer2_chain_modify(tmp, 0);
+               hammer2_chain_modify(tmp, xop->head.mtid, 0);
                wipdata = &tmp->data->ipdata;
                bzero(wipdata, sizeof(*wipdata));
                wipdata->meta.name_key = chain->data->ipdata.meta.name_key;
@@ -442,7 +444,7 @@ hammer2_xop_nlink(hammer2_xop_t *arg, int clindex)
         *
         * WARNING! Frontend assumes filename length is 18 bytes.
         */
-       hammer2_chain_modify(chain, 0);
+       hammer2_chain_modify(chain, xop->head.mtid, 0);
        wipdata = &chain->data->ipdata;
        ksnprintf(wipdata->filename, sizeof(wipdata->filename),
                  "0x%016jx", (intmax_t)ip->meta.inum);
@@ -471,7 +473,7 @@ hammer2_xop_nlink(hammer2_xop_t *arg, int clindex)
                                     wipdata->meta.name_key, 0,
                                     HAMMER2_BREF_TYPE_INODE,
                                     HAMMER2_INODE_BYTES,
-                                    0);
+                                    xop->head.mtid, 0);
        /*
         * To avoid having to scan the collision space we can simply
         * reuse the inode's original name_key.  But ip->meta.name_key
@@ -586,7 +588,7 @@ hammer2_xop_nrename(hammer2_xop_t *arg, int clindex)
        /*
         * Delete it, then create it in the new namespace.
         */
-       hammer2_chain_delete(parent, chain, 0);
+       hammer2_chain_delete(parent, chain, xop->head.mtid, 0);
        hammer2_chain_unlock(parent);
        hammer2_chain_drop(parent);
        parent = NULL;          /* safety */
@@ -610,7 +612,7 @@ hammer2_xop_nrename(hammer2_xop_t *arg, int clindex)
            bcmp(xop->head.name, xop->head.name2, xop->head.name_len) != 0) {
                hammer2_inode_data_t *wipdata;
 
-               hammer2_chain_modify(chain, 0);
+               hammer2_chain_modify(chain, xop->head.mtid, 0);
                wipdata = &chain->data->ipdata;
 
                bzero(wipdata->filename, sizeof(wipdata->filename));
@@ -642,7 +644,7 @@ hammer2_xop_nrename(hammer2_xop_t *arg, int clindex)
                                     xop->lhc, 0,
                                     HAMMER2_BREF_TYPE_INODE,
                                     HAMMER2_INODE_BYTES,
-                                    0);
+                                    xop->head.mtid, 0);
        /*
         * (frontend is responsible for fixing up ip->pip).
         */