mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 16:37:50 +00:00
bcachefs: Normal update/commit path now works before going RW
This improves __bch2_trans_commit - early in the recovery process, when we're running btree_gc and before we want to go RW, it now uses bch2_journal_key_insert() to add the update to the list of updates for journal replay to do, instead of btree_gc having to use separate interfaces depending on whether we're running at bringup or, later, runtime. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
b66b2bc0f6
commit
78c8fe20be
5 changed files with 61 additions and 47 deletions
|
@ -515,6 +515,7 @@ enum {
|
||||||
BCH_FS_TOPOLOGY_REPAIR_DONE,
|
BCH_FS_TOPOLOGY_REPAIR_DONE,
|
||||||
BCH_FS_FSCK_DONE,
|
BCH_FS_FSCK_DONE,
|
||||||
BCH_FS_STARTED,
|
BCH_FS_STARTED,
|
||||||
|
BCH_FS_MAY_GO_RW,
|
||||||
BCH_FS_RW,
|
BCH_FS_RW,
|
||||||
BCH_FS_WAS_RW,
|
BCH_FS_WAS_RW,
|
||||||
|
|
||||||
|
|
|
@ -753,7 +753,8 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
|
||||||
atomic64_set(&c->key_version, k->k->version.lo);
|
atomic64_set(&c->key_version, k->k->version.lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bch2_mark_key(trans, old, *k, flags);
|
ret = __bch2_trans_do(trans, NULL, NULL, 0,
|
||||||
|
bch2_mark_key(trans, old, *k, flags));
|
||||||
fsck_err:
|
fsck_err:
|
||||||
err:
|
err:
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1259,7 +1260,7 @@ static int bch2_gc_start(struct bch_fs *c,
|
||||||
|
|
||||||
static int bch2_alloc_write_key(struct btree_trans *trans,
|
static int bch2_alloc_write_key(struct btree_trans *trans,
|
||||||
struct btree_iter *iter,
|
struct btree_iter *iter,
|
||||||
bool initial, bool metadata_only)
|
bool metadata_only)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
struct bch_dev *ca = bch_dev_bkey_exists(c, iter->pos.inode);
|
struct bch_dev *ca = bch_dev_bkey_exists(c, iter->pos.inode);
|
||||||
|
@ -1327,14 +1328,12 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
|
||||||
if (IS_ERR(a))
|
if (IS_ERR(a))
|
||||||
return PTR_ERR(a);
|
return PTR_ERR(a);
|
||||||
|
|
||||||
ret = initial
|
ret = bch2_trans_update(trans, iter, &a->k, BTREE_TRIGGER_NORUN);
|
||||||
? bch2_journal_key_insert(c, BTREE_ID_alloc, 0, &a->k)
|
|
||||||
: bch2_trans_update(trans, iter, &a->k, BTREE_TRIGGER_NORUN);
|
|
||||||
fsck_err:
|
fsck_err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bch2_gc_alloc_done(struct bch_fs *c, bool initial, bool metadata_only)
|
static int bch2_gc_alloc_done(struct bch_fs *c, bool metadata_only)
|
||||||
{
|
{
|
||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
|
@ -1356,7 +1355,7 @@ static int bch2_gc_alloc_done(struct bch_fs *c, bool initial, bool metadata_only
|
||||||
ret = __bch2_trans_do(&trans, NULL, NULL,
|
ret = __bch2_trans_do(&trans, NULL, NULL,
|
||||||
BTREE_INSERT_LAZY_RW,
|
BTREE_INSERT_LAZY_RW,
|
||||||
bch2_alloc_write_key(&trans, &iter,
|
bch2_alloc_write_key(&trans, &iter,
|
||||||
initial, metadata_only));
|
metadata_only));
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1373,7 +1372,7 @@ static int bch2_gc_alloc_done(struct bch_fs *c, bool initial, bool metadata_only
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bch2_gc_alloc_start(struct bch_fs *c, bool initial, bool metadata_only)
|
static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only)
|
||||||
{
|
{
|
||||||
struct bch_dev *ca;
|
struct bch_dev *ca;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -1397,7 +1396,7 @@ static int bch2_gc_alloc_start(struct bch_fs *c, bool initial, bool metadata_onl
|
||||||
return bch2_alloc_read(c, true, metadata_only);
|
return bch2_alloc_read(c, true, metadata_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bch2_gc_alloc_reset(struct bch_fs *c, bool initial, bool metadata_only)
|
static void bch2_gc_alloc_reset(struct bch_fs *c, bool metadata_only)
|
||||||
{
|
{
|
||||||
struct bch_dev *ca;
|
struct bch_dev *ca;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -1418,8 +1417,7 @@ static void bch2_gc_alloc_reset(struct bch_fs *c, bool initial, bool metadata_on
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
|
static int bch2_gc_reflink_done(struct bch_fs *c, bool metadata_only)
|
||||||
bool metadata_only)
|
|
||||||
{
|
{
|
||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
|
@ -1466,22 +1464,12 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
|
||||||
|
|
||||||
bkey_reassemble(new, k);
|
bkey_reassemble(new, k);
|
||||||
|
|
||||||
if (!r->refcount) {
|
if (!r->refcount)
|
||||||
new->k.type = KEY_TYPE_deleted;
|
new->k.type = KEY_TYPE_deleted;
|
||||||
/*
|
else
|
||||||
* XXX ugly: bch2_journal_key_insert() queues up
|
|
||||||
* the key for the journal replay code, which
|
|
||||||
* doesn't run the extent overwrite pass
|
|
||||||
*/
|
|
||||||
if (initial)
|
|
||||||
new->k.size = 0;
|
|
||||||
} else {
|
|
||||||
*bkey_refcount(new) = cpu_to_le64(r->refcount);
|
*bkey_refcount(new) = cpu_to_le64(r->refcount);
|
||||||
}
|
|
||||||
|
|
||||||
ret = initial
|
ret = __bch2_trans_do(&trans, NULL, NULL, 0,
|
||||||
? bch2_journal_key_insert(c, BTREE_ID_stripes, 0, new)
|
|
||||||
: __bch2_trans_do(&trans, NULL, NULL, 0,
|
|
||||||
__bch2_btree_insert(&trans, BTREE_ID_reflink, new));
|
__bch2_btree_insert(&trans, BTREE_ID_reflink, new));
|
||||||
kfree(new);
|
kfree(new);
|
||||||
|
|
||||||
|
@ -1496,7 +1484,7 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bch2_gc_reflink_start(struct bch_fs *c, bool initial,
|
static int bch2_gc_reflink_start(struct bch_fs *c,
|
||||||
bool metadata_only)
|
bool metadata_only)
|
||||||
{
|
{
|
||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
|
@ -1535,8 +1523,7 @@ static int bch2_gc_reflink_start(struct bch_fs *c, bool initial,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bch2_gc_reflink_reset(struct bch_fs *c, bool initial,
|
static void bch2_gc_reflink_reset(struct bch_fs *c, bool metadata_only)
|
||||||
bool metadata_only)
|
|
||||||
{
|
{
|
||||||
struct genradix_iter iter;
|
struct genradix_iter iter;
|
||||||
struct reflink_gc *r;
|
struct reflink_gc *r;
|
||||||
|
@ -1545,8 +1532,7 @@ static void bch2_gc_reflink_reset(struct bch_fs *c, bool initial,
|
||||||
r->refcount = 0;
|
r->refcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bch2_gc_stripes_done(struct bch_fs *c, bool initial,
|
static int bch2_gc_stripes_done(struct bch_fs *c, bool metadata_only)
|
||||||
bool metadata_only)
|
|
||||||
{
|
{
|
||||||
struct btree_trans trans;
|
struct btree_trans trans;
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
|
@ -1594,9 +1580,7 @@ static int bch2_gc_stripes_done(struct bch_fs *c, bool initial,
|
||||||
for (i = 0; i < new->v.nr_blocks; i++)
|
for (i = 0; i < new->v.nr_blocks; i++)
|
||||||
stripe_blockcount_set(&new->v, i, m ? m->block_sectors[i] : 0);
|
stripe_blockcount_set(&new->v, i, m ? m->block_sectors[i] : 0);
|
||||||
|
|
||||||
ret = initial
|
ret = __bch2_trans_do(&trans, NULL, NULL, 0,
|
||||||
? bch2_journal_key_insert(c, BTREE_ID_stripes, 0, &new->k_i)
|
|
||||||
: __bch2_trans_do(&trans, NULL, NULL, 0,
|
|
||||||
__bch2_btree_insert(&trans, BTREE_ID_reflink, &new->k_i));
|
__bch2_btree_insert(&trans, BTREE_ID_reflink, &new->k_i));
|
||||||
kfree(new);
|
kfree(new);
|
||||||
}
|
}
|
||||||
|
@ -1608,8 +1592,7 @@ static int bch2_gc_stripes_done(struct bch_fs *c, bool initial,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bch2_gc_stripes_reset(struct bch_fs *c, bool initial,
|
static void bch2_gc_stripes_reset(struct bch_fs *c, bool metadata_only)
|
||||||
bool metadata_only)
|
|
||||||
{
|
{
|
||||||
genradix_free(&c->gc_stripes);
|
genradix_free(&c->gc_stripes);
|
||||||
}
|
}
|
||||||
|
@ -1649,8 +1632,8 @@ int bch2_gc(struct bch_fs *c, bool initial, bool metadata_only)
|
||||||
!bch2_btree_interior_updates_nr_pending(c));
|
!bch2_btree_interior_updates_nr_pending(c));
|
||||||
|
|
||||||
ret = bch2_gc_start(c, metadata_only) ?:
|
ret = bch2_gc_start(c, metadata_only) ?:
|
||||||
bch2_gc_alloc_start(c, initial, metadata_only) ?:
|
bch2_gc_alloc_start(c, metadata_only) ?:
|
||||||
bch2_gc_reflink_start(c, initial, metadata_only);
|
bch2_gc_reflink_start(c, metadata_only);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
again:
|
again:
|
||||||
|
@ -1705,9 +1688,9 @@ int bch2_gc(struct bch_fs *c, bool initial, bool metadata_only)
|
||||||
clear_bit(BCH_FS_NEED_ANOTHER_GC, &c->flags);
|
clear_bit(BCH_FS_NEED_ANOTHER_GC, &c->flags);
|
||||||
__gc_pos_set(c, gc_phase(GC_PHASE_NOT_RUNNING));
|
__gc_pos_set(c, gc_phase(GC_PHASE_NOT_RUNNING));
|
||||||
|
|
||||||
bch2_gc_stripes_reset(c, initial, metadata_only);
|
bch2_gc_stripes_reset(c, metadata_only);
|
||||||
bch2_gc_alloc_reset(c, initial, metadata_only);
|
bch2_gc_alloc_reset(c, metadata_only);
|
||||||
bch2_gc_reflink_reset(c, initial, metadata_only);
|
bch2_gc_reflink_reset(c, metadata_only);
|
||||||
|
|
||||||
/* flush fsck errors, reset counters */
|
/* flush fsck errors, reset counters */
|
||||||
bch2_flush_fsck_errs(c);
|
bch2_flush_fsck_errs(c);
|
||||||
|
@ -1717,9 +1700,9 @@ int bch2_gc(struct bch_fs *c, bool initial, bool metadata_only)
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
bch2_journal_block(&c->journal);
|
bch2_journal_block(&c->journal);
|
||||||
|
|
||||||
ret = bch2_gc_stripes_done(c, initial, metadata_only) ?:
|
ret = bch2_gc_stripes_done(c, metadata_only) ?:
|
||||||
bch2_gc_reflink_done(c, initial, metadata_only) ?:
|
bch2_gc_reflink_done(c, metadata_only) ?:
|
||||||
bch2_gc_alloc_done(c, initial, metadata_only) ?:
|
bch2_gc_alloc_done(c, metadata_only) ?:
|
||||||
bch2_gc_done(c, initial, metadata_only);
|
bch2_gc_done(c, initial, metadata_only);
|
||||||
|
|
||||||
bch2_journal_unblock(&c->journal);
|
bch2_journal_unblock(&c->journal);
|
||||||
|
|
|
@ -968,6 +968,27 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is for updates done in the early part of fsck - btree_gc - before we've
|
||||||
|
* gone RW. we only add the new key to the list of keys for journal replay to
|
||||||
|
* do.
|
||||||
|
*/
|
||||||
|
static noinline int
|
||||||
|
do_bch2_trans_commit_to_journal_replay(struct btree_trans *trans)
|
||||||
|
{
|
||||||
|
struct bch_fs *c = trans->c;
|
||||||
|
struct btree_insert_entry *i;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
trans_for_each_update(trans, i) {
|
||||||
|
ret = bch2_journal_key_insert(c, i->btree_id, i->level, i->k);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int __bch2_trans_commit(struct btree_trans *trans)
|
int __bch2_trans_commit(struct btree_trans *trans)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
|
@ -986,6 +1007,11 @@ int __bch2_trans_commit(struct btree_trans *trans)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_reset;
|
goto out_reset;
|
||||||
|
|
||||||
|
if (unlikely(!test_bit(BCH_FS_MAY_GO_RW, &c->flags))) {
|
||||||
|
ret = do_bch2_trans_commit_to_journal_replay(trans);
|
||||||
|
goto out_reset;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(trans->flags & BTREE_INSERT_NOCHECK_RW) &&
|
if (!(trans->flags & BTREE_INSERT_NOCHECK_RW) &&
|
||||||
unlikely(!percpu_ref_tryget(&c->writes))) {
|
unlikely(!percpu_ref_tryget(&c->writes))) {
|
||||||
ret = bch2_trans_commit_get_rw_cold(trans);
|
ret = bch2_trans_commit_get_rw_cold(trans);
|
||||||
|
|
|
@ -1164,9 +1164,11 @@ static int bch2_mark_reservation(struct btree_trans *trans,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s64 __bch2_mark_reflink_p(struct bch_fs *c, struct bkey_s_c_reflink_p p,
|
static s64 __bch2_mark_reflink_p(struct btree_trans *trans,
|
||||||
|
struct bkey_s_c_reflink_p p,
|
||||||
u64 *idx, unsigned flags, size_t r_idx)
|
u64 *idx, unsigned flags, size_t r_idx)
|
||||||
{
|
{
|
||||||
|
struct bch_fs *c = trans->c;
|
||||||
struct reflink_gc *r;
|
struct reflink_gc *r;
|
||||||
int add = !(flags & BTREE_TRIGGER_OVERWRITE) ? 1 : -1;
|
int add = !(flags & BTREE_TRIGGER_OVERWRITE) ? 1 : -1;
|
||||||
s64 ret = 0;
|
s64 ret = 0;
|
||||||
|
@ -1199,7 +1201,7 @@ static s64 __bch2_mark_reflink_p(struct bch_fs *c, struct bkey_s_c_reflink_p p,
|
||||||
new.k.type = KEY_TYPE_error;
|
new.k.type = KEY_TYPE_error;
|
||||||
new.k.p = p.k->p;
|
new.k.p = p.k->p;
|
||||||
new.k.size = p.k->size;
|
new.k.size = p.k->size;
|
||||||
ret = bch2_journal_key_insert(c, BTREE_ID_extents, 0, &new.k_i);
|
ret = __bch2_btree_insert(trans, BTREE_ID_extents, &new.k_i);
|
||||||
}
|
}
|
||||||
fsck_err:
|
fsck_err:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1238,7 +1240,7 @@ static int bch2_mark_reflink_p(struct btree_trans *trans,
|
||||||
}
|
}
|
||||||
|
|
||||||
while (idx < end && !ret)
|
while (idx < end && !ret)
|
||||||
ret = __bch2_mark_reflink_p(c, p, &idx, flags, l++);
|
ret = __bch2_mark_reflink_p(trans, p, &idx, flags, l++);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1157,6 +1157,7 @@ int bch2_fs_recovery(struct bch_fs *c)
|
||||||
|
|
||||||
clear_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
|
clear_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
|
||||||
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
|
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
|
||||||
|
set_bit(BCH_FS_MAY_GO_RW, &c->flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip past versions that might have possibly been used (as nonces),
|
* Skip past versions that might have possibly been used (as nonces),
|
||||||
|
@ -1317,6 +1318,7 @@ int bch2_fs_initialize(struct bch_fs *c)
|
||||||
mutex_unlock(&c->sb_lock);
|
mutex_unlock(&c->sb_lock);
|
||||||
|
|
||||||
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
|
set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
|
||||||
|
set_bit(BCH_FS_MAY_GO_RW, &c->flags);
|
||||||
set_bit(BCH_FS_FSCK_DONE, &c->flags);
|
set_bit(BCH_FS_FSCK_DONE, &c->flags);
|
||||||
|
|
||||||
for (i = 0; i < BTREE_ID_NR; i++)
|
for (i = 0; i < BTREE_ID_NR; i++)
|
||||||
|
|
Loading…
Reference in a new issue