History

Merge branch 'for-chris' of git://git.jan-o-sch.net/btrfs-unstable into for-linus

Chris Mason committed 14 years ago

Commit acbcabd2 parents 69e380d 3310c363 files · +70 −35Browse files

Unified · Split

3 files
  1. fs/btrfs/backref.c +5 −12
  2. fs/btrfs/ctree.c +63 −23
  3. fs/btrfs/ctree.h +2 −0
fs/btrfs/backref.c+5−12
@@ -179,7 +179,8 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id, · 178 unmodified lines
179 179
180static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,180static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
181 struct ulist *parents, int level,181 struct ulist *parents, int level,
182 struct btrfs_key *key, u64 wanted_disk_byte,182 struct btrfs_key *key, u64 time_seq,
183 u64 wanted_disk_byte,
183 const u64 *extent_item_pos)184 const u64 *extent_item_pos)
184{185{
185 int ret;186 int ret;
@@ -212,7 +213,7 @@ add_parent: · 26 unmodified lines
212 */213 */
213 while (1) {214 while (1) {
214 eie = NULL;215 eie = NULL;
215 ret = btrfs_next_leaf(root, path);216 ret = btrfs_next_old_leaf(root, path, time_seq);
216 if (ret < 0)217 if (ret < 0)
217 return ret;218 return ret;
218 if (ret)219 if (ret)
@@ -294,18 +295,10 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, · 75 unmodified lines
294 goto out;295 goto out;
295 }296 }
296 297
297 if (level == 0) {298 if (level == 0)
298 if (ret == 1 && path->slots[0] >= btrfs_header_nritems(eb)) {
299 ret = btrfs_next_leaf(root, path);
300 if (ret)
301 goto out;
302 eb = path->nodes[0];
303 }
304
305 btrfs_item_key_to_cpu(eb, &key, path->slots[0]);299 btrfs_item_key_to_cpu(eb, &key, path->slots[0]);
306 }
307 300
308 ret = add_all_parents(root, path, parents, level, &key,301 ret = add_all_parents(root, path, parents, level, &key, time_seq,
309 ref->wanted_disk_byte, extent_item_pos);302 ref->wanted_disk_byte, extent_item_pos);
310out:303out:
311 btrfs_free_path(path);304 btrfs_free_path(path);
fs/btrfs/ctree.c+63−23
@@ -467,6 +467,15 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, · 466 unmodified lines
467 return 0;467 return 0;
468}468}
469 469
470/*
471 * This allocates memory and gets a tree modification sequence number when
472 * needed.
473 *
474 * Returns 0 when no sequence number is needed, < 0 on error.
475 * Returns 1 when a sequence number was added. In this case,
476 * fs_info->tree_mod_seq_lock was acquired and must be released by the caller
477 * after inserting into the rb tree.
478 */
470static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,479static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,
471 struct tree_mod_elem **tm_ret)480 struct tree_mod_elem **tm_ret)
472{481{
@@ -491,11 +500,11 @@ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, · 18 unmodified lines
491 */500 */
492 kfree(tm);501 kfree(tm);
493 seq = 0;502 seq = 0;
503 spin_unlock(&fs_info->tree_mod_seq_lock);
494 } else {504 } else {
495 __get_tree_mod_seq(fs_info, &tm->elem);505 __get_tree_mod_seq(fs_info, &tm->elem);
496 seq = tm->elem.seq;506 seq = tm->elem.seq;
497 }507 }
498 spin_unlock(&fs_info->tree_mod_seq_lock);
499 508
500 return seq;509 return seq;
501}510}
@@ -521,7 +530,9 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, · 19 unmodified lines
521 tm->slot = slot;530 tm->slot = slot;
522 tm->generation = btrfs_node_ptr_generation(eb, slot);531 tm->generation = btrfs_node_ptr_generation(eb, slot);
523 532
524 return __tree_mod_log_insert(fs_info, tm);533 ret = __tree_mod_log_insert(fs_info, tm);
534 spin_unlock(&fs_info->tree_mod_seq_lock);
535 return ret;
525}536}
526 537
527static noinline int538static noinline int
@@ -559,7 +570,9 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, · 31 unmodified lines
559 tm->move.nr_items = nr_items;570 tm->move.nr_items = nr_items;
560 tm->op = MOD_LOG_MOVE_KEYS;571 tm->op = MOD_LOG_MOVE_KEYS;
561 572
562 return __tree_mod_log_insert(fs_info, tm);573 ret = __tree_mod_log_insert(fs_info, tm);
574 spin_unlock(&fs_info->tree_mod_seq_lock);
575 return ret;
563}576}
564 577
565static noinline int578static noinline int
@@ -580,7 +593,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, · 14 unmodified lines
580 tm->generation = btrfs_header_generation(old_root);593 tm->generation = btrfs_header_generation(old_root);
581 tm->op = MOD_LOG_ROOT_REPLACE;594 tm->op = MOD_LOG_ROOT_REPLACE;
582 595
583 return __tree_mod_log_insert(fs_info, tm);596 ret = __tree_mod_log_insert(fs_info, tm);
597 spin_unlock(&fs_info->tree_mod_seq_lock);
598 return ret;
584}599}
585 600
586static struct tree_mod_elem *601static struct tree_mod_elem *
@@ -1023,6 +1038,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, · 436 unmodified lines
1023 looped = 1;1038 looped = 1;
1024 }1039 }
1025 1040
1041 /* if there's no old root to return, return what we found instead */
1042 if (!found)
1043 found = tm;
1044
1026 return found;1045 return found;
1027}1046}
1028 1047
@@ -1143,22 +1162,36 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, · 114 unmodified lines
1143 return eb_rewin;1162 return eb_rewin;
1144}1163}
1145 1164
1165/*
1166 * get_old_root() rewinds the state of @root's root node to the given @time_seq
1167 * value. If there are no changes, the current root->root_node is returned. If
1168 * anything changed in between, there's a fresh buffer allocated on which the
1169 * rewind operations are done. In any case, the returned buffer is read locked.
1170 * Returns NULL on error (with no locks held).
1171 */
1146static inline struct extent_buffer *1172static inline struct extent_buffer *
1147get_old_root(struct btrfs_root *root, u64 time_seq)1173get_old_root(struct btrfs_root *root, u64 time_seq)
1148{1174{
1149 struct tree_mod_elem *tm;1175 struct tree_mod_elem *tm;
1150 struct extent_buffer *eb;1176 struct extent_buffer *eb;
1151 struct tree_mod_root *old_root;1177 struct tree_mod_root *old_root = NULL;
1152 u64 old_generation;1178 u64 old_generation;
1179 u64 logical;
1153 1180
1181 eb = btrfs_read_lock_root_node(root);
1154 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);1182 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
1155 if (!tm)1183 if (!tm)
1156 return root->node;1184 return root->node;
1157 1185
1158 old_root = &tm->old_root;1186 if (tm->op == MOD_LOG_ROOT_REPLACE) {
1159 old_generation = tm->generation;1187 old_root = &tm->old_root;
1188 old_generation = tm->generation;
1189 logical = old_root->logical;
1190 } else {
1191 logical = root->node->start;
1192 }
1160 1193
1161 tm = tree_mod_log_search(root->fs_info, old_root->logical, time_seq);1194 tm = tree_mod_log_search(root->fs_info, logical, time_seq);
1162 /*1195 /*
1163 * there was an item in the log when __tree_mod_log_oldest_root1196 * there was an item in the log when __tree_mod_log_oldest_root
1164 * returned. this one must not go away, because the time_seq passed to1197 * returned. this one must not go away, because the time_seq passed to
@@ -1166,22 +1199,25 @@ get_old_root(struct btrfs_root *root, u64 time_seq) · 1 unmodified line
1166 */1199 */
1167 BUG_ON(!tm);1200 BUG_ON(!tm);
1168 1201
1169 if (old_root->logical == root->node->start) {1202 if (old_root)
1170 /* there are logged operations for the current root */
1171 eb = btrfs_clone_extent_buffer(root->node);
1172 } else {
1173 /* there's a root replace operation for the current root */
1174 eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT,1203 eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT,
1175 root->nodesize);1204 root->nodesize);
1205 else
1206 eb = btrfs_clone_extent_buffer(root->node);
1207 btrfs_tree_read_unlock(root->node);
1208 free_extent_buffer(root->node);
1209 if (!eb)
1210 return NULL;
1211 btrfs_tree_read_lock(eb);
1212 if (old_root) {
1176 btrfs_set_header_bytenr(eb, eb->start);1213 btrfs_set_header_bytenr(eb, eb->start);
1177 btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV);1214 btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV);
1178 btrfs_set_header_owner(eb, root->root_key.objectid);1215 btrfs_set_header_owner(eb, root->root_key.objectid);
1216 btrfs_set_header_level(eb, old_root->level);
1217 btrfs_set_header_generation(eb, old_generation);
1179 }1218 }
1180 if (!eb)
1181 return NULL;
1182 btrfs_set_header_level(eb, old_root->level);
1183 btrfs_set_header_generation(eb, old_generation);
1184 __tree_mod_log_rewind(eb, time_seq, tm);1219 __tree_mod_log_rewind(eb, time_seq, tm);
1220 extent_buffer_get(eb);
1185 1221
1186 return eb;1222 return eb;
1187}1223}
@@ -1650,8 +1686,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, · 462 unmodified lines
1650 BTRFS_NODEPTRS_PER_BLOCK(root) / 4)1686 BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
1651 return 0;1687 return 0;
1652 1688
1653 btrfs_header_nritems(mid);
1654
1655 left = read_node_slot(root, parent, pslot - 1);1689 left = read_node_slot(root, parent, pslot - 1);
1656 if (left) {1690 if (left) {
1657 btrfs_tree_lock(left);1691 btrfs_tree_lock(left);
@@ -1681,7 +1715,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, · 23 unmodified lines
1681 wret = push_node_left(trans, root, left, mid, 1);1715 wret = push_node_left(trans, root, left, mid, 1);
1682 if (wret < 0)1716 if (wret < 0)
1683 ret = wret;1717 ret = wret;
1684 btrfs_header_nritems(mid);
1685 }1718 }
1686 1719
1687 /*1720 /*
@@ -2615,9 +2648,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, · 927 unmodified lines
2615 2648
2616again:2649again:
2617 b = get_old_root(root, time_seq);2650 b = get_old_root(root, time_seq);
2618 extent_buffer_get(b);
2619 level = btrfs_header_level(b);2651 level = btrfs_header_level(b);
2620 btrfs_tree_read_lock(b);
2621 p->locks[level] = BTRFS_READ_LOCK;2652 p->locks[level] = BTRFS_READ_LOCK;
2622 2653
2623 while (b) {2654 while (b) {
@@ -5000,6 +5031,12 @@ next: · 2376 unmodified lines
5000 * returns < 0 on io errors.5031 * returns < 0 on io errors.
5001 */5032 */
5002int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)5033int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
5034{
5035 return btrfs_next_old_leaf(root, path, 0);
5036}
5037
5038int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
5039 u64 time_seq)
5003{5040{
5004 int slot;5041 int slot;
5005 int level;5042 int level;
@@ -5025,7 +5062,10 @@ again: · 19 unmodified lines
5025 path->keep_locks = 1;5062 path->keep_locks = 1;
5026 path->leave_spinning = 1;5063 path->leave_spinning = 1;
5027 5064
5028 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);5065 if (time_seq)
5066 ret = btrfs_search_old_slot(root, &key, path, time_seq);
5067 else
5068 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
5029 path->keep_locks = 0;5069 path->keep_locks = 0;
5030 5070
5031 if (ret < 0)5071 if (ret < 0)
fs/btrfs/ctree.h+2−0
@@ -2753,6 +2753,8 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, · 2752 unmodified lines
2753}2753}
2754 2754
2755int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);2755int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
2756int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
2757 u64 time_seq);
2756static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)2758static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
2757{2759{
2758 ++p->slots[0];2760 ++p->slots[0];