Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec...
Linus Torvalds [Wed, 23 Sep 2009 16:29:20 +0000 (09:29 -0700)]
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2: (85 commits)
  ocfs2: Use buffer IO if we are appending a file.
  ocfs2: add spinlock protection when dealing with lockres->purge.
  dlmglue.c: add missed mlog lines
  ocfs2: __ocfs2_abort() should not enable panic for local mounts
  ocfs2: Add ioctl for reflink.
  ocfs2: Enable refcount tree support.
  ocfs2: Implement ocfs2_reflink.
  ocfs2: Add preserve to reflink.
  ocfs2: Create reflinked file in orphan dir.
  ocfs2: Use proper parameter for some inode operation.
  ocfs2: Make transaction extend more efficient.
  ocfs2: Don't merge in 1st refcount ops of reflink.
  ocfs2: Modify removing xattr process for refcount.
  ocfs2: Add reflink support for xattr.
  ocfs2: Create an xattr indexed block if needed.
  ocfs2: Call refcount tree remove process properly.
  ocfs2: Attach xattr clusters to refcount tree.
  ocfs2: Abstract ocfs2 xattr tree extend rec iteration process.
  ocfs2: Abstract the creation of xattr block.
  ocfs2: Remove inode from ocfs2_xattr_bucket_get_name_value.
  ...

40 files changed:
fs/ocfs2/Makefile
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/buffer_head_io.c
fs/ocfs2/buffer_head_io.h
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h
fs/ocfs2/extent_map.c
fs/ocfs2/extent_map.h
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/localalloc.c
fs/ocfs2/namei.c
fs/ocfs2/namei.h
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/ocfs2_lockid.h
fs/ocfs2/quota_global.c
fs/ocfs2/quota_local.c
fs/ocfs2/refcounttree.c [new file with mode: 0644]
fs/ocfs2/refcounttree.h [new file with mode: 0644]
fs/ocfs2/resize.c
fs/ocfs2/slot_map.c
fs/ocfs2/suballoc.c
fs/ocfs2/super.c
fs/ocfs2/uptodate.c
fs/ocfs2/uptodate.h
fs/ocfs2/xattr.c
fs/ocfs2/xattr.h

index 0159607..31f25ce 100644 (file)
@@ -28,6 +28,7 @@ ocfs2-objs := \
        locks.o                 \
        mmap.o                  \
        namei.o                 \
+       refcounttree.o          \
        resize.o                \
        slot_map.o              \
        suballoc.o              \
index ab513dd..38a42f5 100644 (file)
 #include "super.h"
 #include "uptodate.h"
 #include "xattr.h"
+#include "refcounttree.h"
 
 #include "buffer_head_io.h"
 
+enum ocfs2_contig_type {
+       CONTIG_NONE = 0,
+       CONTIG_LEFT,
+       CONTIG_RIGHT,
+       CONTIG_LEFTRIGHT,
+};
 
+static enum ocfs2_contig_type
+       ocfs2_extent_rec_contig(struct super_block *sb,
+                               struct ocfs2_extent_rec *ext,
+                               struct ocfs2_extent_rec *insert_rec);
 /*
  * Operations for a specific extent tree type.
  *
@@ -79,18 +90,30 @@ struct ocfs2_extent_tree_operations {
         * that value.  new_clusters is the delta, and must be
         * added to the total.  Required.
         */
-       void (*eo_update_clusters)(struct inode *inode,
-                                  struct ocfs2_extent_tree *et,
+       void (*eo_update_clusters)(struct ocfs2_extent_tree *et,
                                   u32 new_clusters);
 
        /*
+        * If this extent tree is supported by an extent map, insert
+        * a record into the map.
+        */
+       void (*eo_extent_map_insert)(struct ocfs2_extent_tree *et,
+                                    struct ocfs2_extent_rec *rec);
+
+       /*
+        * If this extent tree is supported by an extent map, truncate the
+        * map to clusters,
+        */
+       void (*eo_extent_map_truncate)(struct ocfs2_extent_tree *et,
+                                      u32 clusters);
+
+       /*
         * If ->eo_insert_check() exists, it is called before rec is
         * inserted into the extent tree.  It is optional.
         */
-       int (*eo_insert_check)(struct inode *inode,
-                              struct ocfs2_extent_tree *et,
+       int (*eo_insert_check)(struct ocfs2_extent_tree *et,
                               struct ocfs2_extent_rec *rec);
-       int (*eo_sanity_check)(struct inode *inode, struct ocfs2_extent_tree *et);
+       int (*eo_sanity_check)(struct ocfs2_extent_tree *et);
 
        /*
         * --------------------------------------------------------------
@@ -109,8 +132,17 @@ struct ocfs2_extent_tree_operations {
         * it exists.  If it does not, et->et_max_leaf_clusters is set
         * to 0 (unlimited).  Optional.
         */
-       void (*eo_fill_max_leaf_clusters)(struct inode *inode,
-                                         struct ocfs2_extent_tree *et);
+       void (*eo_fill_max_leaf_clusters)(struct ocfs2_extent_tree *et);
+
+       /*
+        * ->eo_extent_contig test whether the 2 ocfs2_extent_rec
+        * are contiguous or not. Optional. Don't need to set it if use
+        * ocfs2_extent_rec as the tree leaf.
+        */
+       enum ocfs2_contig_type
+               (*eo_extent_contig)(struct ocfs2_extent_tree *et,
+                                   struct ocfs2_extent_rec *ext,
+                                   struct ocfs2_extent_rec *insert_rec);
 };
 
 
@@ -121,19 +153,22 @@ struct ocfs2_extent_tree_operations {
 static u64 ocfs2_dinode_get_last_eb_blk(struct ocfs2_extent_tree *et);
 static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
                                         u64 blkno);
-static void ocfs2_dinode_update_clusters(struct inode *inode,
-                                        struct ocfs2_extent_tree *et,
+static void ocfs2_dinode_update_clusters(struct ocfs2_extent_tree *et,
                                         u32 clusters);
-static int ocfs2_dinode_insert_check(struct inode *inode,
-                                    struct ocfs2_extent_tree *et,
+static void ocfs2_dinode_extent_map_insert(struct ocfs2_extent_tree *et,
+                                          struct ocfs2_extent_rec *rec);
+static void ocfs2_dinode_extent_map_truncate(struct ocfs2_extent_tree *et,
+                                            u32 clusters);
+static int ocfs2_dinode_insert_check(struct ocfs2_extent_tree *et,
                                     struct ocfs2_extent_rec *rec);
-static int ocfs2_dinode_sanity_check(struct inode *inode,
-                                    struct ocfs2_extent_tree *et);
+static int ocfs2_dinode_sanity_check(struct ocfs2_extent_tree *et);
 static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et);
 static struct ocfs2_extent_tree_operations ocfs2_dinode_et_ops = {
        .eo_set_last_eb_blk     = ocfs2_dinode_set_last_eb_blk,
        .eo_get_last_eb_blk     = ocfs2_dinode_get_last_eb_blk,
        .eo_update_clusters     = ocfs2_dinode_update_clusters,
+       .eo_extent_map_insert   = ocfs2_dinode_extent_map_insert,
+       .eo_extent_map_truncate = ocfs2_dinode_extent_map_truncate,
        .eo_insert_check        = ocfs2_dinode_insert_check,
        .eo_sanity_check        = ocfs2_dinode_sanity_check,
        .eo_fill_root_el        = ocfs2_dinode_fill_root_el,
@@ -156,40 +191,53 @@ static u64 ocfs2_dinode_get_last_eb_blk(struct ocfs2_extent_tree *et)
        return le64_to_cpu(di->i_last_eb_blk);
 }
 
-static void ocfs2_dinode_update_clusters(struct inode *inode,
-                                        struct ocfs2_extent_tree *et,
+static void ocfs2_dinode_update_clusters(struct ocfs2_extent_tree *et,
                                         u32 clusters)
 {
+       struct ocfs2_inode_info *oi = cache_info_to_inode(et->et_ci);
        struct ocfs2_dinode *di = et->et_object;
 
        le32_add_cpu(&di->i_clusters, clusters);
-       spin_lock(&OCFS2_I(inode)->ip_lock);
-       OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
-       spin_unlock(&OCFS2_I(inode)->ip_lock);
+       spin_lock(&oi->ip_lock);
+       oi->ip_clusters = le32_to_cpu(di->i_clusters);
+       spin_unlock(&oi->ip_lock);
 }
 
-static int ocfs2_dinode_insert_check(struct inode *inode,
-                                    struct ocfs2_extent_tree *et,
+static void ocfs2_dinode_extent_map_insert(struct ocfs2_extent_tree *et,
+                                          struct ocfs2_extent_rec *rec)
+{
+       struct inode *inode = &cache_info_to_inode(et->et_ci)->vfs_inode;
+
+       ocfs2_extent_map_insert_rec(inode, rec);
+}
+
+static void ocfs2_dinode_extent_map_truncate(struct ocfs2_extent_tree *et,
+                                            u32 clusters)
+{
+       struct inode *inode = &cache_info_to_inode(et->et_ci)->vfs_inode;
+
+       ocfs2_extent_map_trunc(inode, clusters);
+}
+
+static int ocfs2_dinode_insert_check(struct ocfs2_extent_tree *et,
                                     struct ocfs2_extent_rec *rec)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_inode_info *oi = cache_info_to_inode(et->et_ci);
+       struct ocfs2_super *osb = OCFS2_SB(oi->vfs_inode.i_sb);
 
-       BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
+       BUG_ON(oi->ip_dyn_features & OCFS2_INLINE_DATA_FL);
        mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
-                       (OCFS2_I(inode)->ip_clusters !=
-                        le32_to_cpu(rec->e_cpos)),
+                       (oi->ip_clusters != le32_to_cpu(rec->e_cpos)),
                        "Device %s, asking for sparse allocation: inode %llu, "
                        "cpos %u, clusters %u\n",
                        osb->dev_str,
-                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                       rec->e_cpos,
-                       OCFS2_I(inode)->ip_clusters);
+                       (unsigned long long)oi->ip_blkno,
+                       rec->e_cpos, oi->ip_clusters);
 
        return 0;
 }
 
-static int ocfs2_dinode_sanity_check(struct inode *inode,
-                                    struct ocfs2_extent_tree *et)
+static int ocfs2_dinode_sanity_check(struct ocfs2_extent_tree *et)
 {
        struct ocfs2_dinode *di = et->et_object;
 
@@ -229,8 +277,7 @@ static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
        return le64_to_cpu(vb->vb_xv->xr_last_eb_blk);
 }
 
-static void ocfs2_xattr_value_update_clusters(struct inode *inode,
-                                             struct ocfs2_extent_tree *et,
+static void ocfs2_xattr_value_update_clusters(struct ocfs2_extent_tree *et,
                                              u32 clusters)
 {
        struct ocfs2_xattr_value_buf *vb = et->et_object;
@@ -252,12 +299,11 @@ static void ocfs2_xattr_tree_fill_root_el(struct ocfs2_extent_tree *et)
        et->et_root_el = &xb->xb_attrs.xb_root.xt_list;
 }
 
-static void ocfs2_xattr_tree_fill_max_leaf_clusters(struct inode *inode,
-                                                   struct ocfs2_extent_tree *et)
+static void ocfs2_xattr_tree_fill_max_leaf_clusters(struct ocfs2_extent_tree *et)
 {
+       struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
        et->et_max_leaf_clusters =
-               ocfs2_clusters_for_bytes(inode->i_sb,
-                                        OCFS2_MAX_XATTR_TREE_LEAF_SIZE);
+               ocfs2_clusters_for_bytes(sb, OCFS2_MAX_XATTR_TREE_LEAF_SIZE);
 }
 
 static void ocfs2_xattr_tree_set_last_eb_blk(struct ocfs2_extent_tree *et,
@@ -277,8 +323,7 @@ static u64 ocfs2_xattr_tree_get_last_eb_blk(struct ocfs2_extent_tree *et)
        return le64_to_cpu(xt->xt_last_eb_blk);
 }
 
-static void ocfs2_xattr_tree_update_clusters(struct inode *inode,
-                                            struct ocfs2_extent_tree *et,
+static void ocfs2_xattr_tree_update_clusters(struct ocfs2_extent_tree *et,
                                             u32 clusters)
 {
        struct ocfs2_xattr_block *xb = et->et_object;
@@ -309,8 +354,7 @@ static u64 ocfs2_dx_root_get_last_eb_blk(struct ocfs2_extent_tree *et)
        return le64_to_cpu(dx_root->dr_last_eb_blk);
 }
 
-static void ocfs2_dx_root_update_clusters(struct inode *inode,
-                                         struct ocfs2_extent_tree *et,
+static void ocfs2_dx_root_update_clusters(struct ocfs2_extent_tree *et,
                                          u32 clusters)
 {
        struct ocfs2_dx_root_block *dx_root = et->et_object;
@@ -318,8 +362,7 @@ static void ocfs2_dx_root_update_clusters(struct inode *inode,
        le32_add_cpu(&dx_root->dr_clusters, clusters);
 }
 
-static int ocfs2_dx_root_sanity_check(struct inode *inode,
-                                     struct ocfs2_extent_tree *et)
+static int ocfs2_dx_root_sanity_check(struct ocfs2_extent_tree *et)
 {
        struct ocfs2_dx_root_block *dx_root = et->et_object;
 
@@ -343,8 +386,54 @@ static struct ocfs2_extent_tree_operations ocfs2_dx_root_et_ops = {
        .eo_fill_root_el        = ocfs2_dx_root_fill_root_el,
 };
 
+static void ocfs2_refcount_tree_fill_root_el(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_refcount_block *rb = et->et_object;
+
+       et->et_root_el = &rb->rf_list;
+}
+
+static void ocfs2_refcount_tree_set_last_eb_blk(struct ocfs2_extent_tree *et,
+                                               u64 blkno)
+{
+       struct ocfs2_refcount_block *rb = et->et_object;
+
+       rb->rf_last_eb_blk = cpu_to_le64(blkno);
+}
+
+static u64 ocfs2_refcount_tree_get_last_eb_blk(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_refcount_block *rb = et->et_object;
+
+       return le64_to_cpu(rb->rf_last_eb_blk);
+}
+
+static void ocfs2_refcount_tree_update_clusters(struct ocfs2_extent_tree *et,
+                                               u32 clusters)
+{
+       struct ocfs2_refcount_block *rb = et->et_object;
+
+       le32_add_cpu(&rb->rf_clusters, clusters);
+}
+
+static enum ocfs2_contig_type
+ocfs2_refcount_tree_extent_contig(struct ocfs2_extent_tree *et,
+                                 struct ocfs2_extent_rec *ext,
+                                 struct ocfs2_extent_rec *insert_rec)
+{
+       return CONTIG_NONE;
+}
+
+static struct ocfs2_extent_tree_operations ocfs2_refcount_tree_et_ops = {
+       .eo_set_last_eb_blk     = ocfs2_refcount_tree_set_last_eb_blk,
+       .eo_get_last_eb_blk     = ocfs2_refcount_tree_get_last_eb_blk,
+       .eo_update_clusters     = ocfs2_refcount_tree_update_clusters,
+       .eo_fill_root_el        = ocfs2_refcount_tree_fill_root_el,
+       .eo_extent_contig       = ocfs2_refcount_tree_extent_contig,
+};
+
 static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
-                                    struct inode *inode,
+                                    struct ocfs2_caching_info *ci,
                                     struct buffer_head *bh,
                                     ocfs2_journal_access_func access,
                                     void *obj,
@@ -352,6 +441,7 @@ static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
 {
        et->et_ops = ops;
        et->et_root_bh = bh;
+       et->et_ci = ci;
        et->et_root_journal_access = access;
        if (!obj)
                obj = (void *)bh->b_data;
@@ -361,41 +451,49 @@ static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
        if (!et->et_ops->eo_fill_max_leaf_clusters)
                et->et_max_leaf_clusters = 0;
        else
-               et->et_ops->eo_fill_max_leaf_clusters(inode, et);
+               et->et_ops->eo_fill_max_leaf_clusters(et);
 }
 
 void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
-                                  struct inode *inode,
+                                  struct ocfs2_caching_info *ci,
                                   struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_di,
+       __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_di,
                                 NULL, &ocfs2_dinode_et_ops);
 }
 
 void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
-                                      struct inode *inode,
+                                      struct ocfs2_caching_info *ci,
                                       struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_xb,
+       __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_xb,
                                 NULL, &ocfs2_xattr_tree_et_ops);
 }
 
 void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
-                                       struct inode *inode,
+                                       struct ocfs2_caching_info *ci,
                                        struct ocfs2_xattr_value_buf *vb)
 {
-       __ocfs2_init_extent_tree(et, inode, vb->vb_bh, vb->vb_access, vb,
+       __ocfs2_init_extent_tree(et, ci, vb->vb_bh, vb->vb_access, vb,
                                 &ocfs2_xattr_value_et_ops);
 }
 
 void ocfs2_init_dx_root_extent_tree(struct ocfs2_extent_tree *et,
-                                   struct inode *inode,
+                                   struct ocfs2_caching_info *ci,
                                    struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_dr,
+       __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_dr,
                                 NULL, &ocfs2_dx_root_et_ops);
 }
 
+void ocfs2_init_refcount_extent_tree(struct ocfs2_extent_tree *et,
+                                    struct ocfs2_caching_info *ci,
+                                    struct buffer_head *bh)
+{
+       __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_rb,
+                                NULL, &ocfs2_refcount_tree_et_ops);
+}
+
 static inline void ocfs2_et_set_last_eb_blk(struct ocfs2_extent_tree *et,
                                            u64 new_last_eb_blk)
 {
@@ -407,78 +505,71 @@ static inline u64 ocfs2_et_get_last_eb_blk(struct ocfs2_extent_tree *et)
        return et->et_ops->eo_get_last_eb_blk(et);
 }
 
-static inline void ocfs2_et_update_clusters(struct inode *inode,
-                                           struct ocfs2_extent_tree *et,
+static inline void ocfs2_et_update_clusters(struct ocfs2_extent_tree *et,
                                            u32 clusters)
 {
-       et->et_ops->eo_update_clusters(inode, et, clusters);
+       et->et_ops->eo_update_clusters(et, clusters);
+}
+
+static inline void ocfs2_et_extent_map_insert(struct ocfs2_extent_tree *et,
+                                             struct ocfs2_extent_rec *rec)
+{
+       if (et->et_ops->eo_extent_map_insert)
+               et->et_ops->eo_extent_map_insert(et, rec);
+}
+
+static inline void ocfs2_et_extent_map_truncate(struct ocfs2_extent_tree *et,
+                                               u32 clusters)
+{
+       if (et->et_ops->eo_extent_map_truncate)
+               et->et_ops->eo_extent_map_truncate(et, clusters);
 }
 
 static inline int ocfs2_et_root_journal_access(handle_t *handle,
-                                              struct inode *inode,
                                               struct ocfs2_extent_tree *et,
                                               int type)
 {
-       return et->et_root_journal_access(handle, inode, et->et_root_bh,
+       return et->et_root_journal_access(handle, et->et_ci, et->et_root_bh,
                                          type);
 }
 
-static inline int ocfs2_et_insert_check(struct inode *inode,
-                                       struct ocfs2_extent_tree *et,
+static inline enum ocfs2_contig_type
+       ocfs2_et_extent_contig(struct ocfs2_extent_tree *et,
+                              struct ocfs2_extent_rec *rec,
+                              struct ocfs2_extent_rec *insert_rec)
+{
+       if (et->et_ops->eo_extent_contig)
+               return et->et_ops->eo_extent_contig(et, rec, insert_rec);
+
+       return ocfs2_extent_rec_contig(
+                               ocfs2_metadata_cache_get_super(et->et_ci),
+                               rec, insert_rec);
+}
+
+static inline int ocfs2_et_insert_check(struct ocfs2_extent_tree *et,
                                        struct ocfs2_extent_rec *rec)
 {
        int ret = 0;
 
        if (et->et_ops->eo_insert_check)
-               ret = et->et_ops->eo_insert_check(inode, et, rec);
+               ret = et->et_ops->eo_insert_check(et, rec);
        return ret;
 }
 
-static inline int ocfs2_et_sanity_check(struct inode *inode,
-                                       struct ocfs2_extent_tree *et)
+static inline int ocfs2_et_sanity_check(struct ocfs2_extent_tree *et)
 {
        int ret = 0;
 
        if (et->et_ops->eo_sanity_check)
-               ret = et->et_ops->eo_sanity_check(inode, et);
+               ret = et->et_ops->eo_sanity_check(et);
        return ret;
 }
 
 static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
 static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
                                         struct ocfs2_extent_block *eb);
-
-/*
- * Structures which describe a path through a btree, and functions to
- * manipulate them.
- *
- * The idea here is to be as generic as possible with the tree
- * manipulation code.
- */
-struct ocfs2_path_item {
-       struct buffer_head              *bh;
-       struct ocfs2_extent_list        *el;
-};
-
-#define OCFS2_MAX_PATH_DEPTH   5
-
-struct ocfs2_path {
-       int                             p_tree_depth;
-       ocfs2_journal_access_func       p_root_access;
-       struct ocfs2_path_item          p_node[OCFS2_MAX_PATH_DEPTH];
-};
-
-#define path_root_bh(_path) ((_path)->p_node[0].bh)
-#define path_root_el(_path) ((_path)->p_node[0].el)
-#define path_root_access(_path)((_path)->p_root_access)
-#define path_leaf_bh(_path) ((_path)->p_node[(_path)->p_tree_depth].bh)
-#define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el)
-#define path_num_items(_path) ((_path)->p_tree_depth + 1)
-
-static int ocfs2_find_path(struct inode *inode, struct ocfs2_path *path,
-                          u32 cpos);
-static void ocfs2_adjust_rightmost_records(struct inode *inode,
-                                          handle_t *handle,
+static void ocfs2_adjust_rightmost_records(handle_t *handle,
+                                          struct ocfs2_extent_tree *et,
                                           struct ocfs2_path *path,
                                           struct ocfs2_extent_rec *insert_rec);
 /*
@@ -486,7 +577,7 @@ static void ocfs2_adjust_rightmost_records(struct inode *inode,
  * to build another path. Generally, this involves freeing the buffer
  * heads.
  */
-static void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root)
+void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root)
 {
        int i, start = 0, depth = 0;
        struct ocfs2_path_item *node;
@@ -515,7 +606,7 @@ static void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root)
        path->p_tree_depth = depth;
 }
 
-static void ocfs2_free_path(struct ocfs2_path *path)
+void ocfs2_free_path(struct ocfs2_path *path)
 {
        if (path) {
                ocfs2_reinit_path(path, 0);
@@ -613,13 +704,13 @@ static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
        return path;
 }
 
-static struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path)
+struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path)
 {
        return ocfs2_new_path(path_root_bh(path), path_root_el(path),
                              path_root_access(path));
 }
 
-static struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et)
+struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et)
 {
        return ocfs2_new_path(et->et_root_bh, et->et_root_el,
                              et->et_root_journal_access);
@@ -632,10 +723,10 @@ static struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et)
  * I don't like the way this function's name looks next to
  * ocfs2_journal_access_path(), but I don't have a better one.
  */
-static int ocfs2_path_bh_journal_access(handle_t *handle,
-                                       struct inode *inode,
-                                       struct ocfs2_path *path,
-                                       int idx)
+int ocfs2_path_bh_journal_access(handle_t *handle,
+                                struct ocfs2_caching_info *ci,
+                                struct ocfs2_path *path,
+                                int idx)
 {
        ocfs2_journal_access_func access = path_root_access(path);
 
@@ -645,15 +736,16 @@ static int ocfs2_path_bh_journal_access(handle_t *handle,
        if (idx)
                access = ocfs2_journal_access_eb;
 
-       return access(handle, inode, path->p_node[idx].bh,
+       return access(handle, ci, path->p_node[idx].bh,
                      OCFS2_JOURNAL_ACCESS_WRITE);
 }
 
 /*
  * Convenience function to journal all components in a path.
  */
-static int ocfs2_journal_access_path(struct inode *inode, handle_t *handle,
-                                    struct ocfs2_path *path)
+int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
+                             handle_t *handle,
+                             struct ocfs2_path *path)
 {
        int i, ret = 0;
 
@@ -661,7 +753,7 @@ static int ocfs2_journal_access_path(struct inode *inode, handle_t *handle,
                goto out;
 
        for(i = 0; i < path_num_items(path); i++) {
-               ret = ocfs2_path_bh_journal_access(handle, inode, path, i);
+               ret = ocfs2_path_bh_journal_access(handle, ci, path, i);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -702,17 +794,9 @@ int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
        return ret;
 }
 
-enum ocfs2_contig_type {
-       CONTIG_NONE = 0,
-       CONTIG_LEFT,
-       CONTIG_RIGHT,
-       CONTIG_LEFTRIGHT,
-};
-
-
 /*
  * NOTE: ocfs2_block_extent_contig(), ocfs2_extents_adjacent() and
- * ocfs2_extent_contig only work properly against leaf nodes!
+ * ocfs2_extent_rec_contig only work properly against leaf nodes!
  */
 static int ocfs2_block_extent_contig(struct super_block *sb,
                                     struct ocfs2_extent_rec *ext,
@@ -738,9 +822,9 @@ static int ocfs2_extents_adjacent(struct ocfs2_extent_rec *left,
 }
 
 static enum ocfs2_contig_type
-       ocfs2_extent_contig(struct inode *inode,
-                           struct ocfs2_extent_rec *ext,
-                           struct ocfs2_extent_rec *insert_rec)
+       ocfs2_extent_rec_contig(struct super_block *sb,
+                               struct ocfs2_extent_rec *ext,
+                               struct ocfs2_extent_rec *insert_rec)
 {
        u64 blkno = le64_to_cpu(insert_rec->e_blkno);
 
@@ -753,12 +837,12 @@ static enum ocfs2_contig_type
                return CONTIG_NONE;
 
        if (ocfs2_extents_adjacent(ext, insert_rec) &&
-           ocfs2_block_extent_contig(inode->i_sb, ext, blkno))
+           ocfs2_block_extent_contig(sb, ext, blkno))
                        return CONTIG_RIGHT;
 
        blkno = le64_to_cpu(ext->e_blkno);
        if (ocfs2_extents_adjacent(insert_rec, ext) &&
-           ocfs2_block_extent_contig(inode->i_sb, insert_rec, blkno))
+           ocfs2_block_extent_contig(sb, insert_rec, blkno))
                return CONTIG_LEFT;
 
        return CONTIG_NONE;
@@ -853,13 +937,13 @@ static int ocfs2_validate_extent_block(struct super_block *sb,
        return 0;
 }
 
-int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
+int ocfs2_read_extent_block(struct ocfs2_caching_info *ci, u64 eb_blkno,
                            struct buffer_head **bh)
 {
        int rc;
        struct buffer_head *tmp = *bh;
 
-       rc = ocfs2_read_block(inode, eb_blkno, &tmp,
+       rc = ocfs2_read_block(ci, eb_blkno, &tmp,
                              ocfs2_validate_extent_block);
 
        /* If ocfs2_read_block() got us a new bh, pass it up. */
@@ -874,7 +958,6 @@ int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
  * How many free extents have we got before we need more meta data?
  */
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
-                          struct inode *inode,
                           struct ocfs2_extent_tree *et)
 {
        int retval;
@@ -889,7 +972,8 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
        last_eb_blk = ocfs2_et_get_last_eb_blk(et);
 
        if (last_eb_blk) {
-               retval = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
+               retval = ocfs2_read_extent_block(et->et_ci, last_eb_blk,
+                                                &eb_bh);
                if (retval < 0) {
                        mlog_errno(retval);
                        goto bail;
@@ -913,9 +997,8 @@ bail:
  * sets h_signature, h_blkno, h_suballoc_bit, h_suballoc_slot, and
  * l_count for you
  */
-static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
-                                    handle_t *handle,
-                                    struct inode *inode,
+static int ocfs2_create_new_meta_bhs(handle_t *handle,
+                                    struct ocfs2_extent_tree *et,
                                     int wanted,
                                     struct ocfs2_alloc_context *meta_ac,
                                     struct buffer_head *bhs[])
@@ -924,6 +1007,8 @@ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
        u16 suballoc_bit_start;
        u32 num_got;
        u64 first_blkno;
+       struct ocfs2_super *osb =
+               OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));
        struct ocfs2_extent_block *eb;
 
        mlog_entry_void();
@@ -949,9 +1034,10 @@ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
                                mlog_errno(status);
                                goto bail;
                        }
-                       ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
+                       ocfs2_set_new_buffer_uptodate(et->et_ci, bhs[i]);
 
-                       status = ocfs2_journal_access_eb(handle, inode, bhs[i],
+                       status = ocfs2_journal_access_eb(handle, et->et_ci,
+                                                        bhs[i],
                                                         OCFS2_JOURNAL_ACCESS_CREATE);
                        if (status < 0) {
                                mlog_errno(status);
@@ -1023,7 +1109,6 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list  *el)
  * extent block's rightmost record.
  */
 static int ocfs2_adjust_rightmost_branch(handle_t *handle,
-                                        struct inode *inode,
                                         struct ocfs2_extent_tree *et)
 {
        int status;
@@ -1037,7 +1122,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle,
                return status;
        }
 
-       status = ocfs2_find_path(inode, path, UINT_MAX);
+       status = ocfs2_find_path(et->et_ci, path, UINT_MAX);
        if (status < 0) {
                mlog_errno(status);
                goto out;
@@ -1050,7 +1135,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle,
                goto out;
        }
 
-       status = ocfs2_journal_access_path(inode, handle, path);
+       status = ocfs2_journal_access_path(et->et_ci, handle, path);
        if (status < 0) {
                mlog_errno(status);
                goto out;
@@ -1059,7 +1144,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle,
        el = path_leaf_el(path);
        rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1];
 
-       ocfs2_adjust_rightmost_records(inode, handle, path, rec);
+       ocfs2_adjust_rightmost_records(handle, et, path, rec);
 
 out:
        ocfs2_free_path(path);
@@ -1068,7 +1153,7 @@ out:
 
 /*
  * Add an entire tree branch to our inode. eb_bh is the extent block
- * to start at, if we don't want to start the branch at the dinode
+ * to start at, if we don't want to start the branch at the root
  * structure.
  *
  * last_eb_bh is required as we have to update it's next_leaf pointer
@@ -1077,9 +1162,7 @@ out:
  * the new branch will be 'empty' in the sense that every block will
  * contain a single record with cluster count == 0.
  */
-static int ocfs2_add_branch(struct ocfs2_super *osb,
-                           handle_t *handle,
-                           struct inode *inode,
+static int ocfs2_add_branch(handle_t *handle,
                            struct ocfs2_extent_tree *et,
                            struct buffer_head *eb_bh,
                            struct buffer_head **last_eb_bh,
@@ -1123,7 +1206,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
        if (root_end > new_cpos) {
                mlog(0, "adjust the cluster end from %u to %u\n",
                     root_end, new_cpos);
-               status = ocfs2_adjust_rightmost_branch(handle, inode, et);
+               status = ocfs2_adjust_rightmost_branch(handle, et);
                if (status) {
                        mlog_errno(status);
                        goto bail;
@@ -1139,7 +1222,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_create_new_meta_bhs(osb, handle, inode, new_blocks,
+       status = ocfs2_create_new_meta_bhs(handle, et, new_blocks,
                                           meta_ac, new_eb_bhs);
        if (status < 0) {
                mlog_errno(status);
@@ -1161,7 +1244,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
                BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
                eb_el = &eb->h_list;
 
-               status = ocfs2_journal_access_eb(handle, inode, bh,
+               status = ocfs2_journal_access_eb(handle, et->et_ci, bh,
                                                 OCFS2_JOURNAL_ACCESS_CREATE);
                if (status < 0) {
                        mlog_errno(status);
@@ -1201,20 +1284,20 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
         * journal_dirty erroring as it won't unless we've aborted the
         * handle (in which case we would never be here) so reserving
         * the write with journal_access is all we need to do. */
-       status = ocfs2_journal_access_eb(handle, inode, *last_eb_bh,
+       status = ocfs2_journal_access_eb(handle, et->et_ci, *last_eb_bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
-       status = ocfs2_et_root_journal_access(handle, inode, et,
+       status = ocfs2_et_root_journal_access(handle, et,
                                              OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        if (eb_bh) {
-               status = ocfs2_journal_access_eb(handle, inode, eb_bh,
+               status = ocfs2_journal_access_eb(handle, et->et_ci, eb_bh,
                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
@@ -1274,9 +1357,7 @@ bail:
  * returns back the new extent block so you can add a branch to it
  * after this call.
  */
-static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
-                                 handle_t *handle,
-                                 struct inode *inode,
+static int ocfs2_shift_tree_depth(handle_t *handle,
                                  struct ocfs2_extent_tree *et,
                                  struct ocfs2_alloc_context *meta_ac,
                                  struct buffer_head **ret_new_eb_bh)
@@ -1290,7 +1371,7 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
 
        mlog_entry_void();
 
-       status = ocfs2_create_new_meta_bhs(osb, handle, inode, 1, meta_ac,
+       status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac,
                                           &new_eb_bh);
        if (status < 0) {
                mlog_errno(status);
@@ -1304,7 +1385,7 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
        eb_el = &eb->h_list;
        root_el = et->et_root_el;
 
-       status = ocfs2_journal_access_eb(handle, inode, new_eb_bh,
+       status = ocfs2_journal_access_eb(handle, et->et_ci, new_eb_bh,
                                         OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
@@ -1323,7 +1404,7 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_et_root_journal_access(handle, inode, et,
+       status = ocfs2_et_root_journal_access(handle, et,
                                              OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -1379,9 +1460,7 @@ bail:
  *
  * return status < 0 indicates an error.
  */
-static int ocfs2_find_branch_target(struct ocfs2_super *osb,
-                                   struct inode *inode,
-                                   struct ocfs2_extent_tree *et,
+static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et,
                                    struct buffer_head **target_bh)
 {
        int status = 0, i;
@@ -1399,19 +1478,21 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
 
        while(le16_to_cpu(el->l_tree_depth) > 1) {
                if (le16_to_cpu(el->l_next_free_rec) == 0) {
-                       ocfs2_error(inode->i_sb, "Dinode %llu has empty "
+                       ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                                   "Owner %llu has empty "
                                    "extent list (next_free_rec == 0)",
-                                   (unsigned long long)OCFS2_I(inode)->ip_blkno);
+                                   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
                        status = -EIO;
                        goto bail;
                }
                i = le16_to_cpu(el->l_next_free_rec) - 1;
                blkno = le64_to_cpu(el->l_recs[i].e_blkno);
                if (!blkno) {
-                       ocfs2_error(inode->i_sb, "Dinode %llu has extent "
+                       ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                                   "Owner %llu has extent "
                                    "list where extent # %d has no physical "
                                    "block start",
-                                   (unsigned long long)OCFS2_I(inode)->ip_blkno, i);
+                                   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), i);
                        status = -EIO;
                        goto bail;
                }
@@ -1419,7 +1500,7 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
                brelse(bh);
                bh = NULL;
 
-               status = ocfs2_read_extent_block(inode, blkno, &bh);
+               status = ocfs2_read_extent_block(et->et_ci, blkno, &bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1460,20 +1541,18 @@ bail:
  *
  * *last_eb_bh will be updated by ocfs2_add_branch().
  */
-static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
-                          struct ocfs2_extent_tree *et, int *final_depth,
-                          struct buffer_head **last_eb_bh,
+static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et,
+                          int *final_depth, struct buffer_head **last_eb_bh,
                           struct ocfs2_alloc_context *meta_ac)
 {
        int ret, shift;
        struct ocfs2_extent_list *el = et->et_root_el;
        int depth = le16_to_cpu(el->l_tree_depth);
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct buffer_head *bh = NULL;
 
        BUG_ON(meta_ac == NULL);
 
-       shift = ocfs2_find_branch_target(osb, inode, et, &bh);
+       shift = ocfs2_find_branch_target(et, &bh);
        if (shift < 0) {
                ret = shift;
                mlog_errno(ret);
@@ -1490,8 +1569,7 @@ static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
                /* ocfs2_shift_tree_depth will return us a buffer with
                 * the new extent block (so we can pass that to
                 * ocfs2_add_branch). */
-               ret = ocfs2_shift_tree_depth(osb, handle, inode, et,
-                                            meta_ac, &bh);
+               ret = ocfs2_shift_tree_depth(handle, et, meta_ac, &bh);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -1517,7 +1595,7 @@ static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
        /* call ocfs2_add_branch to add the final part of the tree with
         * the new data. */
        mlog(0, "add branch. bh = %p\n", bh);
-       ret = ocfs2_add_branch(osb, handle, inode, et, bh, last_eb_bh,
+       ret = ocfs2_add_branch(handle, et, bh, last_eb_bh,
                               meta_ac);
        if (ret < 0) {
                mlog_errno(ret);
@@ -1687,7 +1765,7 @@ set_and_inc:
  *
  * The array index of the subtree root is passed back.
  */
-static int ocfs2_find_subtree_root(struct inode *inode,
+static int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
                                   struct ocfs2_path *left,
                                   struct ocfs2_path *right)
 {
@@ -1705,10 +1783,10 @@ static int ocfs2_find_subtree_root(struct inode *inode,
                 * The caller didn't pass two adjacent paths.
                 */
                mlog_bug_on_msg(i > left->p_tree_depth,
-                               "Inode %lu, left depth %u, right depth %u\n"
+                               "Owner %llu, left depth %u, right depth %u\n"
                                "left leaf blk %llu, right leaf blk %llu\n",
-                               inode->i_ino, left->p_tree_depth,
-                               right->p_tree_depth,
+                               (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+                               left->p_tree_depth, right->p_tree_depth,
                                (unsigned long long)path_leaf_bh(left)->b_blocknr,
                                (unsigned long long)path_leaf_bh(right)->b_blocknr);
        } while (left->p_node[i].bh->b_blocknr ==
@@ -1725,7 +1803,7 @@ typedef void (path_insert_t)(void *, struct buffer_head *);
  * This code can be called with a cpos larger than the tree, in which
  * case it will return the rightmost path.
  */
-static int __ocfs2_find_path(struct inode *inode,
+static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
                             struct ocfs2_extent_list *root_el, u32 cpos,
                             path_insert_t *func, void *data)
 {
@@ -1736,15 +1814,14 @@ static int __ocfs2_find_path(struct inode *inode,
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
        struct ocfs2_extent_rec *rec;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
        el = root_el;
        while (el->l_tree_depth) {
                if (le16_to_cpu(el->l_next_free_rec) == 0) {
-                       ocfs2_error(inode->i_sb,
-                                   "Inode %llu has empty extent list at "
+                       ocfs2_error(ocfs2_metadata_cache_get_super(ci),
+                                   "Owner %llu has empty extent list at "
                                    "depth %u\n",
-                                   (unsigned long long)oi->ip_blkno,
+                                   (unsigned long long)ocfs2_metadata_cache_owner(ci),
                                    le16_to_cpu(el->l_tree_depth));
                        ret = -EROFS;
                        goto out;
@@ -1767,10 +1844,10 @@ static int __ocfs2_find_path(struct inode *inode,
 
                blkno = le64_to_cpu(el->l_recs[i].e_blkno);
                if (blkno == 0) {
-                       ocfs2_error(inode->i_sb,
-                                   "Inode %llu has bad blkno in extent list "
+                       ocfs2_error(ocfs2_metadata_cache_get_super(ci),
+                                   "Owner %llu has bad blkno in extent list "
                                    "at depth %u (index %d)\n",
-                                   (unsigned long long)oi->ip_blkno,
+                                   (unsigned long long)ocfs2_metadata_cache_owner(ci),
                                    le16_to_cpu(el->l_tree_depth), i);
                        ret = -EROFS;
                        goto out;
@@ -1778,7 +1855,7 @@ static int __ocfs2_find_path(struct inode *inode,
 
                brelse(bh);
                bh = NULL;
-               ret = ocfs2_read_extent_block(inode, blkno, &bh);
+               ret = ocfs2_read_extent_block(ci, blkno, &bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -1789,10 +1866,10 @@ static int __ocfs2_find_path(struct inode *inode,
 
                if (le16_to_cpu(el->l_next_free_rec) >
                    le16_to_cpu(el->l_count)) {
-                       ocfs2_error(inode->i_sb,
-                                   "Inode %llu has bad count in extent list "
+                       ocfs2_error(ocfs2_metadata_cache_get_super(ci),
+                                   "Owner %llu has bad count in extent list "
                                    "at block %llu (next free=%u, count=%u)\n",
-                                   (unsigned long long)oi->ip_blkno,
+                                   (unsigned long long)ocfs2_metadata_cache_owner(ci),
                                    (unsigned long long)bh->b_blocknr,
                                    le16_to_cpu(el->l_next_free_rec),
                                    le16_to_cpu(el->l_count));
@@ -1836,14 +1913,14 @@ static void find_path_ins(void *data, struct buffer_head *bh)
        ocfs2_path_insert_eb(fp->path, fp->index, bh);
        fp->index++;
 }
-static int ocfs2_find_path(struct inode *inode, struct ocfs2_path *path,
-                          u32 cpos)
+int ocfs2_find_path(struct ocfs2_caching_info *ci,
+                   struct ocfs2_path *path, u32 cpos)
 {
        struct find_path_data data;
 
        data.index = 1;
        data.path = path;
-       return __ocfs2_find_path(inode, path_root_el(path), cpos,
+       return __ocfs2_find_path(ci, path_root_el(path), cpos,
                                 find_path_ins, &data);
 }
 
@@ -1868,13 +1945,14 @@ static void find_leaf_ins(void *data, struct buffer_head *bh)
  *
  * This function doesn't handle non btree extent lists.
  */
-int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
-                   u32 cpos, struct buffer_head **leaf_bh)
+int ocfs2_find_leaf(struct ocfs2_caching_info *ci,
+                   struct ocfs2_extent_list *root_el, u32 cpos,
+                   struct buffer_head **leaf_bh)
 {
        int ret;
        struct buffer_head *bh = NULL;
 
-       ret = __ocfs2_find_path(inode, root_el, cpos, find_leaf_ins, &bh);
+       ret = __ocfs2_find_path(ci, root_el, cpos, find_leaf_ins, &bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -1980,7 +2058,7 @@ static void ocfs2_adjust_root_records(struct ocfs2_extent_list *root_el,
  *   - When we've adjusted the last extent record in the left path leaf and the
  *     1st extent record in the right path leaf during cross extent block merge.
  */
-static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle,
+static void ocfs2_complete_edge_insert(handle_t *handle,
                                       struct ocfs2_path *left_path,
                                       struct ocfs2_path *right_path,
                                       int subtree_index)
@@ -2058,8 +2136,8 @@ static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle,
                mlog_errno(ret);
 }
 
-static int ocfs2_rotate_subtree_right(struct inode *inode,
-                                     handle_t *handle,
+static int ocfs2_rotate_subtree_right(handle_t *handle,
+                                     struct ocfs2_extent_tree *et,
                                      struct ocfs2_path *left_path,
                                      struct ocfs2_path *right_path,
                                      int subtree_index)
@@ -2075,10 +2153,10 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
        left_el = path_leaf_el(left_path);
 
        if (left_el->l_next_free_rec != left_el->l_count) {
-               ocfs2_error(inode->i_sb,
+               ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
                            "Inode %llu has non-full interior leaf node %llu"
                            "(next free = %u)",
-                           (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                           (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                            (unsigned long long)left_leaf_bh->b_blocknr,
                            le16_to_cpu(left_el->l_next_free_rec));
                return -EROFS;
@@ -2094,7 +2172,7 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
        root_bh = left_path->p_node[subtree_index].bh;
        BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, right_path,
                                           subtree_index);
        if (ret) {
                mlog_errno(ret);
@@ -2102,14 +2180,14 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
        }
 
        for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-               ret = ocfs2_path_bh_journal_access(handle, inode,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                   right_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_path_bh_journal_access(handle, inode,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                   left_path, i);
                if (ret) {
                        mlog_errno(ret);
@@ -2123,7 +2201,7 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
        /* This is a code error, not a disk corruption. */
        mlog_bug_on_msg(!right_el->l_next_free_rec, "Inode %llu: Rotate fails "
                        "because rightmost leaf block %llu is empty\n",
-                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                        (unsigned long long)right_leaf_bh->b_blocknr);
 
        ocfs2_create_empty_extent(right_el);
@@ -2157,8 +2235,8 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
                goto out;
        }
 
-       ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
-                               subtree_index);
+       ocfs2_complete_edge_insert(handle, left_path, right_path,
+                                  subtree_index);
 
 out:
        return ret;
@@ -2248,10 +2326,18 @@ static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
                                           int op_credits,
                                           struct ocfs2_path *path)
 {
+       int ret;
        int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;
 
-       if (handle->h_buffer_credits < credits)
-               return ocfs2_extend_trans(handle, credits);
+       if (handle->h_buffer_credits < credits) {
+               ret = ocfs2_extend_trans(handle,
+                                        credits - handle->h_buffer_credits);
+               if (ret)
+                       return ret;
+
+               if (unlikely(handle->h_buffer_credits < credits))
+                       return ocfs2_extend_trans(handle, credits);
+       }
 
        return 0;
 }
@@ -2321,8 +2407,8 @@ static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
  *   *ret_left_path will contain a valid path which can be passed to
  *   ocfs2_insert_path().
  */
-static int ocfs2_rotate_tree_right(struct inode *inode,
-                                  handle_t *handle,
+static int ocfs2_rotate_tree_right(handle_t *handle,
+                                  struct ocfs2_extent_tree *et,
                                   enum ocfs2_split_type split,
                                   u32 insert_cpos,
                                   struct ocfs2_path *right_path,
@@ -2331,6 +2417,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
        int ret, start, orig_credits = handle->h_buffer_credits;
        u32 cpos;
        struct ocfs2_path *left_path = NULL;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
 
        *ret_left_path = NULL;
 
@@ -2341,7 +2428,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, right_path, &cpos);
+       ret = ocfs2_find_cpos_for_left_leaf(sb, right_path, &cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -2379,7 +2466,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
                mlog(0, "Rotating a tree: ins. cpos: %u, left path cpos: %u\n",
                     insert_cpos, cpos);
 
-               ret = ocfs2_find_path(inode, left_path, cpos);
+               ret = ocfs2_find_path(et->et_ci, left_path, cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2387,10 +2474,11 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
 
                mlog_bug_on_msg(path_leaf_bh(left_path) ==
                                path_leaf_bh(right_path),
-                               "Inode %lu: error during insert of %u "
+                               "Owner %llu: error during insert of %u "
                                "(left path cpos %u) results in two identical "
                                "paths ending at %llu\n",
-                               inode->i_ino, insert_cpos, cpos,
+                               (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+                               insert_cpos, cpos,
                                (unsigned long long)
                                path_leaf_bh(left_path)->b_blocknr);
 
@@ -2416,7 +2504,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
                        goto out_ret_path;
                }
 
-               start = ocfs2_find_subtree_root(inode, left_path, right_path);
+               start = ocfs2_find_subtree_root(et, left_path, right_path);
 
                mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
                     start,
@@ -2430,7 +2518,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
                        goto out;
                }
 
-               ret = ocfs2_rotate_subtree_right(inode, handle, left_path,
+               ret = ocfs2_rotate_subtree_right(handle, et, left_path,
                                                 right_path, start);
                if (ret) {
                        mlog_errno(ret);
@@ -2462,8 +2550,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
                 */
                ocfs2_mv_path(right_path, left_path);
 
-               ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, right_path,
-                                                   &cpos);
+               ret = ocfs2_find_cpos_for_left_leaf(sb, right_path, &cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2477,7 +2564,8 @@ out_ret_path:
        return ret;
 }
 
-static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
+static int ocfs2_update_edge_lengths(handle_t *handle,
+                                    struct ocfs2_extent_tree *et,
                                     int subtree_index, struct ocfs2_path *path)
 {
        int i, idx, ret;
@@ -2502,7 +2590,7 @@ static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
                goto out;
        }
 
-       ret = ocfs2_journal_access_path(inode, handle, path);
+       ret = ocfs2_journal_access_path(et->et_ci, handle, path);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -2532,7 +2620,8 @@ out:
        return ret;
 }
 
-static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
+static void ocfs2_unlink_path(handle_t *handle,
+                             struct ocfs2_extent_tree *et,
                              struct ocfs2_cached_dealloc_ctxt *dealloc,
                              struct ocfs2_path *path, int unlink_start)
 {
@@ -2554,12 +2643,12 @@ static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
                        mlog(ML_ERROR,
                             "Inode %llu, attempted to remove extent block "
                             "%llu with %u records\n",
-                            (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                             (unsigned long long)le64_to_cpu(eb->h_blkno),
                             le16_to_cpu(el->l_next_free_rec));
 
                        ocfs2_journal_dirty(handle, bh);
-                       ocfs2_remove_from_cache(inode, bh);
+                       ocfs2_remove_from_cache(et->et_ci, bh);
                        continue;
                }
 
@@ -2572,11 +2661,12 @@ static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
                if (ret)
                        mlog_errno(ret);
 
-               ocfs2_remove_from_cache(inode, bh);
+               ocfs2_remove_from_cache(et->et_ci, bh);
        }
 }
 
-static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
+static void ocfs2_unlink_subtree(handle_t *handle,
+                                struct ocfs2_extent_tree *et,
                                 struct ocfs2_path *left_path,
                                 struct ocfs2_path *right_path,
                                 int subtree_index,
@@ -2607,17 +2697,17 @@ static void ocfs2_unlink_subtree(struct inode *inode, handle_t *handle,
        ocfs2_journal_dirty(handle, root_bh);
        ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
 
-       ocfs2_unlink_path(inode, handle, dealloc, right_path,
+       ocfs2_unlink_path(handle, et, dealloc, right_path,
                          subtree_index + 1);
 }
 
-static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
+static int ocfs2_rotate_subtree_left(handle_t *handle,
+                                    struct ocfs2_extent_tree *et,
                                     struct ocfs2_path *left_path,
                                     struct ocfs2_path *right_path,
                                     int subtree_index,
                                     struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                    int *deleted,
-                                    struct ocfs2_extent_tree *et)
+                                    int *deleted)
 {
        int ret, i, del_right_subtree = 0, right_has_empty = 0;
        struct buffer_head *root_bh, *et_root_bh = path_root_bh(right_path);
@@ -2653,7 +2743,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                        return -EAGAIN;
 
                if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {
-                       ret = ocfs2_journal_access_eb(handle, inode,
+                       ret = ocfs2_journal_access_eb(handle, et->et_ci,
                                                      path_leaf_bh(right_path),
                                                      OCFS2_JOURNAL_ACCESS_WRITE);
                        if (ret) {
@@ -2672,7 +2762,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                 * We have to update i_last_eb_blk during the meta
                 * data delete.
                 */
-               ret = ocfs2_et_root_journal_access(handle, inode, et,
+               ret = ocfs2_et_root_journal_access(handle, et,
                                                   OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
@@ -2688,7 +2778,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
         */
        BUG_ON(right_has_empty && !del_right_subtree);
 
-       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, right_path,
                                           subtree_index);
        if (ret) {
                mlog_errno(ret);
@@ -2696,14 +2786,14 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
        }
 
        for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-               ret = ocfs2_path_bh_journal_access(handle, inode,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                   right_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_path_bh_journal_access(handle, inode,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                   left_path, i);
                if (ret) {
                        mlog_errno(ret);
@@ -2740,9 +2830,9 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                mlog_errno(ret);
 
        if (del_right_subtree) {
-               ocfs2_unlink_subtree(inode, handle, left_path, right_path,
+               ocfs2_unlink_subtree(handle, et, left_path, right_path,
                                     subtree_index, dealloc);
-               ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
+               ret = ocfs2_update_edge_lengths(handle, et, subtree_index,
                                                left_path);
                if (ret) {
                        mlog_errno(ret);
@@ -2766,7 +2856,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
 
                *deleted = 1;
        } else
-               ocfs2_complete_edge_insert(inode, handle, left_path, right_path,
+               ocfs2_complete_edge_insert(handle, left_path, right_path,
                                           subtree_index);
 
 out:
@@ -2852,8 +2942,8 @@ out:
        return ret;
 }
 
-static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
-                                           handle_t *handle,
+static int ocfs2_rotate_rightmost_leaf_left(handle_t *handle,
+                                           struct ocfs2_extent_tree *et,
                                            struct ocfs2_path *path)
 {
        int ret;
@@ -2863,7 +2953,7 @@ static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
        if (!ocfs2_is_empty_extent(&el->l_recs[0]))
                return 0;
 
-       ret = ocfs2_path_bh_journal_access(handle, inode, path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, path,
                                           path_num_items(path) - 1);
        if (ret) {
                mlog_errno(ret);
@@ -2880,24 +2970,24 @@ out:
        return ret;
 }
 
-static int __ocfs2_rotate_tree_left(struct inode *inode,
-                                   handle_t *handle, int orig_credits,
+static int __ocfs2_rotate_tree_left(handle_t *handle,
+                                   struct ocfs2_extent_tree *et,
+                                   int orig_credits,
                                    struct ocfs2_path *path,
                                    struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                   struct ocfs2_path **empty_extent_path,
-                                   struct ocfs2_extent_tree *et)
+                                   struct ocfs2_path **empty_extent_path)
 {
        int ret, subtree_root, deleted;
        u32 right_cpos;
        struct ocfs2_path *left_path = NULL;
        struct ocfs2_path *right_path = NULL;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
 
        BUG_ON(!ocfs2_is_empty_extent(&(path_leaf_el(path)->l_recs[0])));
 
        *empty_extent_path = NULL;
 
-       ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, path,
-                                            &right_cpos);
+       ret = ocfs2_find_cpos_for_right_leaf(sb, path, &right_cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -2920,13 +3010,13 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
        }
 
        while (right_cpos) {
-               ret = ocfs2_find_path(inode, right_path, right_cpos);
+               ret = ocfs2_find_path(et->et_ci, right_path, right_cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               subtree_root = ocfs2_find_subtree_root(inode, left_path,
+               subtree_root = ocfs2_find_subtree_root(et, left_path,
                                                       right_path);
 
                mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n",
@@ -2946,16 +3036,16 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
                 * Caller might still want to make changes to the
                 * tree root, so re-add it to the journal here.
                 */
-               ret = ocfs2_path_bh_journal_access(handle, inode,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                   left_path, 0);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
+               ret = ocfs2_rotate_subtree_left(handle, et, left_path,
                                                right_path, subtree_root,
-                                               dealloc, &deleted, et);
+                                               dealloc, &deleted);
                if (ret == -EAGAIN) {
                        /*
                         * The rotation has to temporarily stop due to
@@ -2982,7 +3072,7 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
 
                ocfs2_mv_path(left_path, right_path);
 
-               ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
+               ret = ocfs2_find_cpos_for_right_leaf(sb, left_path,
                                                     &right_cpos);
                if (ret) {
                        mlog_errno(ret);
@@ -2997,10 +3087,10 @@ out:
        return ret;
 }
 
-static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
+static int ocfs2_remove_rightmost_path(handle_t *handle,
+                               struct ocfs2_extent_tree *et,
                                struct ocfs2_path *path,
-                               struct ocfs2_cached_dealloc_ctxt *dealloc,
-                               struct ocfs2_extent_tree *et)
+                               struct ocfs2_cached_dealloc_ctxt *dealloc)
 {
        int ret, subtree_index;
        u32 cpos;
@@ -3009,7 +3099,7 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
        struct ocfs2_extent_list *el;
 
 
-       ret = ocfs2_et_sanity_check(inode, et);
+       ret = ocfs2_et_sanity_check(et);
        if (ret)
                goto out;
        /*
@@ -3024,13 +3114,14 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                goto out;
        }
 
-       ret = ocfs2_journal_access_path(inode, handle, path);
+       ret = ocfs2_journal_access_path(et->et_ci, handle, path);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path, &cpos);
+       ret = ocfs2_find_cpos_for_left_leaf(ocfs2_metadata_cache_get_super(et->et_ci),
+                                           path, &cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3048,23 +3139,23 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                        goto out;
                }
 
-               ret = ocfs2_find_path(inode, left_path, cpos);
+               ret = ocfs2_find_path(et->et_ci, left_path, cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_journal_access_path(inode, handle, left_path);
+               ret = ocfs2_journal_access_path(et->et_ci, handle, left_path);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
+               subtree_index = ocfs2_find_subtree_root(et, left_path, path);
 
-               ocfs2_unlink_subtree(inode, handle, left_path, path,
+               ocfs2_unlink_subtree(handle, et, left_path, path,
                                     subtree_index, dealloc);
-               ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
+               ret = ocfs2_update_edge_lengths(handle, et, subtree_index,
                                                left_path);
                if (ret) {
                        mlog_errno(ret);
@@ -3078,10 +3169,10 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                 * 'path' is also the leftmost path which
                 * means it must be the only one. This gets
                 * handled differently because we want to
-                * revert the inode back to having extents
+                * revert the root back to having extents
                 * in-line.
                 */
-               ocfs2_unlink_path(inode, handle, dealloc, path, 1);
+               ocfs2_unlink_path(handle, et, dealloc, path, 1);
 
                el = et->et_root_el;
                el->l_tree_depth = 0;
@@ -3114,10 +3205,10 @@ out:
  * the rightmost tree leaf record is removed so the caller is
  * responsible for detecting and correcting that.
  */
-static int ocfs2_rotate_tree_left(struct inode *inode, handle_t *handle,
+static int ocfs2_rotate_tree_left(handle_t *handle,
+                                 struct ocfs2_extent_tree *et,
                                  struct ocfs2_path *path,
-                                 struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                 struct ocfs2_extent_tree *et)
+                                 struct ocfs2_cached_dealloc_ctxt *dealloc)
 {
        int ret, orig_credits = handle->h_buffer_credits;
        struct ocfs2_path *tmp_path = NULL, *restart_path = NULL;
@@ -3134,8 +3225,7 @@ rightmost_no_delete:
                 * Inline extents. This is trivially handled, so do
                 * it up front.
                 */
-               ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
-                                                      path);
+               ret = ocfs2_rotate_rightmost_leaf_left(handle, et, path);
                if (ret)
                        mlog_errno(ret);
                goto out;
@@ -3151,7 +3241,7 @@ rightmost_no_delete:
         *
         *  1) is handled via ocfs2_rotate_rightmost_leaf_left()
         *  2a) we need the left branch so that we can update it with the unlink
-        *  2b) we need to bring the inode back to inline extents.
+        *  2b) we need to bring the root back to inline extents.
         */
 
        eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
@@ -3167,9 +3257,9 @@ rightmost_no_delete:
 
                if (le16_to_cpu(el->l_next_free_rec) == 0) {
                        ret = -EIO;
-                       ocfs2_error(inode->i_sb,
-                                   "Inode %llu has empty extent block at %llu",
-                                   (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                                   "Owner %llu has empty extent block at %llu",
+                                   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                                    (unsigned long long)le64_to_cpu(eb->h_blkno));
                        goto out;
                }
@@ -3183,8 +3273,8 @@ rightmost_no_delete:
                 * nonempty list.
                 */
 
-               ret = ocfs2_remove_rightmost_path(inode, handle, path,
-                                                 dealloc, et);
+               ret = ocfs2_remove_rightmost_path(handle, et, path,
+                                                 dealloc);
                if (ret)
                        mlog_errno(ret);
                goto out;
@@ -3195,8 +3285,8 @@ rightmost_no_delete:
         * and restarting from there.
         */
 try_rotate:
-       ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits, path,
-                                      dealloc, &restart_path, et);
+       ret = __ocfs2_rotate_tree_left(handle, et, orig_credits, path,
+                                      dealloc, &restart_path);
        if (ret && ret != -EAGAIN) {
                mlog_errno(ret);
                goto out;
@@ -3206,9 +3296,9 @@ try_rotate:
                tmp_path = restart_path;
                restart_path = NULL;
 
-               ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits,
+               ret = __ocfs2_rotate_tree_left(handle, et, orig_credits,
                                               tmp_path, dealloc,
-                                              &restart_path, et);
+                                              &restart_path);
                if (ret && ret != -EAGAIN) {
                        mlog_errno(ret);
                        goto out;
@@ -3259,7 +3349,7 @@ static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
        }
 }
 
-static int ocfs2_get_right_path(struct inode *inode,
+static int ocfs2_get_right_path(struct ocfs2_extent_tree *et,
                                struct ocfs2_path *left_path,
                                struct ocfs2_path **ret_right_path)
 {
@@ -3276,8 +3366,8 @@ static int ocfs2_get_right_path(struct inode *inode,
        left_el = path_leaf_el(left_path);
        BUG_ON(left_el->l_next_free_rec != left_el->l_count);
 
-       ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
-                                            &right_cpos);
+       ret = ocfs2_find_cpos_for_right_leaf(ocfs2_metadata_cache_get_super(et->et_ci),
+                                            left_path, &right_cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3293,7 +3383,7 @@ static int ocfs2_get_right_path(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_find_path(inode, right_path, right_cpos);
+       ret = ocfs2_find_path(et->et_ci, right_path, right_cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3313,9 +3403,9 @@ out:
  * For index == l_count - 1, the "next" means the 1st extent rec of the
  * next extent block.
  */
-static int ocfs2_merge_rec_right(struct inode *inode,
-                                struct ocfs2_path *left_path,
+static int ocfs2_merge_rec_right(struct ocfs2_path *left_path,
                                 handle_t *handle,
+                                struct ocfs2_extent_tree *et,
                                 struct ocfs2_extent_rec *split_rec,
                                 int index)
 {
@@ -3336,7 +3426,7 @@ static int ocfs2_merge_rec_right(struct inode *inode,
        if (index == le16_to_cpu(el->l_next_free_rec) - 1 &&
            le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count)) {
                /* we meet with a cross extent block merge. */
-               ret = ocfs2_get_right_path(inode, left_path, &right_path);
+               ret = ocfs2_get_right_path(et, left_path, &right_path);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3355,8 +3445,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                       le16_to_cpu(left_rec->e_leaf_clusters) !=
                       le32_to_cpu(right_rec->e_cpos));
 
-               subtree_index = ocfs2_find_subtree_root(inode,
-                                                       left_path, right_path);
+               subtree_index = ocfs2_find_subtree_root(et, left_path,
+                                                       right_path);
 
                ret = ocfs2_extend_rotate_transaction(handle, subtree_index,
                                                      handle->h_buffer_credits,
@@ -3369,7 +3459,7 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                root_bh = left_path->p_node[subtree_index].bh;
                BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-               ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci, right_path,
                                                   subtree_index);
                if (ret) {
                        mlog_errno(ret);
@@ -3378,14 +3468,14 @@ static int ocfs2_merge_rec_right(struct inode *inode,
 
                for (i = subtree_index + 1;
                     i < path_num_items(right_path); i++) {
-                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                       ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                           right_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
 
-                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                       ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                           left_path, i);
                        if (ret) {
                                mlog_errno(ret);
@@ -3398,7 +3488,7 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                right_rec = &el->l_recs[index + 1];
        }
 
-       ret = ocfs2_path_bh_journal_access(handle, inode, left_path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, left_path,
                                           path_num_items(left_path) - 1);
        if (ret) {
                mlog_errno(ret);
@@ -3409,7 +3499,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
 
        le32_add_cpu(&right_rec->e_cpos, -split_clusters);
        le64_add_cpu(&right_rec->e_blkno,
-                    -ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+                    -ocfs2_clusters_to_blocks(ocfs2_metadata_cache_get_super(et->et_ci),
+                                              split_clusters));
        le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
 
        ocfs2_cleanup_merge(el, index);
@@ -3423,8 +3514,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                if (ret)
                        mlog_errno(ret);
 
-               ocfs2_complete_edge_insert(inode, handle, left_path,
-                                          right_path, subtree_index);
+               ocfs2_complete_edge_insert(handle, left_path, right_path,
+                                          subtree_index);
        }
 out:
        if (right_path)
@@ -3432,7 +3523,7 @@ out:
        return ret;
 }
 
-static int ocfs2_get_left_path(struct inode *inode,
+static int ocfs2_get_left_path(struct ocfs2_extent_tree *et,
                               struct ocfs2_path *right_path,
                               struct ocfs2_path **ret_left_path)
 {
@@ -3445,7 +3536,7 @@ static int ocfs2_get_left_path(struct inode *inode,
        /* This function shouldn't be called for non-trees. */
        BUG_ON(right_path->p_tree_depth == 0);
 
-       ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
+       ret = ocfs2_find_cpos_for_left_leaf(ocfs2_metadata_cache_get_super(et->et_ci),
                                            right_path, &left_cpos);
        if (ret) {
                mlog_errno(ret);
@@ -3462,7 +3553,7 @@ static int ocfs2_get_left_path(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_find_path(inode, left_path, left_cpos);
+       ret = ocfs2_find_path(et->et_ci, left_path, left_cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3485,12 +3576,11 @@ out:
  * remove the rightmost leaf extent block in the right_path and change
  * the right path to indicate the new rightmost path.
  */
-static int ocfs2_merge_rec_left(struct inode *inode,
-                               struct ocfs2_path *right_path,
+static int ocfs2_merge_rec_left(struct ocfs2_path *right_path,
                                handle_t *handle,
+                               struct ocfs2_extent_tree *et,
                                struct ocfs2_extent_rec *split_rec,
                                struct ocfs2_cached_dealloc_ctxt *dealloc,
-                               struct ocfs2_extent_tree *et,
                                int index)
 {
        int ret, i, subtree_index = 0, has_empty_extent = 0;
@@ -3508,7 +3598,7 @@ static int ocfs2_merge_rec_left(struct inode *inode,
        right_rec = &el->l_recs[index];
        if (index == 0) {
                /* we meet with a cross extent block merge. */
-               ret = ocfs2_get_left_path(inode, right_path, &left_path);
+               ret = ocfs2_get_left_path(et, right_path, &left_path);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3524,8 +3614,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                       le16_to_cpu(left_rec->e_leaf_clusters) !=
                       le32_to_cpu(split_rec->e_cpos));
 
-               subtree_index = ocfs2_find_subtree_root(inode,
-                                                       left_path, right_path);
+               subtree_index = ocfs2_find_subtree_root(et, left_path,
+                                                       right_path);
 
                ret = ocfs2_extend_rotate_transaction(handle, subtree_index,
                                                      handle->h_buffer_credits,
@@ -3538,7 +3628,7 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                root_bh = left_path->p_node[subtree_index].bh;
                BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-               ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+               ret = ocfs2_path_bh_journal_access(handle, et->et_ci, right_path,
                                                   subtree_index);
                if (ret) {
                        mlog_errno(ret);
@@ -3547,14 +3637,14 @@ static int ocfs2_merge_rec_left(struct inode *inode,
 
                for (i = subtree_index + 1;
                     i < path_num_items(right_path); i++) {
-                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                       ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                           right_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
 
-                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                       ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
                                                           left_path, i);
                        if (ret) {
                                mlog_errno(ret);
@@ -3567,7 +3657,7 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                        has_empty_extent = 1;
        }
 
-       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, right_path,
                                           path_num_items(right_path) - 1);
        if (ret) {
                mlog_errno(ret);
@@ -3586,7 +3676,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
 
        le32_add_cpu(&right_rec->e_cpos, split_clusters);
        le64_add_cpu(&right_rec->e_blkno,
-                    ocfs2_clusters_to_blocks(inode->i_sb, split_clusters));
+                    ocfs2_clusters_to_blocks(ocfs2_metadata_cache_get_super(et->et_ci),
+                                             split_clusters));
        le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
 
        ocfs2_cleanup_merge(el, index);
@@ -3608,9 +3699,9 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                if (le16_to_cpu(right_rec->e_leaf_clusters) == 0 &&
                    le16_to_cpu(el->l_next_free_rec) == 1) {
 
-                       ret = ocfs2_remove_rightmost_path(inode, handle,
+                       ret = ocfs2_remove_rightmost_path(handle, et,
                                                          right_path,
-                                                         dealloc, et);
+                                                         dealloc);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -3622,7 +3713,7 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                        ocfs2_mv_path(right_path, left_path);
                        left_path = NULL;
                } else
-                       ocfs2_complete_edge_insert(inode, handle, left_path,
+                       ocfs2_complete_edge_insert(handle, left_path,
                                                   right_path, subtree_index);
        }
 out:
@@ -3631,15 +3722,13 @@ out:
        return ret;
 }
 
-static int ocfs2_try_to_merge_extent(struct inode *inode,
-                                    handle_t *handle,
+static int ocfs2_try_to_merge_extent(handle_t *handle,
+                                    struct ocfs2_extent_tree *et,
                                     struct ocfs2_path *path,
                                     int split_index,
                                     struct ocfs2_extent_rec *split_rec,
                                     struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                    struct ocfs2_merge_ctxt *ctxt,
-                                    struct ocfs2_extent_tree *et)
-
+                                    struct ocfs2_merge_ctxt *ctxt)
 {
        int ret = 0;
        struct ocfs2_extent_list *el = path_leaf_el(path);
@@ -3655,8 +3744,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                 * extents - having more than one in a leaf is
                 * illegal.
                 */
-               ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                            dealloc, et);
+               ret = ocfs2_rotate_tree_left(handle, et, path, dealloc);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3685,8 +3773,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                 * prevoius extent block. It is more efficient and easier
                 * if we do merge_right first and merge_left later.
                 */
-               ret = ocfs2_merge_rec_right(inode, path,
-                                           handle, split_rec,
+               ret = ocfs2_merge_rec_right(path, handle, et, split_rec,
                                            split_index);
                if (ret) {
                        mlog_errno(ret);
@@ -3699,8 +3786,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
 
                /* The merge left us with an empty extent, remove it. */
-               ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                            dealloc, et);
+               ret = ocfs2_rotate_tree_left(handle, et, path, dealloc);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3712,18 +3798,15 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                 * Note that we don't pass split_rec here on purpose -
                 * we've merged it into the rec already.
                 */
-               ret = ocfs2_merge_rec_left(inode, path,
-                                          handle, rec,
-                                          dealloc, et,
-                                          split_index);
+               ret = ocfs2_merge_rec_left(path, handle, et, rec,
+                                          dealloc, split_index);
 
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                            dealloc, et);
+               ret = ocfs2_rotate_tree_left(handle, et, path, dealloc);
                /*
                 * Error from this last rotate is not critical, so
                 * print but don't bubble it up.
@@ -3740,19 +3823,16 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                 * the record on the left (hence the left merge).
                 */
                if (ctxt->c_contig_type == CONTIG_RIGHT) {
-                       ret = ocfs2_merge_rec_left(inode,
-                                                  path,
-                                                  handle, split_rec,
-                                                  dealloc, et,
+                       ret = ocfs2_merge_rec_left(path, handle, et,
+                                                  split_rec, dealloc,
                                                   split_index);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
                } else {
-                       ret = ocfs2_merge_rec_right(inode,
-                                                   path,
-                                                   handle, split_rec,
+                       ret = ocfs2_merge_rec_right(path, handle,
+                                                   et, split_rec,
                                                    split_index);
                        if (ret) {
                                mlog_errno(ret);
@@ -3765,8 +3845,8 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                         * The merge may have left an empty extent in
                         * our leaf. Try to rotate it away.
                         */
-                       ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                                    dealloc, et);
+                       ret = ocfs2_rotate_tree_left(handle, et, path,
+                                                    dealloc);
                        if (ret)
                                mlog_errno(ret);
                        ret = 0;
@@ -3812,10 +3892,10 @@ static void ocfs2_subtract_from_rec(struct super_block *sb,
  * list. If this leaf is part of an allocation tree, it is assumed
  * that the tree above has been prepared.
  */
-static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
+static void ocfs2_insert_at_leaf(struct ocfs2_extent_tree *et,
+                                struct ocfs2_extent_rec *insert_rec,
                                 struct ocfs2_extent_list *el,
-                                struct ocfs2_insert_type *insert,
-                                struct inode *inode)
+                                struct ocfs2_insert_type *insert)
 {
        int i = insert->ins_contig_index;
        unsigned int range;
@@ -3827,7 +3907,8 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
                i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
                BUG_ON(i == -1);
                rec = &el->l_recs[i];
-               ocfs2_subtract_from_rec(inode->i_sb, insert->ins_split, rec,
+               ocfs2_subtract_from_rec(ocfs2_metadata_cache_get_super(et->et_ci),
+                                       insert->ins_split, rec,
                                        insert_rec);
                goto rotate;
        }
@@ -3869,10 +3950,10 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_rec *insert_rec,
 
                mlog_bug_on_msg(le16_to_cpu(el->l_next_free_rec) >=
                                le16_to_cpu(el->l_count),
-                               "inode %lu, depth %u, count %u, next free %u, "
+                               "owner %llu, depth %u, count %u, next free %u, "
                                "rec.cpos %u, rec.clusters %u, "
                                "insert.cpos %u, insert.clusters %u\n",
-                               inode->i_ino,
+                               ocfs2_metadata_cache_owner(et->et_ci),
                                le16_to_cpu(el->l_tree_depth),
                                le16_to_cpu(el->l_count),
                                le16_to_cpu(el->l_next_free_rec),
@@ -3900,8 +3981,8 @@ rotate:
        ocfs2_rotate_leaf(el, insert_rec);
 }
 
-static void ocfs2_adjust_rightmost_records(struct inode *inode,
-                                          handle_t *handle,
+static void ocfs2_adjust_rightmost_records(handle_t *handle,
+                                          struct ocfs2_extent_tree *et,
                                           struct ocfs2_path *path,
                                           struct ocfs2_extent_rec *insert_rec)
 {
@@ -3919,9 +4000,9 @@ static void ocfs2_adjust_rightmost_records(struct inode *inode,
 
                next_free = le16_to_cpu(el->l_next_free_rec);
                if (next_free == 0) {
-                       ocfs2_error(inode->i_sb,
-                                   "Dinode %llu has a bad extent list",
-                                   (unsigned long long)OCFS2_I(inode)->ip_blkno);
+                       ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                                   "Owner %llu has a bad extent list",
+                                   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
                        ret = -EIO;
                        return;
                }
@@ -3941,7 +4022,8 @@ static void ocfs2_adjust_rightmost_records(struct inode *inode,
        }
 }
 
-static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
+static int ocfs2_append_rec_to_path(handle_t *handle,
+                                   struct ocfs2_extent_tree *et,
                                    struct ocfs2_extent_rec *insert_rec,
                                    struct ocfs2_path *right_path,
                                    struct ocfs2_path **ret_left_path)
@@ -3969,8 +4051,8 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
            (next_free == 1 && ocfs2_is_empty_extent(&el->l_recs[0]))) {
                u32 left_cpos;
 
-               ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, right_path,
-                                                   &left_cpos);
+               ret = ocfs2_find_cpos_for_left_leaf(ocfs2_metadata_cache_get_super(et->et_ci),
+                                                   right_path, &left_cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3992,7 +4074,8 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
                                goto out;
                        }
 
-                       ret = ocfs2_find_path(inode, left_path, left_cpos);
+                       ret = ocfs2_find_path(et->et_ci, left_path,
+                                             left_cpos);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -4005,13 +4088,13 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
                }
        }
 
-       ret = ocfs2_journal_access_path(inode, handle, right_path);
+       ret = ocfs2_journal_access_path(et->et_ci, handle, right_path);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ocfs2_adjust_rightmost_records(inode, handle, right_path, insert_rec);
+       ocfs2_adjust_rightmost_records(handle, et, right_path, insert_rec);
 
        *ret_left_path = left_path;
        ret = 0;
@@ -4022,7 +4105,7 @@ out:
        return ret;
 }
 
-static void ocfs2_split_record(struct inode *inode,
+static void ocfs2_split_record(struct ocfs2_extent_tree *et,
                               struct ocfs2_path *left_path,
                               struct ocfs2_path *right_path,
                               struct ocfs2_extent_rec *split_rec,
@@ -4095,7 +4178,8 @@ static void ocfs2_split_record(struct inode *inode,
        }
 
        rec = &el->l_recs[index];
-       ocfs2_subtract_from_rec(inode->i_sb, split, rec, split_rec);
+       ocfs2_subtract_from_rec(ocfs2_metadata_cache_get_super(et->et_ci),
+                               split, rec, split_rec);
        ocfs2_rotate_leaf(insert_el, split_rec);
 }
 
@@ -4107,8 +4191,8 @@ static void ocfs2_split_record(struct inode *inode,
  * in. left_path should only be passed in if we need to update that
  * portion of the tree after an edge insert.
  */
-static int ocfs2_insert_path(struct inode *inode,
-                            handle_t *handle,
+static int ocfs2_insert_path(handle_t *handle,
+                            struct ocfs2_extent_tree *et,
                             struct ocfs2_path *left_path,
                             struct ocfs2_path *right_path,
                             struct ocfs2_extent_rec *insert_rec,
@@ -4134,7 +4218,7 @@ static int ocfs2_insert_path(struct inode *inode,
                        goto out;
                }
 
-               ret = ocfs2_journal_access_path(inode, handle, left_path);
+               ret = ocfs2_journal_access_path(et->et_ci, handle, left_path);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -4145,7 +4229,7 @@ static int ocfs2_insert_path(struct inode *inode,
         * Pass both paths to the journal. The majority of inserts
         * will be touching all components anyway.
         */
-       ret = ocfs2_journal_access_path(inode, handle, right_path);
+       ret = ocfs2_journal_access_path(et->et_ci, handle, right_path);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -4157,7 +4241,7 @@ static int ocfs2_insert_path(struct inode *inode,
                 * of splits, but it's easier to just let one separate
                 * function sort it all out.
                 */
-               ocfs2_split_record(inode, left_path, right_path,
+               ocfs2_split_record(et, left_path, right_path,
                                   insert_rec, insert->ins_split);
 
                /*
@@ -4171,8 +4255,8 @@ static int ocfs2_insert_path(struct inode *inode,
                        if (ret)
                                mlog_errno(ret);
        } else
-               ocfs2_insert_at_leaf(insert_rec, path_leaf_el(right_path),
-                                    insert, inode);
+               ocfs2_insert_at_leaf(et, insert_rec, path_leaf_el(right_path),
+                                    insert);
 
        ret = ocfs2_journal_dirty(handle, leaf_bh);
        if (ret)
@@ -4185,10 +4269,10 @@ static int ocfs2_insert_path(struct inode *inode,
                 *
                 * XXX: Should we extend the transaction here?
                 */
-               subtree_index = ocfs2_find_subtree_root(inode, left_path,
+               subtree_index = ocfs2_find_subtree_root(et, left_path,
                                                        right_path);
-               ocfs2_complete_edge_insert(inode, handle, left_path,
-                                          right_path, subtree_index);
+               ocfs2_complete_edge_insert(handle, left_path, right_path,
+                                          subtree_index);
        }
 
        ret = 0;
@@ -4196,8 +4280,7 @@ out:
        return ret;
 }
 
-static int ocfs2_do_insert_extent(struct inode *inode,
-                                 handle_t *handle,
+static int ocfs2_do_insert_extent(handle_t *handle,
                                  struct ocfs2_extent_tree *et,
                                  struct ocfs2_extent_rec *insert_rec,
                                  struct ocfs2_insert_type *type)
@@ -4210,7 +4293,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
 
        el = et->et_root_el;
 
-       ret = ocfs2_et_root_journal_access(handle, inode, et,
+       ret = ocfs2_et_root_journal_access(handle, et,
                                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -4218,7 +4301,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
        }
 
        if (le16_to_cpu(el->l_tree_depth) == 0) {
-               ocfs2_insert_at_leaf(insert_rec, el, type, inode);
+               ocfs2_insert_at_leaf(et, insert_rec, el, type);
                goto out_update_clusters;
        }
 
@@ -4241,7 +4324,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                cpos = UINT_MAX;
        }
 
-       ret = ocfs2_find_path(inode, right_path, cpos);
+       ret = ocfs2_find_path(et->et_ci, right_path, cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4260,7 +4343,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
         * can wind up skipping both of these two special cases...
         */
        if (rotate) {
-               ret = ocfs2_rotate_tree_right(inode, handle, type->ins_split,
+               ret = ocfs2_rotate_tree_right(handle, et, type->ins_split,
                                              le32_to_cpu(insert_rec->e_cpos),
                                              right_path, &left_path);
                if (ret) {
@@ -4272,7 +4355,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                 * ocfs2_rotate_tree_right() might have extended the
                 * transaction without re-journaling our tree root.
                 */
-               ret = ocfs2_et_root_journal_access(handle, inode, et,
+               ret = ocfs2_et_root_journal_access(handle, et,
                                                   OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
@@ -4280,7 +4363,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                }
        } else if (type->ins_appending == APPEND_TAIL
                   && type->ins_contig != CONTIG_LEFT) {
-               ret = ocfs2_append_rec_to_path(inode, handle, insert_rec,
+               ret = ocfs2_append_rec_to_path(handle, et, insert_rec,
                                               right_path, &left_path);
                if (ret) {
                        mlog_errno(ret);
@@ -4288,7 +4371,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                }
        }
 
-       ret = ocfs2_insert_path(inode, handle, left_path, right_path,
+       ret = ocfs2_insert_path(handle, et, left_path, right_path,
                                insert_rec, type);
        if (ret) {
                mlog_errno(ret);
@@ -4297,7 +4380,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
 
 out_update_clusters:
        if (type->ins_split == SPLIT_NONE)
-               ocfs2_et_update_clusters(inode, et,
+               ocfs2_et_update_clusters(et,
                                         le16_to_cpu(insert_rec->e_leaf_clusters));
 
        ret = ocfs2_journal_dirty(handle, et->et_root_bh);
@@ -4312,7 +4395,8 @@ out:
 }
 
 static enum ocfs2_contig_type
-ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
+ocfs2_figure_merge_contig_type(struct ocfs2_extent_tree *et,
+                              struct ocfs2_path *path,
                               struct ocfs2_extent_list *el, int index,
                               struct ocfs2_extent_rec *split_rec)
 {
@@ -4324,12 +4408,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
        struct ocfs2_path *left_path = NULL, *right_path = NULL;
        struct buffer_head *bh;
        struct ocfs2_extent_block *eb;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
 
        if (index > 0) {
                rec = &el->l_recs[index - 1];
        } else if (path->p_tree_depth > 0) {
-               status = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
-                                                      path, &left_cpos);
+               status = ocfs2_find_cpos_for_left_leaf(sb, path, &left_cpos);
                if (status)
                        goto out;
 
@@ -4338,7 +4422,8 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        if (!left_path)
                                goto out;
 
-                       status = ocfs2_find_path(inode, left_path, left_cpos);
+                       status = ocfs2_find_path(et->et_ci, left_path,
+                                                left_cpos);
                        if (status)
                                goto out;
 
@@ -4348,7 +4433,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                            le16_to_cpu(new_el->l_count)) {
                                bh = path_leaf_bh(left_path);
                                eb = (struct ocfs2_extent_block *)bh->b_data;
-                               ocfs2_error(inode->i_sb,
+                               ocfs2_error(sb,
                                            "Extent block #%llu has an "
                                            "invalid l_next_free_rec of "
                                            "%d.  It should have "
@@ -4373,7 +4458,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        if (split_rec->e_cpos == el->l_recs[index].e_cpos)
                                ret = CONTIG_RIGHT;
                } else {
-                       ret = ocfs2_extent_contig(inode, rec, split_rec);
+                       ret = ocfs2_et_extent_contig(et, rec, split_rec);
                }
        }
 
@@ -4382,8 +4467,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                rec = &el->l_recs[index + 1];
        else if (le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count) &&
                 path->p_tree_depth > 0) {
-               status = ocfs2_find_cpos_for_right_leaf(inode->i_sb,
-                                                       path, &right_cpos);
+               status = ocfs2_find_cpos_for_right_leaf(sb, path, &right_cpos);
                if (status)
                        goto out;
 
@@ -4394,7 +4478,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                if (!right_path)
                        goto out;
 
-               status = ocfs2_find_path(inode, right_path, right_cpos);
+               status = ocfs2_find_path(et->et_ci, right_path, right_cpos);
                if (status)
                        goto out;
 
@@ -4404,7 +4488,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        if (le16_to_cpu(new_el->l_next_free_rec) <= 1) {
                                bh = path_leaf_bh(right_path);
                                eb = (struct ocfs2_extent_block *)bh->b_data;
-                               ocfs2_error(inode->i_sb,
+                               ocfs2_error(sb,
                                            "Extent block #%llu has an "
                                            "invalid l_next_free_rec of %d",
                                            (unsigned long long)le64_to_cpu(eb->h_blkno),
@@ -4419,7 +4503,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
        if (rec) {
                enum ocfs2_contig_type contig_type;
 
-               contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+               contig_type = ocfs2_et_extent_contig(et, rec, split_rec);
 
                if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
                        ret = CONTIG_LEFTRIGHT;
@@ -4436,11 +4520,10 @@ out:
        return ret;
 }
 
-static void ocfs2_figure_contig_type(struct inode *inode,
+static void ocfs2_figure_contig_type(struct ocfs2_extent_tree *et,
                                     struct ocfs2_insert_type *insert,
                                     struct ocfs2_extent_list *el,
-                                    struct ocfs2_extent_rec *insert_rec,
-                                    struct ocfs2_extent_tree *et)
+                                    struct ocfs2_extent_rec *insert_rec)
 {
        int i;
        enum ocfs2_contig_type contig_type = CONTIG_NONE;
@@ -4448,8 +4531,8 @@ static void ocfs2_figure_contig_type(struct inode *inode,
        BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
 
        for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
-               contig_type = ocfs2_extent_contig(inode, &el->l_recs[i],
-                                                 insert_rec);
+               contig_type = ocfs2_et_extent_contig(et, &el->l_recs[i],
+                                                    insert_rec);
                if (contig_type != CONTIG_NONE) {
                        insert->ins_contig_index = i;
                        break;
@@ -4530,8 +4613,7 @@ set_tail_append:
  * All of the information is stored on the ocfs2_insert_type
  * structure.
  */
-static int ocfs2_figure_insert_type(struct inode *inode,
-                                   struct ocfs2_extent_tree *et,
+static int ocfs2_figure_insert_type(struct ocfs2_extent_tree *et,
                                    struct buffer_head **last_eb_bh,
                                    struct ocfs2_extent_rec *insert_rec,
                                    int *free_records,
@@ -4555,7 +4637,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                 * ocfs2_figure_insert_type() and ocfs2_add_branch()
                 * may want it later.
                 */
-               ret = ocfs2_read_extent_block(inode,
+               ret = ocfs2_read_extent_block(et->et_ci,
                                              ocfs2_et_get_last_eb_blk(et),
                                              &bh);
                if (ret) {
@@ -4578,7 +4660,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                le16_to_cpu(el->l_next_free_rec);
 
        if (!insert->ins_tree_depth) {
-               ocfs2_figure_contig_type(inode, insert, el, insert_rec, et);
+               ocfs2_figure_contig_type(et, insert, el, insert_rec);
                ocfs2_figure_appending_type(insert, el, insert_rec);
                return 0;
        }
@@ -4596,7 +4678,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
         * us the rightmost tree path. This is accounted for below in
         * the appending code.
         */
-       ret = ocfs2_find_path(inode, path, le32_to_cpu(insert_rec->e_cpos));
+       ret = ocfs2_find_path(et->et_ci, path, le32_to_cpu(insert_rec->e_cpos));
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4612,7 +4694,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
          *     into two types of appends: simple record append, or a
          *     rotate inside the tail leaf.
         */
-       ocfs2_figure_contig_type(inode, insert, el, insert_rec, et);
+       ocfs2_figure_contig_type(et, insert, el, insert_rec);
 
        /*
         * The insert code isn't quite ready to deal with all cases of
@@ -4657,13 +4739,11 @@ out:
 }
 
 /*
- * Insert an extent into an inode btree.
+ * Insert an extent into a btree.
  *
- * The caller needs to update fe->i_clusters
+ * The caller needs to update the owning btree's cluster count.
  */
-int ocfs2_insert_extent(struct ocfs2_super *osb,
-                       handle_t *handle,
-                       struct inode *inode,
+int ocfs2_insert_extent(handle_t *handle,
                        struct ocfs2_extent_tree *et,
                        u32 cpos,
                        u64 start_blk,
@@ -4677,21 +4757,22 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
        struct ocfs2_insert_type insert = {0, };
        struct ocfs2_extent_rec rec;
 
-       mlog(0, "add %u clusters at position %u to inode %llu\n",
-            new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       mlog(0, "add %u clusters at position %u to owner %llu\n",
+            new_clusters, cpos,
+            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
 
        memset(&rec, 0, sizeof(rec));
        rec.e_cpos = cpu_to_le32(cpos);
        rec.e_blkno = cpu_to_le64(start_blk);
        rec.e_leaf_clusters = cpu_to_le16(new_clusters);
        rec.e_flags = flags;
-       status = ocfs2_et_insert_check(inode, et, &rec);
+       status = ocfs2_et_insert_check(et, &rec);
        if (status) {
                mlog_errno(status);
                goto bail;
        }
 
-       status = ocfs2_figure_insert_type(inode, et, &last_eb_bh, &rec,
+       status = ocfs2_figure_insert_type(et, &last_eb_bh, &rec,
                                          &free_records, &insert);
        if (status < 0) {
                mlog_errno(status);
@@ -4705,7 +4786,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
             free_records, insert.ins_tree_depth);
 
        if (insert.ins_contig == CONTIG_NONE && free_records == 0) {
-               status = ocfs2_grow_tree(inode, handle, et,
+               status = ocfs2_grow_tree(handle, et,
                                         &insert.ins_tree_depth, &last_eb_bh,
                                         meta_ac);
                if (status) {
@@ -4715,11 +4796,11 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
        }
 
        /* Finally, we can add clusters. This might rotate the tree for us. */
-       status = ocfs2_do_insert_extent(inode, handle, et, &rec, &insert);
+       status = ocfs2_do_insert_extent(handle, et, &rec, &insert);
        if (status < 0)
                mlog_errno(status);
-       else if (et->et_ops == &ocfs2_dinode_et_ops)
-               ocfs2_extent_map_insert_rec(inode, &rec);
+       else
+               ocfs2_et_extent_map_insert(et, &rec);
 
 bail:
        brelse(last_eb_bh);
@@ -4735,13 +4816,11 @@ bail:
  * it is not limited to the file storage. Any extent tree can use this
  * function if it implements the proper ocfs2_extent_tree.
  */
-int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
-                               struct inode *inode,
+int ocfs2_add_clusters_in_btree(handle_t *handle,
+                               struct ocfs2_extent_tree *et,
                                u32 *logical_offset,
                                u32 clusters_to_add,
                                int mark_unwritten,
-                               struct ocfs2_extent_tree *et,
-                               handle_t *handle,
                                struct ocfs2_alloc_context *data_ac,
                                struct ocfs2_alloc_context *meta_ac,
                                enum ocfs2_alloc_restarted *reason_ret)
@@ -4752,13 +4831,15 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
        u32 bit_off, num_bits;
        u64 block;
        u8 flags = 0;
+       struct ocfs2_super *osb =
+               OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));
 
        BUG_ON(!clusters_to_add);
 
        if (mark_unwritten)
                flags = OCFS2_EXT_UNWRITTEN;
 
-       free_extents = ocfs2_num_free_extents(osb, inode, et);
+       free_extents = ocfs2_num_free_extents(osb, et);
        if (free_extents < 0) {
                status = free_extents;
                mlog_errno(status);
@@ -4795,7 +4876,7 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
        BUG_ON(num_bits > clusters_to_add);
 
        /* reserve our write early -- insert_extent may update the tree root */
-       status = ocfs2_et_root_journal_access(handle, inode, et,
+       status = ocfs2_et_root_journal_access(handle, et,
                                              OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -4803,10 +4884,10 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
        }
 
        block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
-       mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
-            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
-       status = ocfs2_insert_extent(osb, handle, inode, et,
-                                    *logical_offset, block,
+       mlog(0, "Allocating %u clusters at block %u for owner %llu\n",
+            num_bits, bit_off,
+            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
+       status = ocfs2_insert_extent(handle, et, *logical_offset, block,
                                     num_bits, flags, meta_ac);
        if (status < 0) {
                mlog_errno(status);
@@ -4856,10 +4937,9 @@ static void ocfs2_make_right_split_rec(struct super_block *sb,
        split_rec->e_flags = rec->e_flags;
 }
 
-static int ocfs2_split_and_insert(struct inode *inode,
-                                 handle_t *handle,
-                                 struct ocfs2_path *path,
+static int ocfs2_split_and_insert(handle_t *handle,
                                  struct ocfs2_extent_tree *et,
+                                 struct ocfs2_path *path,
                                  struct buffer_head **last_eb_bh,
                                  int split_index,
                                  struct ocfs2_extent_rec *orig_split_rec,
@@ -4892,7 +4972,7 @@ leftright:
 
        if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
            le16_to_cpu(rightmost_el->l_count)) {
-               ret = ocfs2_grow_tree(inode, handle, et,
+               ret = ocfs2_grow_tree(handle, et,
                                      &depth, last_eb_bh, meta_ac);
                if (ret) {
                        mlog_errno(ret);
@@ -4921,8 +5001,8 @@ leftright:
                 */
                insert.ins_split = SPLIT_RIGHT;
 
-               ocfs2_make_right_split_rec(inode->i_sb, &tmprec, insert_range,
-                                          &rec);
+               ocfs2_make_right_split_rec(ocfs2_metadata_cache_get_super(et->et_ci),
+                                          &tmprec, insert_range, &rec);
 
                split_rec = tmprec;
 
@@ -4930,7 +5010,7 @@ leftright:
                do_leftright = 1;
        }
 
-       ret = ocfs2_do_insert_extent(inode, handle, et, &split_rec, &insert);
+       ret = ocfs2_do_insert_extent(handle, et, &split_rec, &insert);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4946,7 +5026,7 @@ leftright:
                ocfs2_reinit_path(path, 1);
 
                cpos = le32_to_cpu(split_rec.e_cpos);
-               ret = ocfs2_find_path(inode, path, cpos);
+               ret = ocfs2_find_path(et->et_ci, path, cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -4961,8 +5041,8 @@ out:
        return ret;
 }
 
-static int ocfs2_replace_extent_rec(struct inode *inode,
-                                   handle_t *handle,
+static int ocfs2_replace_extent_rec(handle_t *handle,
+                                   struct ocfs2_extent_tree *et,
                                    struct ocfs2_path *path,
                                    struct ocfs2_extent_list *el,
                                    int split_index,
@@ -4970,7 +5050,7 @@ static int ocfs2_replace_extent_rec(struct inode *inode,
 {
        int ret;
 
-       ret = ocfs2_path_bh_journal_access(handle, inode, path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, path,
                                           path_num_items(path) - 1);
        if (ret) {
                mlog_errno(ret);
@@ -4985,9 +5065,8 @@ out:
 }
 
 /*
- * Mark part or all of the extent record at split_index in the leaf
- * pointed to by path as written. This removes the unwritten
- * extent flag.
+ * Split part or all of the extent record at split_index in the leaf
+ * pointed to by path. Merge with the contiguous extent record if needed.
  *
  * Care is taken to handle contiguousness so as to not grow the tree.
  *
@@ -5004,14 +5083,13 @@ out:
  * have been brought into cache (and pinned via the journal), so the
  * extra overhead is not expressed in terms of disk reads.
  */
-static int __ocfs2_mark_extent_written(struct inode *inode,
-                                      struct ocfs2_extent_tree *et,
-                                      handle_t *handle,
-                                      struct ocfs2_path *path,
-                                      int split_index,
-                                      struct ocfs2_extent_rec *split_rec,
-                                      struct ocfs2_alloc_context *meta_ac,
-                                      struct ocfs2_cached_dealloc_ctxt *dealloc)
+int ocfs2_split_extent(handle_t *handle,
+                      struct ocfs2_extent_tree *et,
+                      struct ocfs2_path *path,
+                      int split_index,
+                      struct ocfs2_extent_rec *split_rec,
+                      struct ocfs2_alloc_context *meta_ac,
+                      struct ocfs2_cached_dealloc_ctxt *dealloc)
 {
        int ret = 0;
        struct ocfs2_extent_list *el = path_leaf_el(path);
@@ -5020,12 +5098,6 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
        struct ocfs2_merge_ctxt ctxt;
        struct ocfs2_extent_list *rightmost_el;
 
-       if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) {
-               ret = -EIO;
-               mlog_errno(ret);
-               goto out;
-       }
-
        if (le32_to_cpu(rec->e_cpos) > le32_to_cpu(split_rec->e_cpos) ||
            ((le32_to_cpu(rec->e_cpos) + le16_to_cpu(rec->e_leaf_clusters)) <
             (le32_to_cpu(split_rec->e_cpos) + le16_to_cpu(split_rec->e_leaf_clusters)))) {
@@ -5034,19 +5106,19 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
                goto out;
        }
 
-       ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, path, el,
+       ctxt.c_contig_type = ocfs2_figure_merge_contig_type(et, path, el,
                                                            split_index,
                                                            split_rec);
 
        /*
         * The core merge / split code wants to know how much room is
-        * left in this inodes allocation tree, so we pass the
+        * left in this allocation tree, so we pass the
         * rightmost extent list.
         */
        if (path->p_tree_depth) {
                struct ocfs2_extent_block *eb;
 
-               ret = ocfs2_read_extent_block(inode,
+               ret = ocfs2_read_extent_block(et->et_ci,
                                              ocfs2_et_get_last_eb_blk(et),
                                              &last_eb_bh);
                if (ret) {
@@ -5073,19 +5145,18 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
 
        if (ctxt.c_contig_type == CONTIG_NONE) {
                if (ctxt.c_split_covers_rec)
-                       ret = ocfs2_replace_extent_rec(inode, handle,
-                                                      path, el,
+                       ret = ocfs2_replace_extent_rec(handle, et, path, el,
                                                       split_index, split_rec);
                else
-                       ret = ocfs2_split_and_insert(inode, handle, path, et,
+                       ret = ocfs2_split_and_insert(handle, et, path,
                                                     &last_eb_bh, split_index,
                                                     split_rec, meta_ac);
                if (ret)
                        mlog_errno(ret);
        } else {
-               ret = ocfs2_try_to_merge_extent(inode, handle, path,
+               ret = ocfs2_try_to_merge_extent(handle, et, path,
                                                split_index, split_rec,
-                                               dealloc, &ctxt, et);
+                                               dealloc, &ctxt);
                if (ret)
                        mlog_errno(ret);
        }
@@ -5096,46 +5167,31 @@ out:
 }
 
 /*
- * Mark the already-existing extent at cpos as written for len clusters.
+ * Change the flags of the already-existing extent at cpos for len clusters.
+ *
+ * new_flags: the flags we want to set.
+ * clear_flags: the flags we want to clear.
+ * phys: the new physical offset we want this new extent starts from.
  *
  * If the existing extent is larger than the request, initiate a
  * split. An attempt will be made at merging with adjacent extents.
  *
  * The caller is responsible for passing down meta_ac if we'll need it.
  */
-int ocfs2_mark_extent_written(struct inode *inode,
-                             struct ocfs2_extent_tree *et,
-                             handle_t *handle, u32 cpos, u32 len, u32 phys,
-                             struct ocfs2_alloc_context *meta_ac,
-                             struct ocfs2_cached_dealloc_ctxt *dealloc)
+int ocfs2_change_extent_flag(handle_t *handle,
+                            struct ocfs2_extent_tree *et,
+                            u32 cpos, u32 len, u32 phys,
+                            struct ocfs2_alloc_context *meta_ac,
+                            struct ocfs2_cached_dealloc_ctxt *dealloc,
+                            int new_flags, int clear_flags)
 {
        int ret, index;
-       u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
+       struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
+       u64 start_blkno = ocfs2_clusters_to_blocks(sb, phys);
        struct ocfs2_extent_rec split_rec;
        struct ocfs2_path *left_path = NULL;
        struct ocfs2_extent_list *el;
-
-       mlog(0, "Inode %lu cpos %u, len %u, phys %u (%llu)\n",
-            inode->i_ino, cpos, len, phys, (unsigned long long)start_blkno);
-
-       if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
-               ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
-                           "that are being written to, but the feature bit "
-                           "is not set in the super block.",
-                           (unsigned long long)OCFS2_I(inode)->ip_blkno);
-               ret = -EROFS;
-               goto out;
-       }
-
-       /*
-        * XXX: This should be fixed up so that we just re-insert the
-        * next extent records.
-        *
-        * XXX: This is a hack on the extent tree, maybe it should be
-        * an op?
-        */
-       if (et->et_ops == &ocfs2_dinode_et_ops)
-               ocfs2_extent_map_trunc(inode, 0);
+       struct ocfs2_extent_rec *rec;
 
        left_path = ocfs2_new_path_from_et(et);
        if (!left_path) {
@@ -5144,7 +5200,7 @@ int ocfs2_mark_extent_written(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_find_path(inode, left_path, cpos);
+       ret = ocfs2_find_path(et->et_ci, left_path, cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -5153,34 +5209,102 @@ int ocfs2_mark_extent_written(struct inode *inode,
 
        index = ocfs2_search_extent_list(el, cpos);
        if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
-               ocfs2_error(inode->i_sb,
-                           "Inode %llu has an extent at cpos %u which can no "
+               ocfs2_error(sb,
+                           "Owner %llu has an extent at cpos %u which can no "
                            "longer be found.\n",
-                           (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+                            (unsigned long long)
+                            ocfs2_metadata_cache_owner(et->et_ci), cpos);
                ret = -EROFS;
                goto out;
        }
 
+       ret = -EIO;
+       rec = &el->l_recs[index];
+       if (new_flags && (rec->e_flags & new_flags)) {
+               mlog(ML_ERROR, "Owner %llu tried to set %d flags on an "
+                    "extent that already had them",
+                    (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+                    new_flags);
+               goto out;
+       }
+
+       if (clear_flags && !(rec->e_flags & clear_flags)) {
+               mlog(ML_ERROR, "Owner %llu tried to clear %d flags on an "
+                    "extent that didn't have them",
+                    (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+                    clear_flags);
+               goto out;
+       }
+
        memset(&split_rec, 0, sizeof(struct ocfs2_extent_rec));
        split_rec.e_cpos = cpu_to_le32(cpos);
        split_rec.e_leaf_clusters = cpu_to_le16(len);
        split_rec.e_blkno = cpu_to_le64(start_blkno);
-       split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
-       split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
-
-       ret = __ocfs2_mark_extent_written(inode, et, handle, left_path,
-                                         index, &split_rec, meta_ac,
-                                         dealloc);
+       split_rec.e_flags = rec->e_flags;
+       if (new_flags)
+               split_rec.e_flags |= new_flags;
+       if (clear_flags)
+               split_rec.e_flags &= ~clear_flags;
+
+       ret = ocfs2_split_extent(handle, et, left_path,
+                                index, &split_rec, meta_ac,
+                                dealloc);
        if (ret)
                mlog_errno(ret);
 
 out:
        ocfs2_free_path(left_path);
        return ret;
+
 }
 
-static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
-                           handle_t *handle, struct ocfs2_path *path,
+/*
+ * Mark the already-existing extent at cpos as written for len clusters.
+ * This removes the unwritten extent flag.
+ *
+ * If the existing extent is larger than the request, initiate a
+ * split. An attempt will be made at merging with adjacent extents.
+ *
+ * The caller is responsible for passing down meta_ac if we'll need it.
+ */
+int ocfs2_mark_extent_written(struct inode *inode,
+                             struct ocfs2_extent_tree *et,
+                             handle_t *handle, u32 cpos, u32 len, u32 phys,
+                             struct ocfs2_alloc_context *meta_ac,
+                             struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+       int ret;
+
+       mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n",
+            inode->i_ino, cpos, len, phys);
+
+       if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) {
+               ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents "
+                           "that are being written to, but the feature bit "
+                           "is not set in the super block.",
+                           (unsigned long long)OCFS2_I(inode)->ip_blkno);
+               ret = -EROFS;
+               goto out;
+       }
+
+       /*
+        * XXX: This should be fixed up so that we just re-insert the
+        * next extent records.
+        */
+       ocfs2_et_extent_map_truncate(et, 0);
+
+       ret = ocfs2_change_extent_flag(handle, et, cpos,
+                                      len, phys, meta_ac, dealloc,
+                                      0, OCFS2_EXT_UNWRITTEN);
+       if (ret)
+               mlog_errno(ret);
+
+out:
+       return ret;
+}
+
+static int ocfs2_split_tree(handle_t *handle, struct ocfs2_extent_tree *et,
+                           struct ocfs2_path *path,
                            int index, u32 new_range,
                            struct ocfs2_alloc_context *meta_ac)
 {
@@ -5197,11 +5321,12 @@ static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
         */
        el = path_leaf_el(path);
        rec = &el->l_recs[index];
-       ocfs2_make_right_split_rec(inode->i_sb, &split_rec, new_range, rec);
+       ocfs2_make_right_split_rec(ocfs2_metadata_cache_get_super(et->et_ci),
+                                  &split_rec, new_range, rec);
 
        depth = path->p_tree_depth;
        if (depth > 0) {
-               ret = ocfs2_read_extent_block(inode,
+               ret = ocfs2_read_extent_block(et->et_ci,
                                              ocfs2_et_get_last_eb_blk(et),
                                              &last_eb_bh);
                if (ret < 0) {
@@ -5224,7 +5349,7 @@ static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
 
        if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
            le16_to_cpu(rightmost_el->l_count)) {
-               ret = ocfs2_grow_tree(inode, handle, et, &depth, &last_eb_bh,
+               ret = ocfs2_grow_tree(handle, et, &depth, &last_eb_bh,
                                      meta_ac);
                if (ret) {
                        mlog_errno(ret);
@@ -5238,7 +5363,7 @@ static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
        insert.ins_split = SPLIT_RIGHT;
        insert.ins_tree_depth = depth;
 
-       ret = ocfs2_do_insert_extent(inode, handle, et, &split_rec, &insert);
+       ret = ocfs2_do_insert_extent(handle, et, &split_rec, &insert);
        if (ret)
                mlog_errno(ret);
 
@@ -5247,23 +5372,23 @@ out:
        return ret;
 }
 
-static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
+static int ocfs2_truncate_rec(handle_t *handle,
+                             struct ocfs2_extent_tree *et,
                              struct ocfs2_path *path, int index,
                              struct ocfs2_cached_dealloc_ctxt *dealloc,
-                             u32 cpos, u32 len,
-                             struct ocfs2_extent_tree *et)
+                             u32 cpos, u32 len)
 {
        int ret;
        u32 left_cpos, rec_range, trunc_range;
        int wants_rotate = 0, is_rightmost_tree_rec = 0;
-       struct super_block *sb = inode->i_sb;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
        struct ocfs2_path *left_path = NULL;
        struct ocfs2_extent_list *el = path_leaf_el(path);
        struct ocfs2_extent_rec *rec;
        struct ocfs2_extent_block *eb;
 
        if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) {
-               ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc, et);
+               ret = ocfs2_rotate_tree_left(handle, et, path, dealloc);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5295,14 +5420,13 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                 * by this leaf and the one to it's left.
                 *
                 * There are two cases we can skip:
-                *   1) Path is the leftmost one in our inode tree.
+                *   1) Path is the leftmost one in our btree.
                 *   2) The leaf is rightmost and will be empty after
                 *      we remove the extent record - the rotate code
                 *      knows how to update the newly formed edge.
                 */
 
-               ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path,
-                                                   &left_cpos);
+               ret = ocfs2_find_cpos_for_left_leaf(sb, path, &left_cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5316,7 +5440,8 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                                goto out;
                        }
 
-                       ret = ocfs2_find_path(inode, left_path, left_cpos);
+                       ret = ocfs2_find_path(et->et_ci, left_path,
+                                             left_cpos);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -5332,13 +5457,13 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                goto out;
        }
 
-       ret = ocfs2_journal_access_path(inode, handle, path);
+       ret = ocfs2_journal_access_path(et->et_ci, handle, path);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access_path(inode, handle, left_path);
+       ret = ocfs2_journal_access_path(et->et_ci, handle, left_path);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -5361,7 +5486,7 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                         * be deleted by the rotate code.
                         */
                        rec = &el->l_recs[next_free - 1];
-                       ocfs2_adjust_rightmost_records(inode, handle, path,
+                       ocfs2_adjust_rightmost_records(handle, et, path,
                                                       rec);
                }
        } else if (le32_to_cpu(rec->e_cpos) == cpos) {
@@ -5373,11 +5498,12 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                /* Remove rightmost portion of the record */
                le16_add_cpu(&rec->e_leaf_clusters, -len);
                if (is_rightmost_tree_rec)
-                       ocfs2_adjust_rightmost_records(inode, handle, path, rec);
+                       ocfs2_adjust_rightmost_records(handle, et, path, rec);
        } else {
                /* Caller should have trapped this. */
-               mlog(ML_ERROR, "Inode %llu: Invalid record truncate: (%u, %u) "
-                    "(%u, %u)\n", (unsigned long long)OCFS2_I(inode)->ip_blkno,
+               mlog(ML_ERROR, "Owner %llu: Invalid record truncate: (%u, %u) "
+                    "(%u, %u)\n",
+                    (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                     le32_to_cpu(rec->e_cpos),
                     le16_to_cpu(rec->e_leaf_clusters), cpos, len);
                BUG();
@@ -5386,14 +5512,14 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
        if (left_path) {
                int subtree_index;
 
-               subtree_index = ocfs2_find_subtree_root(inode, left_path, path);
-               ocfs2_complete_edge_insert(inode, handle, left_path, path,
+               subtree_index = ocfs2_find_subtree_root(et, left_path, path);
+               ocfs2_complete_edge_insert(handle, left_path, path,
                                           subtree_index);
        }
 
        ocfs2_journal_dirty(handle, path_leaf_bh(path));
 
-       ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc, et);
+       ret = ocfs2_rotate_tree_left(handle, et, path, dealloc);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -5404,9 +5530,9 @@ out:
        return ret;
 }
 
-int ocfs2_remove_extent(struct inode *inode,
+int ocfs2_remove_extent(handle_t *handle,
                        struct ocfs2_extent_tree *et,
-                       u32 cpos, u32 len, handle_t *handle,
+                       u32 cpos, u32 len,
                        struct ocfs2_alloc_context *meta_ac,
                        struct ocfs2_cached_dealloc_ctxt *dealloc)
 {
@@ -5416,7 +5542,11 @@ int ocfs2_remove_extent(struct inode *inode,
        struct ocfs2_extent_list *el;
        struct ocfs2_path *path = NULL;
 
-       ocfs2_extent_map_trunc(inode, 0);
+       /*
+        * XXX: Why are we truncating to 0 instead of wherever this
+        * affects us?
+        */
+       ocfs2_et_extent_map_truncate(et, 0);
 
        path = ocfs2_new_path_from_et(et);
        if (!path) {
@@ -5425,7 +5555,7 @@ int ocfs2_remove_extent(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_find_path(inode, path, cpos);
+       ret = ocfs2_find_path(et->et_ci, path, cpos);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -5434,10 +5564,11 @@ int ocfs2_remove_extent(struct inode *inode,
        el = path_leaf_el(path);
        index = ocfs2_search_extent_list(el, cpos);
        if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
-               ocfs2_error(inode->i_sb,
-                           "Inode %llu has an extent at cpos %u which can no "
+               ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                           "Owner %llu has an extent at cpos %u which can no "
                            "longer be found.\n",
-                           (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos);
+                           (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+                           cpos);
                ret = -EROFS;
                goto out;
        }
@@ -5464,20 +5595,21 @@ int ocfs2_remove_extent(struct inode *inode,
 
        BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range);
 
-       mlog(0, "Inode %llu, remove (cpos %u, len %u). Existing index %d "
+       mlog(0, "Owner %llu, remove (cpos %u, len %u). Existing index %d "
             "(cpos %u, len %u)\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos, len, index,
+            (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
+            cpos, len, index,
             le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec));
 
        if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {
-               ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
-                                        cpos, len, et);
+               ret = ocfs2_truncate_rec(handle, et, path, index, dealloc,
+                                        cpos, len);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
        } else {
-               ret = ocfs2_split_tree(inode, et, handle, path, index,
+               ret = ocfs2_split_tree(handle, et, path, index,
                                       trunc_range, meta_ac);
                if (ret) {
                        mlog_errno(ret);
@@ -5490,7 +5622,7 @@ int ocfs2_remove_extent(struct inode *inode,
                 */
                ocfs2_reinit_path(path, 1);
 
-               ret = ocfs2_find_path(inode, path, cpos);
+               ret = ocfs2_find_path(et->et_ci, path, cpos);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5499,9 +5631,9 @@ int ocfs2_remove_extent(struct inode *inode,
                el = path_leaf_el(path);
                index = ocfs2_search_extent_list(el, cpos);
                if (index == -1 || index >= le16_to_cpu(el->l_next_free_rec)) {
-                       ocfs2_error(inode->i_sb,
-                                   "Inode %llu: split at cpos %u lost record.",
-                                   (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                                   "Owner %llu: split at cpos %u lost record.",
+                                   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                                    cpos);
                        ret = -EROFS;
                        goto out;
@@ -5515,18 +5647,18 @@ int ocfs2_remove_extent(struct inode *inode,
                rec_range = le32_to_cpu(rec->e_cpos) +
                        ocfs2_rec_clusters(el, rec);
                if (rec_range != trunc_range) {
-                       ocfs2_error(inode->i_sb,
-                                   "Inode %llu: error after split at cpos %u"
+                       ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
+                                   "Owner %llu: error after split at cpos %u"
                                    "trunc len %u, existing record is (%u,%u)",
-                                   (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                                   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                                    cpos, len, le32_to_cpu(rec->e_cpos),
                                    ocfs2_rec_clusters(el, rec));
                        ret = -EROFS;
                        goto out;
                }
 
-               ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
-                                        cpos, len, et);
+               ret = ocfs2_truncate_rec(handle, et, path, index, dealloc,
+                                        cpos, len);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5573,7 +5705,7 @@ int ocfs2_remove_btree_range(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_et_root_journal_access(handle, inode, et,
+       ret = ocfs2_et_root_journal_access(handle, et,
                                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -5583,14 +5715,13 @@ int ocfs2_remove_btree_range(struct inode *inode,
        vfs_dq_free_space_nodirty(inode,
                                  ocfs2_clusters_to_bytes(inode->i_sb, len));
 
-       ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac,
-                                 dealloc);
+       ret = ocfs2_remove_extent(handle, et, cpos, len, meta_ac, dealloc);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
        }
 
-       ocfs2_et_update_clusters(inode, et, -len);
+       ocfs2_et_update_clusters(et, -len);
 
        ret = ocfs2_journal_dirty(handle, et->et_root_bh);
        if (ret) {
@@ -5690,7 +5821,7 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_journal_access_di(handle, tl_inode, tl_bh,
+       status = ocfs2_journal_access_di(handle, INODE_CACHE(tl_inode), tl_bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -5752,7 +5883,7 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
        while (i >= 0) {
                /* Caller has given us at least enough credits to
                 * update the truncate log dinode */
-               status = ocfs2_journal_access_di(handle, tl_inode, tl_bh,
+               status = ocfs2_journal_access_di(handle, INODE_CACHE(tl_inode), tl_bh,
                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
@@ -6010,7 +6141,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
                tl->tl_used = 0;
 
                ocfs2_compute_meta_ecc(osb->sb, tl_bh->b_data, &di->i_check);
-               status = ocfs2_write_block(osb, tl_bh, tl_inode);
+               status = ocfs2_write_block(osb, tl_bh, INODE_CACHE(tl_inode));
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -6400,9 +6531,9 @@ ocfs2_find_per_slot_free_list(int type,
        return fl;
 }
 
-static int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
-                                    int type, int slot, u64 blkno,
-                                    unsigned int bit)
+int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+                             int type, int slot, u64 blkno,
+                             unsigned int bit)
 {
        int ret;
        struct ocfs2_per_slot_free_list *fl;
@@ -6518,7 +6649,7 @@ static int ocfs2_find_new_last_ext_blk(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_find_leaf(inode, path_root_el(path), cpos, &bh);
+       ret = ocfs2_find_leaf(INODE_CACHE(inode), path_root_el(path), cpos, &bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -6551,7 +6682,7 @@ out:
  */
 static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
                           handle_t *handle, struct ocfs2_truncate_context *tc,
-                          u32 clusters_to_del, u64 *delete_start)
+                          u32 clusters_to_del, u64 *delete_start, u8 *flags)
 {
        int ret, i, index = path->p_tree_depth;
        u32 new_edge = 0;
@@ -6561,6 +6692,7 @@ static int ocfs2_trim_tree(struct inode *inode, struct ocfs2_path *path,
        struct ocfs2_extent_rec *rec;
 
        *delete_start = 0;
+       *flags = 0;
 
        while (index >= 0) {
                bh = path->p_node[index].bh;
@@ -6648,6 +6780,7 @@ find_tail_record:
                        *delete_start = le64_to_cpu(rec->e_blkno)
                                + ocfs2_clusters_to_blocks(inode->i_sb,
                                        le16_to_cpu(rec->e_leaf_clusters));
+                       *flags = rec->e_flags;
 
                        /*
                         * If it's now empty, remove this record.
@@ -6719,7 +6852,7 @@ delete:
 
                        mlog(0, "deleting this extent block.\n");
 
-                       ocfs2_remove_from_cache(inode, bh);
+                       ocfs2_remove_from_cache(INODE_CACHE(inode), bh);
 
                        BUG_ON(ocfs2_rec_clusters(el, &el->l_recs[0]));
                        BUG_ON(le32_to_cpu(el->l_recs[0].e_cpos));
@@ -6747,7 +6880,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
                             struct buffer_head *fe_bh,
                             handle_t *handle,
                             struct ocfs2_truncate_context *tc,
-                            struct ocfs2_path *path)
+                            struct ocfs2_path *path,
+                            struct ocfs2_alloc_context *meta_ac)
 {
        int status;
        struct ocfs2_dinode *fe;
@@ -6755,6 +6889,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
        struct ocfs2_extent_list *el;
        struct buffer_head *last_eb_bh = NULL;
        u64 delete_blk = 0;
+       u8 rec_flags;
 
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
@@ -6769,14 +6904,14 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
         * Each component will be touched, so we might as well journal
         * here to avoid having to handle errors later.
         */
-       status = ocfs2_journal_access_path(inode, handle, path);
+       status = ocfs2_journal_access_path(INODE_CACHE(inode), handle, path);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
 
        if (last_eb_bh) {
-               status = ocfs2_journal_access_eb(handle, inode, last_eb_bh,
+               status = ocfs2_journal_access_eb(handle, INODE_CACHE(inode), last_eb_bh,
                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
@@ -6810,7 +6945,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
        inode->i_blocks = ocfs2_inode_sector_count(inode);
 
        status = ocfs2_trim_tree(inode, path, handle, tc,
-                                clusters_to_del, &delete_blk);
+                                clusters_to_del, &delete_blk, &rec_flags);
        if (status) {
                mlog_errno(status);
                goto bail;
@@ -6842,8 +6977,16 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
        }
 
        if (delete_blk) {
-               status = ocfs2_truncate_log_append(osb, handle, delete_blk,
-                                                  clusters_to_del);
+               if (rec_flags & OCFS2_EXT_REFCOUNTED)
+                       status = ocfs2_decrease_refcount(inode, handle,
+                                       ocfs2_blocks_to_clusters(osb->sb,
+                                                                delete_blk),
+                                       clusters_to_del, meta_ac,
+                                       &tc->tc_dealloc, 1);
+               else
+                       status = ocfs2_truncate_log_append(osb, handle,
+                                                          delete_blk,
+                                                          clusters_to_del);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -6863,9 +7006,9 @@ static int ocfs2_zero_func(handle_t *handle, struct buffer_head *bh)
        return 0;
 }
 
-static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
-                                    unsigned int from, unsigned int to,
-                                    struct page *page, int zero, u64 *phys)
+void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
+                             unsigned int from, unsigned int to,
+                             struct page *page, int zero, u64 *phys)
 {
        int ret, partial = 0;
 
@@ -6933,20 +7076,16 @@ out:
                ocfs2_unlock_and_free_pages(pages, numpages);
 }
 
-static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
-                               struct page **pages, int *num)
+int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end,
+                    struct page **pages, int *num)
 {
        int numpages, ret = 0;
-       struct super_block *sb = inode->i_sb;
        struct address_space *mapping = inode->i_mapping;
        unsigned long index;
        loff_t last_page_bytes;
 
        BUG_ON(start > end);
 
-       BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
-              (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
-
        numpages = 0;
        last_page_bytes = PAGE_ALIGN(end);
        index = start >> PAGE_CACHE_SHIFT;
@@ -6974,6 +7113,17 @@ out:
        return ret;
 }
 
+static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
+                               struct page **pages, int *num)
+{
+       struct super_block *sb = inode->i_sb;
+
+       BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
+              (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
+
+       return ocfs2_grab_pages(inode, start, end, pages, num);
+}
+
 /*
  * Zero the area past i_size but still within an allocated
  * cluster. This avoids exposing nonzero data on subsequent file
@@ -7138,7 +7288,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                goto out_unlock;
        }
 
-       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -7218,9 +7368,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                 * this proves to be false, we could always re-build
                 * the in-inode data from our pages.
                 */
-               ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
-               ret = ocfs2_insert_extent(osb, handle, inode, &et,
-                                         0, block, 1, 0, NULL);
+               ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
+               ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL);
                if (ret) {
                        mlog_errno(ret);
                        goto out_commit;
@@ -7262,11 +7411,14 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
 {
        int status, i, credits, tl_sem = 0;
        u32 clusters_to_del, new_highest_cpos, range;
+       u64 blkno = 0;
        struct ocfs2_extent_list *el;
        handle_t *handle = NULL;
        struct inode *tl_inode = osb->osb_tl_inode;
        struct ocfs2_path *path = NULL;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       struct ocfs2_refcount_tree *ref_tree = NULL;
 
        mlog_entry_void();
 
@@ -7292,10 +7444,12 @@ start:
                goto bail;
        }
 
+       credits = 0;
+
        /*
         * Truncate always works against the rightmost tree branch.
         */
-       status = ocfs2_find_path(inode, path, UINT_MAX);
+       status = ocfs2_find_path(INODE_CACHE(inode), path, UINT_MAX);
        if (status) {
                mlog_errno(status);
                goto bail;
@@ -7332,10 +7486,15 @@ start:
                clusters_to_del = 0;
        } else if (le32_to_cpu(el->l_recs[i].e_cpos) >= new_highest_cpos) {
                clusters_to_del = ocfs2_rec_clusters(el, &el->l_recs[i]);
+               blkno = le64_to_cpu(el->l_recs[i].e_blkno);
        } else if (range > new_highest_cpos) {
                clusters_to_del = (ocfs2_rec_clusters(el, &el->l_recs[i]) +
                                   le32_to_cpu(el->l_recs[i].e_cpos)) -
                                  new_highest_cpos;
+               blkno = le64_to_cpu(el->l_recs[i].e_blkno) +
+                       ocfs2_clusters_to_blocks(inode->i_sb,
+                               ocfs2_rec_clusters(el, &el->l_recs[i]) -
+                               clusters_to_del);
        } else {
                status = 0;
                goto bail;
@@ -7344,6 +7503,29 @@ start:
        mlog(0, "clusters_to_del = %u in this pass, tail blk=%llu\n",
             clusters_to_del, (unsigned long long)path_leaf_bh(path)->b_blocknr);
 
+       if (el->l_recs[i].e_flags & OCFS2_EXT_REFCOUNTED && clusters_to_del) {
+               BUG_ON(!(OCFS2_I(inode)->ip_dyn_features &
+                        OCFS2_HAS_REFCOUNT_FL));
+
+               status = ocfs2_lock_refcount_tree(osb,
+                                               le64_to_cpu(di->i_refcount_loc),
+                                               1, &ref_tree, NULL);
+               if (status) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+
+               status = ocfs2_prepare_refcount_change_for_del(inode, fe_bh,
+                                                              blkno,
+                                                              clusters_to_del,
+                                                              &credits,
+                                                              &meta_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        mutex_lock(&tl_inode->i_mutex);
        tl_sem = 1;
        /* ocfs2_truncate_log_needs_flush guarantees us at least one
@@ -7357,7 +7539,7 @@ start:
                }
        }
 
-       credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
+       credits += ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
                                                (struct ocfs2_dinode *)fe_bh->b_data,
                                                el);
        handle = ocfs2_start_trans(osb, credits);
@@ -7369,7 +7551,7 @@ start:
        }
 
        status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh, handle,
-                                  tc, path);
+                                  tc, path, meta_ac);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -7383,6 +7565,16 @@ start:
 
        ocfs2_reinit_path(path, 1);
 
+       if (meta_ac) {
+               ocfs2_free_alloc_context(meta_ac);
+               meta_ac = NULL;
+       }
+
+       if (ref_tree) {
+               ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+               ref_tree = NULL;
+       }
+
        /*
         * The check above will catch the case where we've truncated
         * away all allocation.
@@ -7399,6 +7591,12 @@ bail:
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
+       if (meta_ac)
+               ocfs2_free_alloc_context(meta_ac);
+
+       if (ref_tree)
+               ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+
        ocfs2_run_deallocs(osb, &tc->tc_dealloc);
 
        ocfs2_free_path(path);
@@ -7445,7 +7643,7 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
        ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
 
        if (fe->id2.i_list.l_tree_depth) {
-               status = ocfs2_read_extent_block(inode,
+               status = ocfs2_read_extent_block(INODE_CACHE(inode),
                                                 le64_to_cpu(fe->i_last_eb_blk),
                                                 &last_eb_bh);
                if (status < 0) {
@@ -7507,7 +7705,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
                goto out;
        }
 
-       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
index 353254b..9c122d5 100644 (file)
@@ -45,7 +45,8 @@
  *
  * ocfs2_extent_tree contains info for the root of the b-tree, it must have a
  * root ocfs2_extent_list and a root_bh so that they can be used in the b-tree
- * functions.  With metadata ecc, we now call different journal_access
+ * functions.  It needs the ocfs2_caching_info structure associated with
+ * I/O on the tree.  With metadata ecc, we now call different journal_access
  * functions for each type of metadata, so it must have the
  * root_journal_access function.
  * ocfs2_extent_tree_operations abstract the normal operations we do for
@@ -56,6 +57,7 @@ struct ocfs2_extent_tree {
        struct ocfs2_extent_tree_operations     *et_ops;
        struct buffer_head                      *et_root_bh;
        struct ocfs2_extent_list                *et_root_el;
+       struct ocfs2_caching_info               *et_ci;
        ocfs2_journal_access_func               et_root_journal_access;
        void                                    *et_object;
        unsigned int                            et_max_leaf_clusters;
@@ -66,31 +68,32 @@ struct ocfs2_extent_tree {
  * specified object buffer.
  */
 void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
-                                  struct inode *inode,
+                                  struct ocfs2_caching_info *ci,
                                   struct buffer_head *bh);
 void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
-                                      struct inode *inode,
+                                      struct ocfs2_caching_info *ci,
                                       struct buffer_head *bh);
 struct ocfs2_xattr_value_buf;
 void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
-                                       struct inode *inode,
+                                       struct ocfs2_caching_info *ci,
                                        struct ocfs2_xattr_value_buf *vb);
 void ocfs2_init_dx_root_extent_tree(struct ocfs2_extent_tree *et,
-                                   struct inode *inode,
+                                   struct ocfs2_caching_info *ci,
                                    struct buffer_head *bh);
+void ocfs2_init_refcount_extent_tree(struct ocfs2_extent_tree *et,
+                                    struct ocfs2_caching_info *ci,
+                                    struct buffer_head *bh);
 
 /*
  * Read an extent block into *bh.  If *bh is NULL, a bh will be
  * allocated.  This is a cached read.  The extent block will be validated
  * with ocfs2_validate_extent_block().
  */
-int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
+int ocfs2_read_extent_block(struct ocfs2_caching_info *ci, u64 eb_blkno,
                            struct buffer_head **bh);
 
 struct ocfs2_alloc_context;
-int ocfs2_insert_extent(struct ocfs2_super *osb,
-                       handle_t *handle,
-                       struct inode *inode,
+int ocfs2_insert_extent(handle_t *handle,
                        struct ocfs2_extent_tree *et,
                        u32 cpos,
                        u64 start_blk,
@@ -103,25 +106,36 @@ enum ocfs2_alloc_restarted {
        RESTART_TRANS,
        RESTART_META
 };
-int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
-                               struct inode *inode,
+int ocfs2_add_clusters_in_btree(handle_t *handle,
+                               struct ocfs2_extent_tree *et,
                                u32 *logical_offset,
                                u32 clusters_to_add,
                                int mark_unwritten,
-                               struct ocfs2_extent_tree *et,
-                               handle_t *handle,
                                struct ocfs2_alloc_context *data_ac,
                                struct ocfs2_alloc_context *meta_ac,
                                enum ocfs2_alloc_restarted *reason_ret);
 struct ocfs2_cached_dealloc_ctxt;
+struct ocfs2_path;
+int ocfs2_split_extent(handle_t *handle,
+                      struct ocfs2_extent_tree *et,
+                      struct ocfs2_path *path,
+                      int split_index,
+                      struct ocfs2_extent_rec *split_rec,
+                      struct ocfs2_alloc_context *meta_ac,
+                      struct ocfs2_cached_dealloc_ctxt *dealloc);
 int ocfs2_mark_extent_written(struct inode *inode,
                              struct ocfs2_extent_tree *et,
                              handle_t *handle, u32 cpos, u32 len, u32 phys,
                              struct ocfs2_alloc_context *meta_ac,
                              struct ocfs2_cached_dealloc_ctxt *dealloc);
-int ocfs2_remove_extent(struct inode *inode,
-                       struct ocfs2_extent_tree *et,
-                       u32 cpos, u32 len, handle_t *handle,
+int ocfs2_change_extent_flag(handle_t *handle,
+                            struct ocfs2_extent_tree *et,
+                            u32 cpos, u32 len, u32 phys,
+                            struct ocfs2_alloc_context *meta_ac,
+                            struct ocfs2_cached_dealloc_ctxt *dealloc,
+                            int new_flags, int clear_flags);
+int ocfs2_remove_extent(handle_t *handle, struct ocfs2_extent_tree *et,
+                       u32 cpos, u32 len,
                        struct ocfs2_alloc_context *meta_ac,
                        struct ocfs2_cached_dealloc_ctxt *dealloc);
 int ocfs2_remove_btree_range(struct inode *inode,
@@ -130,7 +144,6 @@ int ocfs2_remove_btree_range(struct inode *inode,
                             struct ocfs2_cached_dealloc_ctxt *dealloc);
 
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
-                          struct inode *inode,
                           struct ocfs2_extent_tree *et);
 
 /*
@@ -195,6 +208,9 @@ static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
 }
 int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
                                u64 blkno, unsigned int bit);
+int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+                             int type, int slot, u64 blkno,
+                             unsigned int bit);
 static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c)
 {
        return c->c_global_allocator != NULL;
@@ -222,8 +238,9 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
 int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
                          unsigned int start, unsigned int end, int trunc);
 
-int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
-                   u32 cpos, struct buffer_head **leaf_bh);
+int ocfs2_find_leaf(struct ocfs2_caching_info *ci,
+                   struct ocfs2_extent_list *root_el, u32 cpos,
+                   struct buffer_head **leaf_bh);
 int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
 
 /*
@@ -254,4 +271,50 @@ static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec)
        return !rec->e_leaf_clusters;
 }
 
+int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end,
+                    struct page **pages, int *num);
+void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
+                             unsigned int from, unsigned int to,
+                             struct page *page, int zero, u64 *phys);
+/*
+ * Structures which describe a path through a btree, and functions to
+ * manipulate them.
+ *
+ * The idea here is to be as generic as possible with the tree
+ * manipulation code.
+ */
+struct ocfs2_path_item {
+       struct buffer_head              *bh;
+       struct ocfs2_extent_list        *el;
+};
+
+#define OCFS2_MAX_PATH_DEPTH   5
+
+struct ocfs2_path {
+       int                             p_tree_depth;
+       ocfs2_journal_access_func       p_root_access;
+       struct ocfs2_path_item          p_node[OCFS2_MAX_PATH_DEPTH];
+};
+
+#define path_root_bh(_path) ((_path)->p_node[0].bh)
+#define path_root_el(_path) ((_path)->p_node[0].el)
+#define path_root_access(_path)((_path)->p_root_access)
+#define path_leaf_bh(_path) ((_path)->p_node[(_path)->p_tree_depth].bh)
+#define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el)
+#define path_num_items(_path) ((_path)->p_tree_depth + 1)
+
+void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root);
+void ocfs2_free_path(struct ocfs2_path *path);
+int ocfs2_find_path(struct ocfs2_caching_info *ci,
+                   struct ocfs2_path *path,
+                   u32 cpos);
+struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path);
+struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et);
+int ocfs2_path_bh_journal_access(handle_t *handle,
+                                struct ocfs2_caching_info *ci,
+                                struct ocfs2_path *path,
+                                int idx);
+int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
+                             handle_t *handle,
+                             struct ocfs2_path *path);
 #endif /* OCFS2_ALLOC_H */
index 8a1e615..72e7606 100644 (file)
@@ -44,6 +44,7 @@
 #include "suballoc.h"
 #include "super.h"
 #include "symlink.h"
+#include "refcounttree.h"
 
 #include "buffer_head_io.h"
 
@@ -126,8 +127,8 @@ bail:
        return err;
 }
 
-static int ocfs2_get_block(struct inode *inode, sector_t iblock,
-                          struct buffer_head *bh_result, int create)
+int ocfs2_get_block(struct inode *inode, sector_t iblock,
+                   struct buffer_head *bh_result, int create)
 {
        int err = 0;
        unsigned int ext_flags;
@@ -590,6 +591,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
                goto bail;
        }
 
+       /* We should already CoW the refcounted extent. */
+       BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
        /*
         * get_more_blocks() expects us to describe a hole by clearing
         * the mapped bit on bh_result().
@@ -687,6 +690,10 @@ static ssize_t ocfs2_direct_IO(int rw,
        if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
                return 0;
 
+       /* Fallback to buffered I/O if we are appending. */
+       if (i_size_read(inode) <= offset)
+               return 0;
+
        ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
                                            inode->i_sb->s_bdev, iov, offset,
                                            nr_segs, 
@@ -1259,7 +1266,8 @@ static int ocfs2_write_cluster(struct address_space *mapping,
                        goto out;
                }
        } else if (unwritten) {
-               ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh);
+               ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode),
+                                             wc->w_di_bh);
                ret = ocfs2_mark_extent_written(inode, &et,
                                                wc->w_handle, cpos, 1, phys,
                                                meta_ac, &wc->w_dealloc);
@@ -1448,6 +1456,9 @@ static int ocfs2_populate_write_desc(struct inode *inode,
                                goto out;
                        }
 
+                       /* We should already CoW the refcountd extent. */
+                       BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
+
                        /*
                         * Assume worst case - that we're writing in
                         * the middle of the extent.
@@ -1528,7 +1539,7 @@ static int ocfs2_write_begin_inline(struct address_space *mapping,
                goto out;
        }
 
-       ret = ocfs2_journal_access_di(handle, inode, wc->w_di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), wc->w_di_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                ocfs2_commit_trans(osb, handle);
@@ -1699,6 +1710,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
                goto out;
        }
 
+       ret = ocfs2_check_range_for_refcount(inode, pos, len);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       } else if (ret == 1) {
+               ret = ocfs2_refcount_cow(inode, di_bh,
+                                        wc->w_cpos, wc->w_clen, UINT_MAX);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
        ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
                                        &extents_to_split);
        if (ret) {
@@ -1726,7 +1750,8 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
                     (long long)i_size_read(inode), le32_to_cpu(di->i_clusters),
                     clusters_to_alloc, extents_to_split);
 
-               ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh);
+               ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode),
+                                             wc->w_di_bh);
                ret = ocfs2_lock_allocators(inode, &et,
                                            clusters_to_alloc, extents_to_split,
                                            &data_ac, &meta_ac);
@@ -1773,7 +1798,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
         * We don't want this to fail in ocfs2_write_end(), so do it
         * here.
         */
-       ret = ocfs2_journal_access_di(handle, inode, wc->w_di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), wc->w_di_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
index 503e492..c48e93f 100644 (file)
@@ -57,6 +57,8 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page,
                           struct buffer_head *di_bh);
 int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size);
 
+int ocfs2_get_block(struct inode *inode, sector_t iblock,
+                   struct buffer_head *bh_result, int create);
 /* all ocfs2_dio_end_io()'s fault */
 #define ocfs2_iocb_is_rw_locked(iocb) \
        test_bit(0, (unsigned long *)&iocb->private)
index 15c8e6d..d43d34a 100644 (file)
@@ -52,12 +52,12 @@ enum ocfs2_state_bits {
 BUFFER_FNS(NeedsValidate, needs_validate);
 
 int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
-                     struct inode *inode)
+                     struct ocfs2_caching_info *ci)
 {
        int ret = 0;
 
-       mlog_entry("(bh->b_blocknr = %llu, inode=%p)\n",
-                  (unsigned long long)bh->b_blocknr, inode);
+       mlog_entry("(bh->b_blocknr = %llu, ci=%p)\n",
+                  (unsigned long long)bh->b_blocknr, ci);
 
        BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO);
        BUG_ON(buffer_jbd(bh));
@@ -70,7 +70,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
                goto out;
        }
 
-       mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
+       ocfs2_metadata_cache_io_lock(ci);
 
        lock_buffer(bh);
        set_buffer_uptodate(bh);
@@ -85,7 +85,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
        wait_on_buffer(bh);
 
        if (buffer_uptodate(bh)) {
-               ocfs2_set_buffer_uptodate(inode, bh);
+               ocfs2_set_buffer_uptodate(ci, bh);
        } else {
                /* We don't need to remove the clustered uptodate
                 * information for this bh as it's not marked locally
@@ -94,7 +94,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
                put_bh(bh);
        }
 
-       mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
+       ocfs2_metadata_cache_io_unlock(ci);
 out:
        mlog_exit(ret);
        return ret;
@@ -177,7 +177,7 @@ bail:
        return status;
 }
 
-int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
+int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                      struct buffer_head *bhs[], int flags,
                      int (*validate)(struct super_block *sb,
                                      struct buffer_head *bh))
@@ -185,11 +185,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
        int status = 0;
        int i, ignore_cache = 0;
        struct buffer_head *bh;
+       struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
 
-       mlog_entry("(inode=%p, block=(%llu), nr=(%d), flags=%d)\n",
-                  inode, (unsigned long long)block, nr, flags);
+       mlog_entry("(ci=%p, block=(%llu), nr=(%d), flags=%d)\n",
+                  ci, (unsigned long long)block, nr, flags);
 
-       BUG_ON(!inode);
+       BUG_ON(!ci);
        BUG_ON((flags & OCFS2_BH_READAHEAD) &&
               (flags & OCFS2_BH_IGNORE_CACHE));
 
@@ -212,12 +213,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                goto bail;
        }
 
-       mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
+       ocfs2_metadata_cache_io_lock(ci);
        for (i = 0 ; i < nr ; i++) {
                if (bhs[i] == NULL) {
-                       bhs[i] = sb_getblk(inode->i_sb, block++);
+                       bhs[i] = sb_getblk(sb, block++);
                        if (bhs[i] == NULL) {
-                               mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
+                               ocfs2_metadata_cache_io_unlock(ci);
                                status = -EIO;
                                mlog_errno(status);
                                goto bail;
@@ -250,11 +251,11 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                 *    before our is-it-in-flight check.
                 */
 
-               if (!ignore_cache && !ocfs2_buffer_uptodate(inode, bh)) {
+               if (!ignore_cache && !ocfs2_buffer_uptodate(ci, bh)) {
                        mlog(ML_UPTODATE,
-                            "bh (%llu), inode %llu not uptodate\n",
+                            "bh (%llu), owner %llu not uptodate\n",
                             (unsigned long long)bh->b_blocknr,
-                            (unsigned long long)OCFS2_I(inode)->ip_blkno);
+                            (unsigned long long)ocfs2_metadata_cache_owner(ci));
                        /* We're using ignore_cache here to say
                         * "go to disk" */
                        ignore_cache = 1;
@@ -283,7 +284,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                         * previously submitted request than we are
                         * done here. */
                        if ((flags & OCFS2_BH_READAHEAD)
-                           && ocfs2_buffer_read_ahead(inode, bh))
+                           && ocfs2_buffer_read_ahead(ci, bh))
                                continue;
 
                        lock_buffer(bh);
@@ -305,7 +306,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                         * buffer lock. */
                        if (!(flags & OCFS2_BH_IGNORE_CACHE)
                            && !(flags & OCFS2_BH_READAHEAD)
-                           && ocfs2_buffer_uptodate(inode, bh)) {
+                           && ocfs2_buffer_uptodate(ci, bh)) {
                                unlock_buffer(bh);
                                continue;
                        }
@@ -327,7 +328,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
 
                if (!(flags & OCFS2_BH_READAHEAD)) {
                        /* We know this can't have changed as we hold the
-                        * inode sem. Avoid doing any work on the bh if the
+                        * owner sem. Avoid doing any work on the bh if the
                         * journal has it. */
                        if (!buffer_jbd(bh))
                                wait_on_buffer(bh);
@@ -351,7 +352,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                                 * that better not have changed */
                                BUG_ON(buffer_jbd(bh));
                                clear_buffer_needs_validate(bh);
-                               status = validate(inode->i_sb, bh);
+                               status = validate(sb, bh);
                                if (status) {
                                        put_bh(bh);
                                        bhs[i] = NULL;
@@ -363,9 +364,9 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                /* Always set the buffer in the cache, even if it was
                 * a forced read, or read-ahead which hasn't yet
                 * completed. */
-               ocfs2_set_buffer_uptodate(inode, bh);
+               ocfs2_set_buffer_uptodate(ci, bh);
        }
-       mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
+       ocfs2_metadata_cache_io_unlock(ci);
 
        mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", 
             (unsigned long long)block, nr,
@@ -399,7 +400,7 @@ static void ocfs2_check_super_or_backup(struct super_block *sb,
 
 /*
  * Write super block and backups doesn't need to collaborate with journal,
- * so we don't need to lock ip_io_mutex and inode doesn't need to bea passed
+ * so we don't need to lock ip_io_mutex and ci doesn't need to bea passed
  * into this function.
  */
 int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
index c75d682..b97bcc6 100644 (file)
@@ -33,7 +33,7 @@ void ocfs2_end_buffer_io_sync(struct buffer_head *bh,
 
 int ocfs2_write_block(struct ocfs2_super          *osb,
                      struct buffer_head  *bh,
-                     struct inode        *inode);
+                     struct ocfs2_caching_info   *ci);
 int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
                           unsigned int nr, struct buffer_head *bhs[]);
 
@@ -44,7 +44,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
  * be set even for a READAHEAD call, as it marks the buffer for later
  * validation.
  */
-int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
+int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
                      struct buffer_head *bhs[], int flags,
                      int (*validate)(struct super_block *sb,
                                      struct buffer_head *bh));
@@ -55,7 +55,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
 #define OCFS2_BH_IGNORE_CACHE      1
 #define OCFS2_BH_READAHEAD         8
 
-static inline int ocfs2_read_block(struct inode *inode, u64 off,
+static inline int ocfs2_read_block(struct ocfs2_caching_info *ci, u64 off,
                                   struct buffer_head **bh,
                                   int (*validate)(struct super_block *sb,
                                                   struct buffer_head *bh))
@@ -68,7 +68,7 @@ static inline int ocfs2_read_block(struct inode *inode, u64 off,
                goto bail;
        }
 
-       status = ocfs2_read_blocks(inode, off, 1, bh, 0, validate);
+       status = ocfs2_read_blocks(ci, off, 1, bh, 0, validate);
 
 bail:
        return status;
index 96df541..1cd2934 100644 (file)
@@ -111,6 +111,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
        define_mask(EXPORT),
        define_mask(XATTR),
        define_mask(QUOTA),
+       define_mask(REFCOUNT),
        define_mask(ERROR),
        define_mask(NOTICE),
        define_mask(KTHREAD),
index 696c32e..9b4d117 100644 (file)
 #define ML_EXPORT      0x0000000010000000ULL /* ocfs2 export operations */
 #define ML_XATTR       0x0000000020000000ULL /* ocfs2 extended attributes */
 #define ML_QUOTA       0x0000000040000000ULL /* ocfs2 quota operations */
+#define ML_REFCOUNT    0x0000000080000000ULL /* refcount tree operations */
 /* bits that are infrequently given and frequently matched in the high word */
 #define ML_ERROR       0x0000000100000000ULL /* sent to KERN_ERR */
 #define ML_NOTICE      0x0000000200000000ULL /* setn to KERN_NOTICE */
index b358f3b..28c3ec2 100644 (file)
@@ -176,7 +176,7 @@ static int ocfs2_dx_dir_link_trailer(struct inode *dir, handle_t *handle,
        struct ocfs2_dx_root_block *dx_root;
        struct ocfs2_dir_block_trailer *trailer;
 
-       ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
+       ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -564,7 +564,8 @@ static int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys,
        int ret;
        struct buffer_head *tmp = *bh;
 
-       ret = ocfs2_read_block(dir, phys, &tmp, ocfs2_validate_dir_block);
+       ret = ocfs2_read_block(INODE_CACHE(dir), phys, &tmp,
+                              ocfs2_validate_dir_block);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -622,7 +623,8 @@ static int ocfs2_read_dx_root(struct inode *dir, struct ocfs2_dinode *di,
        u64 blkno = le64_to_cpu(di->i_dx_root);
        struct buffer_head *tmp = *dx_root_bh;
 
-       ret = ocfs2_read_block(dir, blkno, &tmp, ocfs2_validate_dx_root);
+       ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
+                              ocfs2_validate_dx_root);
 
        /* If ocfs2_read_block() got us a new bh, pass it up. */
        if (!ret && !*dx_root_bh)
@@ -662,7 +664,8 @@ static int ocfs2_read_dx_leaf(struct inode *dir, u64 blkno,
        int ret;
        struct buffer_head *tmp = *dx_leaf_bh;
 
-       ret = ocfs2_read_block(dir, blkno, &tmp, ocfs2_validate_dx_leaf);
+       ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
+                              ocfs2_validate_dx_leaf);
 
        /* If ocfs2_read_block() got us a new bh, pass it up. */
        if (!ret && !*dx_leaf_bh)
@@ -680,7 +683,7 @@ static int ocfs2_read_dx_leaves(struct inode *dir, u64 start, int num,
 {
        int ret;
 
-       ret = ocfs2_read_blocks(dir, start, num, dx_leaf_bhs, 0,
+       ret = ocfs2_read_blocks(INODE_CACHE(dir), start, num, dx_leaf_bhs, 0,
                                ocfs2_validate_dx_leaf);
        if (ret)
                mlog_errno(ret);
@@ -802,7 +805,8 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode,
        struct ocfs2_extent_rec *rec = NULL;
 
        if (el->l_tree_depth) {
-               ret = ocfs2_find_leaf(inode, el, major_hash, &eb_bh);
+               ret = ocfs2_find_leaf(INODE_CACHE(inode), el, major_hash,
+                                     &eb_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -1133,7 +1137,8 @@ int ocfs2_update_entry(struct inode *dir, handle_t *handle,
        if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
                access = ocfs2_journal_access_di;
 
-       ret = access(handle, dir, de_bh, OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = access(handle, INODE_CACHE(dir), de_bh,
+                    OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -1176,7 +1181,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
                        goto bail;
                }
                if (de == de_del)  {
-                       status = access(handle, dir, bh,
+                       status = access(handle, INODE_CACHE(dir), bh,
                                        OCFS2_JOURNAL_ACCESS_WRITE);
                        if (status < 0) {
                                status = -EIO;
@@ -1326,7 +1331,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
         * the entry count needs to be updated. Also, we might be
         * adding to the start of the free list.
         */
-       ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
+       ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -1334,7 +1339,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
        }
 
        if (!ocfs2_dx_root_inline(dx_root)) {
-               ret = ocfs2_journal_access_dl(handle, dir,
+               ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
                                              lookup->dl_dx_leaf_bh,
                                              OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
@@ -1493,7 +1498,7 @@ static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
        int ret;
        struct ocfs2_dx_leaf *dx_leaf;
 
-       ret = ocfs2_journal_access_dl(handle, dir, dx_leaf_bh,
+       ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -1523,7 +1528,7 @@ static int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle,
        struct ocfs2_dx_root_block *dx_root;
        struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
 
-       ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
+       ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -1645,11 +1650,13 @@ int __ocfs2_add_entry(handle_t *handle,
                 */
                if (ocfs2_free_list_at_root(lookup)) {
                        bh = lookup->dl_dx_root_bh;
-                       retval = ocfs2_journal_access_dr(handle, dir, bh,
+                       retval = ocfs2_journal_access_dr(handle,
+                                                INODE_CACHE(dir), bh,
                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                } else {
                        bh = lookup->dl_prev_leaf_bh;
-                       retval = ocfs2_journal_access_db(handle, dir, bh,
+                       retval = ocfs2_journal_access_db(handle,
+                                                INODE_CACHE(dir), bh,
                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                }
                if (retval) {
@@ -1700,11 +1707,13 @@ int __ocfs2_add_entry(handle_t *handle,
                        }
 
                        if (insert_bh == parent_fe_bh)
-                               status = ocfs2_journal_access_di(handle, dir,
+                               status = ocfs2_journal_access_di(handle,
+                                                                INODE_CACHE(dir),
                                                                 insert_bh,
                                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                        else {
-                               status = ocfs2_journal_access_db(handle, dir,
+                               status = ocfs2_journal_access_db(handle,
+                                                                INODE_CACHE(dir),
                                                                 insert_bh,
                                              OCFS2_JOURNAL_ACCESS_WRITE);
 
@@ -2280,7 +2289,7 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
        struct ocfs2_inline_data *data = &di->id2.i_data;
        unsigned int size = le16_to_cpu(data->id_count);
 
-       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -2332,9 +2341,9 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
                goto bail;
        }
 
-       ocfs2_set_new_buffer_uptodate(inode, new_bh);
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), new_bh);
 
-       status = ocfs2_journal_access_db(handle, inode, new_bh,
+       status = ocfs2_journal_access_db(handle, INODE_CACHE(inode), new_bh,
                                         OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
@@ -2418,9 +2427,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
                ret = -EIO;
                goto out;
        }
-       ocfs2_set_new_buffer_uptodate(dir, dx_root_bh);
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dx_root_bh);
 
-       ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
+       ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
                                      OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret < 0) {
                mlog_errno(ret);
@@ -2454,7 +2463,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
        if (ret)
                mlog_errno(ret);
 
-       ret = ocfs2_journal_access_di(handle, dir, di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
                                      OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret) {
                mlog_errno(ret);
@@ -2495,9 +2504,9 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
                }
                dx_leaves[i] = bh;
 
-               ocfs2_set_new_buffer_uptodate(dir, bh);
+               ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), bh);
 
-               ret = ocfs2_journal_access_dl(handle, dir, bh,
+               ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), bh,
                                              OCFS2_JOURNAL_ACCESS_CREATE);
                if (ret < 0) {
                        mlog_errno(ret);
@@ -2582,7 +2591,6 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir,
 {
        int ret;
        u64 phys_blkno;
-       struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
 
        ret = __ocfs2_dx_dir_new_cluster(dir, cpos, handle, data_ac, dx_leaves,
                                         num_dx_leaves, &phys_blkno);
@@ -2591,7 +2599,7 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir,
                goto out;
        }
 
-       ret = ocfs2_insert_extent(osb, handle, dir, et, cpos, phys_blkno, 1, 0,
+       ret = ocfs2_insert_extent(handle, et, cpos, phys_blkno, 1, 0,
                                  meta_ac);
        if (ret)
                mlog_errno(ret);
@@ -2895,7 +2903,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
        struct ocfs2_extent_tree dx_et;
        int did_quota = 0, bytes_allocated = 0;
 
-       ocfs2_init_dinode_extent_tree(&et, dir, di_bh);
+       ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir), di_bh);
 
        alloc = ocfs2_clusters_for_bytes(sb, bytes);
        dx_alloc = 0;
@@ -3005,9 +3013,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                goto out_commit;
        }
 
-       ocfs2_set_new_buffer_uptodate(dir, dirdata_bh);
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dirdata_bh);
 
-       ret = ocfs2_journal_access_db(handle, dir, dirdata_bh,
+       ret = ocfs2_journal_access_db(handle, INODE_CACHE(dir), dirdata_bh,
                                      OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret) {
                mlog_errno(ret);
@@ -3060,7 +3068,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
         * We let the later dirent insert modify c/mtime - to the user
         * the data hasn't changed.
         */
-       ret = ocfs2_journal_access_di(handle, dir, di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
                                      OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret) {
                mlog_errno(ret);
@@ -3085,7 +3093,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
         * This should never fail as our extent list is empty and all
         * related blocks have been journaled already.
         */
-       ret = ocfs2_insert_extent(osb, handle, dir, &et, 0, blkno, len,
+       ret = ocfs2_insert_extent(handle, &et, 0, blkno, len,
                                  0, NULL);
        if (ret) {
                mlog_errno(ret);
@@ -3117,8 +3125,10 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                        ocfs2_dx_dir_index_root_block(dir, dx_root_bh,
                                                      dirdata_bh);
                } else {
-                       ocfs2_init_dx_root_extent_tree(&dx_et, dir, dx_root_bh);
-                       ret = ocfs2_insert_extent(osb, handle, dir, &dx_et, 0,
+                       ocfs2_init_dx_root_extent_tree(&dx_et,
+                                                      INODE_CACHE(dir),
+                                                      dx_root_bh);
+                       ret = ocfs2_insert_extent(handle, &dx_et, 0,
                                                  dx_insert_blkno, 1, 0, NULL);
                        if (ret)
                                mlog_errno(ret);
@@ -3138,7 +3148,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                }
                blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
 
-               ret = ocfs2_insert_extent(osb, handle, dir, &et, 1,
+               ret = ocfs2_insert_extent(handle, &et, 1,
                                          blkno, len, 0, NULL);
                if (ret) {
                        mlog_errno(ret);
@@ -3337,8 +3347,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        spin_lock(&OCFS2_I(dir)->ip_lock);
        if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
                spin_unlock(&OCFS2_I(dir)->ip_lock);
-               ocfs2_init_dinode_extent_tree(&et, dir, parent_fe_bh);
-               num_free_extents = ocfs2_num_free_extents(osb, dir, &et);
+               ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir),
+                                             parent_fe_bh);
+               num_free_extents = ocfs2_num_free_extents(osb, &et);
                if (num_free_extents < 0) {
                        status = num_free_extents;
                        mlog_errno(status);
@@ -3387,9 +3398,9 @@ do_extend:
                goto bail;
        }
 
-       ocfs2_set_new_buffer_uptodate(dir, new_bh);
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), new_bh);
 
-       status = ocfs2_journal_access_db(handle, dir, new_bh,
+       status = ocfs2_journal_access_db(handle, INODE_CACHE(dir), new_bh,
                                         OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
@@ -3829,7 +3840,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
             (unsigned long long)OCFS2_I(dir)->ip_blkno,
             (unsigned long long)leaf_blkno, insert_hash);
 
-       ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh);
+       ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
 
        dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
        /*
@@ -3885,7 +3896,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
        }
        did_quota = 1;
 
-       ret = ocfs2_journal_access_dl(handle, dir, dx_leaf_bh,
+       ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -3949,7 +3960,8 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
        }
 
        for (i = 0; i < num_dx_leaves; i++) {
-               ret = ocfs2_journal_access_dl(handle, dir, orig_dx_leaves[i],
+               ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
+                                             orig_dx_leaves[i],
                                              OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
@@ -4165,7 +4177,7 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir,
         * failure to add the dx_root_bh to the journal won't result
         * us losing clusters.
         */
-       ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh,
+       ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -4207,9 +4219,8 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir,
 
        /* This should never fail considering we start with an empty
         * dx_root. */
-       ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh);
-       ret = ocfs2_insert_extent(osb, handle, dir, &et, 0,
-                                 insert_blkno, 1, 0, NULL);
+       ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
+       ret = ocfs2_insert_extent(handle, &et, 0, insert_blkno, 1, 0, NULL);
        if (ret)
                mlog_errno(ret);
        did_quota = 0;
@@ -4469,7 +4480,7 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,
                goto out_unlock;
        }
 
-       ret = ocfs2_journal_access_di(handle, dir, di_bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -4532,7 +4543,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
        if (ocfs2_dx_root_inline(dx_root))
                goto remove_index;
 
-       ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh);
+       ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
 
        /* XXX: What if dr_clusters is too large? */
        while (le32_to_cpu(dx_root->dr_clusters)) {
@@ -4565,7 +4576,7 @@ remove_index:
                goto out;
        }
 
-       ocfs2_remove_from_cache(dir, dx_root_bh);
+       ocfs2_remove_from_cache(INODE_CACHE(dir), dx_root_bh);
 out:
        ocfs2_schedule_truncate_log_flush(osb, 1);
        ocfs2_run_deallocs(osb, &dealloc);
index d490b66..98569e8 100644 (file)
@@ -212,14 +212,18 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
                spin_lock(&dlm->spinlock);
        }
 
+       spin_lock(&res->spinlock);
        if (!list_empty(&res->purge)) {
                mlog(0, "removing lockres %.*s:%p from purgelist, "
                     "master = %d\n", res->lockname.len, res->lockname.name,
                     res, master);
                list_del_init(&res->purge);
+               spin_unlock(&res->spinlock);
                dlm_lockres_put(res);
                dlm->purge_count--;
-       }
+       } else
+               spin_unlock(&res->spinlock);
+
        __dlm_unhash_lockres(res);
 
        /* lockres is not in the hash now.  drop the flag and wake up
index 110bb57..0d38d67 100644 (file)
@@ -53,6 +53,7 @@
 #include "super.h"
 #include "uptodate.h"
 #include "quota.h"
+#include "refcounttree.h"
 
 #include "buffer_head_io.h"
 
@@ -110,6 +111,11 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
 
 static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
 
+static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
+                                           int new_level);
+static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
+                                        int blocking);
+
 #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
 
 /* This aids in debugging situations where a bad LVB might be involved. */
@@ -278,6 +284,12 @@ static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
        .flags          = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
 };
 
+static struct ocfs2_lock_res_ops ocfs2_refcount_block_lops = {
+       .check_downconvert = ocfs2_check_refcount_downconvert,
+       .downconvert_worker = ocfs2_refcount_convert_worker,
+       .flags          = 0,
+};
+
 static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
 {
        return lockres->l_type == OCFS2_LOCK_TYPE_META ||
@@ -306,6 +318,12 @@ static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_re
        return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
 }
 
+static inline struct ocfs2_refcount_tree *
+ocfs2_lock_res_refcount_tree(struct ocfs2_lock_res *res)
+{
+       return container_of(res, struct ocfs2_refcount_tree, rf_lockres);
+}
+
 static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
 {
        if (lockres->l_ops->get_osb)
@@ -693,6 +711,17 @@ void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
                                   info);
 }
 
+void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
+                                 struct ocfs2_super *osb, u64 ref_blkno,
+                                 unsigned int generation)
+{
+       ocfs2_lock_res_init_once(lockres);
+       ocfs2_build_lock_name(OCFS2_LOCK_TYPE_REFCOUNT, ref_blkno,
+                             generation, lockres->l_name);
+       ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_REFCOUNT,
+                                  &ocfs2_refcount_block_lops, osb);
+}
+
 void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
 {
        mlog_entry_void();
@@ -1548,8 +1577,10 @@ int ocfs2_rw_lock(struct inode *inode, int write)
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
-       if (ocfs2_mount_local(osb))
+       if (ocfs2_mount_local(osb)) {
+               mlog_exit(0);
                return 0;
+       }
 
        lockres = &OCFS2_I(inode)->ip_rw_lockres;
 
@@ -2127,7 +2158,7 @@ static int ocfs2_inode_lock_update(struct inode *inode,
 
        /* This will discard any caching information we might have had
         * for the inode metadata. */
-       ocfs2_metadata_cache_purge(inode);
+       ocfs2_metadata_cache_purge(INODE_CACHE(inode));
 
        ocfs2_extent_map_trunc(inode, 0);
 
@@ -3009,6 +3040,7 @@ static void ocfs2_unlock_ast(void *opaque, int error)
                     "unlock_action %d\n", error, lockres->l_name,
                     lockres->l_unlock_action);
                spin_unlock_irqrestore(&lockres->l_lock, flags);
+               mlog_exit_void();
                return;
        }
 
@@ -3495,11 +3527,11 @@ out:
        return UNBLOCK_CONTINUE;
 }
 
-static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
-                                       int new_level)
+static int ocfs2_ci_checkpointed(struct ocfs2_caching_info *ci,
+                                struct ocfs2_lock_res *lockres,
+                                int new_level)
 {
-       struct inode *inode = ocfs2_lock_res_inode(lockres);
-       int checkpointed = ocfs2_inode_fully_checkpointed(inode);
+       int checkpointed = ocfs2_ci_fully_checkpointed(ci);
 
        BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR);
        BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed);
@@ -3507,10 +3539,18 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
        if (checkpointed)
                return 1;
 
-       ocfs2_start_checkpoint(OCFS2_SB(inode->i_sb));
+       ocfs2_start_checkpoint(OCFS2_SB(ocfs2_metadata_cache_get_super(ci)));
        return 0;
 }
 
+static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
+                                       int new_level)
+{
+       struct inode *inode = ocfs2_lock_res_inode(lockres);
+
+       return ocfs2_ci_checkpointed(INODE_CACHE(inode), lockres, new_level);
+}
+
 static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres)
 {
        struct inode *inode = ocfs2_lock_res_inode(lockres);
@@ -3640,6 +3680,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
        return UNBLOCK_CONTINUE_POST;
 }
 
+static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
+                                           int new_level)
+{
+       struct ocfs2_refcount_tree *tree =
+                               ocfs2_lock_res_refcount_tree(lockres);
+
+       return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level);
+}
+
+static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
+                                        int blocking)
+{
+       struct ocfs2_refcount_tree *tree =
+                               ocfs2_lock_res_refcount_tree(lockres);
+
+       ocfs2_metadata_cache_purge(&tree->rf_ci);
+
+       return UNBLOCK_CONTINUE;
+}
+
 static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
 {
        struct ocfs2_qinfo_lvb *lvb;
@@ -3752,6 +3812,37 @@ bail:
        return status;
 }
 
+int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex)
+{
+       int status;
+       int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+       struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
+       struct ocfs2_super *osb = lockres->l_priv;
+
+
+       if (ocfs2_is_hard_readonly(osb))
+               return -EROFS;
+
+       if (ocfs2_mount_local(osb))
+               return 0;
+
+       status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
+       if (status < 0)
+               mlog_errno(status);
+
+       return status;
+}
+
+void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex)
+{
+       int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+       struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
+       struct ocfs2_super *osb = lockres->l_priv;
+
+       if (!ocfs2_mount_local(osb))
+               ocfs2_cluster_unlock(osb, lockres, level);
+}
+
 /*
  * This is the filesystem locking protocol.  It provides the lock handling
  * hooks for the underlying DLM.  It has a maximum version number.
index 7553836..d1ce48e 100644 (file)
@@ -101,6 +101,9 @@ void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
 struct ocfs2_mem_dqinfo;
 void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
                                struct ocfs2_mem_dqinfo *info);
+void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
+                                 struct ocfs2_super *osb, u64 ref_blkno,
+                                 unsigned int generation);
 void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
 int ocfs2_create_new_inode_locks(struct inode *inode);
 int ocfs2_drop_inode_locks(struct inode *inode);
@@ -148,6 +151,9 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock);
 void ocfs2_file_unlock(struct file *file);
 int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex);
 void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex);
+struct ocfs2_refcount_tree;
+int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex);
+void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex);
 
 
 void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
index f2bb1a0..843db64 100644 (file)
@@ -293,7 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
 
-       ret = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
+       ret = ocfs2_read_extent_block(INODE_CACHE(inode), last_eb_blk, &eb_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -353,11 +353,11 @@ static int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el,
  * eb_bh is NULL. Otherwise, eb_bh should point to the extent block
  * containing el.
  */
-static int ocfs2_figure_hole_clusters(struct inode *inode,
-                                     struct ocfs2_extent_list *el,
-                                     struct buffer_head *eb_bh,
-                                     u32 v_cluster,
-                                     u32 *num_clusters)
+int ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci,
+                              struct ocfs2_extent_list *el,
+                              struct buffer_head *eb_bh,
+                              u32 v_cluster,
+                              u32 *num_clusters)
 {
        int ret, i;
        struct buffer_head *next_eb_bh = NULL;
@@ -375,7 +375,7 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
                if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
                        goto no_more_extents;
 
-               ret = ocfs2_read_extent_block(inode,
+               ret = ocfs2_read_extent_block(ci,
                                              le64_to_cpu(eb->h_next_leaf_blk),
                                              &next_eb_bh);
                if (ret) {
@@ -428,7 +428,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode,
        tree_height = le16_to_cpu(el->l_tree_depth);
 
        if (tree_height > 0) {
-               ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh);
+               ret = ocfs2_find_leaf(INODE_CACHE(inode), el, v_cluster,
+                                     &eb_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -455,7 +456,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode,
                 * field.
                 */
                if (hole_len) {
-                       ret = ocfs2_figure_hole_clusters(inode, el, eb_bh,
+                       ret = ocfs2_figure_hole_clusters(INODE_CACHE(inode),
+                                                        el, eb_bh,
                                                         v_cluster, &len);
                        if (ret) {
                                mlog_errno(ret);
@@ -539,7 +541,8 @@ static void ocfs2_relative_extent_offsets(struct super_block *sb,
 
 int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
                             u32 *p_cluster, u32 *num_clusters,
-                            struct ocfs2_extent_list *el)
+                            struct ocfs2_extent_list *el,
+                            unsigned int *extent_flags)
 {
        int ret = 0, i;
        struct buffer_head *eb_bh = NULL;
@@ -548,7 +551,8 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
        u32 coff;
 
        if (el->l_tree_depth) {
-               ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh);
+               ret = ocfs2_find_leaf(INODE_CACHE(inode), el, v_cluster,
+                                     &eb_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -590,6 +594,9 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
                *p_cluster = *p_cluster + coff;
                if (num_clusters)
                        *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
+
+               if (extent_flags)
+                       *extent_flags = rec->e_flags;
        }
 out:
        if (eb_bh)
@@ -862,8 +869,8 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
                        BUG_ON(bhs[done + i]->b_blocknr != (p_block + i));
                }
 
-               rc = ocfs2_read_blocks(inode, p_block, count, bhs + done,
-                                      flags, validate);
+               rc = ocfs2_read_blocks(INODE_CACHE(inode), p_block, count,
+                                      bhs + done, flags, validate);
                if (rc) {
                        mlog_errno(rc);
                        break;
index b7dd973..e79d41c 100644 (file)
@@ -55,12 +55,18 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
 int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
                             u32 *p_cluster, u32 *num_clusters,
-                            struct ocfs2_extent_list *el);
+                            struct ocfs2_extent_list *el,
+                            unsigned int *extent_flags);
 
 int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
                           struct buffer_head *bhs[], int flags,
                           int (*validate)(struct super_block *sb,
                                           struct buffer_head *bh));
+int ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci,
+                              struct ocfs2_extent_list *el,
+                              struct buffer_head *eb_bh,
+                              u32 v_cluster,
+                              u32 *num_clusters);
 static inline int ocfs2_read_virt_block(struct inode *inode, u64 v_block,
                                        struct buffer_head **bh,
                                        int (*validate)(struct super_block *sb,
index 221c5e9..89fc8ee 100644 (file)
@@ -59,6 +59,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "quota.h"
+#include "refcounttree.h"
 
 #include "buffer_head_io.h"
 
@@ -259,7 +260,7 @@ int ocfs2_update_inode_atime(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_journal_access_di(handle, inode, bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -334,6 +335,39 @@ out:
        return ret;
 }
 
+static int ocfs2_cow_file_pos(struct inode *inode,
+                             struct buffer_head *fe_bh,
+                             u64 offset)
+{
+       int status;
+       u32 phys, cpos = offset >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+       unsigned int num_clusters = 0;
+       unsigned int ext_flags = 0;
+
+       /*
+        * If the new offset is aligned to the range of the cluster, there is
+        * no space for ocfs2_zero_range_for_truncate to fill, so no need to
+        * CoW either.
+        */
+       if ((offset & (OCFS2_SB(inode->i_sb)->s_clustersize - 1)) == 0)
+               return 0;
+
+       status = ocfs2_get_clusters(inode, cpos, &phys,
+                                   &num_clusters, &ext_flags);
+       if (status) {
+               mlog_errno(status);
+               goto out;
+       }
+
+       if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
+               goto out;
+
+       return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1);
+
+out:
+       return status;
+}
+
 static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
                                     struct inode *inode,
                                     struct buffer_head *fe_bh,
@@ -346,6 +380,17 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
 
        mlog_entry_void();
 
+       /*
+        * We need to CoW the cluster contains the offset if it is reflinked
+        * since we will call ocfs2_zero_range_for_truncate later which will
+        * write "0" from offset to the end of the cluster.
+        */
+       status = ocfs2_cow_file_pos(inode, fe_bh, new_i_size);
+       if (status) {
+               mlog_errno(status);
+               return status;
+       }
+
        /* TODO: This needs to actually orphan the inode in this
         * transaction. */
 
@@ -356,7 +401,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
                goto out;
        }
 
-       status = ocfs2_journal_access_di(handle, inode, fe_bh,
+       status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -486,6 +531,8 @@ bail_unlock_sem:
        up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
 bail:
+       if (!status && OCFS2_I(inode)->ip_clusters == 0)
+               status = ocfs2_try_remove_refcount_tree(inode, di_bh);
 
        mlog_exit(status);
        return status;
@@ -515,11 +562,10 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb,
        int ret;
        struct ocfs2_extent_tree et;
 
-       ocfs2_init_dinode_extent_tree(&et, inode, fe_bh);
-       ret = ocfs2_add_clusters_in_btree(osb, inode, logical_offset,
-                                          clusters_to_add, mark_unwritten,
-                                          &et, handle,
-                                          data_ac, meta_ac, reason_ret);
+       ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), fe_bh);
+       ret = ocfs2_add_clusters_in_btree(handle, &et, logical_offset,
+                                         clusters_to_add, mark_unwritten,
+                                         data_ac, meta_ac, reason_ret);
 
        return ret;
 }
@@ -564,7 +610,7 @@ restart_all:
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
             clusters_to_add);
-       ocfs2_init_dinode_extent_tree(&et, inode, bh);
+       ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), bh);
        status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
                                       &data_ac, &meta_ac);
        if (status) {
@@ -593,7 +639,7 @@ restarted_transaction:
        /* reserve a write to the file entry early on - that we if we
         * run out of credits in the allocation path, we can still
         * update i_size. */
-       status = ocfs2_journal_access_di(handle, inode, bh,
+       status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -1131,7 +1177,7 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_journal_access_di(handle, inode, bh,
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
@@ -1395,7 +1441,7 @@ static int ocfs2_remove_inode_range(struct inode *inode,
        struct address_space *mapping = inode->i_mapping;
        struct ocfs2_extent_tree et;
 
-       ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
+       ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
        ocfs2_init_dealloc_ctxt(&dealloc);
 
        if (byte_len == 0)
@@ -1657,6 +1703,70 @@ static long ocfs2_fallocate(struct inode *inode, int mode, loff_t offset,
                                         OCFS2_IOC_RESVSP64, &sr, change_size);
 }
 
+int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
+                                  size_t count)
+{
+       int ret = 0;
+       unsigned int extent_flags;
+       u32 cpos, clusters, extent_len, phys_cpos;
+       struct super_block *sb = inode->i_sb;
+
+       if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)) ||
+           !(OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL))
+               return 0;
+
+       cpos = pos >> OCFS2_SB(sb)->s_clustersize_bits;
+       clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos;
+
+       while (clusters) {
+               ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len,
+                                        &extent_flags);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               if (phys_cpos && (extent_flags & OCFS2_EXT_REFCOUNTED)) {
+                       ret = 1;
+                       break;
+               }
+
+               if (extent_len > clusters)
+                       extent_len = clusters;
+
+               clusters -= extent_len;
+               cpos += extent_len;
+       }
+out:
+       return ret;
+}
+
+static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
+                                           loff_t pos, size_t count,
+                                           int *meta_level)
+{
+       int ret;
+       struct buffer_head *di_bh = NULL;
+       u32 cpos = pos >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+       u32 clusters =
+               ocfs2_clusters_for_bytes(inode->i_sb, pos + count) - cpos;
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 1);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       *meta_level = 1;
+
+       ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
+       if (ret)
+               mlog_errno(ret);
+out:
+       brelse(di_bh);
+       return ret;
+}
+
 static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                                         loff_t *ppos,
                                         size_t count,
@@ -1713,6 +1823,22 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
 
                end = saved_pos + count;
 
+               ret = ocfs2_check_range_for_refcount(inode, saved_pos, count);
+               if (ret == 1) {
+                       ocfs2_inode_unlock(inode, meta_level);
+                       meta_level = -1;
+
+                       ret = ocfs2_prepare_inode_for_refcount(inode,
+                                                              saved_pos,
+                                                              count,
+                                                              &meta_level);
+               }
+
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_unlock;
+               }
+
                /*
                 * Skip the O_DIRECT checks if we don't need
                 * them.
@@ -1759,7 +1885,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
                *ppos = saved_pos;
 
 out_unlock:
-       ocfs2_inode_unlock(inode, meta_level);
+       if (meta_level >= 0)
+               ocfs2_inode_unlock(inode, meta_level);
 
 out:
        return ret;
index 172f9fb..d66cf4f 100644 (file)
@@ -69,4 +69,6 @@ int ocfs2_update_inode_atime(struct inode *inode,
 int ocfs2_change_file_space(struct file *file, unsigned int cmd,
                            struct ocfs2_space_resv *sr);
 
+int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
+                                  size_t count);
 #endif /* OCFS2_FILE_H */
index 4dc8890..0297fb8 100644 (file)
@@ -53,6 +53,7 @@
 #include "sysfile.h"
 #include "uptodate.h"
 #include "xattr.h"
+#include "refcounttree.h"
 
 #include "buffer_head_io.h"
 
@@ -562,7 +563,8 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
                        goto out;
                }
 
-               status = ocfs2_journal_access_di(handle, inode, fe_bh,
+               status = ocfs2_journal_access_di(handle, INODE_CACHE(inode),
+                                                fe_bh,
                                                 OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
@@ -646,7 +648,7 @@ static int ocfs2_remove_inode(struct inode *inode,
        }
 
        /* set the inodes dtime */
-       status = ocfs2_journal_access_di(handle, inode, di_bh,
+       status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -662,7 +664,7 @@ static int ocfs2_remove_inode(struct inode *inode,
                goto bail_commit;
        }
 
-       ocfs2_remove_from_cache(inode, di_bh);
+       ocfs2_remove_from_cache(INODE_CACHE(inode), di_bh);
        vfs_dq_free_inode(inode);
 
        status = ocfs2_free_dinode(handle, inode_alloc_inode,
@@ -781,6 +783,12 @@ static int ocfs2_wipe_inode(struct inode *inode,
                goto bail_unlock_dir;
        }
 
+       status = ocfs2_remove_refcount_tree(inode, di_bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto bail_unlock_dir;
+       }
+
        status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
                                    orphan_dir_bh);
        if (status < 0)
@@ -1112,13 +1120,14 @@ void ocfs2_clear_inode(struct inode *inode)
        ocfs2_lock_res_free(&oi->ip_inode_lockres);
        ocfs2_lock_res_free(&oi->ip_open_lockres);
 
-       ocfs2_metadata_cache_purge(inode);
+       ocfs2_metadata_cache_exit(INODE_CACHE(inode));
 
-       mlog_bug_on_msg(oi->ip_metadata_cache.ci_num_cached,
+       mlog_bug_on_msg(INODE_CACHE(inode)->ci_num_cached,
                        "Clear inode of %llu, inode has %u cache items\n",
-                       (unsigned long long)oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached);
+                       (unsigned long long)oi->ip_blkno,
+                       INODE_CACHE(inode)->ci_num_cached);
 
-       mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),
+       mlog_bug_on_msg(!(INODE_CACHE(inode)->ci_flags & OCFS2_CACHE_FL_INLINE),
                        "Clear inode of %llu, inode has a bad flag\n",
                        (unsigned long long)oi->ip_blkno);
 
@@ -1145,9 +1154,7 @@ void ocfs2_clear_inode(struct inode *inode)
                        (unsigned long long)oi->ip_blkno, oi->ip_open_count);
 
        /* Clear all other flags. */
-       oi->ip_flags = OCFS2_INODE_CACHE_INLINE;
-       oi->ip_created_trans = 0;
-       oi->ip_last_trans = 0;
+       oi->ip_flags = 0;
        oi->ip_dir_start_lookup = 0;
        oi->ip_blkno = 0ULL;
 
@@ -1239,7 +1246,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
        mlog_entry("(inode %llu)\n",
                   (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       status = ocfs2_journal_access_di(handle, inode, bh,
+       status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
                                         OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -1380,8 +1387,8 @@ int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
        int rc;
        struct buffer_head *tmp = *bh;
 
-       rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp,
-                              flags, ocfs2_validate_inode_block);
+       rc = ocfs2_read_blocks(INODE_CACHE(inode), OCFS2_I(inode)->ip_blkno,
+                              1, &tmp, flags, ocfs2_validate_inode_block);
 
        /* If ocfs2_read_blocks() got us a new bh, pass it up. */
        if (!rc && !*bh)
@@ -1394,3 +1401,56 @@ int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh)
 {
        return ocfs2_read_inode_block_full(inode, bh, 0);
 }
+
+
+static u64 ocfs2_inode_cache_owner(struct ocfs2_caching_info *ci)
+{
+       struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
+
+       return oi->ip_blkno;
+}
+
+static struct super_block *ocfs2_inode_cache_get_super(struct ocfs2_caching_info *ci)
+{
+       struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
+
+       return oi->vfs_inode.i_sb;
+}
+
+static void ocfs2_inode_cache_lock(struct ocfs2_caching_info *ci)
+{
+       struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
+
+       spin_lock(&oi->ip_lock);
+}
+
+static void ocfs2_inode_cache_unlock(struct ocfs2_caching_info *ci)
+{
+       struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
+
+       spin_unlock(&oi->ip_lock);
+}
+
+static void ocfs2_inode_cache_io_lock(struct ocfs2_caching_info *ci)
+{
+       struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
+
+       mutex_lock(&oi->ip_io_mutex);
+}
+
+static void ocfs2_inode_cache_io_unlock(struct ocfs2_caching_info *ci)
+{
+       struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
+
+       mutex_unlock(&oi->ip_io_mutex);
+}
+
+const struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
+       .co_owner               = ocfs2_inode_cache_owner,
+       .co_get_super           = ocfs2_inode_cache_get_super,
+       .co_cache_lock          = ocfs2_inode_cache_lock,
+       .co_cache_unlock        = ocfs2_inode_cache_unlock,
+       .co_io_lock             = ocfs2_inode_cache_io_lock,
+       .co_io_unlock           = ocfs2_inode_cache_io_unlock,
+};
+
index ea71525..ba4fe07 100644 (file)
@@ -60,12 +60,6 @@ struct ocfs2_inode_info
 
        u32                             ip_dir_start_lookup;
 
-       /* next two are protected by trans_inc_lock */
-       /* which transaction were we created on? Zero if none. */
-       unsigned long                   ip_created_trans;
-       /* last transaction we were a part of. */
-       unsigned long                   ip_last_trans;
-
        struct ocfs2_caching_info       ip_metadata_cache;
 
        struct ocfs2_extent_map         ip_extent_map;
@@ -106,8 +100,6 @@ struct ocfs2_inode_info
 #define OCFS2_INODE_MAYBE_ORPHANED     0x00000020
 /* Does someone have the file open O_DIRECT */
 #define OCFS2_INODE_OPEN_DIRECT                0x00000040
-/* Indicates that the metadata cache should be used as an array. */
-#define OCFS2_INODE_CACHE_INLINE       0x00000080
 
 static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
 {
@@ -120,6 +112,12 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
 extern struct kmem_cache *ocfs2_inode_cache;
 
 extern const struct address_space_operations ocfs2_aops;
+extern const struct ocfs2_caching_operations ocfs2_inode_caching_ops;
+
+static inline struct ocfs2_caching_info *INODE_CACHE(struct inode *inode)
+{
+       return &OCFS2_I(inode)->ip_metadata_cache;
+}
 
 void ocfs2_clear_inode(struct inode *inode);
 void ocfs2_delete_inode(struct inode *inode);
@@ -172,4 +170,10 @@ int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh);
 /* The same, but can be passed OCFS2_BH_* flags */
 int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
                                int flags);
+
+static inline struct ocfs2_inode_info *cache_info_to_inode(struct ocfs2_caching_info *ci)
+{
+       return container_of(ci, struct ocfs2_inode_info, ip_metadata_cache);
+}
+
 #endif /* OCFS2_INODE_H */
index 467b413..31fbb06 100644 (file)
@@ -21,6 +21,7 @@
 #include "ocfs2_fs.h"
 #include "ioctl.h"
 #include "resize.h"
+#include "refcounttree.h"
 
 #include <linux/ext2_fs.h>
 
@@ -115,6 +116,9 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int status;
        struct ocfs2_space_resv sr;
        struct ocfs2_new_group_input input;
+       struct reflink_arguments args;
+       const char *old_path, *new_path;
+       bool preserve;
 
        switch (cmd) {
        case OCFS2_IOC_GETFLAGS:
@@ -160,6 +164,15 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        return -EFAULT;
 
                return ocfs2_group_add(inode, &input);
+       case OCFS2_IOC_REFLINK:
+               if (copy_from_user(&args, (struct reflink_arguments *)arg,
+                                  sizeof(args)))
+                       return -EFAULT;
+               old_path = (const char *)(unsigned long)args.old_path;
+               new_path = (const char *)(unsigned long)args.new_path;
+               preserve = (args.preserve != 0);
+
+               return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
        default:
                return -ENOTTY;
        }
@@ -182,6 +195,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        case OCFS2_IOC_GROUP_EXTEND:
        case OCFS2_IOC_GROUP_ADD:
        case OCFS2_IOC_GROUP_ADD64:
+       case OCFS2_IOC_REFLINK:
                break;
        default:
                return -ENOIOCTLCMD;
index c48b93a..54c16b6 100644 (file)
@@ -48,6 +48,7 @@
 #include "slot_map.h"
 #include "super.h"
 #include "sysfile.h"
+#include "uptodate.h"
 #include "quota.h"
 
 #include "buffer_head_io.h"
@@ -554,6 +555,14 @@ static struct ocfs2_triggers eb_triggers = {
        .ot_offset      = offsetof(struct ocfs2_extent_block, h_check),
 };
 
+static struct ocfs2_triggers rb_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+       .ot_offset      = offsetof(struct ocfs2_refcount_block, rf_check),
+};
+
 static struct ocfs2_triggers gd_triggers = {
        .ot_triggers = {
                .t_commit = ocfs2_commit_trigger,
@@ -601,14 +610,16 @@ static struct ocfs2_triggers dl_triggers = {
 };
 
 static int __ocfs2_journal_access(handle_t *handle,
-                                 struct inode *inode,
+                                 struct ocfs2_caching_info *ci,
                                  struct buffer_head *bh,
                                  struct ocfs2_triggers *triggers,
                                  int type)
 {
        int status;
+       struct ocfs2_super *osb =
+               OCFS2_SB(ocfs2_metadata_cache_get_super(ci));
 
-       BUG_ON(!inode);
+       BUG_ON(!ci || !ci->ci_ops);
        BUG_ON(!handle);
        BUG_ON(!bh);
 
@@ -627,15 +638,15 @@ static int __ocfs2_journal_access(handle_t *handle,
                BUG();
        }
 
-       /* Set the current transaction information on the inode so
+       /* Set the current transaction information on the ci so
         * that the locking code knows whether it can drop it's locks
-        * on this inode or not. We're protected from the commit
+        * on this ci or not. We're protected from the commit
         * thread updating the current transaction id until
         * ocfs2_commit_trans() because ocfs2_start_trans() took
         * j_trans_barrier for us. */
-       ocfs2_set_inode_lock_trans(OCFS2_SB(inode->i_sb)->journal, inode);
+       ocfs2_set_ci_lock_trans(osb->journal, ci);
 
-       mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
+       ocfs2_metadata_cache_io_lock(ci);
        switch (type) {
        case OCFS2_JOURNAL_ACCESS_CREATE:
        case OCFS2_JOURNAL_ACCESS_WRITE:
@@ -650,9 +661,9 @@ static int __ocfs2_journal_access(handle_t *handle,
                status = -EINVAL;
                mlog(ML_ERROR, "Uknown access type!\n");
        }
-       if (!status && ocfs2_meta_ecc(OCFS2_SB(inode->i_sb)) && triggers)
+       if (!status && ocfs2_meta_ecc(osb) && triggers)
                jbd2_journal_set_triggers(bh, &triggers->ot_triggers);
-       mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
+       ocfs2_metadata_cache_io_unlock(ci);
 
        if (status < 0)
                mlog(ML_ERROR, "Error %d getting %d access to buffer!\n",
@@ -662,66 +673,65 @@ static int __ocfs2_journal_access(handle_t *handle,
        return status;
 }
 
-int ocfs2_journal_access_di(handle_t *handle, struct inode *inode,
-                              struct buffer_head *bh, int type)
+int ocfs2_journal_access_di(handle_t *handle, struct ocfs2_caching_info *ci,
+                           struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &di_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &di_triggers, type);
 }
 
-int ocfs2_journal_access_eb(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_eb(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &eb_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &eb_triggers, type);
 }
 
-int ocfs2_journal_access_gd(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_rb(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &gd_triggers,
+       return __ocfs2_journal_access(handle, ci, bh, &rb_triggers,
                                      type);
 }
 
-int ocfs2_journal_access_db(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_gd(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &db_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &gd_triggers, type);
 }
 
-int ocfs2_journal_access_xb(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_db(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &xb_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &db_triggers, type);
 }
 
-int ocfs2_journal_access_dq(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_xb(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &dq_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &xb_triggers, type);
 }
 
-int ocfs2_journal_access_dr(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_dq(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &dr_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &dq_triggers, type);
 }
 
-int ocfs2_journal_access_dl(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_dr(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, &dl_triggers,
-                                     type);
+       return __ocfs2_journal_access(handle, ci, bh, &dr_triggers, type);
+}
+
+int ocfs2_journal_access_dl(handle_t *handle, struct ocfs2_caching_info *ci,
+                           struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, ci, bh, &dl_triggers, type);
 }
 
-int ocfs2_journal_access(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access(handle_t *handle, struct ocfs2_caching_info *ci,
                         struct buffer_head *bh, int type)
 {
-       return __ocfs2_journal_access(handle, inode, bh, NULL, type);
+       return __ocfs2_journal_access(handle, ci, bh, NULL, type);
 }
 
 int ocfs2_journal_dirty(handle_t *handle,
@@ -898,7 +908,7 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
                ocfs2_bump_recovery_generation(fe);
 
        ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &fe->i_check);
-       status = ocfs2_write_block(osb, bh, journal->j_inode);
+       status = ocfs2_write_block(osb, bh, INODE_CACHE(journal->j_inode));
        if (status < 0)
                mlog_errno(status);
 
@@ -1642,7 +1652,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
                                        ocfs2_get_recovery_generation(fe);
 
        ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &fe->i_check);
-       status = ocfs2_write_block(osb, bh, inode);
+       status = ocfs2_write_block(osb, bh, INODE_CACHE(inode));
        if (status < 0)
                mlog_errno(status);
 
index 2c3222a..3f74e09 100644 (file)
@@ -90,56 +90,66 @@ static inline unsigned long ocfs2_inc_trans_id(struct ocfs2_journal *j)
        return old_id;
 }
 
-static inline void ocfs2_set_inode_lock_trans(struct ocfs2_journal *journal,
-                                             struct inode *inode)
+static inline void ocfs2_set_ci_lock_trans(struct ocfs2_journal *journal,
+                                          struct ocfs2_caching_info *ci)
 {
        spin_lock(&trans_inc_lock);
-       OCFS2_I(inode)->ip_last_trans = journal->j_trans_id;
+       ci->ci_last_trans = journal->j_trans_id;
        spin_unlock(&trans_inc_lock);
 }
 
 /* Used to figure out whether it's safe to drop a metadata lock on an
- * inode. Returns true if all the inodes changes have been
+ * cached object. Returns true if all the object's changes have been
  * checkpointed to disk. You should be holding the spinlock on the
  * metadata lock while calling this to be sure that nobody can take
  * the lock and put it on another transaction. */
-static inline int ocfs2_inode_fully_checkpointed(struct inode *inode)
+static inline int ocfs2_ci_fully_checkpointed(struct ocfs2_caching_info *ci)
 {
        int ret;
-       struct ocfs2_journal *journal = OCFS2_SB(inode->i_sb)->journal;
+       struct ocfs2_journal *journal =
+               OCFS2_SB(ocfs2_metadata_cache_get_super(ci))->journal;
 
        spin_lock(&trans_inc_lock);
-       ret = time_after(journal->j_trans_id, OCFS2_I(inode)->ip_last_trans);
+       ret = time_after(journal->j_trans_id, ci->ci_last_trans);
        spin_unlock(&trans_inc_lock);
        return ret;
 }
 
-/* convenience function to check if an inode is still new (has never
- * hit disk) Will do you a favor and set created_trans = 0 when you've
- * been checkpointed.  returns '1' if the inode is still new. */
-static inline int ocfs2_inode_is_new(struct inode *inode)
+/* convenience function to check if an object backed by struct
+ * ocfs2_caching_info  is still new (has never hit disk) Will do you a
+ * favor and set created_trans = 0 when you've
+ * been checkpointed.  returns '1' if the ci is still new. */
+static inline int ocfs2_ci_is_new(struct ocfs2_caching_info *ci)
 {
        int ret;
+       struct ocfs2_journal *journal =
+               OCFS2_SB(ocfs2_metadata_cache_get_super(ci))->journal;
 
+       spin_lock(&trans_inc_lock);
+       ret = !(time_after(journal->j_trans_id, ci->ci_created_trans));
+       if (!ret)
+               ci->ci_created_trans = 0;
+       spin_unlock(&trans_inc_lock);
+       return ret;
+}
+
+/* Wrapper for inodes so we can check system files */
+static inline int ocfs2_inode_is_new(struct inode *inode)
+{
        /* System files are never "new" as they're written out by
         * mkfs. This helps us early during mount, before we have the
         * journal open and j_trans_id could be junk. */
        if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE)
                return 0;
-       spin_lock(&trans_inc_lock);
-       ret = !(time_after(OCFS2_SB(inode->i_sb)->journal->j_trans_id,
-                          OCFS2_I(inode)->ip_created_trans));
-       if (!ret)
-               OCFS2_I(inode)->ip_created_trans = 0;
-       spin_unlock(&trans_inc_lock);
-       return ret;
+
+       return ocfs2_ci_is_new(INODE_CACHE(inode));
 }
 
-static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
-                                      struct inode *inode)
+static inline void ocfs2_ci_set_new(struct ocfs2_super *osb,
+                                   struct ocfs2_caching_info *ci)
 {
        spin_lock(&trans_inc_lock);
-       OCFS2_I(inode)->ip_created_trans = osb->journal->j_trans_id;
+       ci->ci_created_trans = osb->journal->j_trans_id;
        spin_unlock(&trans_inc_lock);
 }
 
@@ -200,7 +210,7 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
        if (ocfs2_mount_local(osb))
                return;
 
-       if (!ocfs2_inode_fully_checkpointed(inode)) {
+       if (!ocfs2_ci_fully_checkpointed(INODE_CACHE(inode))) {
                /* WARNING: This only kicks off a single
                 * checkpoint. If someone races you and adds more
                 * metadata to the journal, you won't know, and will
@@ -210,7 +220,7 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
                ocfs2_start_checkpoint(osb);
 
                wait_event(osb->journal->j_checkpointed,
-                          ocfs2_inode_fully_checkpointed(inode));
+                          ocfs2_ci_fully_checkpointed(INODE_CACHE(inode)));
        }
 }
 
@@ -266,31 +276,34 @@ int                            ocfs2_extend_trans(handle_t *handle, int nblocks);
 
 
 /* ocfs2_inode */
-int ocfs2_journal_access_di(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_di(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* ocfs2_extent_block */
-int ocfs2_journal_access_eb(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_eb(handle_t *handle, struct ocfs2_caching_info *ci,
+                           struct buffer_head *bh, int type);
+/* ocfs2_refcount_block */
+int ocfs2_journal_access_rb(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* ocfs2_group_desc */
-int ocfs2_journal_access_gd(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_gd(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* ocfs2_xattr_block */
-int ocfs2_journal_access_xb(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_xb(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* quota blocks */
-int ocfs2_journal_access_dq(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_dq(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* dirblock */
-int ocfs2_journal_access_db(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_db(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* ocfs2_dx_root_block */
-int ocfs2_journal_access_dr(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_dr(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* ocfs2_dx_leaf */
-int ocfs2_journal_access_dl(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access_dl(handle_t *handle, struct ocfs2_caching_info *ci,
                            struct buffer_head *bh, int type);
 /* Anything that has no ecc */
-int ocfs2_journal_access(handle_t *handle, struct inode *inode,
+int ocfs2_journal_access(handle_t *handle, struct ocfs2_caching_info *ci,
                         struct buffer_head *bh, int type);
 
 /*
@@ -477,6 +490,23 @@ static inline int ocfs2_calc_dxi_expand_credits(struct super_block *sb)
        return credits;
 }
 
+/* inode update, new refcount block and its allocation credits. */
+#define OCFS2_REFCOUNT_TREE_CREATE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1 \
+                                           + OCFS2_SUBALLOC_ALLOC)
+
+/* inode and the refcount block update. */
+#define OCFS2_REFCOUNT_TREE_SET_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
+
+/*
+ * inode and the refcount block update.
+ * It doesn't include the credits for sub alloc change.
+ * So if we need to free the bit, OCFS2_SUBALLOC_FREE needs to be added.
+ */
+#define OCFS2_REFCOUNT_TREE_REMOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
+
+/* 2 metadata alloc, 2 new blocks and root refcount block */
+#define OCFS2_EXPAND_REFCOUNT_TREE_CREDITS (OCFS2_SUBALLOC_ALLOC * 2 + 3)
+
 /*
  * Please note that the caller must make sure that root_el is the root
  * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise