r6040: add helpers to allocate and free the Tx/Rx buffers
[safe/jmp/linux-2.6] / fs / ocfs2 / suballoc.c
index 7ac68ca..72c198a 100644 (file)
@@ -49,7 +49,7 @@
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
 static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
 static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
-static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
+static int ocfs2_block_group_fill(handle_t *handle,
                                  struct inode *alloc_inode,
                                  struct buffer_head *bg_bh,
                                  u64 group_blkno,
@@ -59,9 +59,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
                                   struct inode *alloc_inode,
                                   struct buffer_head *bh);
 
-static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
-                                      struct ocfs2_alloc_context *ac);
-
 static int ocfs2_cluster_group_search(struct inode *inode,
                                      struct buffer_head *group_bh,
                                      u32 bits_wanted, u32 min_bits,
@@ -70,14 +67,9 @@ static int ocfs2_block_group_search(struct inode *inode,
                                    struct buffer_head *group_bh,
                                    u32 bits_wanted, u32 min_bits,
                                    u16 *bit_off, u16 *bits_found);
-static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
-                             u32 bits_wanted,
-                             u32 min_bits,
-                             u16 *bit_off,
-                             unsigned int *num_bits,
-                             u64 *bg_blkno);
 static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                                     struct ocfs2_alloc_context *ac,
+                                    handle_t *handle,
                                     u32 bits_wanted,
                                     u32 min_bits,
                                     u16 *bit_off,
@@ -85,20 +77,20 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                                     u64 *bg_blkno);
 static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
                                         int nr);
-static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
+static inline int ocfs2_block_group_set_bits(handle_t *handle,
                                             struct inode *alloc_inode,
                                             struct ocfs2_group_desc *bg,
                                             struct buffer_head *group_bh,
                                             unsigned int bit_off,
                                             unsigned int num_bits);
-static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle,
+static inline int ocfs2_block_group_clear_bits(handle_t *handle,
                                               struct inode *alloc_inode,
                                               struct ocfs2_group_desc *bg,
                                               struct buffer_head *group_bh,
                                               unsigned int bit_off,
                                               unsigned int num_bits);
 
-static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
+static int ocfs2_relink_block_group(handle_t *handle,
                                    struct inode *alloc_inode,
                                    struct buffer_head *fe_bh,
                                    struct buffer_head *bg_bh,
@@ -106,19 +98,9 @@ static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
                                    u16 chain);
 static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
                                                     u32 wanted);
-static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
-                                   struct inode *alloc_inode,
-                                   struct buffer_head *alloc_bh,
-                                   unsigned int start_bit,
-                                   u64 bg_blkno,
-                                   unsigned int count);
-static inline u64 ocfs2_which_suballoc_group(u64 block,
-                                            unsigned int bit);
 static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
                                                   u64 bg_blkno,
                                                   u16 bg_bit_off);
-static inline u64 ocfs2_which_cluster_group(struct inode *inode,
-                                           u32 cluster);
 static inline void ocfs2_block_to_cluster_group(struct inode *inode,
                                                u64 data_blkno,
                                                u64 *bg_blkno,
@@ -126,8 +108,16 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
 {
-       if (ac->ac_inode)
-               iput(ac->ac_inode);
+       struct inode *inode = ac->ac_inode;
+
+       if (inode) {
+               if (ac->ac_which != OCFS2_AC_USE_LOCAL)
+                       ocfs2_inode_unlock(inode, 1);
+
+               mutex_unlock(&inode->i_mutex);
+
+               iput(inode);
+       }
        if (ac->ac_bh)
                brelse(ac->ac_bh);
        kfree(ac);
@@ -139,9 +129,9 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
 }
 
 /* somewhat more expensive than our other checks, so use sparingly. */
-static int ocfs2_check_group_descriptor(struct super_block *sb,
-                                       struct ocfs2_dinode *di,
-                                       struct ocfs2_group_desc *gd)
+int ocfs2_check_group_descriptor(struct super_block *sb,
+                                struct ocfs2_dinode *di,
+                                struct ocfs2_group_desc *gd)
 {
        unsigned int max_bits;
 
@@ -196,7 +186,7 @@ static int ocfs2_check_group_descriptor(struct super_block *sb,
        return 0;
 }
 
-static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
+static int ocfs2_block_group_fill(handle_t *handle,
                                  struct inode *alloc_inode,
                                  struct buffer_head *bg_bh,
                                  u64 group_blkno,
@@ -279,7 +269,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
        struct ocfs2_chain_list *cl;
        struct ocfs2_alloc_context *ac = NULL;
-       struct ocfs2_journal_handle *handle = NULL;
+       handle_t *handle = NULL;
        u32 bit_off, num_bits;
        u16 alloc_rec;
        u64 bg_blkno;
@@ -290,16 +280,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 
        mlog_entry_void();
 
-       handle = ocfs2_alloc_handle(osb);
-       if (!handle) {
-               status = -ENOMEM;
-               mlog_errno(status);
-               goto bail;
-       }
-
        cl = &fe->id2.i_chain;
        status = ocfs2_reserve_clusters(osb,
-                                       handle,
                                        le16_to_cpu(cl->cl_cpg),
                                        &ac);
        if (status < 0) {
@@ -310,7 +292,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 
        credits = ocfs2_calc_group_alloc_credits(osb->sb,
                                                 le16_to_cpu(cl->cl_cpg));
-       handle = ocfs2_start_trans(osb, handle, credits);
+       handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -389,13 +371,12 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
                                             le32_to_cpu(fe->i_clusters)));
        spin_unlock(&OCFS2_I(alloc_inode)->ip_lock);
        i_size_write(alloc_inode, le64_to_cpu(fe->i_size));
-       alloc_inode->i_blocks =
-               ocfs2_align_bytes_to_sectors(i_size_read(alloc_inode));
+       alloc_inode->i_blocks = ocfs2_inode_sector_count(alloc_inode);
 
        status = 0;
 bail:
        if (handle)
-               ocfs2_commit_trans(handle);
+               ocfs2_commit_trans(osb, handle);
 
        if (ac)
                ocfs2_free_alloc_context(ac);
@@ -408,27 +389,38 @@ bail:
 }
 
 static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
-                                      struct ocfs2_alloc_context *ac)
+                                      struct ocfs2_alloc_context *ac,
+                                      int type,
+                                      u32 slot)
 {
        int status;
        u32 bits_wanted = ac->ac_bits_wanted;
-       struct inode *alloc_inode = ac->ac_inode;
+       struct inode *alloc_inode;
        struct buffer_head *bh = NULL;
-       struct ocfs2_journal_handle *handle = ac->ac_handle;
        struct ocfs2_dinode *fe;
        u32 free_bits;
 
        mlog_entry_void();
 
-       BUG_ON(handle->flags & OCFS2_HANDLE_STARTED);
+       alloc_inode = ocfs2_get_system_file_inode(osb, type, slot);
+       if (!alloc_inode) {
+               mlog_errno(-EINVAL);
+               return -EINVAL;
+       }
+
+       mutex_lock(&alloc_inode->i_mutex);
 
-       ocfs2_handle_add_inode(handle, alloc_inode);
-       status = ocfs2_meta_lock(alloc_inode, handle, &bh, 1);
+       status = ocfs2_inode_lock(alloc_inode, &bh, 1);
        if (status < 0) {
+               mutex_unlock(&alloc_inode->i_mutex);
+               iput(alloc_inode);
+
                mlog_errno(status);
-               goto bail;
+               return status;
        }
 
+       ac->ac_inode = alloc_inode;
+
        fe = (struct ocfs2_dinode *) bh->b_data;
        if (!OCFS2_IS_VALID_DINODE(fe)) {
                OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
@@ -479,14 +471,13 @@ bail:
 }
 
 int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
-                              struct ocfs2_journal_handle *handle,
                               struct ocfs2_dinode *fe,
                               struct ocfs2_alloc_context **ac)
 {
        int status;
-       struct inode *alloc_inode = NULL;
+       u32 slot;
 
-       *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+       *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
        if (!(*ac)) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -494,28 +485,12 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
        }
 
        (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
-       (*ac)->ac_handle = handle;
        (*ac)->ac_which = OCFS2_AC_USE_META;
-
-#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
-       alloc_inode = ocfs2_get_system_file_inode(osb,
-                                                 EXTENT_ALLOC_SYSTEM_INODE,
-                                                 0);
-#else
-       alloc_inode = ocfs2_get_system_file_inode(osb,
-                                                 EXTENT_ALLOC_SYSTEM_INODE,
-                                                 osb->slot_num);
-#endif
-       if (!alloc_inode) {
-               status = -ENOMEM;
-               mlog_errno(status);
-               goto bail;
-       }
-
-       (*ac)->ac_inode = igrab(alloc_inode);
+       slot = osb->slot_num;
        (*ac)->ac_group_search = ocfs2_block_group_search;
 
-       status = ocfs2_reserve_suballoc_bits(osb, (*ac));
+       status = ocfs2_reserve_suballoc_bits(osb, (*ac),
+                                            EXTENT_ALLOC_SYSTEM_INODE, slot);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -529,21 +504,16 @@ bail:
                *ac = NULL;
        }
 
-       if (alloc_inode)
-               iput(alloc_inode);
-
        mlog_exit(status);
        return status;
 }
 
 int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
-                           struct ocfs2_journal_handle *handle,
                            struct ocfs2_alloc_context **ac)
 {
        int status;
-       struct inode *alloc_inode = NULL;
 
-       *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+       *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
        if (!(*ac)) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -551,22 +521,13 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
        }
 
        (*ac)->ac_bits_wanted = 1;
-       (*ac)->ac_handle = handle;
        (*ac)->ac_which = OCFS2_AC_USE_INODE;
 
-       alloc_inode = ocfs2_get_system_file_inode(osb,
-                                                 INODE_ALLOC_SYSTEM_INODE,
-                                                 osb->slot_num);
-       if (!alloc_inode) {
-               status = -ENOMEM;
-               mlog_errno(status);
-               goto bail;
-       }
-
-       (*ac)->ac_inode = igrab(alloc_inode);
        (*ac)->ac_group_search = ocfs2_block_group_search;
 
-       status = ocfs2_reserve_suballoc_bits(osb, *ac);
+       status = ocfs2_reserve_suballoc_bits(osb, *ac,
+                                            INODE_ALLOC_SYSTEM_INODE,
+                                            osb->slot_num);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -580,9 +541,6 @@ bail:
                *ac = NULL;
        }
 
-       if (alloc_inode)
-               iput(alloc_inode);
-
        mlog_exit(status);
        return status;
 }
@@ -594,20 +552,17 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
 {
        int status;
 
-       ac->ac_inode = ocfs2_get_system_file_inode(osb,
-                                                  GLOBAL_BITMAP_SYSTEM_INODE,
-                                                  OCFS2_INVALID_SLOT);
-       if (!ac->ac_inode) {
-               status = -EINVAL;
-               mlog(ML_ERROR, "Could not get bitmap inode!\n");
-               goto bail;
-       }
        ac->ac_which = OCFS2_AC_USE_MAIN;
        ac->ac_group_search = ocfs2_cluster_group_search;
 
-       status = ocfs2_reserve_suballoc_bits(osb, ac);
-       if (status < 0 && status != -ENOSPC)
+       status = ocfs2_reserve_suballoc_bits(osb, ac,
+                                            GLOBAL_BITMAP_SYSTEM_INODE,
+                                            OCFS2_INVALID_SLOT);
+       if (status < 0 && status != -ENOSPC) {
                mlog_errno(status);
+               goto bail;
+       }
+
 bail:
        return status;
 }
@@ -616,7 +571,6 @@ bail:
  * use so we figure it out for them, but unfortunately this clutters
  * things a bit. */
 int ocfs2_reserve_clusters(struct ocfs2_super *osb,
-                          struct ocfs2_journal_handle *handle,
                           u32 bits_wanted,
                           struct ocfs2_alloc_context **ac)
 {
@@ -624,9 +578,7 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
 
        mlog_entry_void();
 
-       BUG_ON(!handle);
-
-       *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+       *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
        if (!(*ac)) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -634,12 +586,10 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
        }
 
        (*ac)->ac_bits_wanted = bits_wanted;
-       (*ac)->ac_handle = handle;
 
        status = -ENOSPC;
        if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {
                status = ocfs2_reserve_local_alloc_bits(osb,
-                                                       handle,
                                                        bits_wanted,
                                                        *ac);
                if ((status < 0) && (status != -ENOSPC)) {
@@ -696,7 +646,7 @@ bail:
  * sync-data inodes."
  *
  * Note: OCFS2 already does this differently for metadata vs data
- * allocations, as those bitmaps are seperate and undo access is never
+ * allocations, as those bitmaps are separate and undo access is never
  * called on a metadata group descriptor.
  */
 static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
@@ -780,7 +730,7 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
        return status;
 }
 
-static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
+static inline int ocfs2_block_group_set_bits(handle_t *handle,
                                             struct inode *alloc_inode,
                                             struct ocfs2_group_desc *bg,
                                             struct buffer_head *group_bh,
@@ -851,7 +801,7 @@ static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl)
        return best;
 }
 
-static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
+static int ocfs2_relink_block_group(handle_t *handle,
                                    struct inode *alloc_inode,
                                    struct buffer_head *fe_bh,
                                    struct buffer_head *bg_bh,
@@ -883,9 +833,9 @@ static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
        }
 
        mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
-            (unsigned long long)fe->i_blkno, chain,
-            (unsigned long long)bg->bg_blkno,
-            (unsigned long long)prev_bg->bg_blkno);
+            (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
+            (unsigned long long)le64_to_cpu(bg->bg_blkno),
+            (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));
 
        fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
        bg_ptr = le64_to_cpu(bg->bg_next_group);
@@ -1030,18 +980,109 @@ static int ocfs2_block_group_search(struct inode *inode,
        return ret;
 }
 
+static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
+                                      handle_t *handle,
+                                      struct buffer_head *di_bh,
+                                      u32 num_bits,
+                                      u16 chain)
+{
+       int ret;
+       u32 tmp_used;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
+       struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;
+
+       ret = ocfs2_journal_access(handle, inode, di_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       tmp_used = le32_to_cpu(di->id1.bitmap1.i_used);
+       di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used);
+       le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits);
+
+       ret = ocfs2_journal_dirty(handle, di_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+
+out:
+       return ret;
+}
+
+static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
+                                 handle_t *handle,
+                                 u32 bits_wanted,
+                                 u32 min_bits,
+                                 u16 *bit_off,
+                                 unsigned int *num_bits,
+                                 u64 gd_blkno,
+                                 u16 *bits_left)
+{
+       int ret;
+       u16 found;
+       struct buffer_head *group_bh = NULL;
+       struct ocfs2_group_desc *gd;
+       struct inode *alloc_inode = ac->ac_inode;
+
+       ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
+                              &group_bh, OCFS2_BH_CACHED, alloc_inode);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       gd = (struct ocfs2_group_desc *) group_bh->b_data;
+       if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
+               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
+                                 bit_off, &found);
+       if (ret < 0) {
+               if (ret != -ENOSPC)
+                       mlog_errno(ret);
+               goto out;
+       }
+
+       *num_bits = found;
+
+       ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
+                                              *num_bits,
+                                              le16_to_cpu(gd->bg_chain));
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
+                                        *bit_off, *num_bits);
+       if (ret < 0)
+               mlog_errno(ret);
+
+       *bits_left = le16_to_cpu(gd->bg_free_bits_count);
+
+out:
+       brelse(group_bh);
+
+       return ret;
+}
+
 static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
+                             handle_t *handle,
                              u32 bits_wanted,
                              u32 min_bits,
                              u16 *bit_off,
                              unsigned int *num_bits,
-                             u64 *bg_blkno)
+                             u64 *bg_blkno,
+                             u16 *bits_left)
 {
        int status;
        u16 chain, tmp_bits;
        u32 tmp_used;
        u64 next_group;
-       struct ocfs2_journal_handle *handle = ac->ac_handle;
        struct inode *alloc_inode = ac->ac_inode;
        struct buffer_head *group_bh = NULL;
        struct buffer_head *prev_group_bh = NULL;
@@ -1105,7 +1146,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        }
 
        mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",
-            tmp_bits, (unsigned long long)bg->bg_blkno);
+            tmp_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));
 
        *num_bits = tmp_bits;
 
@@ -1170,9 +1211,10 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        }
 
        mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits,
-            (unsigned long long)fe->i_blkno);
+            (unsigned long long)le64_to_cpu(fe->i_blkno));
 
        *bg_blkno = le64_to_cpu(bg->bg_blkno);
+       *bits_left = le16_to_cpu(bg->bg_free_bits_count);
 bail:
        if (group_bh)
                brelse(group_bh);
@@ -1186,6 +1228,7 @@ bail:
 /* will give out up to bits_wanted contiguous bits. */
 static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                                     struct ocfs2_alloc_context *ac,
+                                    handle_t *handle,
                                     u32 bits_wanted,
                                     u32 min_bits,
                                     u16 *bit_off,
@@ -1194,6 +1237,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 {
        int status;
        u16 victim, i;
+       u16 bits_left = 0;
+       u64 hint_blkno = ac->ac_last_group;
        struct ocfs2_chain_list *cl;
        struct ocfs2_dinode *fe;
 
@@ -1220,16 +1265,38 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                goto bail;
        }
 
+       if (hint_blkno) {
+               /* Attempt to short-circuit the usual search mechanism
+                * by jumping straight to the most recently used
+                * allocation group. This helps us mantain some
+                * contiguousness across allocations. */
+               status = ocfs2_search_one_group(ac, handle, bits_wanted,
+                                               min_bits, bit_off, num_bits,
+                                               hint_blkno, &bits_left);
+               if (!status) {
+                       /* Be careful to update *bg_blkno here as the
+                        * caller is expecting it to be filled in, and
+                        * ocfs2_search_one_group() won't do that for
+                        * us. */
+                       *bg_blkno = hint_blkno;
+                       goto set_hint;
+               }
+               if (status < 0 && status != -ENOSPC) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
 
        victim = ocfs2_find_victim_chain(cl);
        ac->ac_chain = victim;
        ac->ac_allow_chain_relink = 1;
 
-       status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off,
-                                   num_bits, bg_blkno);
+       status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off,
+                                   num_bits, bg_blkno, &bits_left);
        if (!status)
-               goto bail;
+               goto set_hint;
        if (status < 0 && status != -ENOSPC) {
                mlog_errno(status);
                goto bail;
@@ -1250,9 +1317,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                        continue;
 
                ac->ac_chain = i;
-               status = ocfs2_search_chain(ac, bits_wanted, min_bits,
-                                           bit_off, num_bits,
-                                           bg_blkno);
+               status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
+                                           bit_off, num_bits, bg_blkno,
+                                           &bits_left);
                if (!status)
                        break;
                if (status < 0 && status != -ENOSPC) {
@@ -1260,14 +1327,25 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                        goto bail;
                }
        }
-bail:
 
+set_hint:
+       if (status != -ENOSPC) {
+               /* If the next search of this group is not likely to
+                * yield a suitable extent, then we reset the last
+                * group hint so as to not waste a disk read */
+               if (bits_left < min_bits)
+                       ac->ac_last_group = 0;
+               else
+                       ac->ac_last_group = *bg_blkno;
+       }
+
+bail:
        mlog_exit(status);
        return status;
 }
 
 int ocfs2_claim_metadata(struct ocfs2_super *osb,
-                        struct ocfs2_journal_handle *handle,
+                        handle_t *handle,
                         struct ocfs2_alloc_context *ac,
                         u32 bits_wanted,
                         u16 *suballoc_bit_start,
@@ -1280,10 +1358,10 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb,
        BUG_ON(!ac);
        BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted));
        BUG_ON(ac->ac_which != OCFS2_AC_USE_META);
-       BUG_ON(ac->ac_handle != handle);
 
        status = ocfs2_claim_suballoc_bits(osb,
                                           ac,
+                                          handle,
                                           bits_wanted,
                                           1,
                                           suballoc_bit_start,
@@ -1304,7 +1382,7 @@ bail:
 }
 
 int ocfs2_claim_new_inode(struct ocfs2_super *osb,
-                         struct ocfs2_journal_handle *handle,
+                         handle_t *handle,
                          struct ocfs2_alloc_context *ac,
                          u16 *suballoc_bit,
                          u64 *fe_blkno)
@@ -1319,10 +1397,10 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb,
        BUG_ON(ac->ac_bits_given != 0);
        BUG_ON(ac->ac_bits_wanted != 1);
        BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE);
-       BUG_ON(ac->ac_handle != handle);
 
        status = ocfs2_claim_suballoc_bits(osb,
                                           ac,
+                                          handle,
                                           1,
                                           1,
                                           suballoc_bit,
@@ -1363,8 +1441,7 @@ static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
 
 /* given a cluster offset, calculate which block group it belongs to
  * and return that block offset. */
-static inline u64 ocfs2_which_cluster_group(struct inode *inode,
-                                           u32 cluster)
+u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster)
 {
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        u32 group_no;
@@ -1406,26 +1483,25 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
  * contig. allocation, set to '1' to indicate we can deal with extents
  * of any size.
  */
-int ocfs2_claim_clusters(struct ocfs2_super *osb,
-                        struct ocfs2_journal_handle *handle,
-                        struct ocfs2_alloc_context *ac,
-                        u32 min_clusters,
-                        u32 *cluster_start,
-                        u32 *num_clusters)
+int __ocfs2_claim_clusters(struct ocfs2_super *osb,
+                          handle_t *handle,
+                          struct ocfs2_alloc_context *ac,
+                          u32 min_clusters,
+                          u32 max_clusters,
+                          u32 *cluster_start,
+                          u32 *num_clusters)
 {
        int status;
-       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
-       u64 bg_blkno;
+       unsigned int bits_wanted = max_clusters;
+       u64 bg_blkno = 0;
        u16 bg_bit_off;
 
        mlog_entry_void();
 
-       BUG_ON(!ac);
        BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
 
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
               && ac->ac_which != OCFS2_AC_USE_MAIN);
-       BUG_ON(ac->ac_handle != handle);
 
        if (ac->ac_which == OCFS2_AC_USE_LOCAL) {
                status = ocfs2_claim_local_alloc_bits(osb,
@@ -1440,8 +1516,9 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
                if (min_clusters > (osb->bitmap_cpg - 1)) {
                        /* The only paths asking for contiguousness
                         * should know about this already. */
-                       mlog(ML_ERROR, "minimum allocation requested exceeds "
-                                      "group bitmap size!");
+                       mlog(ML_ERROR, "minimum allocation requested %u exceeds "
+                            "group bitmap size %u!\n", min_clusters,
+                            osb->bitmap_cpg);
                        status = -ENOSPC;
                        goto bail;
                }
@@ -1451,6 +1528,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
 
                status = ocfs2_claim_suballoc_bits(osb,
                                                   ac,
+                                                  handle,
                                                   bits_wanted,
                                                   min_clusters,
                                                   &bg_bit_off,
@@ -1477,7 +1555,20 @@ bail:
        return status;
 }
 
-static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle,
+int ocfs2_claim_clusters(struct ocfs2_super *osb,
+                        handle_t *handle,
+                        struct ocfs2_alloc_context *ac,
+                        u32 min_clusters,
+                        u32 *cluster_start,
+                        u32 *num_clusters)
+{
+       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+
+       return __ocfs2_claim_clusters(osb, handle, ac, min_clusters,
+                                     bits_wanted, cluster_start, num_clusters);
+}
+
+static inline int ocfs2_block_group_clear_bits(handle_t *handle,
                                               struct inode *alloc_inode,
                                               struct ocfs2_group_desc *bg,
                                               struct buffer_head *group_bh,
@@ -1532,12 +1623,12 @@ bail:
 /*
  * expects the suballoc inode to already be locked.
  */
-static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
-                                   struct inode *alloc_inode,
-                                   struct buffer_head *alloc_bh,
-                                   unsigned int start_bit,
-                                   u64 bg_blkno,
-                                   unsigned int count)
+int ocfs2_free_suballoc_bits(handle_t *handle,
+                            struct inode *alloc_inode,
+                            struct buffer_head *alloc_bh,
+                            unsigned int start_bit,
+                            u64 bg_blkno,
+                            unsigned int count)
 {
        int status = 0;
        u32 tmp_used;
@@ -1609,14 +1700,7 @@ bail:
        return status;
 }
 
-static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
-{
-       u64 group = block - (u64) bit;
-
-       return group;
-}
-
-int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
+int ocfs2_free_dinode(handle_t *handle,
                      struct inode *inode_alloc_inode,
                      struct buffer_head *inode_alloc_bh,
                      struct ocfs2_dinode *di)
@@ -1629,20 +1713,7 @@ int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
                                        inode_alloc_bh, bit, bg_blkno, 1);
 }
 
-int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle,
-                           struct inode *eb_alloc_inode,
-                           struct buffer_head *eb_alloc_bh,
-                           struct ocfs2_extent_block *eb)
-{
-       u64 blk = le64_to_cpu(eb->h_blkno);
-       u16 bit = le16_to_cpu(eb->h_suballoc_bit);
-       u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
-
-       return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
-                                       bit, bg_blkno, 1);
-}
-
-int ocfs2_free_clusters(struct ocfs2_journal_handle *handle,
+int ocfs2_free_clusters(handle_t *handle,
                       struct inode *bitmap_inode,
                       struct buffer_head *bitmap_bh,
                       u64 start_blk,