tree-wide: fix assorted typos all over the place
[safe/jmp/linux-2.6] / fs / ocfs2 / alloc.c
index 4022fa4..7c7198a 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.
  *
@@ -83,6 +94,20 @@ struct ocfs2_extent_tree_operations {
                                   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.
         */
@@ -108,6 +133,16 @@ struct ocfs2_extent_tree_operations {
         * to 0 (unlimited).  Optional.
         */
        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);
 };
 
 
@@ -120,6 +155,10 @@ static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
                                         u64 blkno);
 static void ocfs2_dinode_update_clusters(struct ocfs2_extent_tree *et,
                                         u32 clusters);
+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 ocfs2_extent_tree *et);
@@ -128,6 +167,8 @@ 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,
@@ -162,6 +203,22 @@ static void ocfs2_dinode_update_clusters(struct ocfs2_extent_tree *et,
        spin_unlock(&oi->ip_lock);
 }
 
+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)
 {
@@ -329,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,
@@ -338,7 +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 = INODE_CACHE(inode);
+       et->et_ci = ci;
        et->et_root_journal_access = access;
        if (!obj)
                obj = (void *)bh->b_data;
@@ -352,37 +455,45 @@ static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *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)
 {
@@ -400,6 +511,20 @@ static inline void ocfs2_et_update_clusters(struct ocfs2_extent_tree *et,
        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 ocfs2_extent_tree *et,
                                               int type)
@@ -408,6 +533,19 @@ static inline int ocfs2_et_root_journal_access(handle_t *handle,
                                          type);
 }
 
+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)
 {
@@ -430,36 +568,6 @@ static inline int ocfs2_et_sanity_check(struct ocfs2_extent_tree *et)
 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 ocfs2_caching_info *ci,
-                          struct ocfs2_path *path, u32 cpos);
 static void ocfs2_adjust_rightmost_records(handle_t *handle,
                                           struct ocfs2_extent_tree *et,
                                           struct ocfs2_path *path,
@@ -469,7 +577,7 @@ static void ocfs2_adjust_rightmost_records(handle_t *handle,
  * 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;
@@ -498,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);
@@ -596,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);
@@ -615,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 ocfs2_caching_info *ci,
-                                       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);
 
@@ -635,9 +743,9 @@ static int ocfs2_path_bh_journal_access(handle_t *handle,
 /*
  * Convenience function to journal all components in a path.
  */
-static int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
-                                    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;
 
@@ -686,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,
@@ -722,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);
 
@@ -737,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;
@@ -1813,8 +1913,8 @@ 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 ocfs2_caching_info *ci,
-                          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;
 
@@ -2226,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;
 }
@@ -2290,7 +2398,7 @@ static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
  *
  * The array is assumed to be large enough to hold an entire path (tree depth).
  *
- * Upon succesful return from this function:
+ * Upon successful return from this function:
  *
  * - The 'right_path' array will contain a path to the leaf block
  *   whose range contains e_cpos.
@@ -3784,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;
@@ -3799,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;
        }
@@ -3841,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),
@@ -3996,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,
@@ -4069,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);
 }
 
@@ -4081,8 +4191,7 @@ 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,
@@ -4132,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);
 
                /*
@@ -4146,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)
@@ -4171,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)
@@ -4193,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;
        }
 
@@ -4263,7 +4371,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                }
        }
 
-       ret = ocfs2_insert_path(inode, handle, et, left_path, right_path,
+       ret = ocfs2_insert_path(handle, et, left_path, right_path,
                                insert_rec, type);
        if (ret) {
                mlog_errno(ret);
@@ -4287,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)
 {
@@ -4299,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;
 
@@ -4313,8 +4422,8 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        if (!left_path)
                                goto out;
 
-                       status = ocfs2_find_path(INODE_CACHE(inode),
-                                                left_path, left_cpos);
+                       status = ocfs2_find_path(et->et_ci, left_path,
+                                                left_cpos);
                        if (status)
                                goto out;
 
@@ -4324,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 "
@@ -4349,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);
                }
        }
 
@@ -4358,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;
 
@@ -4370,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_CACHE(inode), right_path, right_cpos);
+               status = ocfs2_find_path(et->et_ci, right_path, right_cpos);
                if (status)
                        goto out;
 
@@ -4380,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),
@@ -4395,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;
@@ -4412,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;
@@ -4424,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;
@@ -4506,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,
@@ -4554,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;
        }
@@ -4588,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
@@ -4633,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,
@@ -4653,8 +4757,9 @@ 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);
@@ -4667,7 +4772,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
                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);
@@ -4691,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);
@@ -4711,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)
@@ -4728,6 +4831,8 @@ 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);
 
@@ -4779,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);
@@ -4832,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,
@@ -4897,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;
 
@@ -4906,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;
@@ -4937,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,
@@ -4946,7 +5050,7 @@ static int ocfs2_replace_extent_rec(struct inode *inode,
 {
        int ret;
 
-       ret = ocfs2_path_bh_journal_access(handle, INODE_CACHE(inode), path,
+       ret = ocfs2_path_bh_journal_access(handle, et->et_ci, path,
                                           path_num_items(path) - 1);
        if (ret) {
                mlog_errno(ret);
@@ -4961,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.
  *
@@ -4980,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);
@@ -4996,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)))) {
@@ -5010,13 +5106,13 @@ 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) {
@@ -5049,11 +5145,10 @@ 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)
@@ -5072,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) {
@@ -5129,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;
+
+}
+
+/*
+ * 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(struct inode *inode, struct ocfs2_extent_tree *et,
-                           handle_t *handle, struct ocfs2_path *path,
+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)
 {
@@ -5173,7 +5321,8 @@ 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) {
@@ -5214,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);
 
@@ -5381,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)
 {
@@ -5393,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) {
@@ -5411,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;
        }
@@ -5441,9 +5595,10 @@ 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) {
@@ -5454,7 +5609,7 @@ int ocfs2_remove_extent(struct inode *inode,
                        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);
@@ -5476,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;
@@ -5492,10 +5647,10 @@ 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;
@@ -5560,8 +5715,7 @@ 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;
@@ -6377,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;
@@ -6528,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;
@@ -6538,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;
@@ -6625,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.
@@ -6724,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;
@@ -6732,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;
 
@@ -6787,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;
@@ -6819,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;
@@ -6840,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;
 
@@ -6910,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;
@@ -6951,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
@@ -7195,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;
@@ -7239,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();
 
@@ -7269,6 +7444,8 @@ start:
                goto bail;
        }
 
+       credits = 0;
+
        /*
         * Truncate always works against the rightmost tree branch.
         */
@@ -7309,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;
@@ -7321,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
@@ -7334,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);
@@ -7346,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;
@@ -7360,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.
@@ -7376,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);