btrfs: move btrfs_realloc_node() from ctree.c into defrag.c
btrfs_realloc_node() is only used by the defrag code. Nowadays we have a defrag.c file, so move it, and its helper close_blocks(), into defrag.c. During the move also do a few minor cosmetic changes: 1) Change the return value of close_blocks() from int to bool; 2) Use SZ_32K instead of 32768 at close_blocks(); 3) Make some variables const in btrfs_realloc_node(), 'blocksize' and 'end_slot'; 4) Get rid of 'parent_nritems' variable, in both places where it was used it could be replaced by calling btrfs_header_nritems(parent); 5) Change the type of a couple variables from int to bool; 6) Rename variable 'err' to 'ret', as that's the most common name we use to track the return value of a function; 7) Move some variables from the top scope to the scope of the for loop where they are used. Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
79d25df0d7
commit
6422b4cd95
112
fs/btrfs/ctree.c
112
fs/btrfs/ctree.c
@ -736,19 +736,6 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
ALLOW_ERROR_INJECTION(btrfs_cow_block, ERRNO);
|
||||
|
||||
/*
|
||||
* helper function for defrag to decide if two blocks pointed to by a
|
||||
* node are actually close by
|
||||
*/
|
||||
static int close_blocks(u64 blocknr, u64 other, u32 blocksize)
|
||||
{
|
||||
if (blocknr < other && other - (blocknr + blocksize) < 32768)
|
||||
return 1;
|
||||
if (blocknr > other && blocknr - (other + blocksize) < 32768)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* same as comp_keys only with two btrfs_key's
|
||||
*/
|
||||
@ -769,105 +756,6 @@ int __pure btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_ke
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is used by the defrag code to go through all the
|
||||
* leaves pointed to by a node and reallocate them so that
|
||||
* disk order is close to key order
|
||||
*/
|
||||
int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct extent_buffer *parent,
|
||||
int start_slot, u64 *last_ret,
|
||||
struct btrfs_key *progress)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct extent_buffer *cur;
|
||||
u64 blocknr;
|
||||
u64 search_start = *last_ret;
|
||||
u64 last_block = 0;
|
||||
u64 other;
|
||||
u32 parent_nritems;
|
||||
int end_slot;
|
||||
int i;
|
||||
int err = 0;
|
||||
u32 blocksize;
|
||||
int progress_passed = 0;
|
||||
struct btrfs_disk_key disk_key;
|
||||
|
||||
/*
|
||||
* COWing must happen through a running transaction, which always
|
||||
* matches the current fs generation (it's a transaction with a state
|
||||
* less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs
|
||||
* into error state to prevent the commit of any transaction.
|
||||
*/
|
||||
if (unlikely(trans->transaction != fs_info->running_transaction ||
|
||||
trans->transid != fs_info->generation)) {
|
||||
btrfs_abort_transaction(trans, -EUCLEAN);
|
||||
btrfs_crit(fs_info,
|
||||
"unexpected transaction when attempting to reallocate parent %llu for root %llu, transaction %llu running transaction %llu fs generation %llu",
|
||||
parent->start, btrfs_root_id(root), trans->transid,
|
||||
fs_info->running_transaction->transid,
|
||||
fs_info->generation);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
parent_nritems = btrfs_header_nritems(parent);
|
||||
blocksize = fs_info->nodesize;
|
||||
end_slot = parent_nritems - 1;
|
||||
|
||||
if (parent_nritems <= 1)
|
||||
return 0;
|
||||
|
||||
for (i = start_slot; i <= end_slot; i++) {
|
||||
int close = 1;
|
||||
|
||||
btrfs_node_key(parent, &disk_key, i);
|
||||
if (!progress_passed && btrfs_comp_keys(&disk_key, progress) < 0)
|
||||
continue;
|
||||
|
||||
progress_passed = 1;
|
||||
blocknr = btrfs_node_blockptr(parent, i);
|
||||
if (last_block == 0)
|
||||
last_block = blocknr;
|
||||
|
||||
if (i > 0) {
|
||||
other = btrfs_node_blockptr(parent, i - 1);
|
||||
close = close_blocks(blocknr, other, blocksize);
|
||||
}
|
||||
if (!close && i < end_slot) {
|
||||
other = btrfs_node_blockptr(parent, i + 1);
|
||||
close = close_blocks(blocknr, other, blocksize);
|
||||
}
|
||||
if (close) {
|
||||
last_block = blocknr;
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = btrfs_read_node_slot(parent, i);
|
||||
if (IS_ERR(cur))
|
||||
return PTR_ERR(cur);
|
||||
if (search_start == 0)
|
||||
search_start = last_block;
|
||||
|
||||
btrfs_tree_lock(cur);
|
||||
err = btrfs_force_cow_block(trans, root, cur, parent, i,
|
||||
&cur, search_start,
|
||||
min(16 * blocksize,
|
||||
(end_slot - i) * blocksize),
|
||||
BTRFS_NESTING_COW);
|
||||
if (err) {
|
||||
btrfs_tree_unlock(cur);
|
||||
free_extent_buffer(cur);
|
||||
break;
|
||||
}
|
||||
search_start = cur->start;
|
||||
last_block = cur->start;
|
||||
*last_ret = search_start;
|
||||
btrfs_tree_unlock(cur);
|
||||
free_extent_buffer(cur);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a key in the given extent_buffer.
|
||||
*
|
||||
|
@ -557,10 +557,6 @@ int btrfs_search_slot_for_read(struct btrfs_root *root,
|
||||
const struct btrfs_key *key,
|
||||
struct btrfs_path *p, int find_higher,
|
||||
int return_any);
|
||||
int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct extent_buffer *parent,
|
||||
int start_slot, u64 *last_ret,
|
||||
struct btrfs_key *progress);
|
||||
void btrfs_release_path(struct btrfs_path *p);
|
||||
struct btrfs_path *btrfs_alloc_path(void);
|
||||
void btrfs_free_path(struct btrfs_path *p);
|
||||
|
@ -337,6 +337,111 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if two blocks addresses are close, used by defrag.
|
||||
*/
|
||||
static bool close_blocks(u64 blocknr, u64 other, u32 blocksize)
|
||||
{
|
||||
if (blocknr < other && other - (blocknr + blocksize) < SZ_32K)
|
||||
return true;
|
||||
if (blocknr > other && blocknr - (other + blocksize) < SZ_32K)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through all the leaves pointed to by a node and reallocate them so that
|
||||
* disk order is close to key order.
|
||||
*/
|
||||
static int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct extent_buffer *parent,
|
||||
int start_slot, u64 *last_ret,
|
||||
struct btrfs_key *progress)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
const u32 blocksize = fs_info->nodesize;
|
||||
const int end_slot = btrfs_header_nritems(parent) - 1;
|
||||
u64 search_start = *last_ret;
|
||||
u64 last_block = 0;
|
||||
int ret = 0;
|
||||
bool progress_passed = false;
|
||||
|
||||
/*
|
||||
* COWing must happen through a running transaction, which always
|
||||
* matches the current fs generation (it's a transaction with a state
|
||||
* less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs
|
||||
* into error state to prevent the commit of any transaction.
|
||||
*/
|
||||
if (unlikely(trans->transaction != fs_info->running_transaction ||
|
||||
trans->transid != fs_info->generation)) {
|
||||
btrfs_abort_transaction(trans, -EUCLEAN);
|
||||
btrfs_crit(fs_info,
|
||||
"unexpected transaction when attempting to reallocate parent %llu for root %llu, transaction %llu running transaction %llu fs generation %llu",
|
||||
parent->start, btrfs_root_id(root), trans->transid,
|
||||
fs_info->running_transaction->transid,
|
||||
fs_info->generation);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
if (btrfs_header_nritems(parent) <= 1)
|
||||
return 0;
|
||||
|
||||
for (int i = start_slot; i <= end_slot; i++) {
|
||||
struct extent_buffer *cur;
|
||||
struct btrfs_disk_key disk_key;
|
||||
u64 blocknr;
|
||||
u64 other;
|
||||
bool close = true;
|
||||
|
||||
btrfs_node_key(parent, &disk_key, i);
|
||||
if (!progress_passed && btrfs_comp_keys(&disk_key, progress) < 0)
|
||||
continue;
|
||||
|
||||
progress_passed = true;
|
||||
blocknr = btrfs_node_blockptr(parent, i);
|
||||
if (last_block == 0)
|
||||
last_block = blocknr;
|
||||
|
||||
if (i > 0) {
|
||||
other = btrfs_node_blockptr(parent, i - 1);
|
||||
close = close_blocks(blocknr, other, blocksize);
|
||||
}
|
||||
if (!close && i < end_slot) {
|
||||
other = btrfs_node_blockptr(parent, i + 1);
|
||||
close = close_blocks(blocknr, other, blocksize);
|
||||
}
|
||||
if (close) {
|
||||
last_block = blocknr;
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = btrfs_read_node_slot(parent, i);
|
||||
if (IS_ERR(cur))
|
||||
return PTR_ERR(cur);
|
||||
if (search_start == 0)
|
||||
search_start = last_block;
|
||||
|
||||
btrfs_tree_lock(cur);
|
||||
ret = btrfs_force_cow_block(trans, root, cur, parent, i,
|
||||
&cur, search_start,
|
||||
min(16 * blocksize,
|
||||
(end_slot - i) * blocksize),
|
||||
BTRFS_NESTING_COW);
|
||||
if (ret) {
|
||||
btrfs_tree_unlock(cur);
|
||||
free_extent_buffer(cur);
|
||||
break;
|
||||
}
|
||||
search_start = cur->start;
|
||||
last_block = cur->start;
|
||||
*last_ret = search_start;
|
||||
btrfs_tree_unlock(cur);
|
||||
free_extent_buffer(cur);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Defrag all the leaves in a given btree.
|
||||
* Read all the leaves and try to get key order to
|
||||
|
Loading…
x
Reference in New Issue
Block a user