During deletes and truncate, remove many items at once from the tree
authorChris Mason <chris.mason@oracle.com>
Tue, 29 Jan 2008 20:11:36 +0000 (15:11 -0500)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Tue, 29 Jan 2008 20:11:36 +0000 (15:11 -0500)
ctree.c
ctree.h

diff --git a/ctree.c b/ctree.c
index 9483661..6357580 100644 (file)
--- a/ctree.c
+++ b/ctree.c
@@ -2368,34 +2368,36 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
  * delete the item at the leaf level in path.  If that empties
  * the leaf, remove it from the tree
  */
-int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                  struct btrfs_path *path)
+int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+                   struct btrfs_path *path, int slot, int nr)
 {
-       int slot;
        struct extent_buffer *leaf;
        struct btrfs_item *item;
-       int doff;
-       int dsize;
+       int last_off;
+       int dsize = 0;
        int ret = 0;
        int wret;
+       int i;
        u32 nritems;
 
        leaf = path->nodes[0];
-       slot = path->slots[0];
-       doff = btrfs_item_offset_nr(leaf, slot);
-       dsize = btrfs_item_size_nr(leaf, slot);
+       last_off = btrfs_item_offset_nr(leaf, slot + nr - 1);
+
+       for (i = 0; i < nr; i++)
+               dsize += btrfs_item_size_nr(leaf, slot + i);
+
        nritems = btrfs_header_nritems(leaf);
 
-       if (slot != nritems - 1) {
+       if (slot + nr != nritems) {
                int i;
                int data_end = leaf_data_end(root, leaf);
 
                memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
                              data_end + dsize,
                              btrfs_leaf_data(leaf) + data_end,
-                             doff - data_end);
+                             last_off - data_end);
 
-               for (i = slot + 1; i < nritems; i++) {
+               for (i = slot + nr; i < nritems; i++) {
                        u32 ioff;
 
                        item = btrfs_item_nr(leaf, i);
@@ -2404,12 +2406,12 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                }
 
                memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot),
-                             btrfs_item_nr_offset(slot + 1),
+                             btrfs_item_nr_offset(slot + nr),
                              sizeof(struct btrfs_item) *
-                             (nritems - slot - 1));
+                             (nritems - slot - nr));
        }
-       btrfs_set_header_nritems(leaf, nritems - 1);
-       nritems--;
+       btrfs_set_header_nritems(leaf, nritems - nr);
+       nritems -= nr;
 
        /* delete the leaf if we've emptied it */
        if (nritems == 0) {
@@ -2442,7 +2444,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                }
 
                /* delete the leaf if it is mostly empty */
-               if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
+               if (used < BTRFS_LEAF_DATA_SIZE(root) / 4) {
                        /* push_leaf_left fixes the path.
                         * make sure the path still points to our leaf
                         * for possible call to del_ptr below
@@ -2450,13 +2452,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                        slot = path->slots[1];
                        extent_buffer_get(leaf);
 
-                       wret = push_leaf_right(trans, root, path, 1, 1);
+                       wret = push_leaf_left(trans, root, path, 1, 1);
                        if (wret < 0 && wret != -ENOSPC)
                                ret = wret;
 
                        if (path->nodes[0] == leaf &&
                            btrfs_header_nritems(leaf)) {
-                               wret = push_leaf_left(trans, root, path, 1, 1);
+                               wret = push_leaf_right(trans, root, path, 1, 1);
                                if (wret < 0 && wret != -ENOSPC)
                                        ret = wret;
                        }
diff --git a/ctree.h b/ctree.h
index 1166f94..a219c23 100644 (file)
--- a/ctree.h
+++ b/ctree.h
@@ -997,8 +997,16 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
 struct btrfs_path *btrfs_alloc_path(void);
 void btrfs_free_path(struct btrfs_path *p);
 void btrfs_init_path(struct btrfs_path *p);
-int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-                  struct btrfs_path *path);
+int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+                  struct btrfs_path *path, int slot, int nr);
+
+static inline int btrfs_del_item(struct btrfs_trans_handle *trans,
+                                struct btrfs_root *root,
+                                struct btrfs_path *path)
+{
+       return btrfs_del_items(trans, root, path, path->slots[0], 1);
+}
+
 int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
                      *root, struct btrfs_key *key, void *data, u32 data_size);
 int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root