Commit 1c59b483 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: BTREE_ID_snapshot_tree

This adds a new btree which gets us a persistent per-snapshot-tree
identifier.

 - BTREE_ID_snapshot_trees
 - KEY_TYPE_snapshot_tree
 - bch_snapshot now has a field that points to a snapshot_tree

This is going to be used to designate one snapshot ID/subvolume out of a
given tree of snapshots as the "main" subvolume, so that we can do quota
accounting in that subvolume and not the rest.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 51e84d3b
......@@ -445,6 +445,7 @@ enum gc_phase {
GC_PHASE_BTREE_need_discard,
GC_PHASE_BTREE_backpointers,
GC_PHASE_BTREE_bucket_gens,
GC_PHASE_BTREE_snapshot_trees,
GC_PHASE_PENDING_DELETE,
};
......
......@@ -364,7 +364,8 @@ static inline void bkey_init(struct bkey *k)
x(alloc_v4, 27) \
x(backpointer, 28) \
x(inode_v3, 29) \
x(bucket_gens, 30)
x(bucket_gens, 30) \
x(snapshot_tree, 31)
enum bch_bkey_type {
#define x(name, nr) KEY_TYPE_##name = nr,
......@@ -1123,7 +1124,7 @@ struct bch_snapshot {
__le32 parent;
__le32 children[2];
__le32 subvol;
__le32 pad;
__le32 tree;
};
LE32_BITMASK(BCH_SNAPSHOT_DELETED, struct bch_snapshot, flags, 0, 1)
......@@ -1131,6 +1132,19 @@ LE32_BITMASK(BCH_SNAPSHOT_DELETED, struct bch_snapshot, flags, 0, 1)
/* True if a subvolume points to this snapshot node: */
LE32_BITMASK(BCH_SNAPSHOT_SUBVOL, struct bch_snapshot, flags, 1, 2)
/*
* Snapshot trees:
*
* The snapshot_trees btree gives us persistent indentifier for each tree of
* bch_snapshot nodes, and allow us to record and easily find the root/master
* subvolume that other snapshots were created from:
*/
struct bch_snapshot_tree {
struct bch_val v;
__le32 master_subvol;
__le32 root_snapshot;
};
/* LRU btree: */
struct bch_lru {
......@@ -1559,7 +1573,8 @@ struct bch_sb_field_journal_seq_blacklist {
x(bucket_gens, 25) \
x(lru_v2, 26) \
x(fragmentation_lru, 27) \
x(no_bps_in_alloc_keys, 28)
x(no_bps_in_alloc_keys, 28) \
x(snapshot_trees, 29)
enum bcachefs_metadata_version {
bcachefs_metadata_version_min = 9,
......@@ -1569,6 +1584,8 @@ enum bcachefs_metadata_version {
bcachefs_metadata_version_max
};
static const unsigned bcachefs_metadata_required_upgrade_below = bcachefs_metadata_version_snapshot_trees;
#define bcachefs_metadata_version_current (bcachefs_metadata_version_max - 1)
#define BCH_SB_SECTOR 8
......@@ -2095,7 +2112,8 @@ LE32_BITMASK(JSET_NO_FLUSH, struct jset, flags, 5, 6);
x(freespace, 11) \
x(need_discard, 12) \
x(backpointers, 13) \
x(bucket_gens, 14)
x(bucket_gens, 14) \
x(snapshot_trees, 15)
enum btree_id {
#define x(kwd, val) BTREE_ID_##kwd = val,
......
......@@ -204,6 +204,9 @@ static unsigned bch2_key_types_allowed[] = {
[BKEY_TYPE_bucket_gens] =
(1U << KEY_TYPE_deleted)|
(1U << KEY_TYPE_bucket_gens),
[BKEY_TYPE_snapshot_trees] =
(1U << KEY_TYPE_deleted)|
(1U << KEY_TYPE_snapshot_tree),
[BKEY_TYPE_btree] =
(1U << KEY_TYPE_deleted)|
(1U << KEY_TYPE_btree_ptr)|
......
......@@ -93,6 +93,7 @@
x(ENOSPC, ENOSPC_sb_members) \
x(ENOSPC, ENOSPC_sb_crypt) \
x(ENOSPC, ENOSPC_btree_slot) \
x(ENOSPC, ENOSPC_snapshot_tree) \
x(0, open_buckets_empty) \
x(0, freelist_empty) \
x(BCH_ERR_freelist_empty, no_buckets_found) \
......
......@@ -2427,7 +2427,8 @@ int bch2_fsck_full(struct bch_fs *c)
{
int ret;
again:
ret = bch2_fs_check_snapshots(c) ?:
ret = bch2_fs_check_snapshot_trees(c);
bch2_fs_check_snapshots(c) ?:
bch2_fs_check_subvols(c) ?:
bch2_delete_dead_snapshots(c) ?:
check_inodes(c, true) ?:
......
......@@ -1025,16 +1025,25 @@ static int read_btree_roots(struct bch_fs *c)
static int bch2_fs_initialize_subvolumes(struct bch_fs *c)
{
struct bkey_i_snapshot root_snapshot;
struct bkey_i_subvolume root_volume;
struct bkey_i_snapshot_tree root_tree;
struct bkey_i_snapshot root_snapshot;
struct bkey_i_subvolume root_volume;
int ret;
bkey_snapshot_tree_init(&root_tree.k_i);
root_tree.k.p.offset = 1;
root_tree.v.master_subvol = cpu_to_le32(1);
root_tree.v.root_snapshot = cpu_to_le32(U32_MAX);
ret = bch2_btree_insert(c, BTREE_ID_snapshot_trees,
&root_tree.k_i,
NULL, NULL, 0);
bkey_snapshot_init(&root_snapshot.k_i);
root_snapshot.k.p.offset = U32_MAX;
root_snapshot.v.flags = 0;
root_snapshot.v.parent = 0;
root_snapshot.v.subvol = BCACHEFS_ROOT_SUBVOL;
root_snapshot.v.pad = 0;
root_snapshot.v.tree = cpu_to_le32(1);
SET_BCH_SNAPSHOT_SUBVOL(&root_snapshot.v, true);
ret = bch2_btree_insert(c, BTREE_ID_snapshots,
......@@ -1135,8 +1144,12 @@ int bch2_fs_recovery(struct bch_fs *c)
}
if (!c->opts.nochanges) {
if (c->sb.version < bcachefs_metadata_version_no_bps_in_alloc_keys) {
bch_info(c, "version prior to no_bps_in_alloc_keys, upgrade and fsck required");
if (c->sb.version < bcachefs_metadata_required_upgrade_below) {
bch_info(c, "version %s (%u) prior to %s (%u), upgrade and fsck required",
bch2_metadata_versions[c->sb.version],
c->sb.version,
bch2_metadata_versions[bcachefs_metadata_required_upgrade_below],
bcachefs_metadata_required_upgrade_below);
c->opts.version_upgrade = true;
c->opts.fsck = true;
c->opts.fix_errors = FSCK_OPT_YES;
......
This diff is collapsed.
......@@ -5,6 +5,16 @@
#include "darray.h"
#include "subvolume_types.h"
void bch2_snapshot_tree_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
int bch2_snapshot_tree_invalid(const struct bch_fs *, struct bkey_s_c,
unsigned, struct printbuf *);
#define bch2_bkey_ops_snapshot_tree ((struct bkey_ops) { \
.key_invalid = bch2_snapshot_tree_invalid, \
.val_to_text = bch2_snapshot_tree_to_text, \
.min_val_size = 8, \
})
void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
int bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c,
unsigned, struct printbuf *);
......@@ -28,6 +38,15 @@ static inline u32 bch2_snapshot_parent(struct bch_fs *c, u32 id)
return snapshot_t(c, id)->parent;
}
static inline u32 bch2_snapshot_root(struct bch_fs *c, u32 id)
{
u32 parent;
while ((parent = bch2_snapshot_parent(c, id)))
id = parent;
return id;
}
static inline u32 bch2_snapshot_equiv(struct bch_fs *c, u32 id)
{
return snapshot_t(c, id)->equiv;
......@@ -107,6 +126,7 @@ static inline int snapshot_list_add(struct bch_fs *c, snapshot_id_list *s, u32 i
return ret;
}
int bch2_fs_check_snapshot_trees(struct bch_fs *);
int bch2_fs_check_snapshots(struct bch_fs *);
int bch2_fs_check_subvols(struct bch_fs *);
......
......@@ -10,6 +10,7 @@ struct snapshot_t {
u32 parent;
u32 children[2];
u32 subvol; /* Nonzero only if a subvolume points to this node: */
u32 tree;
u32 equiv;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment