aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-09-05 16:13:11 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:07 -0400
commite02119d5a7b4396c5a872582fddc8bd6d305a70a (patch)
tree825efe2a79dbca8d61256183f3526a5b5dc40dc6 /fs/btrfs/ctree.c
parenta1b32a5932cfac7c38b442582285f3da2a09dfd8 (diff)
Btrfs: Add a write ahead tree log to optimize synchronous operations
File syncs and directory syncs are optimized by copying their items into a special (copy-on-write) log tree. There is one log tree per subvolume and the btrfs super block points to a tree of log tree roots. After a crash, items are copied out of the log tree and back into the subvolume. See tree-log.c for all the details. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 7114faafa9d4..579124043d9b 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -60,7 +60,7 @@ void btrfs_free_path(struct btrfs_path *p)
60 kmem_cache_free(btrfs_path_cachep, p); 60 kmem_cache_free(btrfs_path_cachep, p);
61} 61}
62 62
63void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) 63void noinline btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
64{ 64{
65 int i; 65 int i;
66 66
@@ -176,7 +176,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
176 return 0; 176 return 0;
177} 177}
178 178
179int __btrfs_cow_block(struct btrfs_trans_handle *trans, 179int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans,
180 struct btrfs_root *root, 180 struct btrfs_root *root,
181 struct extent_buffer *buf, 181 struct extent_buffer *buf,
182 struct extent_buffer *parent, int parent_slot, 182 struct extent_buffer *parent, int parent_slot,
@@ -294,7 +294,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
294 return 0; 294 return 0;
295} 295}
296 296
297int btrfs_cow_block(struct btrfs_trans_handle *trans, 297int noinline btrfs_cow_block(struct btrfs_trans_handle *trans,
298 struct btrfs_root *root, struct extent_buffer *buf, 298 struct btrfs_root *root, struct extent_buffer *buf,
299 struct extent_buffer *parent, int parent_slot, 299 struct extent_buffer *parent, int parent_slot,
300 struct extent_buffer **cow_ret, u64 prealloc_dest) 300 struct extent_buffer **cow_ret, u64 prealloc_dest)
@@ -677,9 +677,10 @@ static int noinline check_block(struct btrfs_root *root,
677 * 677 *
678 * slot may point to max if the key is bigger than all of the keys 678 * slot may point to max if the key is bigger than all of the keys
679 */ 679 */
680static int generic_bin_search(struct extent_buffer *eb, unsigned long p, 680static noinline int generic_bin_search(struct extent_buffer *eb,
681 int item_size, struct btrfs_key *key, 681 unsigned long p,
682 int max, int *slot) 682 int item_size, struct btrfs_key *key,
683 int max, int *slot)
683{ 684{
684 int low = 0; 685 int low = 0;
685 int high = max; 686 int high = max;
@@ -765,7 +766,7 @@ static int bin_search(struct extent_buffer *eb, struct btrfs_key *key,
765 return -1; 766 return -1;
766} 767}
767 768
768static struct extent_buffer *read_node_slot(struct btrfs_root *root, 769static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
769 struct extent_buffer *parent, int slot) 770 struct extent_buffer *parent, int slot)
770{ 771{
771 int level = btrfs_header_level(parent); 772 int level = btrfs_header_level(parent);
@@ -781,7 +782,7 @@ static struct extent_buffer *read_node_slot(struct btrfs_root *root,
781 btrfs_node_ptr_generation(parent, slot)); 782 btrfs_node_ptr_generation(parent, slot));
782} 783}
783 784
784static int balance_level(struct btrfs_trans_handle *trans, 785static noinline int balance_level(struct btrfs_trans_handle *trans,
785 struct btrfs_root *root, 786 struct btrfs_root *root,
786 struct btrfs_path *path, int level) 787 struct btrfs_path *path, int level)
787{ 788{
@@ -1128,8 +1129,9 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans,
1128/* 1129/*
1129 * readahead one full node of leaves 1130 * readahead one full node of leaves
1130 */ 1131 */
1131static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, 1132static noinline void reada_for_search(struct btrfs_root *root,
1132 int level, int slot, u64 objectid) 1133 struct btrfs_path *path,
1134 int level, int slot, u64 objectid)
1133{ 1135{
1134 struct extent_buffer *node; 1136 struct extent_buffer *node;
1135 struct btrfs_disk_key disk_key; 1137 struct btrfs_disk_key disk_key;
@@ -1201,7 +1203,8 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
1201 } 1203 }
1202} 1204}
1203 1205
1204static void unlock_up(struct btrfs_path *path, int level, int lowest_unlock) 1206static noinline void unlock_up(struct btrfs_path *path, int level,
1207 int lowest_unlock)
1205{ 1208{
1206 int i; 1209 int i;
1207 int skip_level = level; 1210 int skip_level = level;
@@ -1759,8 +1762,9 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
1759 * 1762 *
1760 * returns 0 on success and < 0 on failure 1763 * returns 0 on success and < 0 on failure
1761 */ 1764 */
1762static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root 1765static noinline int split_node(struct btrfs_trans_handle *trans,
1763 *root, struct btrfs_path *path, int level) 1766 struct btrfs_root *root,
1767 struct btrfs_path *path, int level)
1764{ 1768{
1765 u64 root_gen; 1769 u64 root_gen;
1766 struct extent_buffer *c; 1770 struct extent_buffer *c;
@@ -1874,7 +1878,8 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr)
1874 * the start of the leaf data. IOW, how much room 1878 * the start of the leaf data. IOW, how much room
1875 * the leaf has left for both items and data 1879 * the leaf has left for both items and data
1876 */ 1880 */
1877int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf) 1881int noinline btrfs_leaf_free_space(struct btrfs_root *root,
1882 struct extent_buffer *leaf)
1878{ 1883{
1879 int nritems = btrfs_header_nritems(leaf); 1884 int nritems = btrfs_header_nritems(leaf);
1880 int ret; 1885 int ret;
@@ -2283,9 +2288,11 @@ out:
2283 * 2288 *
2284 * returns 0 if all went well and < 0 on failure. 2289 * returns 0 if all went well and < 0 on failure.
2285 */ 2290 */
2286static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root 2291static noinline int split_leaf(struct btrfs_trans_handle *trans,
2287 *root, struct btrfs_key *ins_key, 2292 struct btrfs_root *root,
2288 struct btrfs_path *path, int data_size, int extend) 2293 struct btrfs_key *ins_key,
2294 struct btrfs_path *path, int data_size,
2295 int extend)
2289{ 2296{
2290 u64 root_gen; 2297 u64 root_gen;
2291 struct extent_buffer *l; 2298 struct extent_buffer *l;
@@ -3079,6 +3086,7 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
3079 * was nothing in the tree that matched the search criteria. 3086 * was nothing in the tree that matched the search criteria.
3080 */ 3087 */
3081int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, 3088int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
3089 struct btrfs_key *max_key,
3082 struct btrfs_path *path, int cache_only, 3090 struct btrfs_path *path, int cache_only,
3083 u64 min_trans) 3091 u64 min_trans)
3084{ 3092{
@@ -3093,6 +3101,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
3093again: 3101again:
3094 cur = btrfs_lock_root_node(root); 3102 cur = btrfs_lock_root_node(root);
3095 level = btrfs_header_level(cur); 3103 level = btrfs_header_level(cur);
3104 WARN_ON(path->nodes[level]);
3096 path->nodes[level] = cur; 3105 path->nodes[level] = cur;
3097 path->locks[level] = 1; 3106 path->locks[level] = 1;
3098 3107
@@ -3107,6 +3116,8 @@ again:
3107 3116
3108 /* at level = 0, we're done, setup the path and exit */ 3117 /* at level = 0, we're done, setup the path and exit */
3109 if (level == 0) { 3118 if (level == 0) {
3119 if (slot >= nritems)
3120 goto find_next_key;
3110 ret = 0; 3121 ret = 0;
3111 path->slots[level] = slot; 3122 path->slots[level] = slot;
3112 btrfs_item_key_to_cpu(cur, &found_key, slot); 3123 btrfs_item_key_to_cpu(cur, &found_key, slot);
@@ -3123,6 +3134,8 @@ again:
3123 u64 blockptr; 3134 u64 blockptr;
3124 u64 gen; 3135 u64 gen;
3125 struct extent_buffer *tmp; 3136 struct extent_buffer *tmp;
3137 struct btrfs_disk_key disk_key;
3138
3126 blockptr = btrfs_node_blockptr(cur, slot); 3139 blockptr = btrfs_node_blockptr(cur, slot);
3127 gen = btrfs_node_ptr_generation(cur, slot); 3140 gen = btrfs_node_ptr_generation(cur, slot);
3128 if (gen < min_trans) { 3141 if (gen < min_trans) {
@@ -3132,6 +3145,14 @@ again:
3132 if (!cache_only) 3145 if (!cache_only)
3133 break; 3146 break;
3134 3147
3148 if (max_key) {
3149 btrfs_node_key(cur, &disk_key, slot);
3150 if (comp_keys(&disk_key, max_key) >= 0) {
3151 ret = 1;
3152 goto out;
3153 }
3154 }
3155
3135 tmp = btrfs_find_tree_block(root, blockptr, 3156 tmp = btrfs_find_tree_block(root, blockptr,
3136 btrfs_level_size(root, level - 1)); 3157 btrfs_level_size(root, level - 1));
3137 3158
@@ -3143,14 +3164,16 @@ again:
3143 free_extent_buffer(tmp); 3164 free_extent_buffer(tmp);
3144 slot++; 3165 slot++;
3145 } 3166 }
3167find_next_key:
3146 /* 3168 /*
3147 * we didn't find a candidate key in this node, walk forward 3169 * we didn't find a candidate key in this node, walk forward
3148 * and find another one 3170 * and find another one
3149 */ 3171 */
3150 if (slot >= nritems) { 3172 if (slot >= nritems) {
3151 ret = btrfs_find_next_key(root, path, min_key, level, 3173 path->slots[level] = slot;
3174 sret = btrfs_find_next_key(root, path, min_key, level,
3152 cache_only, min_trans); 3175 cache_only, min_trans);
3153 if (ret == 0) { 3176 if (sret == 0) {
3154 btrfs_release_path(root, path); 3177 btrfs_release_path(root, path);
3155 goto again; 3178 goto again;
3156 } else { 3179 } else {
@@ -3351,6 +3374,7 @@ int btrfs_previous_item(struct btrfs_root *root,
3351{ 3374{
3352 struct btrfs_key found_key; 3375 struct btrfs_key found_key;
3353 struct extent_buffer *leaf; 3376 struct extent_buffer *leaf;
3377 u32 nritems;
3354 int ret; 3378 int ret;
3355 3379
3356 while(1) { 3380 while(1) {
@@ -3362,9 +3386,20 @@ int btrfs_previous_item(struct btrfs_root *root,
3362 path->slots[0]--; 3386 path->slots[0]--;
3363 } 3387 }
3364 leaf = path->nodes[0]; 3388 leaf = path->nodes[0];
3389 nritems = btrfs_header_nritems(leaf);
3390 if (nritems == 0)
3391 return 1;
3392 if (path->slots[0] == nritems)
3393 path->slots[0]--;
3394
3365 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 3395 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
3366 if (found_key.type == type) 3396 if (found_key.type == type)
3367 return 0; 3397 return 0;
3398 if (found_key.objectid < min_objectid)
3399 break;
3400 if (found_key.objectid == min_objectid &&
3401 found_key.type < type)
3402 break;
3368 } 3403 }
3369 return 1; 3404 return 1;
3370} 3405}