mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
bcachefs: BCH_FEATURE_no_alloc_info
If a filesystem is going to only be used read-only, and will be a deployable image, we can strip out alloc info for a substantial reduction in metadata size - around half, due to backpointers. Alloc info will be regenerated on first read-write mount. Remounting RW is disallowed for now, since we don't yet have check_allocations running in RW mode. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
576493133f
commit
203852d9db
|
|
@ -923,7 +923,8 @@ static inline void SET_BCH_SB_BACKGROUND_COMPRESSION_TYPE(struct bch_sb *sb, __u
|
|||
x(alloc_v2, 17) \
|
||||
x(extents_across_btree_nodes, 18) \
|
||||
x(incompat_version_field, 19) \
|
||||
x(casefolding, 20)
|
||||
x(casefolding, 20) \
|
||||
x(no_alloc_info, 21)
|
||||
|
||||
#define BCH_SB_FEATURES_ALWAYS \
|
||||
(BIT_ULL(BCH_FEATURE_new_extent_overwrite)| \
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@
|
|||
x(EROFS, erofs_unfixed_errors) \
|
||||
x(EROFS, erofs_norecovery) \
|
||||
x(EROFS, erofs_nochanges) \
|
||||
x(EROFS, erofs_no_alloc_info) \
|
||||
x(EROFS, insufficient_devices) \
|
||||
x(0, operation_blocked) \
|
||||
x(BCH_ERR_operation_blocked, btree_cache_cannibalize_lock_blocked) \
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include <linux/sort.h>
|
||||
#include <linux/stat.h>
|
||||
|
||||
|
||||
int bch2_btree_lost_data(struct bch_fs *c, enum btree_id btree)
|
||||
{
|
||||
u64 b = BIT_ULL(btree);
|
||||
|
|
@ -114,11 +113,8 @@ static void kill_btree(struct bch_fs *c, enum btree_id btree)
|
|||
}
|
||||
|
||||
/* for -o reconstruct_alloc: */
|
||||
static void bch2_reconstruct_alloc(struct bch_fs *c)
|
||||
void bch2_reconstruct_alloc(struct bch_fs *c)
|
||||
{
|
||||
bch2_journal_log_msg(c, "dropping alloc info");
|
||||
bch_info(c, "dropping and reconstructing all alloc info");
|
||||
|
||||
mutex_lock(&c->sb_lock);
|
||||
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
|
||||
|
||||
|
|
@ -160,6 +156,8 @@ static void bch2_reconstruct_alloc(struct bch_fs *c)
|
|||
|
||||
c->opts.recovery_passes |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
|
||||
|
||||
c->disk_sb.sb->features[0] &= ~cpu_to_le64(BIT_ULL(BCH_FEATURE_no_alloc_info));
|
||||
|
||||
bch2_write_super(c);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
|
||||
|
|
@ -889,8 +887,26 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (c->opts.reconstruct_alloc)
|
||||
if (!c->opts.read_only &&
|
||||
(c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info))) {
|
||||
bch_info(c, "mounting a filesystem with no alloc info read-write; will recreate");
|
||||
|
||||
bch2_reconstruct_alloc(c);
|
||||
} else if (c->opts.reconstruct_alloc) {
|
||||
bch2_journal_log_msg(c, "dropping alloc info");
|
||||
bch_info(c, "dropping and reconstructing all alloc info");
|
||||
|
||||
bch2_reconstruct_alloc(c);
|
||||
}
|
||||
|
||||
if (c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)) {
|
||||
/* We can't go RW to fix errors without alloc info */
|
||||
if (c->opts.fix_errors == FSCK_FIX_yes ||
|
||||
c->opts.fix_errors == FSCK_FIX_ask)
|
||||
c->opts.fix_errors = FSCK_FIX_no;
|
||||
if (c->opts.errors == BCH_ON_ERROR_fix_safe)
|
||||
c->opts.errors = BCH_ON_ERROR_continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* After an unclean shutdown, skip then next few journal sequence
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#define _BCACHEFS_RECOVERY_H
|
||||
|
||||
int bch2_btree_lost_data(struct bch_fs *, enum btree_id);
|
||||
void bch2_reconstruct_alloc(struct bch_fs *);
|
||||
|
||||
int bch2_journal_replay(struct bch_fs *);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,18 @@ static int bch2_set_may_go_rw(struct bch_fs *c)
|
|||
|
||||
set_bit(BCH_FS_may_go_rw, &c->flags);
|
||||
|
||||
if (keys->nr || !c->opts.read_only || c->opts.fsck || !c->sb.clean || c->opts.recovery_passes)
|
||||
if (keys->nr ||
|
||||
!c->opts.read_only ||
|
||||
!c->sb.clean ||
|
||||
c->opts.recovery_passes ||
|
||||
(c->opts.fsck && !(c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)))) {
|
||||
if (c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)) {
|
||||
bch_info(c, "mounting a filesystem with no alloc info read-write; will recreate");
|
||||
bch2_reconstruct_alloc(c);
|
||||
}
|
||||
|
||||
return bch2_fs_read_write_early(c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -240,6 +250,8 @@ static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pa
|
|||
{
|
||||
struct recovery_pass_fn *p = recovery_pass_fns + pass;
|
||||
|
||||
if ((p->when & PASS_ALLOC) && (c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)))
|
||||
return false;
|
||||
if (c->opts.recovery_passes_exclude & BIT_ULL(pass))
|
||||
return false;
|
||||
if (c->opts.recovery_passes & BIT_ULL(pass))
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#define PASS_UNCLEAN BIT(2)
|
||||
#define PASS_ALWAYS BIT(3)
|
||||
#define PASS_ONLINE BIT(4)
|
||||
#define PASS_ALLOC BIT(5)
|
||||
#define PASS_FSCK_ALLOC (PASS_FSCK|PASS_ALLOC)
|
||||
|
||||
#ifdef CONFIG_BCACHEFS_DEBUG
|
||||
#define PASS_FSCK_DEBUG BIT(1)
|
||||
|
|
@ -27,17 +29,17 @@
|
|||
x(stripes_read, 1, 0) \
|
||||
x(initialize_subvolumes, 2, 0) \
|
||||
x(snapshots_read, 3, PASS_ALWAYS) \
|
||||
x(check_allocations, 5, PASS_FSCK) \
|
||||
x(trans_mark_dev_sbs, 6, PASS_ALWAYS|PASS_SILENT) \
|
||||
x(fs_journal_alloc, 7, PASS_ALWAYS|PASS_SILENT) \
|
||||
x(check_allocations, 5, PASS_FSCK_ALLOC) \
|
||||
x(trans_mark_dev_sbs, 6, PASS_ALWAYS|PASS_SILENT|PASS_ALLOC) \
|
||||
x(fs_journal_alloc, 7, PASS_ALWAYS|PASS_SILENT|PASS_ALLOC) \
|
||||
x(set_may_go_rw, 8, PASS_ALWAYS|PASS_SILENT) \
|
||||
x(journal_replay, 9, PASS_ALWAYS) \
|
||||
x(check_alloc_info, 10, PASS_ONLINE|PASS_FSCK) \
|
||||
x(check_lrus, 11, PASS_ONLINE|PASS_FSCK) \
|
||||
x(check_btree_backpointers, 12, PASS_ONLINE|PASS_FSCK) \
|
||||
x(check_alloc_info, 10, PASS_ONLINE|PASS_FSCK_ALLOC) \
|
||||
x(check_lrus, 11, PASS_ONLINE|PASS_FSCK_ALLOC) \
|
||||
x(check_btree_backpointers, 12, PASS_ONLINE|PASS_FSCK_ALLOC) \
|
||||
x(check_backpointers_to_extents, 13, PASS_ONLINE|PASS_FSCK_DEBUG) \
|
||||
x(check_extents_to_backpointers, 14, PASS_ONLINE|PASS_FSCK) \
|
||||
x(check_alloc_to_lru_refs, 15, PASS_ONLINE|PASS_FSCK) \
|
||||
x(check_extents_to_backpointers, 14, PASS_ONLINE|PASS_FSCK_ALLOC) \
|
||||
x(check_alloc_to_lru_refs, 15, PASS_ONLINE|PASS_FSCK_ALLOC) \
|
||||
x(fs_freespace_init, 16, PASS_ALWAYS|PASS_SILENT) \
|
||||
x(bucket_gens_init, 17, 0) \
|
||||
x(reconstruct_snapshots, 38, 0) \
|
||||
|
|
|
|||
|
|
@ -190,6 +190,12 @@ static int validate_member(struct printbuf *err,
|
|||
return -BCH_ERR_invalid_sb_members;
|
||||
}
|
||||
|
||||
if (BCH_MEMBER_FREESPACE_INITIALIZED(&m) &&
|
||||
sb->features[0] & cpu_to_le64(BIT_ULL(BCH_FEATURE_no_alloc_info))) {
|
||||
prt_printf(err, "device %u: freespace initialized but fs has no alloc info", i);
|
||||
return -BCH_ERR_invalid_sb_members;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -443,6 +443,9 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early)
|
|||
|
||||
BUG_ON(!test_bit(BCH_FS_may_go_rw, &c->flags));
|
||||
|
||||
if (WARN_ON(c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)))
|
||||
return -BCH_ERR_erofs_no_alloc_info;
|
||||
|
||||
if (test_bit(BCH_FS_initial_gc_unfixed, &c->flags)) {
|
||||
bch_err(c, "cannot go rw, unfixed btree errors");
|
||||
return -BCH_ERR_erofs_unfixed_errors;
|
||||
|
|
@ -535,6 +538,9 @@ int bch2_fs_read_write(struct bch_fs *c)
|
|||
if (c->opts.nochanges)
|
||||
return -BCH_ERR_erofs_nochanges;
|
||||
|
||||
if (c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info))
|
||||
return -BCH_ERR_erofs_no_alloc_info;
|
||||
|
||||
return __bch2_fs_read_write(c, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user