mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Update bcachefs sources to 42284b8b2b bcachefs: Fix race between btree updates & journal replay
This commit is contained in:
parent
a5bd96ff58
commit
8a632ea60d
@ -1 +1 @@
|
|||||||
9d28e4a535cac3b88104a4525dd39fc16175f38c
|
42284b8b2bb980c80140b640de7cb12bc1e4541c
|
||||||
|
@ -561,6 +561,7 @@ struct journal_keys {
|
|||||||
enum btree_id btree_id:8;
|
enum btree_id btree_id:8;
|
||||||
unsigned level:8;
|
unsigned level:8;
|
||||||
bool allocated;
|
bool allocated;
|
||||||
|
bool overwritten;
|
||||||
struct bkey_i *k;
|
struct bkey_i *k;
|
||||||
u32 journal_seq;
|
u32 journal_seq;
|
||||||
u32 journal_offset;
|
u32 journal_offset;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "journal.h"
|
#include "journal.h"
|
||||||
#include "journal_reclaim.h"
|
#include "journal_reclaim.h"
|
||||||
#include "keylist.h"
|
#include "keylist.h"
|
||||||
|
#include "recovery.h"
|
||||||
#include "subvolume.h"
|
#include "subvolume.h"
|
||||||
#include "replicas.h"
|
#include "replicas.h"
|
||||||
|
|
||||||
@ -624,6 +625,14 @@ fail:
|
|||||||
return btree_trans_restart(trans);
|
return btree_trans_restart(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static noinline void bch2_drop_overwrites_from_journal(struct btree_trans *trans)
|
||||||
|
{
|
||||||
|
struct btree_insert_entry *i;
|
||||||
|
|
||||||
|
trans_for_each_update(trans, i)
|
||||||
|
bch2_journal_key_overwritten(trans->c, i->btree_id, i->level, i->k->k.p);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get journal reservation, take write locks, and attempt to do btree update(s):
|
* Get journal reservation, take write locks, and attempt to do btree update(s):
|
||||||
*/
|
*/
|
||||||
@ -701,6 +710,9 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans,
|
|||||||
|
|
||||||
ret = bch2_trans_commit_write_locked(trans, stopped_at, trace_ip);
|
ret = bch2_trans_commit_write_locked(trans, stopped_at, trace_ip);
|
||||||
|
|
||||||
|
if (!ret && unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)))
|
||||||
|
bch2_drop_overwrites_from_journal(trans);
|
||||||
|
|
||||||
trans_for_each_update(trans, i)
|
trans_for_each_update(trans, i)
|
||||||
if (!same_leaf_as_prev(trans, i))
|
if (!same_leaf_as_prev(trans, i))
|
||||||
bch2_btree_node_unlock_write_inlined(trans, i->path,
|
bch2_btree_node_unlock_write_inlined(trans, i->path,
|
||||||
|
@ -531,20 +531,6 @@ void bch2_mark_alloc_bucket(struct bch_fs *c, struct bch_dev *ca,
|
|||||||
BUG_ON(owned_by_allocator == old.owned_by_allocator);
|
BUG_ON(owned_by_allocator == old.owned_by_allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 bkey_alloc_gen(struct bkey_s_c k)
|
|
||||||
{
|
|
||||||
switch (k.k->type) {
|
|
||||||
case KEY_TYPE_alloc:
|
|
||||||
return bkey_s_c_to_alloc(k).v->gen;
|
|
||||||
case KEY_TYPE_alloc_v2:
|
|
||||||
return bkey_s_c_to_alloc_v2(k).v->gen;
|
|
||||||
case KEY_TYPE_alloc_v3:
|
|
||||||
return bkey_s_c_to_alloc_v3(k).v->gen;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bch2_mark_alloc(struct btree_trans *trans,
|
static int bch2_mark_alloc(struct btree_trans *trans,
|
||||||
struct bkey_s_c old, struct bkey_s_c new,
|
struct bkey_s_c old, struct bkey_s_c new,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
@ -589,7 +575,7 @@ static int bch2_mark_alloc(struct btree_trans *trans,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
percpu_down_read(&c->mark_lock);
|
percpu_down_read(&c->mark_lock);
|
||||||
if (!gc && new_u.gen != bkey_alloc_gen(old))
|
if (!gc && new_u.gen != old_u.gen)
|
||||||
*bucket_gen(ca, new.k->p.offset) = new_u.gen;
|
*bucket_gen(ca, new.k->p.offset) = new_u.gen;
|
||||||
|
|
||||||
g = __bucket(ca, new.k->p.offset, gc);
|
g = __bucket(ca, new.k->p.offset, gc);
|
||||||
|
@ -558,20 +558,20 @@ static void journal_entry_dev_usage_to_text(struct printbuf *out, struct bch_fs
|
|||||||
container_of(entry, struct jset_entry_dev_usage, entry);
|
container_of(entry, struct jset_entry_dev_usage, entry);
|
||||||
unsigned i, nr_types = jset_entry_dev_usage_nr_types(u);
|
unsigned i, nr_types = jset_entry_dev_usage_nr_types(u);
|
||||||
|
|
||||||
pr_buf(out, "dev=%u ", le32_to_cpu(u->dev));
|
pr_buf(out, "dev=%u", le32_to_cpu(u->dev));
|
||||||
|
|
||||||
for (i = 0; i < nr_types; i++) {
|
for (i = 0; i < nr_types; i++) {
|
||||||
if (i < BCH_DATA_NR)
|
if (i < BCH_DATA_NR)
|
||||||
pr_buf(out, "%s", bch2_data_types[i]);
|
pr_buf(out, " %s", bch2_data_types[i]);
|
||||||
else
|
else
|
||||||
pr_buf(out, "(unknown data type %u)", i);
|
pr_buf(out, " (unknown data type %u)", i);
|
||||||
pr_buf(out, ": buckets=%llu sectors=%llu fragmented=%llu",
|
pr_buf(out, ": buckets=%llu sectors=%llu fragmented=%llu",
|
||||||
le64_to_cpu(u->d[i].buckets),
|
le64_to_cpu(u->d[i].buckets),
|
||||||
le64_to_cpu(u->d[i].sectors),
|
le64_to_cpu(u->d[i].sectors),
|
||||||
le64_to_cpu(u->d[i].fragmented));
|
le64_to_cpu(u->d[i].fragmented));
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_buf(out, "buckets_ec: %llu buckets_unavailable: %llu",
|
pr_buf(out, " buckets_ec: %llu buckets_unavailable: %llu",
|
||||||
le64_to_cpu(u->buckets_ec),
|
le64_to_cpu(u->buckets_ec),
|
||||||
le64_to_cpu(u->buckets_unavailable));
|
le64_to_cpu(u->buckets_unavailable));
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,19 @@ int bch2_journal_key_delete(struct bch_fs *c, enum btree_id id,
|
|||||||
return bch2_journal_key_insert(c, id, level, &whiteout);
|
return bch2_journal_key_insert(c, id, level, &whiteout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bch2_journal_key_overwritten(struct bch_fs *c, enum btree_id btree,
|
||||||
|
unsigned level, struct bpos pos)
|
||||||
|
{
|
||||||
|
struct journal_keys *keys = &c->journal_keys;
|
||||||
|
size_t idx = journal_key_search(keys, btree, level, pos);
|
||||||
|
|
||||||
|
if (idx < keys->nr &&
|
||||||
|
keys->d[idx].btree_id == btree &&
|
||||||
|
keys->d[idx].level == level &&
|
||||||
|
!bpos_cmp(keys->d[idx].k->k.p, pos))
|
||||||
|
keys->d[idx].overwritten = true;
|
||||||
|
}
|
||||||
|
|
||||||
static struct bkey_i *bch2_journal_iter_peek(struct journal_iter *iter)
|
static struct bkey_i *bch2_journal_iter_peek(struct journal_iter *iter)
|
||||||
{
|
{
|
||||||
struct journal_key *k = iter->idx - iter->keys->nr
|
struct journal_key *k = iter->idx - iter->keys->nr
|
||||||
@ -533,6 +546,10 @@ static int __bch2_journal_replay_key(struct btree_trans *trans,
|
|||||||
BTREE_ITER_NOT_EXTENTS;
|
BTREE_ITER_NOT_EXTENTS;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Must be checked with btree locked: */
|
||||||
|
if (k->overwritten)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!k->level && k->btree_id == BTREE_ID_alloc)
|
if (!k->level && k->btree_id == BTREE_ID_alloc)
|
||||||
iter_flags |= BTREE_ITER_CACHED|BTREE_ITER_CACHED_NOFILL;
|
iter_flags |= BTREE_ITER_CACHED|BTREE_ITER_CACHED_NOFILL;
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ int bch2_journal_key_insert(struct bch_fs *, enum btree_id,
|
|||||||
unsigned, struct bkey_i *);
|
unsigned, struct bkey_i *);
|
||||||
int bch2_journal_key_delete(struct bch_fs *, enum btree_id,
|
int bch2_journal_key_delete(struct bch_fs *, enum btree_id,
|
||||||
unsigned, struct bpos);
|
unsigned, struct bpos);
|
||||||
|
void bch2_journal_key_overwritten(struct bch_fs *, enum btree_id,
|
||||||
|
unsigned, struct bpos);
|
||||||
|
|
||||||
void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *);
|
void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *);
|
||||||
struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *);
|
struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *);
|
||||||
|
Loading…
Reference in New Issue
Block a user