diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-06-05 10:41:24 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-06-14 12:44:22 -0400 |
commit | a95236d99fa56766f11056903439f55fe5038bcf (patch) | |
tree | 90a9ea2656772900ac411cf43333ec25ed712363 /fs/btrfs/ctree.c | |
parent | 8ba97a15e7d4f70b9af71fa1db86a28dd17ad1b2 (diff) |
Btrfs: fix return value for __tree_mod_log_oldest_root
In __tree_mod_log_oldest_root() we must return the found operation even if
it's not a ROOT_REPLACE operation. Otherwise, the caller assumes that there
are no operations to be rewinded and returns immediately.
The code in the caller is modified to improve readability.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 2cde7b0a0106..50d7c99ddce7 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1023,6 +1023,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, | |||
1023 | looped = 1; | 1023 | looped = 1; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | /* if there's no old root to return, return what we found instead */ | ||
1027 | if (!found) | ||
1028 | found = tm; | ||
1029 | |||
1026 | return found; | 1030 | return found; |
1027 | } | 1031 | } |
1028 | 1032 | ||
@@ -1155,18 +1159,24 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
1155 | { | 1159 | { |
1156 | struct tree_mod_elem *tm; | 1160 | struct tree_mod_elem *tm; |
1157 | struct extent_buffer *eb; | 1161 | struct extent_buffer *eb; |
1158 | struct tree_mod_root *old_root; | 1162 | struct tree_mod_root *old_root = NULL; |
1159 | u64 old_generation; | 1163 | u64 old_generation; |
1164 | u64 logical; | ||
1160 | 1165 | ||
1161 | eb = btrfs_read_lock_root_node(root); | 1166 | eb = btrfs_read_lock_root_node(root); |
1162 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); | 1167 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); |
1163 | if (!tm) | 1168 | if (!tm) |
1164 | return root->node; | 1169 | return root->node; |
1165 | 1170 | ||
1166 | old_root = &tm->old_root; | 1171 | if (tm->op == MOD_LOG_ROOT_REPLACE) { |
1167 | old_generation = tm->generation; | 1172 | old_root = &tm->old_root; |
1173 | old_generation = tm->generation; | ||
1174 | logical = old_root->logical; | ||
1175 | } else { | ||
1176 | logical = root->node->start; | ||
1177 | } | ||
1168 | 1178 | ||
1169 | tm = tree_mod_log_search(root->fs_info, old_root->logical, time_seq); | 1179 | tm = tree_mod_log_search(root->fs_info, logical, time_seq); |
1170 | /* | 1180 | /* |
1171 | * there was an item in the log when __tree_mod_log_oldest_root | 1181 | * there was an item in the log when __tree_mod_log_oldest_root |
1172 | * returned. this one must not go away, because the time_seq passed to | 1182 | * returned. this one must not go away, because the time_seq passed to |
@@ -1174,26 +1184,23 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
1174 | */ | 1184 | */ |
1175 | BUG_ON(!tm); | 1185 | BUG_ON(!tm); |
1176 | 1186 | ||
1177 | if (old_root->logical == root->node->start) { | 1187 | if (old_root) |
1178 | /* there are logged operations for the current root */ | ||
1179 | eb = btrfs_clone_extent_buffer(root->node); | ||
1180 | } else { | ||
1181 | /* there's a root replace operation for the current root */ | ||
1182 | eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, | 1188 | eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, |
1183 | root->nodesize); | 1189 | root->nodesize); |
1184 | } | 1190 | else |
1191 | eb = btrfs_clone_extent_buffer(root->node); | ||
1185 | btrfs_tree_read_unlock(root->node); | 1192 | btrfs_tree_read_unlock(root->node); |
1186 | free_extent_buffer(root->node); | 1193 | free_extent_buffer(root->node); |
1187 | if (!eb) | 1194 | if (!eb) |
1188 | return NULL; | 1195 | return NULL; |
1189 | btrfs_tree_read_lock(eb); | 1196 | btrfs_tree_read_lock(eb); |
1190 | if (old_root->logical != root->node->start) { | 1197 | if (old_root) { |
1191 | btrfs_set_header_bytenr(eb, eb->start); | 1198 | btrfs_set_header_bytenr(eb, eb->start); |
1192 | btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV); | 1199 | btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV); |
1193 | btrfs_set_header_owner(eb, root->root_key.objectid); | 1200 | btrfs_set_header_owner(eb, root->root_key.objectid); |
1201 | btrfs_set_header_level(eb, old_root->level); | ||
1202 | btrfs_set_header_generation(eb, old_generation); | ||
1194 | } | 1203 | } |
1195 | btrfs_set_header_level(eb, old_root->level); | ||
1196 | btrfs_set_header_generation(eb, old_generation); | ||
1197 | __tree_mod_log_rewind(eb, time_seq, tm); | 1204 | __tree_mod_log_rewind(eb, time_seq, tm); |
1198 | extent_buffer_get(eb); | 1205 | extent_buffer_get(eb); |
1199 | 1206 | ||