btrfs-progs: copy btrfs_root::state from kernel

We changed from members in the root for all the different flags to a
bit based flag system.  In order to make syncing the kernel code into
btrfs-progs easier go ahead and sync in the bits we use and update all
the users of the old ->track_dirty and ->ref_cows to use the state bits.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2023-04-19 17:20:42 -04:00 committed by David Sterba
parent c6b160c4e4
commit 8e427ada49
5 changed files with 94 additions and 28 deletions

View File

@ -31,6 +31,7 @@
#include "kernel-lib/list.h"
#include "kernel-lib/rbtree.h"
#include "kernel-lib/rbtree_types.h"
#include "kernel-lib/bitops.h"
#include "kernel-shared/uapi/btrfs.h"
#include "kernel-shared/extent_io.h"
#include "kernel-shared/ctree.h"
@ -467,7 +468,7 @@ static void record_root_in_trans(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
if (root->last_trans != trans->transid) {
root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
root->last_trans = trans->transid;
root->commit_root = root->node;
extent_buffer_get(root->node);

View File

@ -20,6 +20,7 @@
#include "kernel-shared/disk-io.h"
#include "kernel-shared/transaction.h"
#include "kernel-shared/print-tree.h"
#include "kernel-lib/bitops.h"
#include "crypto/crc32c.h"
#include "common/internal.h"
#include "common/messages.h"
@ -119,7 +120,8 @@ void btrfs_release_path(struct btrfs_path *p)
void add_root_to_dirty_list(struct btrfs_root *root)
{
if (root->track_dirty && list_empty(&root->dirty_list)) {
if (test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state) &&
list_empty(&root->dirty_list)) {
list_add(&root->dirty_list,
&root->fs_info->dirty_cowonly_roots);
}
@ -155,9 +157,10 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
memcpy(new_root, root, sizeof(*new_root));
new_root->root_key.objectid = new_root_objectid;
WARN_ON(root->ref_cows && trans->transid !=
root->fs_info->running_transaction->transid);
WARN_ON(root->ref_cows && trans->transid != root->last_trans);
WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
trans->transid != root->fs_info->running_transaction->transid);
WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
trans->transid != root->last_trans);
level = btrfs_header_level(buf);
if (level == 0)
@ -219,7 +222,7 @@ int btrfs_create_root(struct btrfs_trans_handle *trans,
btrfs_setup_root(new_root, fs_info, objectid);
if (!is_fstree(objectid))
new_root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &new_root->state);
add_root_to_dirty_list(new_root);
new_root->objectid = objectid;
@ -332,7 +335,7 @@ static int btrfs_block_can_be_shared(struct btrfs_root *root,
* snapshot and the block was not allocated by tree relocation,
* we know the block is not shared.
*/
if (root->ref_cows &&
if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
buf != root->node && buf != root->commit_root &&
(btrfs_header_generation(buf) <=
btrfs_root_last_snapshot(&root->root_item) ||
@ -446,9 +449,10 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_disk_key disk_key;
int level;
WARN_ON(root->ref_cows && trans->transid !=
root->fs_info->running_transaction->transid);
WARN_ON(root->ref_cows && trans->transid != root->last_trans);
WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
trans->transid != root->fs_info->running_transaction->transid);
WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
trans->transid != root->last_trans);
level = btrfs_header_level(buf);

View File

@ -388,6 +388,68 @@ static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info)
return fs_info->zoned != 0;
}
/*
* The state of btrfs root
*/
enum {
/*
* btrfs_record_root_in_trans is a multi-step process, and it can race
* with the balancing code. But the race is very small, and only the
* first time the root is added to each transaction. So IN_TRANS_SETUP
* is used to tell us when more checks are required
*/
BTRFS_ROOT_IN_TRANS_SETUP,
/*
* Set if tree blocks of this root can be shared by other roots.
* Only subvolume trees and their reloc trees have this bit set.
* Conflicts with TRACK_DIRTY bit.
*
* This affects two things:
*
* - How balance works
* For shareable roots, we need to use reloc tree and do path
* replacement for balance, and need various pre/post hooks for
* snapshot creation to handle them.
*
* While for non-shareable trees, we just simply do a tree search
* with COW.
*
* - How dirty roots are tracked
* For shareable roots, btrfs_record_root_in_trans() is needed to
* track them, while non-subvolume roots have TRACK_DIRTY bit, they
* don't need to set this manually.
*/
BTRFS_ROOT_SHAREABLE,
BTRFS_ROOT_TRACK_DIRTY,
BTRFS_ROOT_IN_RADIX,
BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
BTRFS_ROOT_DEFRAG_RUNNING,
BTRFS_ROOT_FORCE_COW,
BTRFS_ROOT_MULTI_LOG_TASKS,
BTRFS_ROOT_DIRTY,
BTRFS_ROOT_DELETING,
/*
* Reloc tree is orphan, only kept here for qgroup delayed subtree scan
*
* Set for the subvolume tree owning the reloc tree.
*/
BTRFS_ROOT_DEAD_RELOC_TREE,
/* Mark dead root stored on device whose cleanup needs to be resumed */
BTRFS_ROOT_DEAD_TREE,
/* The root has a log tree. Used for subvolume roots and the tree root. */
BTRFS_ROOT_HAS_LOG_TREE,
/* Qgroup flushing is in progress */
BTRFS_ROOT_QGROUP_FLUSHING,
/* We started the orphan cleanup for this root. */
BTRFS_ROOT_ORPHAN_CLEANUP,
/* This root has a drop operation that was started previously. */
BTRFS_ROOT_UNFINISHED_DROP,
/* This reloc root needs to have its buffers lockdep class reset. */
BTRFS_ROOT_RESET_LOCKDEP_CLASS,
};
/*
* in ram representation of the tree. extent_root is used for all allocations
* and for the extent tree extent_root root.
@ -401,9 +463,7 @@ struct btrfs_root {
u64 objectid;
u64 last_trans;
int ref_cows;
int track_dirty;
unsigned long state;
u32 type;
u64 last_inode_alloc;

View File

@ -32,6 +32,7 @@
#include "crypto/crc32c.h"
#include "common/utils.h"
#include "kernel-shared/print-tree.h"
#include "kernel-lib/bitops.h"
#include "common/rbtree-utils.h"
#include "common/device-scan.h"
#include "common/device-utils.h"
@ -491,8 +492,7 @@ void btrfs_setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
{
root->node = NULL;
root->commit_root = NULL;
root->ref_cows = 0;
root->track_dirty = 0;
root->state = 0;
root->fs_info = fs_info;
root->objectid = objectid;
@ -654,9 +654,9 @@ out:
}
insert:
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
if (is_fstree(root->root_key.objectid))
root->ref_cows = 1;
set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
return root;
}
@ -1062,7 +1062,7 @@ static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
free(root);
break;
}
root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
ret = btrfs_global_root_insert(fs_info, root);
if (ret) {
@ -1099,7 +1099,7 @@ static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
root->root_key.objectid = objectid;
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
root->root_key.offset = i;
root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
root->node = btrfs_find_create_tree_block(fs_info, 0);
if (!root->node) {
free(root);
@ -1232,7 +1232,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
error("couldn't load block group tree");
return -EIO;
}
fs_info->block_group_root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY,
&fs_info->block_group_root->state);
}
ret = btrfs_find_and_setup_root(root, fs_info,
@ -1242,7 +1243,7 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
printk("Couldn't setup device tree\n");
return -EIO;
}
fs_info->dev_root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &fs_info->dev_root->state);
ret = btrfs_find_and_setup_root(root, fs_info,
BTRFS_UUID_TREE_OBJECTID,
@ -1251,7 +1252,7 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
free(fs_info->uuid_root);
fs_info->uuid_root = NULL;
} else {
fs_info->uuid_root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &fs_info->uuid_root->state);
}
ret = btrfs_find_and_setup_root(root, fs_info,
@ -2355,7 +2356,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
extent_buffer_get(root->node);
root->commit_root = root->node;
root->track_dirty = 1;
set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
root->root_item.flags = 0;
root->root_item.byte_limit = 0;

View File

@ -1470,7 +1470,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
nritems = btrfs_header_nritems(buf);
level = btrfs_header_level(buf);
if (!root->ref_cows && level == 0)
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && level == 0)
return 0;
if (inc)
@ -2358,11 +2358,11 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
}
/*
* Also preallocate metadata for csum tree and fs trees (root->ref_cows
* already set), as they can consume a lot of metadata space.
* Pre-allocate to avoid unexpected ENOSPC.
* Also preallocate metadata for csum tree and fs trees
* (BTRFS_ROOT_SHAREABLE already set) as they can consume a lot of
* metadata space. Pre-allocate to avoid unexpected ENOSPC.
*/
if (root->ref_cows ||
if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) ||
root->root_key.objectid == BTRFS_CSUM_TREE_OBJECTID) {
if (!(profile & BTRFS_BLOCK_GROUP_METADATA)) {
ret = do_chunk_alloc(trans, info,