]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ocfs2/alloc.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx
[linux-2.6-omap-h63xx.git] / fs / ocfs2 / alloc.c
index f63cb32e224d52709fcc7ce01ab4109773397af2..10bfb466e0687eb4c99dd3c5fc1e787c07d68efc 100644 (file)
@@ -1029,8 +1029,7 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,
        BUG_ON(!next_free);
 
        /* The tree code before us didn't allow enough room in the leaf. */
-       if (el->l_next_free_rec == el->l_count && !has_empty)
-               BUG();
+       BUG_ON(el->l_next_free_rec == el->l_count && !has_empty);
 
        /*
         * The easiest way to approach this is to just remove the
@@ -2789,7 +2788,7 @@ static int ocfs2_merge_rec_right(struct inode *inode,
        BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
        left_rec = &el->l_recs[index];
 
-       if (index == le16_to_cpu(el->l_next_free_rec - 1) &&
+       if (index == le16_to_cpu(el->l_next_free_rec) - 1 &&
            le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count)) {
                /* we meet with a cross extent block merge. */
                ret = ocfs2_get_right_path(inode, left_path, &right_path);
@@ -2803,7 +2802,7 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                BUG_ON(next_free <= 0);
                right_rec = &right_el->l_recs[0];
                if (ocfs2_is_empty_extent(right_rec)) {
-                       BUG_ON(le16_to_cpu(next_free) <= 1);
+                       BUG_ON(next_free <= 1);
                        right_rec = &right_el->l_recs[1];
                }
 
@@ -3782,20 +3781,57 @@ out:
 }
 
 static enum ocfs2_contig_type
-ocfs2_figure_merge_contig_type(struct inode *inode,
+ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                               struct ocfs2_extent_list *el, int index,
                               struct ocfs2_extent_rec *split_rec)
 {
-       struct ocfs2_extent_rec *rec;
+       int status;
        enum ocfs2_contig_type ret = CONTIG_NONE;
+       u32 left_cpos, right_cpos;
+       struct ocfs2_extent_rec *rec = NULL;
+       struct ocfs2_extent_list *new_el;
+       struct ocfs2_path *left_path = NULL, *right_path = NULL;
+       struct buffer_head *bh;
+       struct ocfs2_extent_block *eb;
+
+       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);
+               if (status)
+                       goto out;
+
+               if (left_cpos != 0) {
+                       left_path = ocfs2_new_path(path_root_bh(path),
+                                                  path_root_el(path));
+                       if (!left_path)
+                               goto out;
+
+                       status = ocfs2_find_path(inode, left_path, left_cpos);
+                       if (status)
+                               goto out;
+
+                       new_el = path_leaf_el(left_path);
+
+                       if (le16_to_cpu(new_el->l_next_free_rec) !=
+                           le16_to_cpu(new_el->l_count)) {
+                               bh = path_leaf_bh(left_path);
+                               eb = (struct ocfs2_extent_block *)bh->b_data;
+                               OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
+                                                                eb);
+                               goto out;
+                       }
+                       rec = &new_el->l_recs[
+                               le16_to_cpu(new_el->l_next_free_rec) - 1];
+               }
+       }
 
        /*
         * We're careful to check for an empty extent record here -
         * the merge code will know what to do if it sees one.
         */
-
-       if (index > 0) {
-               rec = &el->l_recs[index - 1];
+       if (rec) {
                if (index == 1 && ocfs2_is_empty_extent(rec)) {
                        if (split_rec->e_cpos == el->l_recs[index].e_cpos)
                                ret = CONTIG_RIGHT;
@@ -3804,10 +3840,45 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
                }
        }
 
-       if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
+       rec = NULL;
+       if (index < (le16_to_cpu(el->l_next_free_rec) - 1))
+               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);
+               if (status)
+                       goto out;
+
+               if (right_cpos == 0)
+                       goto out;
+
+               right_path = ocfs2_new_path(path_root_bh(path),
+                                           path_root_el(path));
+               if (!right_path)
+                       goto out;
+
+               status = ocfs2_find_path(inode, right_path, right_cpos);
+               if (status)
+                       goto out;
+
+               new_el = path_leaf_el(right_path);
+               rec = &new_el->l_recs[0];
+               if (ocfs2_is_empty_extent(rec)) {
+                       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_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
+                                                                eb);
+                               goto out;
+                       }
+                       rec = &new_el->l_recs[1];
+               }
+       }
+
+       if (rec) {
                enum ocfs2_contig_type contig_type;
 
-               rec = &el->l_recs[index + 1];
                contig_type = ocfs2_extent_contig(inode, rec, split_rec);
 
                if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
@@ -3816,6 +3887,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
                        ret = contig_type;
        }
 
+out:
+       if (left_path)
+               ocfs2_free_path(left_path);
+       if (right_path)
+               ocfs2_free_path(right_path);
+
        return ret;
 }
 
@@ -4278,7 +4355,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
                goto out;
        }
 
-       ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
+       ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, path, el,
                                                            split_index,
                                                            split_rec);
 
@@ -5072,6 +5149,8 @@ static void ocfs2_truncate_log_worker(struct work_struct *work)
        status = ocfs2_flush_truncate_log(osb);
        if (status < 0)
                mlog_errno(status);
+       else
+               ocfs2_init_inode_steal_slot(osb);
 
        mlog_exit(status);
 }