summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorZheng Yan2008-09-26 16:05:38 +0200
committerChris Mason2008-09-26 16:05:38 +0200
commit5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03 (patch)
tree9af8f539ac487c163f3207bc065767c3c8b37ae7 /fs/btrfs/extent_io.c
parentBtrfs: Add shared reference cache (diff)
downloadkernel-qcow2-linux-5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03.tar.gz
kernel-qcow2-linux-5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03.tar.xz
kernel-qcow2-linux-5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03.zip
Btrfs: extent_map and data=ordered fixes for space balancing
* Add an EXTENT_BOUNDARY state bit to keep the writepage code from merging data extents that are in the process of being relocated. This allows us to do accounting for them properly. * The balancing code relocates data extents indepdent of the underlying inode. The extent_map code was modified to properly account for things moving around (invalidating extent_map caches in the inode). * Don't take the drop_mutex in the create_subvol ioctl. It isn't required. * Fix walking of the ordered extent list to avoid races with sys_unlink * Change the lock ordering rules. Transaction start goes outside the drop_mutex. This allows btrfs_commit_transaction to directly drop the relocation trees. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index e3a25be5c663..8bd1b402f3fd 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -292,7 +292,7 @@ static int merge_state(struct extent_io_tree *tree,
struct extent_state *other;
struct rb_node *other_node;
- if (state->state & EXTENT_IOBITS)
+ if (state->state & (EXTENT_IOBITS | EXTENT_BOUNDARY))
return 0;
other_node = rb_prev(&state->rb_node);
@@ -1070,7 +1070,8 @@ search_again:
while(1) {
state = rb_entry(node, struct extent_state, rb_node);
- if (found && state->start != cur_start) {
+ if (found && (state->start != cur_start ||
+ (state->state & EXTENT_BOUNDARY))) {
goto out;
}
if (!(state->state & EXTENT_DELALLOC)) {
@@ -1078,7 +1079,7 @@ search_again:
*end = state->end;
goto out;
}
- if (!found) {
+ if (!found && !(state->state & EXTENT_BOUNDARY)) {
struct extent_state *prev_state;
struct rb_node *prev_node = node;
while(1) {
@@ -1088,7 +1089,11 @@ search_again:
prev_state = rb_entry(prev_node,
struct extent_state,
rb_node);
- if (!(prev_state->state & EXTENT_DELALLOC))
+ if ((prev_state->end + 1 != state->start) ||
+ !(prev_state->state & EXTENT_DELALLOC))
+ break;
+ if ((cur_start - prev_state->start) * 2 >
+ max_bytes)
break;
state = prev_state;
node = prev_node;