diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-12-17 10:21:48 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-12-17 10:21:48 -0500 |
commit | 87b29b208c6c38f3446d2de6ece946e2459052cf (patch) | |
tree | 43e717289e1e8446fced4093ab39667bba9ea60a /fs | |
parent | d7f735d0bc68c411abda0a612e1421bdade649cc (diff) | |
download | talos-op-linux-87b29b208c6c38f3446d2de6ece946e2459052cf.tar.gz talos-op-linux-87b29b208c6c38f3446d2de6ece946e2459052cf.zip |
Btrfs: properly check free space for tree balancing
btrfs_insert_empty_items takes the space needed by the btrfs_item
structure into account when calculating the required free space.
So the tree balancing code shouldn't add sizeof(struct btrfs_item)
to the size when checking the free space. This patch removes these
superfluous additions.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.c | 52 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 4 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 9 |
3 files changed, 32 insertions, 33 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index f6f7a6af0357..7fad2e3ad6ff 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -1587,8 +1587,8 @@ cow_done: btrfs_tree_lock(b); } else { p->slots[level] = slot; - if (ins_len > 0 && btrfs_leaf_free_space(root, b) < - sizeof(struct btrfs_item) + ins_len) { + if (ins_len > 0 && + btrfs_leaf_free_space(root, b) < ins_len) { int sret = split_leaf(trans, root, key, p, ins_len, ret == 0); BUG_ON(sret > 0); @@ -2231,7 +2231,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root right = read_node_slot(root, upper, slot + 1); btrfs_tree_lock(right); free_space = btrfs_leaf_free_space(root, right); - if (free_space < data_size + sizeof(struct btrfs_item)) + if (free_space < data_size) goto out_unlock; /* cow and double check */ @@ -2241,7 +2241,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root goto out_unlock; free_space = btrfs_leaf_free_space(root, right); - if (free_space < data_size + sizeof(struct btrfs_item)) + if (free_space < data_size) goto out_unlock; left_nritems = btrfs_header_nritems(left); @@ -2254,7 +2254,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root nr = 1; if (path->slots[0] >= left_nritems) - push_space += data_size + sizeof(*item); + push_space += data_size; i = left_nritems - 1; while (i >= nr) { @@ -2271,7 +2271,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root } if (path->slots[0] == i) - push_space += data_size + sizeof(*item); + push_space += data_size; if (!left->map_token) { map_extent_buffer(left, (unsigned long)item, @@ -2427,7 +2427,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root left = read_node_slot(root, path->nodes[1], slot - 1); btrfs_tree_lock(left); free_space = btrfs_leaf_free_space(root, left); - if (free_space < data_size + sizeof(struct btrfs_item)) { + if (free_space < data_size) { ret = 1; goto out; } @@ -2442,7 +2442,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root } free_space = btrfs_leaf_free_space(root, left); - if (free_space < data_size + sizeof(struct btrfs_item)) { + if (free_space < data_size) { ret = 1; goto out; } @@ -2473,7 +2473,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root } if (path->slots[0] == i) - push_space += data_size + sizeof(*item); + push_space += data_size; this_item_size = btrfs_item_size(right, item); if (this_item_size + sizeof(*item) + push_space > free_space) @@ -2510,7 +2510,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root btrfs_item_offset_nr(right, push_items - 1), push_space); old_left_nritems = btrfs_header_nritems(left); - BUG_ON(old_left_nritems < 0); + BUG_ON(old_left_nritems <= 0); old_left_item_size = btrfs_item_offset_nr(left, old_left_nritems - 1); for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { @@ -2628,7 +2628,6 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, int mid; int slot; struct extent_buffer *right; - int space_needed = data_size + sizeof(struct btrfs_item); int data_copy_size; int rt_data_off; int i; @@ -2638,9 +2637,6 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, int num_doubles = 0; struct btrfs_disk_key disk_key; - if (extend && data_size) - space_needed = data_size; - /* first try to make some room by pushing left and right */ if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY) { wret = push_leaf_right(trans, root, path, data_size, 0); @@ -2655,7 +2651,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, l = path->nodes[0]; /* did the pushes work? */ - if (btrfs_leaf_free_space(root, l) >= space_needed) + if (btrfs_leaf_free_space(root, l) >= data_size) return 0; } @@ -2694,7 +2690,7 @@ again: BTRFS_UUID_SIZE); if (mid <= slot) { if (nritems == 1 || - leaf_space_used(l, mid, nritems - mid) + space_needed > + leaf_space_used(l, mid, nritems - mid) + data_size > BTRFS_LEAF_DATA_SIZE(root)) { if (slot >= nritems) { btrfs_cpu_key_to_disk(&disk_key, ins_key); @@ -2716,12 +2712,12 @@ again: mid = slot; if (mid != nritems && leaf_space_used(l, mid, nritems - mid) + - space_needed > BTRFS_LEAF_DATA_SIZE(root)) { + data_size > BTRFS_LEAF_DATA_SIZE(root)) { double_split = 1; } } } else { - if (leaf_space_used(l, 0, mid + 1) + space_needed > + if (leaf_space_used(l, 0, mid) + data_size > BTRFS_LEAF_DATA_SIZE(root)) { if (!extend && data_size && slot == 0) { btrfs_cpu_key_to_disk(&disk_key, ins_key); @@ -2750,7 +2746,7 @@ again: mid = slot; if (mid != nritems && leaf_space_used(l, mid, nritems - mid) + - space_needed > BTRFS_LEAF_DATA_SIZE(root)) { + data_size > BTRFS_LEAF_DATA_SIZE(root)) { double_split = 1; } } @@ -2883,7 +2879,8 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, return -EAGAIN; } - ret = split_leaf(trans, root, &orig_key, path, 0, 0); + ret = split_leaf(trans, root, &orig_key, path, + sizeof(struct btrfs_item), 1); path->keep_locks = 0; BUG_ON(ret); @@ -3169,14 +3166,17 @@ int btrfs_insert_some_items(struct btrfs_trans_handle *trans, struct btrfs_disk_key disk_key; struct btrfs_key found_key; - found_key.objectid = 0; - nr = min_t(int, nr, BTRFS_NODEPTRS_PER_BLOCK(root)); - - for (i = 0; i < nr; i++) + for (i = 0; i < nr; i++) { + if (total_size + data_size[i] + sizeof(struct btrfs_item) > + BTRFS_LEAF_DATA_SIZE(root)) { + break; + nr = i; + } total_data += data_size[i]; + total_size += data_size[i] + sizeof(struct btrfs_item); + } + BUG_ON(nr == 0); - total_data = min_t(u32, total_data, BTRFS_LEAF_DATA_SIZE(root)); - total_size = total_data + (nr * sizeof(struct btrfs_item)); ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); if (ret == 0) return -EEXIST; diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 7acadf3b742a..cc6e0b6de949 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -300,6 +300,10 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, size = btrfs_item_size_nr(leaf, path->slots[0]); csum_end = key.offset + (size / csum_size) * root->sectorsize; + if (csum_end <= start) { + path->slots[0]++; + continue; + } size = min(csum_end, end + 1) - start; sums = kzalloc(btrfs_ordered_sum_size(root, size), GFP_NOFS); diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 6ac1b7f72e2a..33eee256ee81 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -374,13 +374,8 @@ insert: if (found_size > item_size) { btrfs_truncate_item(trans, root, path, item_size, 1); } else if (found_size < item_size) { - ret = btrfs_del_item(trans, root, - path); - BUG_ON(ret); - - btrfs_release_path(root, path); - ret = btrfs_insert_empty_item(trans, - root, path, key, item_size); + ret = btrfs_extend_item(trans, root, path, + item_size - found_size); BUG_ON(ret); } } else if (ret) { |