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
179179
180180 static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
181181 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,
183184 const u64 *extent_item_pos)
184185 {
185186 int ret;
@@ -212,7 +213,7 @@ add_parent: · 26 unmodified lines
212213 */
213214 while (1) {
214215 eie = NULL;
215− ret = btrfs_next_leaf(root, path);
216+ ret = btrfs_next_old_leaf(root, path, time_seq);
216217 if (ret < 0)
217218 return ret;
218219 if (ret)
@@ -294,18 +295,10 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, · 75 unmodified lines
294295 goto out;
295296 }
296297
297− 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−
298+ if (level == 0)
305299 btrfs_item_key_to_cpu(eb, &key, path->slots[0]);
306− }
307300
308− ret = add_all_parents(root, path, parents, level, &key,
301+ ret = add_all_parents(root, path, parents, level, &key, time_seq,
309302 ref->wanted_disk_byte, extent_item_pos);
310303 out:
311304 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
467467 return 0;
468468 }
469469
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+ */
470479 static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags,
471480 struct tree_mod_elem **tm_ret)
472481 {
@@ -491,11 +500,11 @@ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, · 18 unmodified lines
491500 */
492501 kfree(tm);
493502 seq = 0;
503+ spin_unlock(&fs_info->tree_mod_seq_lock);
494504 } else {
495505 __get_tree_mod_seq(fs_info, &tm->elem);
496506 seq = tm->elem.seq;
497507 }
498− spin_unlock(&fs_info->tree_mod_seq_lock);
499508
500509 return seq;
501510 }
@@ -521,7 +530,9 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, · 19 unmodified lines
521530 tm->slot = slot;
522531 tm->generation = btrfs_node_ptr_generation(eb, slot);
523532
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;
525536 }
526537
527538 static noinline int
@@ -559,7 +570,9 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, · 31 unmodified lines
559570 tm->move.nr_items = nr_items;
560571 tm->op = MOD_LOG_MOVE_KEYS;
561572
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;
563576 }
564577
565578 static noinline int
@@ -580,7 +593,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, · 14 unmodified lines
580593 tm->generation = btrfs_header_generation(old_root);
581594 tm->op = MOD_LOG_ROOT_REPLACE;
582595
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;
584599 }
585600
586601 static struct tree_mod_elem *
@@ -1023,6 +1038,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, · 436 unmodified lines
10231038 looped = 1;
10241039 }
10251040
1041+ /* if there's no old root to return, return what we found instead */
1042+ if (!found)
1043+ found = tm;
1044+
10261045 return found;
10271046 }
10281047
@@ -1143,22 +1162,36 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, · 114 unmodified lines
11431162 return eb_rewin;
11441163 }
11451164
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+ */
11461172 static inline struct extent_buffer *
11471173 get_old_root(struct btrfs_root *root, u64 time_seq)
11481174 {
11491175 struct tree_mod_elem *tm;
11501176 struct extent_buffer *eb;
1151− struct tree_mod_root *old_root;
1177+ struct tree_mod_root *old_root = NULL;
11521178 u64 old_generation;
1179+ u64 logical;
11531180
1181+ eb = btrfs_read_lock_root_node(root);
11541182 tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
11551183 if (!tm)
11561184 return root->node;
11571185
1158− old_root = &tm->old_root;
1159− old_generation = tm->generation;
1186+ if (tm->op == MOD_LOG_ROOT_REPLACE) {
1187+ old_root = &tm->old_root;
1188+ old_generation = tm->generation;
1189+ logical = old_root->logical;
1190+ } else {
1191+ logical = root->node->start;
1192+ }
11601193
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);
11621195 /*
11631196 * there was an item in the log when __tree_mod_log_oldest_root
11641197 * 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
11661199 */
11671200 BUG_ON(!tm);
11681201
1169− if (old_root->logical == root->node->start) {
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 */
1202+ if (old_root)
11741203 eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT,
11751204 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) {
11761213 btrfs_set_header_bytenr(eb, eb->start);
11771214 btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV);
11781215 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);
11791218 }
1180− if (!eb)
1181− return NULL;
1182− btrfs_set_header_level(eb, old_root->level);
1183− btrfs_set_header_generation(eb, old_generation);
11841219 __tree_mod_log_rewind(eb, time_seq, tm);
1220+ extent_buffer_get(eb);
11851221
11861222 return eb;
11871223 }
@@ -1650,8 +1686,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, · 462 unmodified lines
16501686 BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
16511687 return 0;
16521688
1653− btrfs_header_nritems(mid);
1654−
16551689 left = read_node_slot(root, parent, pslot - 1);
16561690 if (left) {
16571691 btrfs_tree_lock(left);
@@ -1681,7 +1715,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, · 23 unmodified lines
16811715 wret = push_node_left(trans, root, left, mid, 1);
16821716 if (wret < 0)
16831717 ret = wret;
1684− btrfs_header_nritems(mid);
16851718 }
16861719
16871720 /*
@@ -2615,9 +2648,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, · 927 unmodified lines
26152648
26162649 again:
26172650 b = get_old_root(root, time_seq);
2618− extent_buffer_get(b);
26192651 level = btrfs_header_level(b);
2620− btrfs_tree_read_lock(b);
26212652 p->locks[level] = BTRFS_READ_LOCK;
26222653
26232654 while (b) {
@@ -5000,6 +5031,12 @@ next: · 2376 unmodified lines
50005031 * returns < 0 on io errors.
50015032 */
50025033 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
5034+{
5035+ return btrfs_next_old_leaf(root, path, 0);
5036+}
5037+
5038+int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
5039+ u64 time_seq)
50035040 {
50045041 int slot;
50055042 int level;
@@ -5025,7 +5062,10 @@ again: · 19 unmodified lines
50255062 path->keep_locks = 1;
50265063 path->leave_spinning = 1;
50275064
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);
50295069 path->keep_locks = 0;
50305070
50315071 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
27532753 }
27542754
27552755 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
2756+int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
2757+ u64 time_seq);
27562758 static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
27572759 {
27582760 ++p->slots[0];