diff options
author | Zheng Yan <zheng.yan@oracle.com> | 2008-09-26 10:05:38 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-26 10:05:38 -0400 |
commit | 5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03 (patch) | |
tree | 9af8f539ac487c163f3207bc065767c3c8b37ae7 /fs/btrfs/extent_io.c | |
parent | e465768938f95388723b0fd3c50a0ae48173edb9 (diff) |
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.c | 13 |
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, | |||
292 | struct extent_state *other; | 292 | struct extent_state *other; |
293 | struct rb_node *other_node; | 293 | struct rb_node *other_node; |
294 | 294 | ||
295 | if (state->state & EXTENT_IOBITS) | 295 | if (state->state & (EXTENT_IOBITS | EXTENT_BOUNDARY)) |
296 | return 0; | 296 | return 0; |
297 | 297 | ||
298 | other_node = rb_prev(&state->rb_node); | 298 | other_node = rb_prev(&state->rb_node); |
@@ -1070,7 +1070,8 @@ search_again: | |||
1070 | 1070 | ||
1071 | while(1) { | 1071 | while(1) { |
1072 | state = rb_entry(node, struct extent_state, rb_node); | 1072 | state = rb_entry(node, struct extent_state, rb_node); |
1073 | if (found && state->start != cur_start) { | 1073 | if (found && (state->start != cur_start || |
1074 | (state->state & EXTENT_BOUNDARY))) { | ||
1074 | goto out; | 1075 | goto out; |
1075 | } | 1076 | } |
1076 | if (!(state->state & EXTENT_DELALLOC)) { | 1077 | if (!(state->state & EXTENT_DELALLOC)) { |
@@ -1078,7 +1079,7 @@ search_again: | |||
1078 | *end = state->end; | 1079 | *end = state->end; |
1079 | goto out; | 1080 | goto out; |
1080 | } | 1081 | } |
1081 | if (!found) { | 1082 | if (!found && !(state->state & EXTENT_BOUNDARY)) { |
1082 | struct extent_state *prev_state; | 1083 | struct extent_state *prev_state; |
1083 | struct rb_node *prev_node = node; | 1084 | struct rb_node *prev_node = node; |
1084 | while(1) { | 1085 | while(1) { |
@@ -1088,7 +1089,11 @@ search_again: | |||
1088 | prev_state = rb_entry(prev_node, | 1089 | prev_state = rb_entry(prev_node, |
1089 | struct extent_state, | 1090 | struct extent_state, |
1090 | rb_node); | 1091 | rb_node); |
1091 | if (!(prev_state->state & EXTENT_DELALLOC)) | 1092 | if ((prev_state->end + 1 != state->start) || |
1093 | !(prev_state->state & EXTENT_DELALLOC)) | ||
1094 | break; | ||
1095 | if ((cur_start - prev_state->start) * 2 > | ||
1096 | max_bytes) | ||
1092 | break; | 1097 | break; |
1093 | state = prev_state; | 1098 | state = prev_state; |
1094 | node = prev_node; | 1099 | node = prev_node; |