aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-09-27 17:07:30 -0400
committerChris Mason <chris.mason@fusionio.com>2012-10-09 09:15:41 -0400
commite6138876ad8327250d77291b3262fee356267211 (patch)
treeffc3fe0a05e0fd7e55b92e3ef8bad42d3c73d68c /fs/btrfs/extent_io.c
parentce1953325662fa597197ce728e4195582fc21c8d (diff)
Btrfs: cache extent state when writing out dirty metadata pages
Everytime we write out dirty pages we search for an offset in the tree, convert the bits in the state, and then when we wait we search for the offset again and clear the bits. So for every dirty range in the io tree we are doing 4 rb searches, which is suboptimal. With this patch we are only doing 2 searches for every cycle (modulo weird things happening). Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 979fa0d6bfee..e8ee39b73356 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -937,6 +937,7 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits,
937 * @end: the end offset in bytes (inclusive) 937 * @end: the end offset in bytes (inclusive)
938 * @bits: the bits to set in this range 938 * @bits: the bits to set in this range
939 * @clear_bits: the bits to clear in this range 939 * @clear_bits: the bits to clear in this range
940 * @cached_state: state that we're going to cache
940 * @mask: the allocation mask 941 * @mask: the allocation mask
941 * 942 *
942 * This will go through and set bits for the given range. If any states exist 943 * This will go through and set bits for the given range. If any states exist
@@ -946,7 +947,8 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits,
946 * boundary bits like LOCK. 947 * boundary bits like LOCK.
947 */ 948 */
948int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, 949int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
949 int bits, int clear_bits, gfp_t mask) 950 int bits, int clear_bits,
951 struct extent_state **cached_state, gfp_t mask)
950{ 952{
951 struct extent_state *state; 953 struct extent_state *state;
952 struct extent_state *prealloc = NULL; 954 struct extent_state *prealloc = NULL;
@@ -963,6 +965,15 @@ again:
963 } 965 }
964 966
965 spin_lock(&tree->lock); 967 spin_lock(&tree->lock);
968 if (cached_state && *cached_state) {
969 state = *cached_state;
970 if (state->start <= start && state->end > start &&
971 state->tree) {
972 node = &state->rb_node;
973 goto hit_next;
974 }
975 }
976
966 /* 977 /*
967 * this search will find all the extents that end after 978 * this search will find all the extents that end after
968 * our range starts. 979 * our range starts.
@@ -993,6 +1004,7 @@ hit_next:
993 */ 1004 */
994 if (state->start == start && state->end <= end) { 1005 if (state->start == start && state->end <= end) {
995 set_state_bits(tree, state, &bits); 1006 set_state_bits(tree, state, &bits);
1007 cache_state(state, cached_state);
996 state = clear_state_bit(tree, state, &clear_bits, 0); 1008 state = clear_state_bit(tree, state, &clear_bits, 0);
997 if (last_end == (u64)-1) 1009 if (last_end == (u64)-1)
998 goto out; 1010 goto out;
@@ -1033,6 +1045,7 @@ hit_next:
1033 goto out; 1045 goto out;
1034 if (state->end <= end) { 1046 if (state->end <= end) {
1035 set_state_bits(tree, state, &bits); 1047 set_state_bits(tree, state, &bits);
1048 cache_state(state, cached_state);
1036 state = clear_state_bit(tree, state, &clear_bits, 0); 1049 state = clear_state_bit(tree, state, &clear_bits, 0);
1037 if (last_end == (u64)-1) 1050 if (last_end == (u64)-1)
1038 goto out; 1051 goto out;
@@ -1071,6 +1084,7 @@ hit_next:
1071 &bits); 1084 &bits);
1072 if (err) 1085 if (err)
1073 extent_io_tree_panic(tree, err); 1086 extent_io_tree_panic(tree, err);
1087 cache_state(prealloc, cached_state);
1074 prealloc = NULL; 1088 prealloc = NULL;
1075 start = this_end + 1; 1089 start = this_end + 1;
1076 goto search_again; 1090 goto search_again;
@@ -1093,6 +1107,7 @@ hit_next:
1093 extent_io_tree_panic(tree, err); 1107 extent_io_tree_panic(tree, err);
1094 1108
1095 set_state_bits(tree, prealloc, &bits); 1109 set_state_bits(tree, prealloc, &bits);
1110 cache_state(prealloc, cached_state);
1096 clear_state_bit(tree, prealloc, &clear_bits, 0); 1111 clear_state_bit(tree, prealloc, &clear_bits, 0);
1097 prealloc = NULL; 1112 prealloc = NULL;
1098 goto out; 1113 goto out;
@@ -1297,18 +1312,42 @@ out:
1297 * If nothing was found, 1 is returned. If found something, return 0. 1312 * If nothing was found, 1 is returned. If found something, return 0.
1298 */ 1313 */
1299int find_first_extent_bit(struct extent_io_tree *tree, u64 start, 1314int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
1300 u64 *start_ret, u64 *end_ret, int bits) 1315 u64 *start_ret, u64 *end_ret, int bits,
1316 struct extent_state **cached_state)
1301{ 1317{
1302 struct extent_state *state; 1318 struct extent_state *state;
1319 struct rb_node *n;
1303 int ret = 1; 1320 int ret = 1;
1304 1321
1305 spin_lock(&tree->lock); 1322 spin_lock(&tree->lock);
1323 if (cached_state && *cached_state) {
1324 state = *cached_state;
1325 if (state->end == start - 1 && state->tree) {
1326 n = rb_next(&state->rb_node);
1327 while (n) {
1328 state = rb_entry(n, struct extent_state,
1329 rb_node);
1330 if (state->state & bits)
1331 goto got_it;
1332 n = rb_next(n);
1333 }
1334 free_extent_state(*cached_state);
1335 *cached_state = NULL;
1336 goto out;
1337 }
1338 free_extent_state(*cached_state);
1339 *cached_state = NULL;
1340 }
1341
1306 state = find_first_extent_bit_state(tree, start, bits); 1342 state = find_first_extent_bit_state(tree, start, bits);
1343got_it:
1307 if (state) { 1344 if (state) {
1345 cache_state(state, cached_state);
1308 *start_ret = state->start; 1346 *start_ret = state->start;
1309 *end_ret = state->end; 1347 *end_ret = state->end;
1310 ret = 0; 1348 ret = 0;
1311 } 1349 }
1350out:
1312 spin_unlock(&tree->lock); 1351 spin_unlock(&tree->lock);
1313 return ret; 1352 return ret;
1314} 1353}