]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'discontig-bg' of git://oss.oracle.com/git/tma/linux-2.6 into ocfs2...
authorJoel Becker <joel.becker@oracle.com>
Tue, 18 May 2010 23:40:42 +0000 (16:40 -0700)
committerJoel Becker <joel.becker@oracle.com>
Tue, 18 May 2010 23:40:42 +0000 (16:40 -0700)
1  2 
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/dir.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ocfs2/super.c

diff --combined fs/ocfs2/alloc.c
index 7e9cb753fba79102f48574237b80c3b8ea5a69da,af2d1bd00d0a229b49e937b078ba5f00bb79f048..215e12ce1d85e2079359838cf287f1c3c670ff31
@@@ -1006,7 -1006,7 +1006,7 @@@ static int ocfs2_create_new_meta_bhs(ha
        int count, status, i;
        u16 suballoc_bit_start;
        u32 num_got;
-       u64 first_blkno;
+       u64 suballoc_loc, first_blkno;
        struct ocfs2_super *osb =
                OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));
        struct ocfs2_extent_block *eb;
  
        count = 0;
        while (count < wanted) {
-               status = ocfs2_claim_metadata(osb,
-                                             handle,
+               status = ocfs2_claim_metadata(handle,
                                              meta_ac,
                                              wanted - count,
+                                             &suballoc_loc,
                                              &suballoc_bit_start,
                                              &num_got,
                                              &first_blkno);
                        eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
                        eb->h_suballoc_slot =
                                cpu_to_le16(meta_ac->ac_alloc_slot);
+                       eb->h_suballoc_loc = cpu_to_le64(suballoc_loc);
                        eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
                        eb->h_list.l_count =
                                cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
@@@ -2209,8 -2210,8 +2210,8 @@@ out
   *
   * Will return zero if the path passed in is already the leftmost path.
   */
 -static int ocfs2_find_cpos_for_left_leaf(struct super_block *sb,
 -                                       struct ocfs2_path *path, u32 *cpos)
 +int ocfs2_find_cpos_for_left_leaf(struct super_block *sb,
 +                                struct ocfs2_path *path, u32 *cpos)
  {
        int i, j, ret = 0;
        u64 blkno;
@@@ -4786,7 -4787,7 +4787,7 @@@ int ocfs2_add_clusters_in_btree(handle_
                goto leave;
        }
  
-       status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+       status = __ocfs2_claim_clusters(handle, data_ac, 1,
                                        clusters_to_add, &bit_off, &num_bits);
        if (status < 0) {
                if (status != -ENOSPC)
        return ret;
  }
  
 +/*
 + * ocfs2_reserve_blocks_for_rec_trunc() would look basically the
 + * same as ocfs2_lock_alloctors(), except for it accepts a blocks
 + * number to reserve some extra blocks, and it only handles meta
 + * data allocations.
 + *
 + * Currently, only ocfs2_remove_btree_range() uses it for truncating
 + * and punching holes.
 + */
 +static int ocfs2_reserve_blocks_for_rec_trunc(struct inode *inode,
 +                                            struct ocfs2_extent_tree *et,
 +                                            u32 extents_to_split,
 +                                            struct ocfs2_alloc_context **ac,
 +                                            int extra_blocks)
 +{
 +      int ret = 0, num_free_extents;
 +      unsigned int max_recs_needed = 2 * extents_to_split;
 +      struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 +
 +      *ac = NULL;
 +
 +      num_free_extents = ocfs2_num_free_extents(osb, et);
 +      if (num_free_extents < 0) {
 +              ret = num_free_extents;
 +              mlog_errno(ret);
 +              goto out;
 +      }
 +
 +      if (!num_free_extents ||
 +          (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed))
 +              extra_blocks += ocfs2_extend_meta_needed(et->et_root_el);
 +
 +      if (extra_blocks) {
 +              ret = ocfs2_reserve_new_metadata_blocks(osb, extra_blocks, ac);
 +              if (ret < 0) {
 +                      if (ret != -ENOSPC)
 +                              mlog_errno(ret);
 +                      goto out;
 +              }
 +      }
 +
 +out:
 +      if (ret) {
 +              if (*ac) {
 +                      ocfs2_free_alloc_context(*ac);
 +                      *ac = NULL;
 +              }
 +      }
 +
 +      return ret;
 +}
 +
  int ocfs2_remove_btree_range(struct inode *inode,
                             struct ocfs2_extent_tree *et,
 -                           u32 cpos, u32 phys_cpos, u32 len,
 -                           struct ocfs2_cached_dealloc_ctxt *dealloc)
 +                           u32 cpos, u32 phys_cpos, u32 len, int flags,
 +                           struct ocfs2_cached_dealloc_ctxt *dealloc,
 +                           u64 refcount_loc)
  {
 -      int ret;
 +      int ret, credits = 0, extra_blocks = 0;
        u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct inode *tl_inode = osb->osb_tl_inode;
        handle_t *handle;
        struct ocfs2_alloc_context *meta_ac = NULL;
 +      struct ocfs2_refcount_tree *ref_tree = NULL;
 +
 +      if ((flags & OCFS2_EXT_REFCOUNTED) && len) {
 +              BUG_ON(!(OCFS2_I(inode)->ip_dyn_features &
 +                       OCFS2_HAS_REFCOUNT_FL));
 +
 +              ret = ocfs2_lock_refcount_tree(osb, refcount_loc, 1,
 +                                             &ref_tree, NULL);
 +              if (ret) {
 +                      mlog_errno(ret);
 +                      goto out;
 +              }
 +
 +              ret = ocfs2_prepare_refcount_change_for_del(inode,
 +                                                          refcount_loc,
 +                                                          phys_blkno,
 +                                                          len,
 +                                                          &credits,
 +                                                          &extra_blocks);
 +              if (ret < 0) {
 +                      mlog_errno(ret);
 +                      goto out;
 +              }
 +      }
  
 -      ret = ocfs2_lock_allocators(inode, et, 0, 1, NULL, &meta_ac);
 +      ret = ocfs2_reserve_blocks_for_rec_trunc(inode, et, 1, &meta_ac,
 +                                               extra_blocks);
        if (ret) {
                mlog_errno(ret);
                return ret;
                }
        }
  
 -      handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(osb->sb));
 +      handle = ocfs2_start_trans(osb,
 +                      ocfs2_remove_extent_credits(osb->sb) + credits);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                mlog_errno(ret);
  
        ocfs2_journal_dirty(handle, et->et_root_bh);
  
 -      ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
 -      if (ret)
 -              mlog_errno(ret);
 +      if (phys_blkno) {
 +              if (flags & OCFS2_EXT_REFCOUNTED)
 +                      ret = ocfs2_decrease_refcount(inode, handle,
 +                                      ocfs2_blocks_to_clusters(osb->sb,
 +                                                               phys_blkno),
 +                                      len, meta_ac,
 +                                      dealloc, 1);
 +              else
 +                      ret = ocfs2_truncate_log_append(osb, handle,
 +                                                      phys_blkno, len);
 +              if (ret)
 +                      mlog_errno(ret);
 +
 +      }
  
  out_commit:
        ocfs2_commit_trans(osb, handle);
@@@ -5744,9 -5655,6 +5745,9 @@@ out
        if (meta_ac)
                ocfs2_free_alloc_context(meta_ac);
  
 +      if (ref_tree)
 +              ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
 +
        return ret;
  }
  
@@@ -6295,6 -6203,7 +6296,7 @@@ int ocfs2_truncate_log_init(struct ocfs
   */
  struct ocfs2_cached_block_free {
        struct ocfs2_cached_block_free          *free_next;
+       u64                                     free_bg;
        u64                                     free_blk;
        unsigned int                            free_bit;
  };
@@@ -6341,8 -6250,11 +6343,11 @@@ static int ocfs2_free_cached_blocks(str
        }
  
        while (head) {
-               bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
-                                                     head->free_bit);
+               if (head->free_bg)
+                       bg_blkno = head->free_bg;
+               else
+                       bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
+                                                             head->free_bit);
                mlog(0, "Free bit: (bit %u, blkno %llu)\n",
                     head->free_bit, (unsigned long long)head->free_blk);
  
@@@ -6390,7 -6302,7 +6395,7 @@@ int ocfs2_cache_cluster_dealloc(struct 
        int ret = 0;
        struct ocfs2_cached_block_free *item;
  
-       item = kmalloc(sizeof(*item), GFP_NOFS);
+       item = kzalloc(sizeof(*item), GFP_NOFS);
        if (item == NULL) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@@ -6530,8 -6442,8 +6535,8 @@@ ocfs2_find_per_slot_free_list(int type
  }
  
  int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
-                             int type, int slot, u64 blkno,
-                             unsigned int bit)
+                             int type, int slot, u64 suballoc,
+                             u64 blkno, unsigned int bit)
  {
        int ret;
        struct ocfs2_per_slot_free_list *fl;
                goto out;
        }
  
-       item = kmalloc(sizeof(*item), GFP_NOFS);
+       item = kzalloc(sizeof(*item), GFP_NOFS);
        if (item == NULL) {
                ret = -ENOMEM;
                mlog_errno(ret);
        mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
             type, slot, bit, (unsigned long long)blkno);
  
+       item->free_bg = suballoc;
        item->free_blk = blkno;
        item->free_bit = bit;
        item->free_next = fl->f_first;
@@@ -6570,10 -6483,422 +6576,11 @@@ static int ocfs2_cache_extent_block_fre
  {
        return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
                                         le16_to_cpu(eb->h_suballoc_slot),
+                                        le64_to_cpu(eb->h_suballoc_loc),
                                         le64_to_cpu(eb->h_blkno),
                                         le16_to_cpu(eb->h_suballoc_bit));
  }
  
 -/* This function will figure out whether the currently last extent
 - * block will be deleted, and if it will, what the new last extent
 - * block will be so we can update his h_next_leaf_blk field, as well
 - * as the dinodes i_last_eb_blk */
 -static int ocfs2_find_new_last_ext_blk(struct inode *inode,
 -                                     unsigned int clusters_to_del,
 -                                     struct ocfs2_path *path,
 -                                     struct buffer_head **new_last_eb)
 -{
 -      int next_free, ret = 0;
 -      u32 cpos;
 -      struct ocfs2_extent_rec *rec;
 -      struct ocfs2_extent_block *eb;
 -      struct ocfs2_extent_list *el;
 -      struct buffer_head *bh = NULL;
 -
 -      *new_last_eb = NULL;
 -
 -      /* we have no tree, so of course, no last_eb. */
 -      if (!path->p_tree_depth)
 -              goto out;
 -
 -      /* trunc to zero special case - this makes tree_depth = 0
 -       * regardless of what it is.  */
 -      if (OCFS2_I(inode)->ip_clusters == clusters_to_del)
 -              goto out;
 -
 -      el = path_leaf_el(path);
 -      BUG_ON(!el->l_next_free_rec);
 -
 -      /*
 -       * Make sure that this extent list will actually be empty
 -       * after we clear away the data. We can shortcut out if
 -       * there's more than one non-empty extent in the
 -       * list. Otherwise, a check of the remaining extent is
 -       * necessary.
 -       */
 -      next_free = le16_to_cpu(el->l_next_free_rec);
 -      rec = NULL;
 -      if (ocfs2_is_empty_extent(&el->l_recs[0])) {
 -              if (next_free > 2)
 -                      goto out;
 -
 -              /* We may have a valid extent in index 1, check it. */
 -              if (next_free == 2)
 -                      rec = &el->l_recs[1];
 -
 -              /*
 -               * Fall through - no more nonempty extents, so we want
 -               * to delete this leaf.
 -               */
 -      } else {
 -              if (next_free > 1)
 -                      goto out;
 -
 -              rec = &el->l_recs[0];
 -      }
 -
 -      if (rec) {
 -              /*
 -               * Check it we'll only be trimming off the end of this
 -               * cluster.
 -               */
 -              if (le16_to_cpu(rec->e_leaf_clusters) > clusters_to_del)
 -                      goto out;
 -      }
 -
 -      ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, path, &cpos);
 -      if (ret) {
 -              mlog_errno(ret);
 -              goto out;
 -      }
 -
 -      ret = ocfs2_find_leaf(INODE_CACHE(inode), path_root_el(path), cpos, &bh);
 -      if (ret) {
 -              mlog_errno(ret);
 -              goto out;
 -      }
 -
 -      eb = (struct ocfs2_extent_block *) bh->b_data;
 -      el = &eb->h_list;
 -
 -      /* ocfs2_find_leaf() gets the eb from ocfs2_read_extent_block().
 -       * Any corruption is a code bug. */
 -      BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
 -
 -      *new_last_eb = bh;
 -      get_bh(*new_last_eb);
 -      mlog(0, "returning block %llu, (cpos: %u)\n",
 -           (unsigned long long)le64_to_cpu(eb->h_blkno), cpos);
 -out:
 -      brelse(bh);
 -
 -      return ret;
 -}
 -
 -/*
 - * Trim some clusters off the rightmost edge of a tree. Only called
 - * during truncate.
 - *
 - * The caller needs to:
 - *   - start journaling of each path component.
 - *   - compute and fully set up any new last ext block
 - */
 -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, u8 *flags)
 -{
 -      int ret, i, index = path->p_tree_depth;
 -      u32 new_edge = 0;
 -      u64 deleted_eb = 0;
 -      struct buffer_head *bh;
 -      struct ocfs2_extent_list *el;
 -      struct ocfs2_extent_rec *rec;
 -
 -      *delete_start = 0;
 -      *flags = 0;
 -
 -      while (index >= 0) {
 -              bh = path->p_node[index].bh;
 -              el = path->p_node[index].el;
 -
 -              mlog(0, "traveling tree (index = %d, block = %llu)\n",
 -                   index,  (unsigned long long)bh->b_blocknr);
 -
 -              BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
 -
 -              if (index !=
 -                  (path->p_tree_depth - le16_to_cpu(el->l_tree_depth))) {
 -                      ocfs2_error(inode->i_sb,
 -                                  "Inode %lu has invalid ext. block %llu",
 -                                  inode->i_ino,
 -                                  (unsigned long long)bh->b_blocknr);
 -                      ret = -EROFS;
 -                      goto out;
 -              }
 -
 -find_tail_record:
 -              i = le16_to_cpu(el->l_next_free_rec) - 1;
 -              rec = &el->l_recs[i];
 -
 -              mlog(0, "Extent list before: record %d: (%u, %u, %llu), "
 -                   "next = %u\n", i, le32_to_cpu(rec->e_cpos),
 -                   ocfs2_rec_clusters(el, rec),
 -                   (unsigned long long)le64_to_cpu(rec->e_blkno),
 -                   le16_to_cpu(el->l_next_free_rec));
 -
 -              BUG_ON(ocfs2_rec_clusters(el, rec) < clusters_to_del);
 -
 -              if (le16_to_cpu(el->l_tree_depth) == 0) {
 -                      /*
 -                       * If the leaf block contains a single empty
 -                       * extent and no records, we can just remove
 -                       * the block.
 -                       */
 -                      if (i == 0 && ocfs2_is_empty_extent(rec)) {
 -                              memset(rec, 0,
 -                                     sizeof(struct ocfs2_extent_rec));
 -                              el->l_next_free_rec = cpu_to_le16(0);
 -
 -                              goto delete;
 -                      }
 -
 -                      /*
 -                       * Remove any empty extents by shifting things
 -                       * left. That should make life much easier on
 -                       * the code below. This condition is rare
 -                       * enough that we shouldn't see a performance
 -                       * hit.
 -                       */
 -                      if (ocfs2_is_empty_extent(&el->l_recs[0])) {
 -                              le16_add_cpu(&el->l_next_free_rec, -1);
 -
 -                              for(i = 0;
 -                                  i < le16_to_cpu(el->l_next_free_rec); i++)
 -                                      el->l_recs[i] = el->l_recs[i + 1];
 -
 -                              memset(&el->l_recs[i], 0,
 -                                     sizeof(struct ocfs2_extent_rec));
 -
 -                              /*
 -                               * We've modified our extent list. The
 -                               * simplest way to handle this change
 -                               * is to being the search from the
 -                               * start again.
 -                               */
 -                              goto find_tail_record;
 -                      }
 -
 -                      le16_add_cpu(&rec->e_leaf_clusters, -clusters_to_del);
 -
 -                      /*
 -                       * We'll use "new_edge" on our way back up the
 -                       * tree to know what our rightmost cpos is.
 -                       */
 -                      new_edge = le16_to_cpu(rec->e_leaf_clusters);
 -                      new_edge += le32_to_cpu(rec->e_cpos);
 -
 -                      /*
 -                       * The caller will use this to delete data blocks.
 -                       */
 -                      *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.
 -                       */
 -                      if (le16_to_cpu(rec->e_leaf_clusters) == 0) {
 -                              memset(rec, 0,
 -                                     sizeof(struct ocfs2_extent_rec));
 -                              le16_add_cpu(&el->l_next_free_rec, -1);
 -                      }
 -              } else {
 -                      if (le64_to_cpu(rec->e_blkno) == deleted_eb) {
 -                              memset(rec, 0,
 -                                     sizeof(struct ocfs2_extent_rec));
 -                              le16_add_cpu(&el->l_next_free_rec, -1);
 -
 -                              goto delete;
 -                      }
 -
 -                      /* Can this actually happen? */
 -                      if (le16_to_cpu(el->l_next_free_rec) == 0)
 -                              goto delete;
 -
 -                      /*
 -                       * We never actually deleted any clusters
 -                       * because our leaf was empty. There's no
 -                       * reason to adjust the rightmost edge then.
 -                       */
 -                      if (new_edge == 0)
 -                              goto delete;
 -
 -                      rec->e_int_clusters = cpu_to_le32(new_edge);
 -                      le32_add_cpu(&rec->e_int_clusters,
 -                                   -le32_to_cpu(rec->e_cpos));
 -
 -                       /*
 -                        * A deleted child record should have been
 -                        * caught above.
 -                        */
 -                       BUG_ON(le32_to_cpu(rec->e_int_clusters) == 0);
 -              }
 -
 -delete:
 -              ocfs2_journal_dirty(handle, bh);
 -
 -              mlog(0, "extent list container %llu, after: record %d: "
 -                   "(%u, %u, %llu), next = %u.\n",
 -                   (unsigned long long)bh->b_blocknr, i,
 -                   le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec),
 -                   (unsigned long long)le64_to_cpu(rec->e_blkno),
 -                   le16_to_cpu(el->l_next_free_rec));
 -
 -              /*
 -               * We must be careful to only attempt delete of an
 -               * extent block (and not the root inode block).
 -               */
 -              if (index > 0 && le16_to_cpu(el->l_next_free_rec) == 0) {
 -                      struct ocfs2_extent_block *eb =
 -                              (struct ocfs2_extent_block *)bh->b_data;
 -
 -                      /*
 -                       * Save this for use when processing the
 -                       * parent block.
 -                       */
 -                      deleted_eb = le64_to_cpu(eb->h_blkno);
 -
 -                      mlog(0, "deleting this extent block.\n");
 -
 -                      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));
 -                      BUG_ON(le64_to_cpu(el->l_recs[0].e_blkno));
 -
 -                      ret = ocfs2_cache_extent_block_free(&tc->tc_dealloc, eb);
 -                      /* An error here is not fatal. */
 -                      if (ret < 0)
 -                              mlog_errno(ret);
 -              } else {
 -                      deleted_eb = 0;
 -              }
 -
 -              index--;
 -      }
 -
 -      ret = 0;
 -out:
 -      return ret;
 -}
 -
 -static int ocfs2_do_truncate(struct ocfs2_super *osb,
 -                           unsigned int clusters_to_del,
 -                           struct inode *inode,
 -                           struct buffer_head *fe_bh,
 -                           handle_t *handle,
 -                           struct ocfs2_truncate_context *tc,
 -                           struct ocfs2_path *path,
 -                           struct ocfs2_alloc_context *meta_ac)
 -{
 -      int status;
 -      struct ocfs2_dinode *fe;
 -      struct ocfs2_extent_block *last_eb = NULL;
 -      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;
 -
 -      status = ocfs2_find_new_last_ext_blk(inode, clusters_to_del,
 -                                           path, &last_eb_bh);
 -      if (status < 0) {
 -              mlog_errno(status);
 -              goto bail;
 -      }
 -
 -      /*
 -       * 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_CACHE(inode), handle, path);
 -      if (status < 0) {
 -              mlog_errno(status);
 -              goto bail;
 -      }
 -
 -      if (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);
 -                      goto bail;
 -              }
 -
 -              last_eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
 -      }
 -
 -      el = &(fe->id2.i_list);
 -
 -      /*
 -       * Lower levels depend on this never happening, but it's best
 -       * to check it up here before changing the tree.
 -       */
 -      if (el->l_tree_depth && el->l_recs[0].e_int_clusters == 0) {
 -              ocfs2_error(inode->i_sb,
 -                          "Inode %lu has an empty extent record, depth %u\n",
 -                          inode->i_ino, le16_to_cpu(el->l_tree_depth));
 -              status = -EROFS;
 -              goto bail;
 -      }
 -
 -      dquot_free_space_nodirty(inode,
 -                      ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
 -      spin_lock(&OCFS2_I(inode)->ip_lock);
 -      OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
 -                                    clusters_to_del;
 -      spin_unlock(&OCFS2_I(inode)->ip_lock);
 -      le32_add_cpu(&fe->i_clusters, -clusters_to_del);
 -      inode->i_blocks = ocfs2_inode_sector_count(inode);
 -
 -      status = ocfs2_trim_tree(inode, path, handle, tc,
 -                               clusters_to_del, &delete_blk, &rec_flags);
 -      if (status) {
 -              mlog_errno(status);
 -              goto bail;
 -      }
 -
 -      if (le32_to_cpu(fe->i_clusters) == 0) {
 -              /* trunc to zero is a special case. */
 -              el->l_tree_depth = 0;
 -              fe->i_last_eb_blk = 0;
 -      } else if (last_eb)
 -              fe->i_last_eb_blk = last_eb->h_blkno;
 -
 -      ocfs2_journal_dirty(handle, fe_bh);
 -
 -      if (last_eb) {
 -              /* If there will be a new last extent block, then by
 -               * definition, there cannot be any leaves to the right of
 -               * him. */
 -              last_eb->h_next_leaf_blk = 0;
 -              ocfs2_journal_dirty(handle, last_eb_bh);
 -      }
 -
 -      if (delete_blk) {
 -              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;
 -              }
 -      }
 -      status = 0;
 -bail:
 -      brelse(last_eb_bh);
 -      mlog_exit(status);
 -      return status;
 -}
 -
  static int ocfs2_zero_func(handle_t *handle, struct buffer_head *bh)
  {
        set_buffer_uptodate(bh);
@@@ -6883,7 -7208,7 +6890,7 @@@ int ocfs2_convert_inline_data_to_extent
  
                data_ac->ac_resv = &OCFS2_I(inode)->ip_la_data_resv;
  
-               ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
+               ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off,
                                           &num);
                if (ret) {
                        mlog_errno(ret);
   */
  int ocfs2_commit_truncate(struct ocfs2_super *osb,
                          struct inode *inode,
 -                        struct buffer_head *fe_bh,
 -                        struct ocfs2_truncate_context *tc)
 +                        struct buffer_head *di_bh)
  {
 -      int status, i, credits, tl_sem = 0;
 -      u32 clusters_to_del, new_highest_cpos, range;
 +      int status = 0, i, flags = 0;
 +      u32 new_highest_cpos, range, trunc_cpos, trunc_len, phys_cpos, coff;
        u64 blkno = 0;
        struct ocfs2_extent_list *el;
 -      handle_t *handle = NULL;
 -      struct inode *tl_inode = osb->osb_tl_inode;
 +      struct ocfs2_extent_rec *rec;
        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;
 +      struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
 +      struct ocfs2_extent_list *root_el = &(di->id2.i_list);
 +      u64 refcount_loc = le64_to_cpu(di->i_refcount_loc);
 +      struct ocfs2_extent_tree et;
 +      struct ocfs2_cached_dealloc_ctxt dealloc;
  
        mlog_entry_void();
  
 +      ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
 +      ocfs2_init_dealloc_ctxt(&dealloc);
 +
        new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
                                                     i_size_read(inode));
  
 -      path = ocfs2_new_path(fe_bh, &di->id2.i_list,
 +      path = ocfs2_new_path(di_bh, &di->id2.i_list,
                              ocfs2_journal_access_di);
        if (!path) {
                status = -ENOMEM;
@@@ -7023,6 -7345,8 +7030,6 @@@ start
                goto bail;
        }
  
 -      credits = 0;
 -
        /*
         * Truncate always works against the rightmost tree branch.
         */
        }
  
        i = le16_to_cpu(el->l_next_free_rec) - 1;
 -      range = le32_to_cpu(el->l_recs[i].e_cpos) +
 -              ocfs2_rec_clusters(el, &el->l_recs[i]);
 -      if (i == 0 && ocfs2_is_empty_extent(&el->l_recs[i])) {
 -              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);
 +      rec = &el->l_recs[i];
 +      flags = rec->e_flags;
 +      range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
 +
 +      if (i == 0 && ocfs2_is_empty_extent(rec)) {
 +              /*
 +               * Lower levels depend on this never happening, but it's best
 +               * to check it up here before changing the tree.
 +              */
 +              if (root_el->l_tree_depth && rec->e_int_clusters == 0) {
 +                      ocfs2_error(inode->i_sb, "Inode %lu has an empty "
 +                                  "extent record, depth %u\n", inode->i_ino,
 +                                  le16_to_cpu(root_el->l_tree_depth));
 +                      status = -EROFS;
 +                      goto bail;
 +              }
 +              trunc_cpos = le32_to_cpu(rec->e_cpos);
 +              trunc_len = 0;
 +              blkno = 0;
 +      } else if (le32_to_cpu(rec->e_cpos) >= new_highest_cpos) {
 +              /*
 +               * Truncate entire record.
 +               */
 +              trunc_cpos = le32_to_cpu(rec->e_cpos);
 +              trunc_len = ocfs2_rec_clusters(el, rec);
 +              blkno = le64_to_cpu(rec->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);
 +              /*
 +               * Partial truncate. it also should be
 +               * the last truncate we're doing.
 +               */
 +              trunc_cpos = new_highest_cpos;
 +              trunc_len = range - new_highest_cpos;
 +              coff = new_highest_cpos - le32_to_cpu(rec->e_cpos);
 +              blkno = le64_to_cpu(rec->e_blkno) +
 +                              ocfs2_clusters_to_blocks(inode->i_sb, coff);
        } else {
 +              /*
 +               * Truncate completed, leave happily.
 +               */
                status = 0;
                goto bail;
        }
  
 -      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;
 -              }
 +      phys_cpos = ocfs2_blocks_to_clusters(inode->i_sb, blkno);
  
 -              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
 -       * record is free for use. If there isn't any, we flush to get
 -       * an empty truncate log.  */
 -      if (ocfs2_truncate_log_needs_flush(osb)) {
 -              status = __ocfs2_flush_truncate_log(osb);
 -              if (status < 0) {
 -                      mlog_errno(status);
 -                      goto bail;
 -              }
 -      }
 -
 -      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);
 -      if (IS_ERR(handle)) {
 -              status = PTR_ERR(handle);
 -              handle = NULL;
 -              mlog_errno(status);
 -              goto bail;
 -      }
 -
 -      status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh, handle,
 -                                 tc, path, meta_ac);
 +      status = ocfs2_remove_btree_range(inode, &et, trunc_cpos,
 +                                        phys_cpos, trunc_len, flags, &dealloc,
 +                                        refcount_loc);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
  
 -      mutex_unlock(&tl_inode->i_mutex);
 -      tl_sem = 0;
 -
 -      ocfs2_commit_trans(osb, handle);
 -      handle = NULL;
 -
        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.
@@@ -7123,10 -7486,25 +7130,10 @@@ bail
  
        ocfs2_schedule_truncate_log_flush(osb, 1);
  
 -      if (tl_sem)
 -              mutex_unlock(&tl_inode->i_mutex);
 -
 -      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_run_deallocs(osb, &dealloc);
  
        ocfs2_free_path(path);
  
 -      /* This will drop the ext_alloc cluster lock for us */
 -      ocfs2_free_truncate_context(tc);
 -
        mlog_exit(status);
        return status;
  }
diff --combined fs/ocfs2/alloc.h
index a55a27bb96a559b2a19cf2a7435369d6f607d2dc,fc28d64398c13fad6eaae2f231470359cb543734..55762b554b9956284c40a9ff4967b466ded19dc8
@@@ -140,9 -140,8 +140,9 @@@ int ocfs2_remove_extent(handle_t *handl
                        struct ocfs2_cached_dealloc_ctxt *dealloc);
  int ocfs2_remove_btree_range(struct inode *inode,
                             struct ocfs2_extent_tree *et,
 -                           u32 cpos, u32 phys_cpos, u32 len,
 -                           struct ocfs2_cached_dealloc_ctxt *dealloc);
 +                           u32 cpos, u32 phys_cpos, u32 len, int flags,
 +                           struct ocfs2_cached_dealloc_ctxt *dealloc,
 +                           u64 refcount_loc);
  
  int ocfs2_num_free_extents(struct ocfs2_super *osb,
                           struct ocfs2_extent_tree *et);
@@@ -210,7 -209,7 +210,7 @@@ static inline void ocfs2_init_dealloc_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,
+                             int type, int slot, u64 suballoc, u64 blkno,
                              unsigned int bit);
  static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c)
  {
@@@ -234,7 -233,8 +234,7 @@@ int ocfs2_prepare_truncate(struct ocfs2
                           struct ocfs2_truncate_context **tc);
  int ocfs2_commit_truncate(struct ocfs2_super *osb,
                          struct inode *inode,
 -                        struct buffer_head *fe_bh,
 -                        struct ocfs2_truncate_context *tc);
 +                        struct buffer_head *di_bh);
  int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
                          unsigned int start, unsigned int end, int trunc);
  
@@@ -319,8 -319,6 +319,8 @@@ int ocfs2_journal_access_path(struct oc
                              struct ocfs2_path *path);
  int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
                                   struct ocfs2_path *path, u32 *cpos);
 +int ocfs2_find_cpos_for_left_leaf(struct super_block *sb,
 +                                struct ocfs2_path *path, u32 *cpos);
  int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
                            struct ocfs2_path *left,
                            struct ocfs2_path *right);
diff --combined fs/ocfs2/dir.c
index 4a75c2e2f85503c6ec10d05f6a7a40f7d7722a8e,3fea52d0efd325b15cbf3e84d998635761d0b455..f04ebcfffc4a5e1516c2a7307ffa8032db8e19d7
@@@ -2395,15 -2395,15 +2395,15 @@@ static int ocfs2_dx_dir_attach_index(st
        int ret;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
        u16 dr_suballoc_bit;
-       u64 dr_blkno;
+       u64 suballoc_loc, dr_blkno;
        unsigned int num_bits;
        struct buffer_head *dx_root_bh = NULL;
        struct ocfs2_dx_root_block *dx_root;
        struct ocfs2_dir_block_trailer *trailer =
                ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
  
-       ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1, &dr_suballoc_bit,
-                                  &num_bits, &dr_blkno);
+       ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
+                                  &dr_suballoc_bit, &num_bits, &dr_blkno);
        if (ret) {
                mlog_errno(ret);
                goto out;
        memset(dx_root, 0, osb->sb->s_blocksize);
        strcpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE);
        dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+       dx_root->dr_suballoc_loc = cpu_to_le64(suballoc_loc);
        dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit);
        dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation);
        dx_root->dr_blkno = cpu_to_le64(dr_blkno);
@@@ -2544,7 -2545,7 +2545,7 @@@ static int __ocfs2_dx_dir_new_cluster(s
         * chance of contiguousness as the directory grows in number
         * of entries.
         */
-       ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1, 1, &phys, &num);
+       ret = __ocfs2_claim_clusters(handle, data_ac, 1, 1, &phys, &num);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@@ -2979,7 -2980,7 +2980,7 @@@ static int ocfs2_expand_inline_dir(stru
         */
        if (ocfs2_dir_resv_allowed(osb))
                data_ac->ac_resv = &oi->ip_la_data_resv;
-       ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len);
+       ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off, &len);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
         * pass. Claim the 2nd cluster as a separate extent.
         */
        if (alloc > len) {
-               ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
+               ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off,
                                           &len);
                if (ret) {
                        mlog_errno(ret);
@@@ -4465,7 -4466,10 +4466,10 @@@ static int ocfs2_dx_dir_remove_index(st
  
        blk = le64_to_cpu(dx_root->dr_blkno);
        bit = le16_to_cpu(dx_root->dr_suballoc_bit);
-       bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+       if (dx_root->dr_suballoc_loc)
+               bg_blkno = le64_to_cpu(dx_root->dr_suballoc_loc);
+       else
+               bg_blkno = ocfs2_which_suballoc_group(blk, bit);
        ret = ocfs2_free_suballoc_bits(handle, dx_alloc_inode, dx_alloc_bh,
                                       bit, bg_blkno, 1);
        if (ret)
@@@ -4526,8 -4530,8 +4530,8 @@@ int ocfs2_dx_dir_truncate(struct inode 
  
                p_cpos = ocfs2_blocks_to_clusters(dir->i_sb, blkno);
  
 -              ret = ocfs2_remove_btree_range(dir, &et, cpos, p_cpos, clen,
 -                                             &dealloc);
 +              ret = ocfs2_remove_btree_range(dir, &et, cpos, p_cpos, clen, 0,
 +                                             &dealloc, 0);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
diff --combined fs/ocfs2/namei.c
index 607084b349d4fd424765bddc7447dc9fd11d023c,bfe4571a4fa1e59e64f5f43142d7ae753a6f9386..b0fa6b6507518edbbccb2098fe6e88e93dbb8b0d
@@@ -239,8 -239,6 +239,8 @@@ static int ocfs2_mknod(struct inode *di
        };
        int did_quota_inode = 0;
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 +      sigset_t oldset;
 +      int did_block_signals = 0;
  
        mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
                   (unsigned long)dev, dentry->d_name.len,
                goto leave;
        }
  
 +      /* Starting to change things, restart is no longer possible. */
 +      ocfs2_block_signals(&oldset);
 +      did_block_signals = 1;
 +
        status = dquot_alloc_inode(inode);
        if (status)
                goto leave;
@@@ -436,8 -430,6 +436,8 @@@ leave
                ocfs2_commit_trans(osb, handle);
  
        ocfs2_inode_unlock(dir, 1);
 +      if (did_block_signals)
 +              ocfs2_unblock_signals(&oldset);
  
        if (status == -ENOSPC)
                mlog(0, "Disk is full\n");
@@@ -480,14 -472,15 +480,15 @@@ static int ocfs2_mknod_locked(struct oc
        int status = 0;
        struct ocfs2_dinode *fe = NULL;
        struct ocfs2_extent_list *fel;
-       u64 fe_blkno = 0;
+       u64 suballoc_loc, fe_blkno = 0;
        u16 suballoc_bit;
        u16 feat;
  
        *new_fe_bh = NULL;
  
-       status = ocfs2_claim_new_inode(osb, handle, dir, parent_fe_bh,
-                                      inode_ac, &suballoc_bit, &fe_blkno);
+       status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh,
+                                      inode_ac, &suballoc_loc,
+                                      &suballoc_bit, &fe_blkno);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        fe->i_generation = cpu_to_le32(inode->i_generation);
        fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
        fe->i_blkno = cpu_to_le64(fe_blkno);
+       fe->i_suballoc_loc = cpu_to_le64(suballoc_loc);
        fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
        fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
        fe->i_uid = cpu_to_le32(inode->i_uid);
@@@ -626,7 -620,6 +628,7 @@@ static int ocfs2_link(struct dentry *ol
        struct ocfs2_dinode *fe = NULL;
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 +      sigset_t oldset;
  
        mlog_entry("(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino,
                   old_dentry->d_name.len, old_dentry->d_name.name,
                goto out_unlock_inode;
        }
  
 +      /* Starting to change things, restart is no longer possible. */
 +      ocfs2_block_signals(&oldset);
 +
        err = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (err < 0) {
  
  out_commit:
        ocfs2_commit_trans(osb, handle);
 +      ocfs2_unblock_signals(&oldset);
  out_unlock_inode:
        ocfs2_inode_unlock(inode, 1);
  
@@@ -1581,8 -1570,6 +1583,8 @@@ static int ocfs2_symlink(struct inode *
        };
        int did_quota = 0, did_quota_inode = 0;
        struct ocfs2_dir_lookup_result lookup = { NULL, };
 +      sigset_t oldset;
 +      int did_block_signals = 0;
  
        mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
                   dentry, symname, dentry->d_name.len, dentry->d_name.name);
                goto bail;
        }
  
 +      /* Starting to change things, restart is no longer possible. */
 +      ocfs2_block_signals(&oldset);
 +      did_block_signals = 1;
 +
        status = dquot_alloc_inode(inode);
        if (status)
                goto bail;
@@@ -1785,8 -1768,6 +1787,8 @@@ bail
                ocfs2_commit_trans(osb, handle);
  
        ocfs2_inode_unlock(dir, 1);
 +      if (did_block_signals)
 +              ocfs2_unblock_signals(&oldset);
  
        brelse(new_fe_bh);
        brelse(parent_fe_bh);
diff --combined fs/ocfs2/refcounttree.c
index 6fab28921f3d98fe7adbd9b3b1a3bc000d41f0fb,b34702984225ed38243a796af810dfe8751c7c82..52e4f6ee1e23bdfe2c65069f30291221fd45d19a
@@@ -571,7 -571,7 +571,7 @@@ static int ocfs2_create_refcount_tree(s
        struct ocfs2_refcount_tree *new_tree = NULL, *tree = NULL;
        u16 suballoc_bit_start;
        u32 num_got;
-       u64 first_blkno;
+       u64 suballoc_loc, first_blkno;
  
        BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
  
                goto out_commit;
        }
  
-       ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
+       ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
                                   &suballoc_bit_start, &num_got,
                                   &first_blkno);
        if (ret) {
        memset(rb, 0, inode->i_sb->s_blocksize);
        strcpy((void *)rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE);
        rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+       rb->rf_suballoc_loc = cpu_to_le64(suballoc_loc);
        rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
        rb->rf_fs_generation = cpu_to_le32(osb->fs_generation);
        rb->rf_blkno = cpu_to_le64(first_blkno);
@@@ -791,7 -792,10 +792,10 @@@ int ocfs2_remove_refcount_tree(struct i
        if (le32_to_cpu(rb->rf_count) == 1) {
                blk = le64_to_cpu(rb->rf_blkno);
                bit = le16_to_cpu(rb->rf_suballoc_bit);
-               bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+               if (rb->rf_suballoc_loc)
+                       bg_blkno = le64_to_cpu(rb->rf_suballoc_loc);
+               else
+                       bg_blkno = ocfs2_which_suballoc_group(blk, bit);
  
                alloc_inode = ocfs2_get_system_file_inode(osb,
                                        EXTENT_ALLOC_SYSTEM_INODE,
@@@ -1283,7 -1287,7 +1287,7 @@@ static int ocfs2_expand_inline_ref_root
        int ret;
        u16 suballoc_bit_start;
        u32 num_got;
-       u64 blkno;
+       u64 suballoc_loc, blkno;
        struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
        struct buffer_head *new_bh = NULL;
        struct ocfs2_refcount_block *new_rb;
                goto out;
        }
  
-       ret = ocfs2_claim_metadata(OCFS2_SB(sb), handle, meta_ac, 1,
+       ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
                                   &suballoc_bit_start, &num_got,
                                   &blkno);
        if (ret) {
  
        new_rb = (struct ocfs2_refcount_block *)new_bh->b_data;
        new_rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+       new_rb->rf_suballoc_loc = cpu_to_le64(suballoc_loc);
        new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
        new_rb->rf_blkno = cpu_to_le64(blkno);
        new_rb->rf_cpos = cpu_to_le32(0);
@@@ -1523,7 -1528,7 +1528,7 @@@ static int ocfs2_new_leaf_refcount_bloc
        int ret;
        u16 suballoc_bit_start;
        u32 num_got, new_cpos;
-       u64 blkno;
+       u64 suballoc_loc, blkno;
        struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
        struct ocfs2_refcount_block *root_rb =
                        (struct ocfs2_refcount_block *)ref_root_bh->b_data;
                goto out;
        }
  
-       ret = ocfs2_claim_metadata(OCFS2_SB(sb), handle, meta_ac, 1,
+       ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
                                   &suballoc_bit_start, &num_got,
                                   &blkno);
        if (ret) {
        memset(new_rb, 0, sb->s_blocksize);
        strcpy((void *)new_rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE);
        new_rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+       new_rb->rf_suballoc_loc = cpu_to_le64(suballoc_loc);
        new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
        new_rb->rf_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
        new_rb->rf_blkno = cpu_to_le64(blkno);
@@@ -2105,6 -2111,7 +2111,7 @@@ static int ocfs2_remove_refcount_extent
         */
        ret = ocfs2_cache_block_dealloc(dealloc, EXTENT_ALLOC_SYSTEM_INODE,
                                        le16_to_cpu(rb->rf_suballoc_slot),
+                                       le64_to_cpu(rb->rf_suballoc_loc),
                                        le64_to_cpu(rb->rf_blkno),
                                        le16_to_cpu(rb->rf_suballoc_bit));
        if (ret) {
   *
   * Normally the refcount blocks store these refcount should be
   * contiguous also, so that we can get the number easily.
 - * As for meta_ac, we will at most add split 2 refcount record and
 - * 2 more refcount block, so just check it in a rough way.
 + * We will at most add split 2 refcount records and 2 more
 + * refcount blocks, so just check it in a rough way.
   *
   * Caller must hold refcount tree lock.
   */
  int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
 -                                        struct buffer_head *di_bh,
 +                                        u64 refcount_loc,
                                          u64 phys_blkno,
                                          u32 clusters,
                                          int *credits,
 -                                        struct ocfs2_alloc_context **meta_ac)
 +                                        int *ref_blocks)
  {
 -      int ret, ref_blocks = 0;
 -      struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
 +      int ret;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct buffer_head *ref_root_bh = NULL;
        struct ocfs2_refcount_tree *tree;
        BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
  
        ret = ocfs2_get_refcount_tree(OCFS2_SB(inode->i_sb),
 -                                    le64_to_cpu(di->i_refcount_loc), &tree);
 +                                    refcount_loc, &tree);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
  
 -      ret = ocfs2_read_refcount_block(&tree->rf_ci,
 -                                      le64_to_cpu(di->i_refcount_loc),
 +      ret = ocfs2_read_refcount_block(&tree->rf_ci, refcount_loc,
                                        &ref_root_bh);
        if (ret) {
                mlog_errno(ret);
                                               &tree->rf_ci,
                                               ref_root_bh,
                                               start_cpos, clusters,
 -                                             &ref_blocks, credits);
 +                                             ref_blocks, credits);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
  
 -      mlog(0, "reserve new metadata %d, credits = %d\n",
 -           ref_blocks, *credits);
 -
 -      if (ref_blocks) {
 -              ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb),
 -                                                      ref_blocks, meta_ac);
 -              if (ret)
 -                      mlog_errno(ret);
 -      }
 +      mlog(0, "reserve new metadata %d blocks, credits = %d\n",
 +           *ref_blocks, *credits);
  
  out:
        brelse(ref_root_bh);
@@@ -3262,7 -3278,7 +3269,7 @@@ static int ocfs2_make_clusters_writable
                } else {
                        delete = 1;
  
-                       ret = __ocfs2_claim_clusters(osb, handle,
+                       ret = __ocfs2_claim_clusters(handle,
                                                     context->data_ac,
                                                     1, set_len,
                                                     &new_bit, &new_len);
diff --combined fs/ocfs2/super.c
index cf6d87b574500ef553f7bb150e47d341718c8022,106becf5d00fe1b75cf0b4dbdcf2b84583010fb5..1c2c39f6f0b6d3e69a4a81608e09141e4a1eaf11
@@@ -2277,7 -2277,8 +2277,8 @@@ static int ocfs2_initialize_super(struc
        osb->osb_clusters_at_boot = OCFS2_I(inode)->ip_clusters;
        iput(inode);
  
-       osb->bitmap_cpg = ocfs2_group_bitmap_size(sb) * 8;
+       osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0,
+                                osb->s_feature_incompat) * 8;
  
        status = ocfs2_init_slot_info(osb);
        if (status < 0) {
@@@ -2560,25 -2561,5 +2561,25 @@@ void __ocfs2_abort(struct super_block* 
        ocfs2_handle_error(sb);
  }
  
 +/*
 + * Void signal blockers, because in-kernel sigprocmask() only fails
 + * when SIG_* is wrong.
 + */
 +void ocfs2_block_signals(sigset_t *oldset)
 +{
 +      int rc;
 +      sigset_t blocked;
 +
 +      sigfillset(&blocked);
 +      rc = sigprocmask(SIG_BLOCK, &blocked, oldset);
 +      BUG_ON(rc);
 +}
 +
 +void ocfs2_unblock_signals(sigset_t *oldset)
 +{
 +      int rc = sigprocmask(SIG_SETMASK, oldset, NULL);
 +      BUG_ON(rc);
 +}
 +
  module_init(ocfs2_init);
  module_exit(ocfs2_exit);