Loading fs/btrfs/ctree.h +2 −0 Original line number Diff line number Diff line Loading @@ -1459,6 +1459,8 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *item); int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); int btrfs_search_root(struct btrfs_root *root, u64 search_start, u64 *found_objectid); int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, struct btrfs_root *latest_root); /* dir-item.c */ Loading fs/btrfs/extent-tree.c +109 −11 Original line number Diff line number Diff line Loading @@ -2421,6 +2421,85 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, goto out_unlock; } /* * The back references tell us which tree holds a ref on a block, * but it is possible for the tree root field in the reference to * reflect the original root before a snapshot was made. In this * case we should search through all the children of a given root * to find potential holders of references on a block. * * Instead, we do something a little less fancy and just search * all the roots for a given key/block combination. */ static int find_root_for_ref(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *key0, int level, int file_key, struct btrfs_root **found_root, u64 bytenr) { struct btrfs_key root_location; struct btrfs_root *cur_root = *found_root; struct btrfs_file_extent_item *file_extent; u64 root_search_start = BTRFS_FS_TREE_OBJECTID; u64 found_bytenr; int ret; int i; root_location.offset = (u64)-1; root_location.type = BTRFS_ROOT_ITEM_KEY; path->lowest_level = level; path->reada = 0; while(1) { ret = btrfs_search_slot(NULL, cur_root, key0, path, 0, 0); found_bytenr = 0; if (ret == 0 && file_key) { struct extent_buffer *leaf = path->nodes[0]; file_extent = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); if (btrfs_file_extent_type(leaf, file_extent) == BTRFS_FILE_EXTENT_REG) { found_bytenr = btrfs_file_extent_disk_bytenr(leaf, file_extent); } } else if (ret == 0) { if (path->nodes[level]) found_bytenr = path->nodes[level]->start; } for (i = level; i < BTRFS_MAX_LEVEL; i++) { if (!path->nodes[i]) break; free_extent_buffer(path->nodes[i]); path->nodes[i] = NULL; } btrfs_release_path(cur_root, path); if (found_bytenr == bytenr) { *found_root = cur_root; ret = 0; goto out; } ret = btrfs_search_root(root->fs_info->tree_root, root_search_start, &root_search_start); if (ret) break; root_location.objectid = root_search_start; cur_root = btrfs_read_fs_root_no_name(root->fs_info, &root_location); if (!cur_root) { ret = 1; break; } } out: path->lowest_level = 0; return ret; } /* * note, this releases the path */ Loading @@ -2430,13 +2509,15 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, { struct inode *inode; struct btrfs_root *found_root; struct btrfs_key *root_location; struct btrfs_key root_location; struct btrfs_key found_key; struct btrfs_extent_ref *ref; u64 ref_root; u64 ref_gen; u64 ref_objectid; u64 ref_offset; int ret; int level; ref = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_extent_ref); Loading @@ -2446,20 +2527,30 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, ref_offset = btrfs_ref_offset(path->nodes[0], ref); btrfs_release_path(extent_root, path); root_location = kmalloc(sizeof(*root_location), GFP_NOFS); root_location->objectid = ref_root; root_location.objectid = ref_root; if (ref_gen == 0) root_location->offset = 0; root_location.offset = 0; else root_location->offset = (u64)-1; root_location->type = BTRFS_ROOT_ITEM_KEY; root_location.offset = (u64)-1; root_location.type = BTRFS_ROOT_ITEM_KEY; found_root = btrfs_read_fs_root_no_name(extent_root->fs_info, root_location); &root_location); BUG_ON(!found_root); kfree(root_location); if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) { found_key.objectid = ref_objectid; found_key.type = BTRFS_EXTENT_DATA_KEY; found_key.offset = ref_offset; level = 0; ret = find_root_for_ref(extent_root, path, &found_key, level, 1, &found_root, extent_key->objectid); if (ret) goto out; mutex_unlock(&extent_root->fs_info->fs_mutex); inode = btrfs_iget_locked(extent_root->fs_info->sb, ref_objectid, found_root); Loading @@ -2485,12 +2576,9 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, mutex_lock(&extent_root->fs_info->fs_mutex); } else { struct btrfs_trans_handle *trans; struct btrfs_key found_key; struct extent_buffer *eb; int level; int i; trans = btrfs_start_transaction(found_root, 1); eb = read_tree_block(found_root, extent_key->objectid, extent_key->offset); level = btrfs_header_level(eb); Loading @@ -2502,6 +2590,15 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, free_extent_buffer(eb); ret = find_root_for_ref(extent_root, path, &found_key, level, 0, &found_root, extent_key->objectid); if (ret) goto out; trans = btrfs_start_transaction(found_root, 1); path->lowest_level = level; path->reada = 2; ret = btrfs_search_slot(trans, found_root, &found_key, path, Loading Loading @@ -2578,6 +2675,7 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, } if (ret < 0) goto out; leaf = path->nodes[0]; } btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); Loading fs/btrfs/root-tree.c +45 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,51 @@ #include "disk-io.h" #include "print-tree.h" /* * returns 0 on finding something, 1 if no more roots are there * and < 0 on error */ int btrfs_search_root(struct btrfs_root *root, u64 search_start, u64 *found_objectid) { struct btrfs_path *path; struct btrfs_key search_key; int ret; root = root->fs_info->tree_root; search_key.objectid = search_start; search_key.type = (u8)-1; search_key.offset = (u64)-1; path = btrfs_alloc_path(); BUG_ON(!path); again: ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); if (ret < 0) goto out; if (ret == 0) { ret = 1; goto out; } if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) { ret = btrfs_next_leaf(root, path); if (ret) goto out; } btrfs_item_key_to_cpu(path->nodes[0], &search_key, path->slots[0]); if (search_key.type != BTRFS_ROOT_ITEM_KEY) { search_key.offset++; btrfs_release_path(root, path); goto again; } ret = 0; *found_objectid = search_key.objectid; out: btrfs_free_path(path); return ret; } int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key) { Loading Loading @@ -55,7 +100,6 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, memcpy(key, &found_key, sizeof(found_key)); ret = 0; out: btrfs_release_path(root, path); btrfs_free_path(path); return ret; } Loading Loading
fs/btrfs/ctree.h +2 −0 Original line number Diff line number Diff line Loading @@ -1459,6 +1459,8 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *item); int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); int btrfs_search_root(struct btrfs_root *root, u64 search_start, u64 *found_objectid); int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid, struct btrfs_root *latest_root); /* dir-item.c */ Loading
fs/btrfs/extent-tree.c +109 −11 Original line number Diff line number Diff line Loading @@ -2421,6 +2421,85 @@ static int noinline relocate_inode_pages(struct inode *inode, u64 start, goto out_unlock; } /* * The back references tell us which tree holds a ref on a block, * but it is possible for the tree root field in the reference to * reflect the original root before a snapshot was made. In this * case we should search through all the children of a given root * to find potential holders of references on a block. * * Instead, we do something a little less fancy and just search * all the roots for a given key/block combination. */ static int find_root_for_ref(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *key0, int level, int file_key, struct btrfs_root **found_root, u64 bytenr) { struct btrfs_key root_location; struct btrfs_root *cur_root = *found_root; struct btrfs_file_extent_item *file_extent; u64 root_search_start = BTRFS_FS_TREE_OBJECTID; u64 found_bytenr; int ret; int i; root_location.offset = (u64)-1; root_location.type = BTRFS_ROOT_ITEM_KEY; path->lowest_level = level; path->reada = 0; while(1) { ret = btrfs_search_slot(NULL, cur_root, key0, path, 0, 0); found_bytenr = 0; if (ret == 0 && file_key) { struct extent_buffer *leaf = path->nodes[0]; file_extent = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); if (btrfs_file_extent_type(leaf, file_extent) == BTRFS_FILE_EXTENT_REG) { found_bytenr = btrfs_file_extent_disk_bytenr(leaf, file_extent); } } else if (ret == 0) { if (path->nodes[level]) found_bytenr = path->nodes[level]->start; } for (i = level; i < BTRFS_MAX_LEVEL; i++) { if (!path->nodes[i]) break; free_extent_buffer(path->nodes[i]); path->nodes[i] = NULL; } btrfs_release_path(cur_root, path); if (found_bytenr == bytenr) { *found_root = cur_root; ret = 0; goto out; } ret = btrfs_search_root(root->fs_info->tree_root, root_search_start, &root_search_start); if (ret) break; root_location.objectid = root_search_start; cur_root = btrfs_read_fs_root_no_name(root->fs_info, &root_location); if (!cur_root) { ret = 1; break; } } out: path->lowest_level = 0; return ret; } /* * note, this releases the path */ Loading @@ -2430,13 +2509,15 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, { struct inode *inode; struct btrfs_root *found_root; struct btrfs_key *root_location; struct btrfs_key root_location; struct btrfs_key found_key; struct btrfs_extent_ref *ref; u64 ref_root; u64 ref_gen; u64 ref_objectid; u64 ref_offset; int ret; int level; ref = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_extent_ref); Loading @@ -2446,20 +2527,30 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, ref_offset = btrfs_ref_offset(path->nodes[0], ref); btrfs_release_path(extent_root, path); root_location = kmalloc(sizeof(*root_location), GFP_NOFS); root_location->objectid = ref_root; root_location.objectid = ref_root; if (ref_gen == 0) root_location->offset = 0; root_location.offset = 0; else root_location->offset = (u64)-1; root_location->type = BTRFS_ROOT_ITEM_KEY; root_location.offset = (u64)-1; root_location.type = BTRFS_ROOT_ITEM_KEY; found_root = btrfs_read_fs_root_no_name(extent_root->fs_info, root_location); &root_location); BUG_ON(!found_root); kfree(root_location); if (ref_objectid >= BTRFS_FIRST_FREE_OBJECTID) { found_key.objectid = ref_objectid; found_key.type = BTRFS_EXTENT_DATA_KEY; found_key.offset = ref_offset; level = 0; ret = find_root_for_ref(extent_root, path, &found_key, level, 1, &found_root, extent_key->objectid); if (ret) goto out; mutex_unlock(&extent_root->fs_info->fs_mutex); inode = btrfs_iget_locked(extent_root->fs_info->sb, ref_objectid, found_root); Loading @@ -2485,12 +2576,9 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, mutex_lock(&extent_root->fs_info->fs_mutex); } else { struct btrfs_trans_handle *trans; struct btrfs_key found_key; struct extent_buffer *eb; int level; int i; trans = btrfs_start_transaction(found_root, 1); eb = read_tree_block(found_root, extent_key->objectid, extent_key->offset); level = btrfs_header_level(eb); Loading @@ -2502,6 +2590,15 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, free_extent_buffer(eb); ret = find_root_for_ref(extent_root, path, &found_key, level, 0, &found_root, extent_key->objectid); if (ret) goto out; trans = btrfs_start_transaction(found_root, 1); path->lowest_level = level; path->reada = 2; ret = btrfs_search_slot(trans, found_root, &found_key, path, Loading Loading @@ -2578,6 +2675,7 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, } if (ret < 0) goto out; leaf = path->nodes[0]; } btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); Loading
fs/btrfs/root-tree.c +45 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,51 @@ #include "disk-io.h" #include "print-tree.h" /* * returns 0 on finding something, 1 if no more roots are there * and < 0 on error */ int btrfs_search_root(struct btrfs_root *root, u64 search_start, u64 *found_objectid) { struct btrfs_path *path; struct btrfs_key search_key; int ret; root = root->fs_info->tree_root; search_key.objectid = search_start; search_key.type = (u8)-1; search_key.offset = (u64)-1; path = btrfs_alloc_path(); BUG_ON(!path); again: ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); if (ret < 0) goto out; if (ret == 0) { ret = 1; goto out; } if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) { ret = btrfs_next_leaf(root, path); if (ret) goto out; } btrfs_item_key_to_cpu(path->nodes[0], &search_key, path->slots[0]); if (search_key.type != BTRFS_ROOT_ITEM_KEY) { search_key.offset++; btrfs_release_path(root, path); goto again; } ret = 0; *found_objectid = search_key.objectid; out: btrfs_free_path(path); return ret; } int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key) { Loading Loading @@ -55,7 +100,6 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, memcpy(key, &found_key, sizeof(found_key)); ret = 0; out: btrfs_release_path(root, path); btrfs_free_path(path); return ret; } Loading