Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 297891
b: refs/heads/master
c: 1d4284b
h: refs/heads/master
i:
  297889: a7aa540
  297887: fa6a72d
v: v3
  • Loading branch information
Chris Mason committed Mar 29, 2012
1 parent a74263d commit dc682d5
Show file tree
Hide file tree
Showing 13 changed files with 2,015 additions and 961 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 65139ed99234d8505948cdb7a835452eb5c191f9
refs/heads/master: 1d4284bd6e8d7dd1d5521a6747bdb6dc1caf0225
134 changes: 97 additions & 37 deletions trunk/fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,23 @@ struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
{
struct extent_buffer *eb;

rcu_read_lock();
eb = rcu_dereference(root->node);
extent_buffer_get(eb);
rcu_read_unlock();
while (1) {
rcu_read_lock();
eb = rcu_dereference(root->node);

/*
* RCU really hurts here, we could free up the root node because
* it was cow'ed but we may not get the new root node yet so do
* the inc_not_zero dance and if it doesn't work then
* synchronize_rcu and try again.
*/
if (atomic_inc_not_zero(&eb->refs)) {
rcu_read_unlock();
break;
}
rcu_read_unlock();
synchronize_rcu();
}
return eb;
}

Expand Down Expand Up @@ -514,7 +527,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
}
if (unlock_orig)
btrfs_tree_unlock(buf);
free_extent_buffer(buf);
free_extent_buffer_stale(buf);
btrfs_mark_buffer_dirty(cow);
*cow_ret = cow;
return 0;
Expand Down Expand Up @@ -974,7 +987,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
root_sub_used(root, mid->len);
btrfs_free_tree_block(trans, root, mid, 0, 1, 0);
/* once for the root ptr */
free_extent_buffer(mid);
free_extent_buffer_stale(mid);
return 0;
}
if (btrfs_header_nritems(mid) >
Expand Down Expand Up @@ -1028,7 +1041,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
del_ptr(trans, root, path, level + 1, pslot + 1);
root_sub_used(root, right->len);
btrfs_free_tree_block(trans, root, right, 0, 1, 0);
free_extent_buffer(right);
free_extent_buffer_stale(right);
right = NULL;
} else {
struct btrfs_disk_key right_key;
Expand Down Expand Up @@ -1070,7 +1083,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
del_ptr(trans, root, path, level + 1, pslot);
root_sub_used(root, mid->len);
btrfs_free_tree_block(trans, root, mid, 0, 1, 0);
free_extent_buffer(mid);
free_extent_buffer_stale(mid);
mid = NULL;
} else {
/* update the parent key to reflect our changes */
Expand Down Expand Up @@ -1396,7 +1409,8 @@ static noinline int reada_for_balance(struct btrfs_root *root,
* if lowest_unlock is 1, level 0 won't be unlocked
*/
static noinline void unlock_up(struct btrfs_path *path, int level,
int lowest_unlock)
int lowest_unlock, int min_write_lock_level,
int *write_lock_level)
{
int i;
int skip_level = level;
Expand Down Expand Up @@ -1428,6 +1442,11 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
btrfs_tree_unlock_rw(t, path->locks[i]);
path->locks[i] = 0;
if (write_lock_level &&
i > min_write_lock_level &&
i <= *write_lock_level) {
*write_lock_level = i - 1;
}
}
}
}
Expand Down Expand Up @@ -1651,6 +1670,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
/* everything at write_lock_level or lower must be write locked */
int write_lock_level = 0;
u8 lowest_level = 0;
int min_write_lock_level;

lowest_level = p->lowest_level;
WARN_ON(lowest_level && ins_len > 0);
Expand Down Expand Up @@ -1678,6 +1698,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if (cow && (p->keep_locks || p->lowest_level))
write_lock_level = BTRFS_MAX_LEVEL;

min_write_lock_level = write_lock_level;

again:
/*
* we try very hard to do read locks on the root
Expand Down Expand Up @@ -1809,7 +1831,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
goto again;
}

unlock_up(p, level, lowest_unlock);
unlock_up(p, level, lowest_unlock,
min_write_lock_level, &write_lock_level);

if (level == lowest_level) {
if (dec)
Expand Down Expand Up @@ -1871,7 +1894,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
}
}
if (!p->search_for_split)
unlock_up(p, level, lowest_unlock);
unlock_up(p, level, lowest_unlock,
min_write_lock_level, &write_lock_level);
goto done;
}
}
Expand Down Expand Up @@ -2320,6 +2344,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
{
struct extent_buffer *left = path->nodes[0];
struct extent_buffer *upper = path->nodes[1];
struct btrfs_map_token token;
struct btrfs_disk_key disk_key;
int slot;
u32 i;
Expand All @@ -2331,6 +2356,8 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
u32 data_end;
u32 this_item_size;

btrfs_init_map_token(&token);

if (empty)
nr = 0;
else
Expand Down Expand Up @@ -2408,8 +2435,8 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
push_space = BTRFS_LEAF_DATA_SIZE(root);
for (i = 0; i < right_nritems; i++) {
item = btrfs_item_nr(right, i);
push_space -= btrfs_item_size(right, item);
btrfs_set_item_offset(right, item, push_space);
push_space -= btrfs_token_item_size(right, item, &token);
btrfs_set_token_item_offset(right, item, push_space, &token);
}

left_nritems -= push_items;
Expand Down Expand Up @@ -2539,6 +2566,9 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
int ret = 0;
u32 this_item_size;
u32 old_left_item_size;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

if (empty)
nr = min(right_nritems, max_slot);
Expand Down Expand Up @@ -2599,9 +2629,10 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,

item = btrfs_item_nr(left, i);

ioff = btrfs_item_offset(left, item);
btrfs_set_item_offset(left, item,
ioff - (BTRFS_LEAF_DATA_SIZE(root) - old_left_item_size));
ioff = btrfs_token_item_offset(left, item, &token);
btrfs_set_token_item_offset(left, item,
ioff - (BTRFS_LEAF_DATA_SIZE(root) - old_left_item_size),
&token);
}
btrfs_set_header_nritems(left, old_left_nritems + push_items);

Expand Down Expand Up @@ -2631,8 +2662,9 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
for (i = 0; i < right_nritems; i++) {
item = btrfs_item_nr(right, i);

push_space = push_space - btrfs_item_size(right, item);
btrfs_set_item_offset(right, item, push_space);
push_space = push_space - btrfs_token_item_size(right,
item, &token);
btrfs_set_token_item_offset(right, item, push_space, &token);
}

btrfs_mark_buffer_dirty(left);
Expand Down Expand Up @@ -2748,6 +2780,9 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
int rt_data_off;
int i;
struct btrfs_disk_key disk_key;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

nritems = nritems - mid;
btrfs_set_header_nritems(right, nritems);
Expand All @@ -2769,8 +2804,9 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
struct btrfs_item *item = btrfs_item_nr(right, i);
u32 ioff;

ioff = btrfs_item_offset(right, item);
btrfs_set_item_offset(right, item, ioff + rt_data_off);
ioff = btrfs_token_item_offset(right, item, &token);
btrfs_set_token_item_offset(right, item,
ioff + rt_data_off, &token);
}

btrfs_set_header_nritems(l, mid);
Expand Down Expand Up @@ -3246,6 +3282,9 @@ void btrfs_truncate_item(struct btrfs_trans_handle *trans,
unsigned int old_size;
unsigned int size_diff;
int i;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

leaf = path->nodes[0];
slot = path->slots[0];
Expand All @@ -3272,8 +3311,9 @@ void btrfs_truncate_item(struct btrfs_trans_handle *trans,
u32 ioff;
item = btrfs_item_nr(leaf, i);

ioff = btrfs_item_offset(leaf, item);
btrfs_set_item_offset(leaf, item, ioff + size_diff);
ioff = btrfs_token_item_offset(leaf, item, &token);
btrfs_set_token_item_offset(leaf, item,
ioff + size_diff, &token);
}

/* shift the data */
Expand Down Expand Up @@ -3342,6 +3382,9 @@ void btrfs_extend_item(struct btrfs_trans_handle *trans,
unsigned int old_data;
unsigned int old_size;
int i;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

leaf = path->nodes[0];

Expand Down Expand Up @@ -3371,8 +3414,9 @@ void btrfs_extend_item(struct btrfs_trans_handle *trans,
u32 ioff;
item = btrfs_item_nr(leaf, i);

ioff = btrfs_item_offset(leaf, item);
btrfs_set_item_offset(leaf, item, ioff - data_size);
ioff = btrfs_token_item_offset(leaf, item, &token);
btrfs_set_token_item_offset(leaf, item,
ioff - data_size, &token);
}

/* shift the data */
Expand Down Expand Up @@ -3414,6 +3458,9 @@ int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
unsigned int data_end;
struct btrfs_disk_key disk_key;
struct btrfs_key found_key;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

for (i = 0; i < nr; i++) {
if (total_size + data_size[i] + sizeof(struct btrfs_item) >
Expand Down Expand Up @@ -3479,8 +3526,9 @@ int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
u32 ioff;

item = btrfs_item_nr(leaf, i);
ioff = btrfs_item_offset(leaf, item);
btrfs_set_item_offset(leaf, item, ioff - total_data);
ioff = btrfs_token_item_offset(leaf, item, &token);
btrfs_set_token_item_offset(leaf, item,
ioff - total_data, &token);
}
/* shift the items */
memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
Expand All @@ -3507,9 +3555,10 @@ int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
btrfs_set_item_key(leaf, &disk_key, slot + i);
item = btrfs_item_nr(leaf, slot + i);
btrfs_set_item_offset(leaf, item, data_end - data_size[i]);
btrfs_set_token_item_offset(leaf, item,
data_end - data_size[i], &token);
data_end -= data_size[i];
btrfs_set_item_size(leaf, item, data_size[i]);
btrfs_set_token_item_size(leaf, item, data_size[i], &token);
}
btrfs_set_header_nritems(leaf, nritems + nr);
btrfs_mark_buffer_dirty(leaf);
Expand Down Expand Up @@ -3547,6 +3596,9 @@ void setup_items_for_insert(struct btrfs_trans_handle *trans,
struct btrfs_disk_key disk_key;
struct extent_buffer *leaf;
int slot;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

leaf = path->nodes[0];
slot = path->slots[0];
Expand Down Expand Up @@ -3578,8 +3630,9 @@ void setup_items_for_insert(struct btrfs_trans_handle *trans,
u32 ioff;

item = btrfs_item_nr(leaf, i);
ioff = btrfs_item_offset(leaf, item);
btrfs_set_item_offset(leaf, item, ioff - total_data);
ioff = btrfs_token_item_offset(leaf, item, &token);
btrfs_set_token_item_offset(leaf, item,
ioff - total_data, &token);
}
/* shift the items */
memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
Expand All @@ -3598,9 +3651,10 @@ void setup_items_for_insert(struct btrfs_trans_handle *trans,
btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
btrfs_set_item_key(leaf, &disk_key, slot + i);
item = btrfs_item_nr(leaf, slot + i);
btrfs_set_item_offset(leaf, item, data_end - data_size[i]);
btrfs_set_token_item_offset(leaf, item,
data_end - data_size[i], &token);
data_end -= data_size[i];
btrfs_set_item_size(leaf, item, data_size[i]);
btrfs_set_token_item_size(leaf, item, data_size[i], &token);
}

btrfs_set_header_nritems(leaf, nritems + nr);
Expand Down Expand Up @@ -3740,7 +3794,9 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans,

root_sub_used(root, leaf->len);

extent_buffer_get(leaf);
btrfs_free_tree_block(trans, root, leaf, 0, 1, 0);
free_extent_buffer_stale(leaf);
}
/*
* delete the item at the leaf level in path. If that empties
Expand All @@ -3757,6 +3813,9 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int wret;
int i;
u32 nritems;
struct btrfs_map_token token;

btrfs_init_map_token(&token);

leaf = path->nodes[0];
last_off = btrfs_item_offset_nr(leaf, slot + nr - 1);
Expand All @@ -3778,8 +3837,9 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
u32 ioff;

item = btrfs_item_nr(leaf, i);
ioff = btrfs_item_offset(leaf, item);
btrfs_set_item_offset(leaf, item, ioff + dsize);
ioff = btrfs_token_item_offset(leaf, item, &token);
btrfs_set_token_item_offset(leaf, item,
ioff + dsize, &token);
}

memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot),
Expand Down Expand Up @@ -4013,7 +4073,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
path->slots[level] = slot;
if (level == path->lowest_level) {
ret = 0;
unlock_up(path, level, 1);
unlock_up(path, level, 1, 0, NULL);
goto out;
}
btrfs_set_path_blocking(path);
Expand All @@ -4024,7 +4084,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,

path->locks[level - 1] = BTRFS_READ_LOCK;
path->nodes[level - 1] = cur;
unlock_up(path, level, 1);
unlock_up(path, level, 1, 0, NULL);
btrfs_clear_path_blocking(path, NULL, 0);
}
out:
Expand Down Expand Up @@ -4260,7 +4320,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
}
ret = 0;
done:
unlock_up(path, 0, 1);
unlock_up(path, 0, 1, 0, NULL);
path->leave_spinning = old_spinning;
if (!old_spinning)
btrfs_set_path_blocking(path);
Expand Down
Loading

0 comments on commit dc682d5

Please sign in to comment.