bcachefs: BCH_FEATURE_small_image

We can't go RW if it's an image file that hasn't been resized.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2025-04-15 15:15:36 -04:00
parent 203852d9db
commit 530112d88e
7 changed files with 38 additions and 15 deletions

View File

@ -2392,14 +2392,16 @@ int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
int bch2_fs_freespace_init(struct bch_fs *c)
{
int ret = 0;
bool doing_init = false;
if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image))
return 0;
/*
* We can crash during the device add path, so we need to check this on
* every mount:
*/
bool doing_init = false;
for_each_member_device(c, ca) {
if (ca->mi.freespace_initialized)
continue;
@ -2409,7 +2411,7 @@ int bch2_fs_freespace_init(struct bch_fs *c)
doing_init = true;
}
ret = bch2_dev_freespace_init(c, ca, 0, ca->mi.nbuckets);
int ret = bch2_dev_freespace_init(c, ca, 0, ca->mi.nbuckets);
if (ret) {
bch2_dev_put(ca);
bch_err_fn(c, ret);

View File

@ -924,7 +924,8 @@ static inline void SET_BCH_SB_BACKGROUND_COMPRESSION_TYPE(struct bch_sb *sb, __u
x(extents_across_btree_nodes, 18) \
x(incompat_version_field, 19) \
x(casefolding, 20) \
x(no_alloc_info, 21)
x(no_alloc_info, 21) \
x(small_image, 22)
#define BCH_SB_FEATURES_ALWAYS \
(BIT_ULL(BCH_FEATURE_new_extent_overwrite)| \

View File

@ -222,6 +222,7 @@
x(EROFS, erofs_norecovery) \
x(EROFS, erofs_nochanges) \
x(EROFS, erofs_no_alloc_info) \
x(EROFS, erofs_filesystem_full) \
x(EROFS, insufficient_devices) \
x(0, operation_blocked) \
x(BCH_ERR_operation_blocked, btree_cache_cannibalize_lock_blocked) \

View File

@ -1295,9 +1295,16 @@ int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca,
int bch2_dev_journal_alloc(struct bch_dev *ca, bool new_fs)
{
struct bch_fs *c = ca->fs;
if (!(ca->mi.data_allowed & BIT(BCH_DATA_journal)))
return 0;
if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image)) {
bch_err(c, "cannot allocate journal, filesystem is an unresized image file");
return -BCH_ERR_erofs_filesystem_full;
}
unsigned nr;
int ret;
@ -1318,7 +1325,7 @@ int bch2_dev_journal_alloc(struct bch_dev *ca, bool new_fs)
min(1 << 13,
(1 << 24) / ca->mi.bucket_size));
ret = bch2_set_nr_journal_buckets_loop(ca->fs, ca, nr, new_fs);
ret = bch2_set_nr_journal_buckets_loop(c, ca, nr, new_fs);
err:
bch_err_fn(ca, ret);
return ret;

View File

@ -215,18 +215,20 @@ void bch2_journal_space_available(struct journal *j)
j->can_discard = can_discard;
if (nr_online < metadata_replicas_required(c)) {
struct printbuf buf = PRINTBUF;
buf.atomic++;
prt_printf(&buf, "insufficient writeable journal devices available: have %u, need %u\n"
"rw journal devs:", nr_online, metadata_replicas_required(c));
if (!(c->sb.features & BIT_ULL(BCH_FEATURE_small_image))) {
struct printbuf buf = PRINTBUF;
buf.atomic++;
prt_printf(&buf, "insufficient writeable journal devices available: have %u, need %u\n"
"rw journal devs:", nr_online, metadata_replicas_required(c));
rcu_read_lock();
for_each_member_device_rcu(c, ca, &c->rw_devs[BCH_DATA_journal])
prt_printf(&buf, " %s", ca->name);
rcu_read_unlock();
rcu_read_lock();
for_each_member_device_rcu(c, ca, &c->rw_devs[BCH_DATA_journal])
prt_printf(&buf, " %s", ca->name);
rcu_read_unlock();
bch_err(c, "%s", buf.buf);
printbuf_exit(&buf);
bch_err(c, "%s", buf.buf);
printbuf_exit(&buf);
}
ret = -BCH_ERR_insufficient_journal_devices;
goto out;
}

View File

@ -734,6 +734,11 @@ int bch2_fs_recovery(struct bch_fs *c)
c->opts.read_only = true;
}
if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image)) {
bch_info(c, "filesystem is an unresized image file, mounting ro");
c->opts.read_only = true;
}
mutex_lock(&c->sb_lock);
struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
bool write_sb = false;

View File

@ -451,6 +451,11 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early)
return -BCH_ERR_erofs_unfixed_errors;
}
if (c->sb.features & BIT_ULL(BCH_FEATURE_small_image)) {
bch_err(c, "cannot go rw, filesystem is an unresized image file");
return -BCH_ERR_erofs_filesystem_full;
}
if (test_bit(BCH_FS_rw, &c->flags))
return 0;