hammer2 - Refactor frontend part 5/many
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 17 Jun 2015 07:12:21 +0000 (00:12 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 18 Jun 2015 00:15:40 +0000 (17:15 -0700)
* Separate the inode lock from the cluster lock.  Add a new (possibly
  temporary) API function hammer2_inode_cluster() which handles initial
  ip cluster locking.

* Begin using the meta-data cached in ip->meta and ip->bref.

* Cache bref statistics in ip->bref (might be temporary).

sys/vfs/hammer2/TODO
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_inode.c
sys/vfs/hammer2/hammer2_iocom.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_strategy.c
sys/vfs/hammer2/hammer2_subr.c
sys/vfs/hammer2/hammer2_syncthr.c
sys/vfs/hammer2/hammer2_vfsops.c
sys/vfs/hammer2/hammer2_vnops.c

index c196b1b..9634e8c 100644 (file)
@@ -1,3 +1,6 @@
+
+* Convert xops and hammer2_update_spans() from cluster back into chain calls
+
 * syncthr leaves inode locks for entire sync, which is wrong.
 
 * recovery scan vs unmount.  At the moment an unmount does its flushes,
index 4928f43..e54b821 100644 (file)
@@ -679,6 +679,7 @@ struct hammer2_inode {
        u_int                   refs;           /* +vpref, +flushref */
        uint8_t                 comp_heuristic;
        hammer2_inode_meta_t    meta;           /* copy of meta-data */
+       hammer2_blockref_t      bref;           /* copy of bref statistics */
 };
 
 typedef struct hammer2_inode hammer2_inode_t;
@@ -1063,8 +1064,9 @@ extern int write_thread_wakeup;
 int hammer2_signal_check(time_t *timep);
 const char *hammer2_error_str(int error);
 
-hammer2_cluster_t *hammer2_inode_lock(hammer2_inode_t *ip, int how);
+void hammer2_inode_lock(hammer2_inode_t *ip, int how);
 void hammer2_inode_unlock(hammer2_inode_t *ip, hammer2_cluster_t *cluster);
+hammer2_cluster_t *hammer2_inode_cluster(hammer2_inode_t *ip, int how);
 hammer2_mtx_state_t hammer2_inode_lock_temp_release(hammer2_inode_t *ip);
 void hammer2_inode_lock_temp_restore(hammer2_inode_t *ip,
                        hammer2_mtx_state_t ostate);
@@ -1076,7 +1078,7 @@ void hammer2_dev_shlock(hammer2_dev_t *hmp);
 void hammer2_dev_unlock(hammer2_dev_t *hmp);
 
 int hammer2_get_dtype(const hammer2_inode_data_t *ipdata);
-int hammer2_get_vtype(const hammer2_inode_data_t *ipdata);
+int hammer2_get_vtype(uint8_t type);
 u_int8_t hammer2_get_obj_type(enum vtype vtype);
 void hammer2_time_to_timespec(u_int64_t xtime, struct timespec *ts);
 u_int64_t hammer2_timespec_to_time(const struct timespec *ts);
index 6f97bc0..dc9f8bc 100644 (file)
@@ -98,11 +98,9 @@ hammer2_inode_cmp(hammer2_inode_t *ip1, hammer2_inode_t *ip2)
  *      accesses to one node.  This flag is automatically set if the inode
  *      is locked with HAMMER2_RESOLVE_SHARED.
  */
-hammer2_cluster_t *
+void
 hammer2_inode_lock(hammer2_inode_t *ip, int how)
 {
-       hammer2_cluster_t *cluster;
-
        hammer2_inode_ref(ip);
 
        /* 
@@ -114,18 +112,22 @@ hammer2_inode_lock(hammer2_inode_t *ip, int how)
        } else {
                hammer2_mtx_ex(&ip->lock);
        }
+}
+
+/*
+ * Create a locked copy of ip->cluster.  Note that the copy will have a
+ * ref on the cluster AND its chains and we don't want a second ref to
+ * either when we lock it.
+ *
+ * Exclusive inode locks set the template focus chain in (ip)
+ * as a hint.  Cluster locks can ALWAYS replace the focus in the
+ * working copy if the hint does not work out, so beware.
+ */
+hammer2_cluster_t *
+hammer2_inode_cluster(hammer2_inode_t *ip, int how)
+{
+       hammer2_cluster_t *cluster;
 
-       /*
-        * Create a copy of ip->cluster and lock it.  Note that the copy
-        * will have a ref on the cluster AND its chains and we don't want
-        * a second ref to either when we lock it.
-        *
-        * The copy will not have a focus until it is locked.
-        *
-        * Exclusive inode locks set the template focus chain in (ip)
-        * as a hint.  Cluster locks can ALWAYS replace the focus in the
-        * working copy if the hint does not work out, so beware.
-        */
        cluster = hammer2_cluster_copy(&ip->cluster);
        hammer2_cluster_lock(cluster, how);
        hammer2_cluster_resolve(cluster);
@@ -138,26 +140,7 @@ hammer2_inode_lock(hammer2_inode_t *ip, int how)
        if ((how & HAMMER2_RESOLVE_SHARED) == 0)
                ip->cluster.focus = cluster->focus;
 
-       /*
-        * Initialize pmp->inode_tid and pmp->modify_tid on first access
-        * to the root of mount that resolves good.
-        * XXX probably not the best place for this.
-        */
-       if (ip->pmp->inode_tid == 0 &&
-           cluster->error == 0 && cluster->focus) {
-               const hammer2_inode_data_t *ripdata;
-               hammer2_pfs_t *pmp = ip->pmp;
-               hammer2_blockref_t bref;
-
-               ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
-               hammer2_cluster_bref(cluster, &bref);
-               pmp->inode_tid = ripdata->meta.pfs_inum + 1;
-               pmp->modify_tid = bref.modify_tid;
-               kprintf("PMP focus good set nextino=%ld mod=%016jx\n",
-                       pmp->inode_tid, pmp->modify_tid);
-
-       }
-       return (cluster);
+       return cluster;
 }
 
 void
@@ -554,12 +537,13 @@ again:
        if (cluster) {
                nipdata = &hammer2_cluster_rdata(cluster)->ipdata;
                nip->meta = nipdata->meta;
+               hammer2_cluster_bref(cluster, &nip->bref);
                atomic_set_int(&nip->flags, HAMMER2_INODE_METAGOOD);
                hammer2_inode_repoint(nip, NULL, cluster);
        } else {
                nip->meta.inum = 1;             /* PFS inum is always 1 XXX */
                /* mtime will be updated when a cluster is available */
-               atomic_set_int(&nip->flags, HAMMER2_INODE_METAGOOD);
+               atomic_set_int(&nip->flags, HAMMER2_INODE_METAGOOD);/*XXX*/
        }
 
        nip->pip = dip;                         /* can be NULL */
@@ -645,7 +629,8 @@ hammer2_inode_create(hammer2_trans_t *trans, hammer2_inode_t *dip,
         * NOTE: hidden inodes do not have iterators.
         */
 retry:
-       cparent = hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(dip, HAMMER2_RESOLVE_ALWAYS);
        dipdata = &hammer2_cluster_rdata(cparent)->ipdata;
        dip_uid = dipdata->meta.uid;
        dip_gid = dipdata->meta.gid;
@@ -1315,7 +1300,8 @@ again:
        /*
         * Search for the filename in the directory
         */
-       cparent = hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(dip, HAMMER2_RESOLVE_ALWAYS);
        cluster = hammer2_cluster_lookup(cparent, &key_next,
                                     lhc, lhc + HAMMER2_DIRHASH_LOMASK, 0);
        while (cluster) {
@@ -1606,7 +1592,8 @@ hammer2_inode_install_hidden(hammer2_pfs_t *pmp)
         * and data chains inherit from their respective file inode *_algo
         * fields.
         */
-       cparent = hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
        ripdata = &hammer2_cluster_rdata(cparent)->ipdata;
        dip_check_algo = ripdata->meta.check_algo;
        dip_comp_algo = ripdata->meta.comp_algo;
@@ -1699,7 +1686,8 @@ hammer2_inode_move_to_hidden(hammer2_trans_t *trans,
        KKASSERT(pmp->ihidden != NULL);
 
        hammer2_cluster_delete(trans, *cparentp, *clusterp, 0);
-       dcluster = hammer2_inode_lock(pmp->ihidden, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(pmp->ihidden, HAMMER2_RESOLVE_ALWAYS);
+       dcluster = hammer2_inode_cluster(pmp->ihidden, HAMMER2_RESOLVE_ALWAYS);
        error = hammer2_inode_connect(trans,
                                      NULL/*XXX*/, clusterp, 0,
                                      pmp->ihidden, dcluster,
@@ -1948,7 +1936,8 @@ hammer2_hardlink_find(hammer2_inode_t *dip,
        cparent = NULL;
 
        while ((ip = pip) != NULL) {
-               cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+               hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+               cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
                hammer2_inode_drop(ip);                 /* loop */
                KKASSERT(hammer2_cluster_type(cparent) ==
                         HAMMER2_BREF_TYPE_INODE);
index 9d8963d..4c86f1f 100644 (file)
@@ -298,7 +298,8 @@ hammer2_update_spans(hammer2_dev_t *hmp, kdmsg_state_t *state)
         * up later on.
         */
        spmp = hmp->spmp;
-       cparent = hammer2_inode_lock(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
        cluster = hammer2_cluster_lookup(cparent, &key_next,
                                         HAMMER2_KEY_MIN,
                                         HAMMER2_KEY_MAX,
index c671cfb..2874306 100644 (file)
@@ -380,8 +380,12 @@ hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data)
        error = 0;
        hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
        pfs = data;
-       cparent = hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
-       rcluster = hammer2_inode_lock(ip->pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(hmp->spmp->iroot,
+                                       HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip->pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       rcluster = hammer2_inode_cluster(ip->pmp->iroot,
+                                        HAMMER2_RESOLVE_ALWAYS);
 
        /*
         * Search for the first key or specific key.  Remember that keys
@@ -473,8 +477,11 @@ hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data)
        error = 0;
        hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
        pfs = data;
-       cparent = hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS |
-                                                      HAMMER2_RESOLVE_SHARED);
+       hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS |
+                                            HAMMER2_RESOLVE_SHARED);
+       cparent = hammer2_inode_cluster(hmp->spmp->iroot,
+                                       HAMMER2_RESOLVE_ALWAYS |
+                                       HAMMER2_RESOLVE_SHARED);
 
        pfs->name[sizeof(pfs->name) - 1] = 0;
        len = strlen(pfs->name);
@@ -627,7 +634,8 @@ hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data)
 
        hammer2_trans_init(&trans, ip->pmp,
                           HAMMER2_TRANS_ISFLUSH | HAMMER2_TRANS_NEWINODE);
-       cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
        error = hammer2_cluster_snapshot(&trans, cparent, pfs);
        hammer2_inode_unlock(ip, cparent);
        hammer2_trans_done(&trans);
@@ -648,8 +656,10 @@ hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data)
 
        ino = data;
 
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
-                                        HAMMER2_RESOLVE_SHARED);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
+                              HAMMER2_RESOLVE_SHARED);
+       cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS |
+                                           HAMMER2_RESOLVE_SHARED);
        if (cluster->error) {
                error = EIO;
        } else {
@@ -681,7 +691,8 @@ hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data)
        int dosync = 0;
 
        hammer2_trans_init(&trans, ip->pmp, 0);
-       cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
        ripdata = &hammer2_cluster_rdata(cparent)->ipdata;
 
        if (ino->ip_data.meta.check_algo != ripdata->meta.check_algo) {
index a8d2347..6d2e7ed 100644 (file)
@@ -249,8 +249,10 @@ hammer2_strategy_read(struct vop_strategy_args *ap)
        /*
         * Lookup the file offset.
         */
-       cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
-                                        HAMMER2_RESOLVE_SHARED);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
+                              HAMMER2_RESOLVE_SHARED);
+       cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS |
+                                           HAMMER2_RESOLVE_SHARED);
        cluster = hammer2_cluster_lookup(cparent, &key_dummy,
                                       lbase, lbase,
                                       HAMMER2_LOOKUP_NODATA |
index 808a8fc..0f161e7 100644 (file)
@@ -107,9 +107,9 @@ hammer2_get_dtype(const hammer2_inode_data_t *ipdata)
  * Return the directory entry type for an inode
  */
 int
-hammer2_get_vtype(const hammer2_inode_data_t *ipdata)
+hammer2_get_vtype(uint8_t type)
 {
-       switch(ipdata->meta.type) {
+       switch(type) {
        case HAMMER2_OBJTYPE_UNKNOWN:
                return (VBAD);
        case HAMMER2_OBJTYPE_DIRECTORY:
index ffe1ca6..3889f98 100644 (file)
@@ -185,8 +185,9 @@ hammer2_syncthr_primary(void *arg)
                 * Synchronization scan.
                 */
                hammer2_trans_init(&thr->trans, pmp, HAMMER2_TRANS_KEEPMODIFY);
-               cparent = hammer2_inode_lock(pmp->iroot,
-                                            HAMMER2_RESOLVE_ALWAYS);
+               hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+               cparent = hammer2_inode_cluster(pmp->iroot,
+                                               HAMMER2_RESOLVE_ALWAYS);
                hammer2_update_pfs_status(thr, cparent);
                hammer2_inode_unlock(pmp->iroot, NULL);
                bzero(errors, sizeof(errors));
index ae9b5f0..ace2e00 100644 (file)
@@ -1029,7 +1029,8 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
         * cluster->pmp will incorrectly point to spmp and must be fixed
         * up later on.
         */
-       cparent = hammer2_inode_lock(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
        lhc = hammer2_dirhash(label, strlen(label));
        cluster = hammer2_cluster_lookup(cparent, &key_next,
                                      lhc, lhc + HAMMER2_DIRHASH_LOMASK,
@@ -1174,7 +1175,8 @@ hammer2_update_pmps(hammer2_dev_t *hmp)
         * up later on.
         */
        spmp = hmp->spmp;
-       cparent = hammer2_inode_lock(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
        cluster = hammer2_cluster_lookup(cparent, &key_next,
                                         HAMMER2_KEY_MIN,
                                         HAMMER2_KEY_MAX,
@@ -1272,8 +1274,9 @@ hammer2_write_thread(void *arg)
                         * NOTE: hammer2_write_file_core() may indirectly
                         *       modify and modsync the inode.
                         */
-                       cparent = hammer2_inode_lock(ip,
-                                                    HAMMER2_RESOLVE_ALWAYS);
+                       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+                       cparent = hammer2_inode_cluster(ip,
+                                                       HAMMER2_RESOLVE_ALWAYS);
                        if (ip->flags & (HAMMER2_INODE_RESIZED |
                                         HAMMER2_INODE_MTIME)) {
                                hammer2_inode_fsync(&trans, ip, cparent);
@@ -2220,9 +2223,32 @@ hammer2_vfs_root(struct mount *mp, struct vnode **vpp)
                *vpp = NULL;
                error = EINVAL;
        } else {
-               cparent = hammer2_inode_lock(pmp->iroot,
+               hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_ALWAYS |
+                                              HAMMER2_RESOLVE_SHARED);
+               cparent = hammer2_inode_cluster(pmp->iroot,
                                                HAMMER2_RESOLVE_ALWAYS |
                                                HAMMER2_RESOLVE_SHARED);
+
+               /*
+                * Initialize pmp->inode_tid and pmp->modify_tid on first access
+                * to the root of mount that resolves good.
+                * XXX probably not the best place for this.
+                */
+               if (pmp->inode_tid == 0 &&
+                   cparent->error == 0 && cparent->focus) {
+                       const hammer2_inode_data_t *ripdata;
+                       hammer2_blockref_t bref;
+
+                       ripdata = &hammer2_cluster_rdata(cparent)->ipdata;
+                       hammer2_cluster_bref(cparent, &bref);
+                       pmp->inode_tid = ripdata->meta.pfs_inum + 1;
+                       pmp->modify_tid = bref.modify_tid;
+                       pmp->iroot->meta = ripdata->meta;
+                       hammer2_cluster_bref(cparent, &pmp->iroot->bref);
+                       kprintf("PMP focus good set nextino=%ld mod=%016jx\n",
+                               pmp->inode_tid, pmp->modify_tid);
+               }
+
                vp = hammer2_igetv(pmp->iroot, cparent, &error);
                hammer2_inode_unlock(pmp->iroot, cparent);
                *vpp = vp;
index 95b312b..774e264 100644 (file)
@@ -225,7 +225,8 @@ hammer2_vop_fsync(struct vop_fsync_args *ap)
         * which call this function will eventually call chain_flush
         * on the volume root as a catch-all, which is far more optimal.
         */
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
        atomic_clear_int(&ip->flags, HAMMER2_INODE_MODIFIED);
        /*vclrisdirty(vp);*/
        if (ip->flags & (HAMMER2_INODE_RESIZED|HAMMER2_INODE_MTIME))
@@ -243,21 +244,16 @@ int
 hammer2_vop_access(struct vop_access_args *ap)
 {
        hammer2_inode_t *ip = VTOI(ap->a_vp);
-       const hammer2_inode_data_t *ripdata;
-       hammer2_cluster_t *cluster;
        uid_t uid;
        gid_t gid;
        int error;
 
        LOCKSTART;
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
-                                        HAMMER2_RESOLVE_SHARED);
-       ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
-       uid = hammer2_to_unix_xid(&ripdata->meta.uid);
-       gid = hammer2_to_unix_xid(&ripdata->meta.gid);
-       error = vop_helper_access(ap, uid, gid,
-                                 ripdata->meta.mode, ripdata->meta.uflags);
-       hammer2_inode_unlock(ip, cluster);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS | HAMMER2_RESOLVE_SHARED);
+       uid = hammer2_to_unix_xid(&ip->meta.uid);
+       gid = hammer2_to_unix_xid(&ip->meta.gid);
+       error = vop_helper_access(ap, uid, gid, ip->meta.mode, ip->meta.uflags);
+       hammer2_inode_unlock(ip, NULL);
 
        LOCKSTOP;
        return (error);
@@ -267,11 +263,8 @@ static
 int
 hammer2_vop_getattr(struct vop_getattr_args *ap)
 {
-       const hammer2_inode_data_t *ripdata;
-       hammer2_cluster_t *cluster;
        hammer2_pfs_t *pmp;
        hammer2_inode_t *ip;
-       hammer2_blockref_t bref;
        struct vnode *vp;
        struct vattr *vap;
 
@@ -282,36 +275,32 @@ hammer2_vop_getattr(struct vop_getattr_args *ap)
        ip = VTOI(vp);
        pmp = ip->pmp;
 
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
-                                        HAMMER2_RESOLVE_SHARED);
-       ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
-       KKASSERT(hammer2_cluster_type(cluster) == HAMMER2_BREF_TYPE_INODE);
-       hammer2_cluster_bref(cluster, &bref);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS | HAMMER2_RESOLVE_SHARED);
 
        vap->va_fsid = pmp->mp->mnt_stat.f_fsid.val[0];
-       vap->va_fileid = ripdata->meta.inum;
-       vap->va_mode = ripdata->meta.mode;
-       vap->va_nlink = ripdata->meta.nlinks;
-       vap->va_uid = hammer2_to_unix_xid(&ripdata->meta.uid);
-       vap->va_gid = hammer2_to_unix_xid(&ripdata->meta.gid);
+       vap->va_fileid = ip->meta.inum;
+       vap->va_mode = ip->meta.mode;
+       vap->va_nlink = ip->meta.nlinks;
+       vap->va_uid = hammer2_to_unix_xid(&ip->meta.uid);
+       vap->va_gid = hammer2_to_unix_xid(&ip->meta.gid);
        vap->va_rmajor = 0;
        vap->va_rminor = 0;
        vap->va_size = ip->meta.size;   /* protected by shared lock */
        vap->va_blocksize = HAMMER2_PBUFSIZE;
-       vap->va_flags = ripdata->meta.uflags;
-       hammer2_time_to_timespec(ripdata->meta.ctime, &vap->va_ctime);
-       hammer2_time_to_timespec(ripdata->meta.mtime, &vap->va_mtime);
-       hammer2_time_to_timespec(ripdata->meta.mtime, &vap->va_atime);
+       vap->va_flags = ip->meta.uflags;
+       hammer2_time_to_timespec(ip->meta.ctime, &vap->va_ctime);
+       hammer2_time_to_timespec(ip->meta.mtime, &vap->va_mtime);
+       hammer2_time_to_timespec(ip->meta.mtime, &vap->va_atime);
        vap->va_gen = 1;
-       vap->va_bytes = bref.data_count;
-       vap->va_type = hammer2_get_vtype(ripdata);
+       vap->va_bytes = ip->bref.data_count;
+       vap->va_type = hammer2_get_vtype(ip->meta.type);
        vap->va_filerev = 0;
-       vap->va_uid_uuid = ripdata->meta.uid;
-       vap->va_gid_uuid = ripdata->meta.gid;
+       vap->va_uid_uuid = ip->meta.uid;
+       vap->va_gid_uuid = ip->meta.gid;
        vap->va_vaflags = VA_UID_UUID_VALID | VA_GID_UUID_VALID |
                          VA_FSID_UUID_VALID;
 
-       hammer2_inode_unlock(ip, cluster);
+       hammer2_inode_unlock(ip, NULL);
 
        LOCKSTOP;
        return (0);
@@ -348,7 +337,8 @@ hammer2_vop_setattr(struct vop_setattr_args *ap)
 
        hammer2_pfs_memory_wait(ip->pmp);
        hammer2_trans_init(&trans, ip->pmp, 0);
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
        ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
        error = 0;
 
@@ -426,7 +416,8 @@ hammer2_vop_setattr(struct vop_setattr_args *ap)
                        } else {
                                hammer2_extend_file(ip, vap->va_size);
                        }
-                       cluster = hammer2_inode_lock(ip,
+                       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+                       cluster = hammer2_inode_cluster(ip,
                                                     HAMMER2_RESOLVE_ALWAYS);
                        /* RELOAD */
                        ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
@@ -547,8 +538,9 @@ hammer2_vop_readdir(struct vop_readdir_args *ap)
        }
        cookie_index = 0;
 
-       cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
-                                        HAMMER2_RESOLVE_SHARED);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS | HAMMER2_RESOLVE_SHARED);
+       cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS |
+                                           HAMMER2_RESOLVE_SHARED);
 
        ripdata = &hammer2_cluster_rdata(cparent)->ipdata;
 
@@ -588,11 +580,15 @@ hammer2_vop_readdir(struct vop_readdir_args *ap)
                        xip = ip->pip;
                        hammer2_inode_ref(xip);
                        hammer2_inode_unlock(ip, cparent);
-                       xcluster = hammer2_inode_lock(xip,
+                       hammer2_inode_lock(xip, HAMMER2_RESOLVE_ALWAYS |
+                                               HAMMER2_RESOLVE_SHARED);
+                       xcluster = hammer2_inode_cluster(xip,
                                                      HAMMER2_RESOLVE_ALWAYS |
                                                      HAMMER2_RESOLVE_SHARED);
 
-                       cparent = hammer2_inode_lock(ip,
+                       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
+                                              HAMMER2_RESOLVE_SHARED);
+                       cparent = hammer2_inode_cluster(ip,
                                                      HAMMER2_RESOLVE_ALWAYS |
                                                      HAMMER2_RESOLVE_SHARED);
                        hammer2_inode_drop(xip);
@@ -1152,8 +1148,10 @@ hammer2_vop_nresolve(struct vop_nresolve_args *ap)
        /*
         * Note: In DragonFly the kernel handles '.' and '..'.
         */
-       cparent = hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS |
-                                         HAMMER2_RESOLVE_SHARED);
+       hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS |
+                               HAMMER2_RESOLVE_SHARED);
+       cparent = hammer2_inode_cluster(dip, HAMMER2_RESOLVE_ALWAYS |
+                                            HAMMER2_RESOLVE_SHARED);
 
        cluster = hammer2_cluster_lookup(cparent, &key_next,
                                         lhc, lhc + HAMMER2_DIRHASH_LOMASK,
@@ -1204,7 +1202,8 @@ hammer2_vop_nresolve(struct vop_nresolve_args *ap)
                        hammer2_inode_unlock(ip, NULL);
                        hammer2_cluster_unlock(cluster);
                        hammer2_cluster_drop(cluster);
-                       cluster = hammer2_inode_lock(ip,
+                       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+                       cluster = hammer2_inode_cluster(ip,
                                                     HAMMER2_RESOLVE_ALWAYS);
                        ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
                        hammer2_inode_drop(ip);
@@ -1294,7 +1293,8 @@ hammer2_vop_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
                LOCKSTOP;
                return ENOENT;
        }
-       cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
        *ap->a_vpp = hammer2_igetv(ip, cparent, &error);
        hammer2_inode_unlock(ip, cparent);
 
@@ -1368,8 +1368,10 @@ hammer2_vop_advlock(struct vop_advlock_args *ap)
        hammer2_cluster_t *cparent;
        hammer2_off_t size;
 
-       cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
-                                        HAMMER2_RESOLVE_SHARED);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
+                              HAMMER2_RESOLVE_SHARED);
+       cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS |
+                                           HAMMER2_RESOLVE_SHARED);
        ripdata = &hammer2_cluster_rdata(cparent)->ipdata;
        size = ripdata->meta.size;
        hammer2_inode_unlock(ip, cparent);
@@ -1439,10 +1441,16 @@ hammer2_vop_nlink(struct vop_nlink_args *ap)
         */
        fdip = ip->pip;
        cdip = hammer2_inode_common_parent(fdip, tdip);
-       cdcluster = hammer2_inode_lock(cdip, HAMMER2_RESOLVE_ALWAYS);
-       fdcluster = hammer2_inode_lock(fdip, HAMMER2_RESOLVE_ALWAYS);
-       tdcluster = hammer2_inode_lock(tdip, HAMMER2_RESOLVE_ALWAYS);
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(cdip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(fdip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(tdip, HAMMER2_RESOLVE_ALWAYS);
+       cdcluster = hammer2_inode_cluster(cdip, HAMMER2_RESOLVE_ALWAYS);
+       fdcluster = hammer2_inode_cluster(fdip, HAMMER2_RESOLVE_ALWAYS);
+       tdcluster = hammer2_inode_cluster(tdip, HAMMER2_RESOLVE_ALWAYS);
+
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
+
        error = hammer2_hardlink_consolidate(&trans, ip, &cluster,
                                             cdip, cdcluster, 1);
        if (error)
@@ -1819,9 +1827,12 @@ hammer2_vop_nrename(struct vop_nrename_args *ap)
         *          other pointers.
         */
        cdip = hammer2_inode_common_parent(ip->pip, tdip);
-       cdcluster = hammer2_inode_lock(cdip, HAMMER2_RESOLVE_ALWAYS);
-       fdcluster = hammer2_inode_lock(fdip, HAMMER2_RESOLVE_ALWAYS);
-       tdcluster = hammer2_inode_lock(tdip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(cdip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(fdip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(tdip, HAMMER2_RESOLVE_ALWAYS);
+       cdcluster = hammer2_inode_cluster(cdip, HAMMER2_RESOLVE_ALWAYS);
+       fdcluster = hammer2_inode_cluster(fdip, HAMMER2_RESOLVE_ALWAYS);
+       tdcluster = hammer2_inode_cluster(tdip, HAMMER2_RESOLVE_ALWAYS);
 
        /*
         * Keep a tight grip on the inode so the temporary unlinking from
@@ -1857,7 +1868,8 @@ hammer2_vop_nrename(struct vop_nrename_args *ap)
         *           we do use one later remember that it must be reloaded
         *           on any modification to the inode, including connects.
         */
-       cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+       cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
        error = hammer2_hardlink_consolidate(&trans, ip, &cluster,
                                             cdip, cdcluster, 0);
        if (error)
@@ -2008,7 +2020,8 @@ hammer2_run_unlinkq(hammer2_trans_t *trans, hammer2_pfs_t *pmp)
                ip = ipul->ip;
                kfree(ipul, pmp->minode);
 
-               cluster = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+               hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
+               cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
                ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
                if (hammer2_debug & 0x400) {
                        kprintf("hammer2: unlink on reclaim: %s refs=%d\n",