mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-12 16:15:05 -04:00
bcachefs: BCH_MEMBER_RESIZE_ON_MOUNT
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
@@ -734,11 +734,6 @@ 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;
|
||||
@@ -892,6 +887,17 @@ int bch2_fs_recovery(struct bch_fs *c)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = bch2_fs_resize_on_mount(c);
|
||||
if (ret) {
|
||||
up_write(&c->state_lock);
|
||||
goto err;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
@@ -954,6 +960,8 @@ int bch2_fs_recovery(struct bch_fs *c)
|
||||
set_bit(BCH_FS_btree_running, &c->flags);
|
||||
|
||||
ret = bch2_sb_set_upgrade_extra(c);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = bch2_run_recovery_passes(c);
|
||||
if (ret)
|
||||
|
||||
@@ -294,6 +294,7 @@ static void member_to_text(struct printbuf *out,
|
||||
|
||||
prt_printf(out, "Discard:\t%llu\n", BCH_MEMBER_DISCARD(&m));
|
||||
prt_printf(out, "Freespace initialized:\t%llu\n", BCH_MEMBER_FREESPACE_INITIALIZED(&m));
|
||||
prt_printf(out, "Resize on mount:\t%llu\n", BCH_MEMBER_RESIZE_ON_MOUNT(&m));
|
||||
|
||||
printbuf_indent_sub(out, 2);
|
||||
}
|
||||
|
||||
@@ -353,6 +353,7 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
|
||||
? BCH_MEMBER_DURABILITY(mi) - 1
|
||||
: 1,
|
||||
.freespace_initialized = BCH_MEMBER_FREESPACE_INITIALIZED(mi),
|
||||
.resize_on_mount = BCH_MEMBER_RESIZE_ON_MOUNT(mi),
|
||||
.valid = bch2_member_alive(mi),
|
||||
.btree_bitmap_shift = mi->btree_bitmap_shift,
|
||||
.btree_allocated_bitmap = le64_to_cpu(mi->btree_allocated_bitmap),
|
||||
|
||||
@@ -88,6 +88,8 @@ LE64_BITMASK(BCH_MEMBER_GROUP, struct bch_member, flags, 20, 28)
|
||||
LE64_BITMASK(BCH_MEMBER_DURABILITY, struct bch_member, flags, 28, 30)
|
||||
LE64_BITMASK(BCH_MEMBER_FREESPACE_INITIALIZED,
|
||||
struct bch_member, flags, 30, 31)
|
||||
LE64_BITMASK(BCH_MEMBER_RESIZE_ON_MOUNT,
|
||||
struct bch_member, flags, 31, 32)
|
||||
|
||||
#if 0
|
||||
LE64_BITMASK(BCH_MEMBER_NR_READ_ERRORS, struct bch_member, flags[1], 0, 20);
|
||||
|
||||
@@ -13,6 +13,7 @@ struct bch_member_cpu {
|
||||
u8 data_allowed;
|
||||
u8 durability;
|
||||
u8 freespace_initialized;
|
||||
u8 resize_on_mount;
|
||||
u8 valid;
|
||||
u8 btree_bitmap_shift;
|
||||
u64 btree_allocated_bitmap;
|
||||
|
||||
@@ -1141,6 +1141,9 @@ int bch2_fs_start(struct bch_fs *c)
|
||||
for_each_online_member(c, ca)
|
||||
bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount = cpu_to_le64(now);
|
||||
|
||||
/*
|
||||
* Dno't write superblock yet: recovery might have to downgrade
|
||||
*/
|
||||
mutex_unlock(&c->sb_lock);
|
||||
|
||||
for_each_rw_member(c, ca)
|
||||
@@ -2039,6 +2042,18 @@ int bch2_dev_offline(struct bch_fs *c, struct bch_dev *ca, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __bch2_dev_resize_alloc(struct bch_dev *ca, u64 old_nbuckets, u64 new_nbuckets)
|
||||
{
|
||||
struct bch_fs *c = ca->fs;
|
||||
u64 v[3] = { new_nbuckets - old_nbuckets, 0, 0 };
|
||||
|
||||
return bch2_trans_commit_do(ca->fs, NULL, NULL, 0,
|
||||
bch2_disk_accounting_mod2(trans, false, v, dev_data_type,
|
||||
.dev = ca->dev_idx,
|
||||
.data_type = BCH_DATA_free)) ?:
|
||||
bch2_dev_freespace_init(c, ca, old_nbuckets, new_nbuckets);
|
||||
}
|
||||
|
||||
int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
|
||||
{
|
||||
struct bch_member *m;
|
||||
@@ -2086,13 +2101,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
|
||||
mutex_unlock(&c->sb_lock);
|
||||
|
||||
if (ca->mi.freespace_initialized) {
|
||||
u64 v[3] = { nbuckets - old_nbuckets, 0, 0 };
|
||||
|
||||
ret = bch2_trans_commit_do(ca->fs, NULL, NULL, 0,
|
||||
bch2_disk_accounting_mod2(trans, false, v, dev_data_type,
|
||||
.dev = ca->dev_idx,
|
||||
.data_type = BCH_DATA_free)) ?:
|
||||
bch2_dev_freespace_init(c, ca, old_nbuckets, nbuckets);
|
||||
ret = __bch2_dev_resize_alloc(ca, old_nbuckets, nbuckets);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
@@ -2103,6 +2112,47 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_fs_resize_on_mount(struct bch_fs *c)
|
||||
{
|
||||
for_each_online_member(c, ca) {
|
||||
u64 old_nbuckets = ca->mi.nbuckets;
|
||||
u64 new_nbuckets = div64_u64(get_capacity(ca->disk_sb.bdev->bd_disk),
|
||||
ca->mi.bucket_size);
|
||||
|
||||
if (ca->mi.resize_on_mount &&
|
||||
new_nbuckets > ca->mi.nbuckets) {
|
||||
bch_info(ca, "resizing to size %llu", new_nbuckets * ca->mi.bucket_size);
|
||||
int ret = bch2_dev_buckets_resize(c, ca, new_nbuckets);
|
||||
bch_err_fn(ca, ret);
|
||||
if (ret) {
|
||||
percpu_ref_put(&ca->io_ref[READ]);
|
||||
up_write(&c->state_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&c->sb_lock);
|
||||
struct bch_member *m =
|
||||
bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
|
||||
m->nbuckets = cpu_to_le64(new_nbuckets);
|
||||
SET_BCH_MEMBER_RESIZE_ON_MOUNT(m, false);
|
||||
|
||||
c->disk_sb.sb->features[0] &= ~cpu_to_le64(BIT_ULL(BCH_FEATURE_small_image));
|
||||
bch2_write_super(c);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
|
||||
if (ca->mi.freespace_initialized) {
|
||||
ret = __bch2_dev_resize_alloc(ca, old_nbuckets, new_nbuckets);
|
||||
if (ret) {
|
||||
percpu_ref_put(&ca->io_ref[READ]);
|
||||
up_write(&c->state_lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return with ref on ca->ref: */
|
||||
struct bch_dev *bch2_dev_lookup(struct bch_fs *c, const char *name)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,8 @@ void bch2_fs_read_only(struct bch_fs *);
|
||||
int bch2_fs_read_write(struct bch_fs *);
|
||||
int bch2_fs_read_write_early(struct bch_fs *);
|
||||
|
||||
int bch2_fs_resize_on_mount(struct bch_fs *);
|
||||
|
||||
void __bch2_fs_stop(struct bch_fs *);
|
||||
void bch2_fs_free(struct bch_fs *);
|
||||
void bch2_fs_stop(struct bch_fs *);
|
||||
|
||||
Reference in New Issue
Block a user