]> Pileus Git - ~andy/linux/blobdiff - fs/btrfs/ctree.c
Btrfs: use right clone root offset for compressed extents
[~andy/linux] / fs / btrfs / ctree.c
index 7d88d8543aa1e5c29fc2f55553ac65352f7fcb8e..cbd3a7d6fa681acfc0b00cb515fcddbcf8880f49 100644 (file)
@@ -1480,8 +1480,8 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                old = read_tree_block(root, logical, blocksize, 0);
                if (WARN_ON(!old || !extent_buffer_uptodate(old))) {
                        free_extent_buffer(old);
-                       pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
-                               logical);
+                       btrfs_warn(root->fs_info,
+                               "failed to read tree block %llu from get_old_root", logical);
                } else {
                        eb = btrfs_clone_extent_buffer(old);
                        free_extent_buffer(old);
@@ -2731,6 +2731,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
        lowest_level = p->lowest_level;
        WARN_ON(lowest_level && ins_len > 0);
        WARN_ON(p->nodes[0] != NULL);
+       BUG_ON(!cow && ins_len);
 
        if (ins_len < 0) {
                lowest_unlock = 2;
@@ -2839,8 +2840,6 @@ again:
                        }
                }
 cow_done:
-               BUG_ON(!cow && ins_len);
-
                p->nodes[level] = b;
                btrfs_clear_path_blocking(p, NULL, 0);
 
@@ -2850,13 +2849,19 @@ cow_done:
                 * It is safe to drop the lock on our parent before we
                 * go through the expensive btree search on b.
                 *
-                * If cow is true, then we might be changing slot zero,
-                * which may require changing the parent.  So, we can't
-                * drop the lock until after we know which slot we're
-                * operating on.
+                * If we're inserting or deleting (ins_len != 0), then we might
+                * be changing slot zero, which may require changing the parent.
+                * So, we can't drop the lock until after we know which slot
+                * we're operating on.
                 */
-               if (!cow)
-                       btrfs_unlock_up_safe(p, level + 1);
+               if (!ins_len && !p->keep_locks) {
+                       int u = level + 1;
+
+                       if (u < BTRFS_MAX_LEVEL && p->locks[u]) {
+                               btrfs_tree_unlock_rw(p->nodes[u], p->locks[u]);
+                               p->locks[u] = 0;
+                       }
+               }
 
                ret = key_search(b, key, level, &prev_cmp, &slot);
 
@@ -2884,7 +2889,7 @@ cow_done:
                         * which means we must have a write lock
                         * on the parent
                         */
-                       if (slot == 0 && cow &&
+                       if (slot == 0 && ins_len &&
                            write_lock_level < level + 1) {
                                write_lock_level = level + 1;
                                btrfs_release_path(p);
@@ -3137,7 +3142,9 @@ again:
                        if (ret < 0)
                                return ret;
                        if (!ret) {
-                               p->slots[0] = btrfs_header_nritems(leaf) - 1;
+                               leaf = p->nodes[0];
+                               if (p->slots[0] == btrfs_header_nritems(leaf))
+                                       p->slots[0]--;
                                return 0;
                        }
                        if (!return_any)
@@ -3611,8 +3618,8 @@ noinline int btrfs_leaf_free_space(struct btrfs_root *root,
        int ret;
        ret = BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
        if (ret < 0) {
-               printk(KERN_CRIT "leaf free space ret %d, leaf data size %lu, "
-                      "used %d nritems %d\n",
+               btrfs_crit(root->fs_info,
+                       "leaf free space ret %d, leaf data size %lu, used %d nritems %d",
                       ret, (unsigned long) BTRFS_LEAF_DATA_SIZE(root),
                       leaf_space_used(leaf, 0, nritems), nritems);
        }
@@ -4702,7 +4709,7 @@ void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
        BUG_ON(slot < 0);
        if (slot >= nritems) {
                btrfs_print_leaf(root, leaf);
-               printk(KERN_CRIT "slot %d too large, nritems %d\n",
+               btrfs_crit(root->fs_info, "slot %d too large, nritems %d",
                       slot, nritems);
                BUG_ON(1);
        }
@@ -4765,7 +4772,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
 
        if (btrfs_leaf_free_space(root, leaf) < total_size) {
                btrfs_print_leaf(root, leaf);
-               printk(KERN_CRIT "not enough freespace need %u have %d\n",
+               btrfs_crit(root->fs_info, "not enough freespace need %u have %d",
                       total_size, btrfs_leaf_free_space(root, leaf));
                BUG();
        }
@@ -4775,7 +4782,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
 
                if (old_data < data_end) {
                        btrfs_print_leaf(root, leaf);
-                       printk(KERN_CRIT "slot %d old_data %d data_end %d\n",
+                       btrfs_crit(root->fs_info, "slot %d old_data %d data_end %d",
                               slot, old_data, data_end);
                        BUG_ON(1);
                }
@@ -5510,7 +5517,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
 
                        if (!left_start_ctransid || !right_start_ctransid) {
                                WARN(1, KERN_WARNING
-                                       "btrfs: btrfs_compare_tree detected "
+                                       "BTRFS: btrfs_compare_tree detected "
                                        "a change in one of the trees while "
                                        "iterating. This is probably a "
                                        "bug.\n");
@@ -5950,3 +5957,46 @@ int btrfs_previous_item(struct btrfs_root *root,
        }
        return 1;
 }
+
+/*
+ * search in extent tree to find a previous Metadata/Data extent item with
+ * min objecitd.
+ *
+ * returns 0 if something is found, 1 if nothing was found and < 0 on error
+ */
+int btrfs_previous_extent_item(struct btrfs_root *root,
+                       struct btrfs_path *path, u64 min_objectid)
+{
+       struct btrfs_key found_key;
+       struct extent_buffer *leaf;
+       u32 nritems;
+       int ret;
+
+       while (1) {
+               if (path->slots[0] == 0) {
+                       btrfs_set_path_blocking(path);
+                       ret = btrfs_prev_leaf(root, path);
+                       if (ret != 0)
+                               return ret;
+               } else {
+                       path->slots[0]--;
+               }
+               leaf = path->nodes[0];
+               nritems = btrfs_header_nritems(leaf);
+               if (nritems == 0)
+                       return 1;
+               if (path->slots[0] == nritems)
+                       path->slots[0]--;
+
+               btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+               if (found_key.objectid < min_objectid)
+                       break;
+               if (found_key.type == BTRFS_EXTENT_ITEM_KEY ||
+                   found_key.type == BTRFS_METADATA_ITEM_KEY)
+                       return 0;
+               if (found_key.objectid == min_objectid &&
+                   found_key.type < BTRFS_EXTENT_ITEM_KEY)
+                       break;
+       }
+       return 1;
+}