Update bcachefs sources to 043cfba30c fixup! bcachefs: Improve transaction restart handling in fsck code

This commit is contained in:
Kent Overstreet 2021-11-01 06:39:12 -04:00
parent a315a3f664
commit 0da2d968eb
20 changed files with 216 additions and 170 deletions

View File

@ -1 +1 @@
82c5cc8f00d08f4a315f99595e328d7b74cbd2b7 043cfba30c743a6faa4e53c5a88a259f8726ac01

View File

@ -261,8 +261,9 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c,
#undef x #undef x
} }
static int bch2_alloc_read_fn(struct bch_fs *c, struct bkey_s_c k) static int bch2_alloc_read_fn(struct btree_trans *trans, struct bkey_s_c k)
{ {
struct bch_fs *c = trans->c;
struct bch_dev *ca; struct bch_dev *ca;
struct bucket *g; struct bucket *g;
struct bkey_alloc_unpacked u; struct bkey_alloc_unpacked u;
@ -289,11 +290,14 @@ static int bch2_alloc_read_fn(struct bch_fs *c, struct bkey_s_c k)
int bch2_alloc_read(struct bch_fs *c) int bch2_alloc_read(struct bch_fs *c)
{ {
struct btree_trans trans;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
down_read(&c->gc_lock); down_read(&c->gc_lock);
ret = bch2_btree_and_journal_walk(c, BTREE_ID_alloc, bch2_alloc_read_fn); ret = bch2_btree_and_journal_walk(&trans, BTREE_ID_alloc, bch2_alloc_read_fn);
up_read(&c->gc_lock); up_read(&c->gc_lock);
bch2_trans_exit(&trans);
if (ret) { if (ret) {
bch_err(c, "error reading alloc info: %i", ret); bch_err(c, "error reading alloc info: %i", ret);
return ret; return ret;

View File

@ -688,17 +688,18 @@ fsck_err:
/* marking of btree keys/nodes: */ /* marking of btree keys/nodes: */
static int bch2_gc_mark_key(struct bch_fs *c, enum btree_id btree_id, static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
unsigned level, bool is_root, unsigned level, bool is_root,
struct bkey_s_c *k, struct bkey_s_c *k,
u8 *max_stale, bool initial) u8 *max_stale, bool initial)
{ {
struct bch_fs *c = trans->c;
struct bkey_ptrs_c ptrs; struct bkey_ptrs_c ptrs;
const struct bch_extent_ptr *ptr; const struct bch_extent_ptr *ptr;
unsigned flags = unsigned flags =
BTREE_TRIGGER_INSERT|
BTREE_TRIGGER_GC| BTREE_TRIGGER_GC|
(initial ? BTREE_TRIGGER_NOATOMIC : 0); (initial ? BTREE_TRIGGER_NOATOMIC : 0);
char buf[200];
int ret = 0; int ret = 0;
if (initial) { if (initial) {
@ -717,8 +718,9 @@ static int bch2_gc_mark_key(struct bch_fs *c, enum btree_id btree_id,
if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) || if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
fsck_err_on(!bch2_bkey_replicas_marked(c, *k), c, fsck_err_on(!bch2_bkey_replicas_marked(c, *k), c,
"superblock not marked as containing replicas (type %u)", "superblock not marked as containing replicas\n"
k->k->type)) { " while marking %s",
(bch2_bkey_val_to_text(&PBUF(buf), c, *k), buf))) {
ret = bch2_mark_bkey_replicas(c, *k); ret = bch2_mark_bkey_replicas(c, *k);
if (ret) { if (ret) {
bch_err(c, "error marking bkey replicas: %i", ret); bch_err(c, "error marking bkey replicas: %i", ret);
@ -738,7 +740,7 @@ static int bch2_gc_mark_key(struct bch_fs *c, enum btree_id btree_id,
*max_stale = max(*max_stale, ptr_stale(ca, ptr)); *max_stale = max(*max_stale, ptr_stale(ca, ptr));
} }
ret = bch2_mark_key(c, *k, flags); ret = bch2_mark_key(trans, *k, flags);
fsck_err: fsck_err:
err: err:
if (ret) if (ret)
@ -746,9 +748,10 @@ err:
return ret; return ret;
} }
static int btree_gc_mark_node(struct bch_fs *c, struct btree *b, u8 *max_stale, static int btree_gc_mark_node(struct btree_trans *trans, struct btree *b, u8 *max_stale,
bool initial) bool initial)
{ {
struct bch_fs *c = trans->c;
struct btree_node_iter iter; struct btree_node_iter iter;
struct bkey unpacked; struct bkey unpacked;
struct bkey_s_c k; struct bkey_s_c k;
@ -766,7 +769,7 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b, u8 *max_stale,
bkey_init(&prev.k->k); bkey_init(&prev.k->k);
while ((k = bch2_btree_node_iter_peek_unpack(&iter, b, &unpacked)).k) { while ((k = bch2_btree_node_iter_peek_unpack(&iter, b, &unpacked)).k) {
ret = bch2_gc_mark_key(c, b->c.btree_id, b->c.level, false, ret = bch2_gc_mark_key(trans, b->c.btree_id, b->c.level, false,
&k, max_stale, initial); &k, max_stale, initial);
if (ret) if (ret)
break; break;
@ -788,10 +791,10 @@ static int btree_gc_mark_node(struct bch_fs *c, struct btree *b, u8 *max_stale,
return ret; return ret;
} }
static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id, static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree_id,
bool initial, bool metadata_only) bool initial, bool metadata_only)
{ {
struct btree_trans trans; struct bch_fs *c = trans->c;
struct btree_iter iter; struct btree_iter iter;
struct btree *b; struct btree *b;
unsigned depth = metadata_only ? 1 unsigned depth = metadata_only ? 1
@ -801,35 +804,32 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
u8 max_stale = 0; u8 max_stale = 0;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0)); gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0));
__for_each_btree_node(&trans, iter, btree_id, POS_MIN, __for_each_btree_node(trans, iter, btree_id, POS_MIN,
0, depth, BTREE_ITER_PREFETCH, b, ret) { 0, depth, BTREE_ITER_PREFETCH, b, ret) {
bch2_verify_btree_nr_keys(b); bch2_verify_btree_nr_keys(b);
gc_pos_set(c, gc_pos_btree_node(b)); gc_pos_set(c, gc_pos_btree_node(b));
ret = btree_gc_mark_node(c, b, &max_stale, initial); ret = btree_gc_mark_node(trans, b, &max_stale, initial);
if (ret) if (ret)
break; break;
if (!initial) { if (!initial) {
if (max_stale > 64) if (max_stale > 64)
bch2_btree_node_rewrite(&trans, &iter, b, bch2_btree_node_rewrite(trans, &iter, b,
BTREE_INSERT_NOWAIT| BTREE_INSERT_NOWAIT|
BTREE_INSERT_GC_LOCK_HELD); BTREE_INSERT_GC_LOCK_HELD);
else if (!bch2_btree_gc_rewrite_disabled && else if (!bch2_btree_gc_rewrite_disabled &&
(bch2_btree_gc_always_rewrite || max_stale > 16)) (bch2_btree_gc_always_rewrite || max_stale > 16))
bch2_btree_node_rewrite(&trans, &iter, bch2_btree_node_rewrite(trans, &iter,
b, BTREE_INSERT_NOWAIT| b, BTREE_INSERT_NOWAIT|
BTREE_INSERT_GC_LOCK_HELD); BTREE_INSERT_GC_LOCK_HELD);
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans);
if (ret) if (ret)
return ret; return ret;
@ -838,7 +838,7 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
if (!btree_node_fake(b)) { if (!btree_node_fake(b)) {
struct bkey_s_c k = bkey_i_to_s_c(&b->key); struct bkey_s_c k = bkey_i_to_s_c(&b->key);
ret = bch2_gc_mark_key(c, b->c.btree_id, b->c.level, true, ret = bch2_gc_mark_key(trans, b->c.btree_id, b->c.level, true,
&k, &max_stale, initial); &k, &max_stale, initial);
} }
gc_pos_set(c, gc_pos_btree_root(b->c.btree_id)); gc_pos_set(c, gc_pos_btree_root(b->c.btree_id));
@ -847,9 +847,10 @@ static int bch2_gc_btree(struct bch_fs *c, enum btree_id btree_id,
return ret; return ret;
} }
static int bch2_gc_btree_init_recurse(struct bch_fs *c, struct btree *b, static int bch2_gc_btree_init_recurse(struct btree_trans *trans, struct btree *b,
unsigned target_depth) unsigned target_depth)
{ {
struct bch_fs *c = trans->c;
struct btree_and_journal_iter iter; struct btree_and_journal_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_buf cur, prev; struct bkey_buf cur, prev;
@ -866,7 +867,7 @@ static int bch2_gc_btree_init_recurse(struct bch_fs *c, struct btree *b,
BUG_ON(bpos_cmp(k.k->p, b->data->min_key) < 0); BUG_ON(bpos_cmp(k.k->p, b->data->min_key) < 0);
BUG_ON(bpos_cmp(k.k->p, b->data->max_key) > 0); BUG_ON(bpos_cmp(k.k->p, b->data->max_key) > 0);
ret = bch2_gc_mark_key(c, b->c.btree_id, b->c.level, false, ret = bch2_gc_mark_key(trans, b->c.btree_id, b->c.level, false,
&k, &max_stale, true); &k, &max_stale, true);
if (ret) { if (ret) {
bch_err(c, "%s: error %i from bch2_gc_mark_key", __func__, ret); bch_err(c, "%s: error %i from bch2_gc_mark_key", __func__, ret);
@ -933,7 +934,7 @@ static int bch2_gc_btree_init_recurse(struct bch_fs *c, struct btree *b,
break; break;
} }
ret = bch2_gc_btree_init_recurse(c, child, ret = bch2_gc_btree_init_recurse(trans, child,
target_depth); target_depth);
six_unlock_read(&child->c.lock); six_unlock_read(&child->c.lock);
@ -948,10 +949,11 @@ fsck_err:
return ret; return ret;
} }
static int bch2_gc_btree_init(struct bch_fs *c, static int bch2_gc_btree_init(struct btree_trans *trans,
enum btree_id btree_id, enum btree_id btree_id,
bool metadata_only) bool metadata_only)
{ {
struct bch_fs *c = trans->c;
struct btree *b; struct btree *b;
unsigned target_depth = metadata_only ? 1 unsigned target_depth = metadata_only ? 1
: bch2_expensive_debug_checks ? 0 : bch2_expensive_debug_checks ? 0
@ -984,12 +986,12 @@ static int bch2_gc_btree_init(struct bch_fs *c,
} }
if (b->c.level >= target_depth) if (b->c.level >= target_depth)
ret = bch2_gc_btree_init_recurse(c, b, target_depth); ret = bch2_gc_btree_init_recurse(trans, b, target_depth);
if (!ret) { if (!ret) {
struct bkey_s_c k = bkey_i_to_s_c(&b->key); struct bkey_s_c k = bkey_i_to_s_c(&b->key);
ret = bch2_gc_mark_key(c, b->c.btree_id, b->c.level, true, ret = bch2_gc_mark_key(trans, b->c.btree_id, b->c.level, true,
&k, &max_stale, true); &k, &max_stale, true);
} }
fsck_err: fsck_err:
@ -1008,21 +1010,26 @@ static inline int btree_id_gc_phase_cmp(enum btree_id l, enum btree_id r)
static int bch2_gc_btrees(struct bch_fs *c, bool initial, bool metadata_only) static int bch2_gc_btrees(struct bch_fs *c, bool initial, bool metadata_only)
{ {
struct btree_trans trans;
enum btree_id ids[BTREE_ID_NR]; enum btree_id ids[BTREE_ID_NR];
unsigned i; unsigned i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < BTREE_ID_NR; i++) for (i = 0; i < BTREE_ID_NR; i++)
ids[i] = i; ids[i] = i;
bubble_sort(ids, BTREE_ID_NR, btree_id_gc_phase_cmp); bubble_sort(ids, BTREE_ID_NR, btree_id_gc_phase_cmp);
for (i = 0; i < BTREE_ID_NR && !ret; i++) for (i = 0; i < BTREE_ID_NR && !ret; i++)
ret = initial ret = initial
? bch2_gc_btree_init(c, ids[i], metadata_only) ? bch2_gc_btree_init(&trans, ids[i], metadata_only)
: bch2_gc_btree(c, ids[i], initial, metadata_only); : bch2_gc_btree(&trans, ids[i], initial, metadata_only);
if (ret < 0) if (ret < 0)
bch_err(c, "%s: ret %i", __func__, ret); bch_err(c, "%s: ret %i", __func__, ret);
bch2_trans_exit(&trans);
return ret; return ret;
} }
@ -1109,8 +1116,7 @@ static void bch2_mark_pending_btree_node_frees(struct bch_fs *c)
for_each_pending_btree_node_free(c, as, d) for_each_pending_btree_node_free(c, as, d)
if (d->index_update_done) if (d->index_update_done)
bch2_mark_key(c, bkey_i_to_s_c(&d->key), bch2_mark_key(c, bkey_i_to_s_c(&d->key), BTREE_TRIGGER_GC);
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_GC);
mutex_unlock(&c->btree_interior_update_lock); mutex_unlock(&c->btree_interior_update_lock);
} }
@ -1371,8 +1377,10 @@ static int bch2_gc_start(struct bch_fs *c,
return 0; return 0;
} }
static int bch2_gc_reflink_done_initial_fn(struct bch_fs *c, struct bkey_s_c k) static int bch2_gc_reflink_done_initial_fn(struct btree_trans *trans,
struct bkey_s_c k)
{ {
struct bch_fs *c = trans->c;
struct reflink_gc *r; struct reflink_gc *r;
const __le64 *refcount = bkey_refcount_c(k); const __le64 *refcount = bkey_refcount_c(k);
char buf[200]; char buf[200];
@ -1437,16 +1445,16 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
if (metadata_only) if (metadata_only)
return 0; return 0;
bch2_trans_init(&trans, c, 0, 0);
if (initial) { if (initial) {
c->reflink_gc_idx = 0; c->reflink_gc_idx = 0;
ret = bch2_btree_and_journal_walk(c, BTREE_ID_reflink, ret = bch2_btree_and_journal_walk(&trans, BTREE_ID_reflink,
bch2_gc_reflink_done_initial_fn); bch2_gc_reflink_done_initial_fn);
goto out; goto out;
} }
bch2_trans_init(&trans, c, 0, 0);
for_each_btree_key(&trans, iter, BTREE_ID_reflink, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_reflink, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
const __le64 *refcount = bkey_refcount_c(k); const __le64 *refcount = bkey_refcount_c(k);
@ -1494,16 +1502,18 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
} }
fsck_err: fsck_err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans);
out: out:
genradix_free(&c->reflink_gc_table); genradix_free(&c->reflink_gc_table);
c->reflink_gc_nr = 0; c->reflink_gc_nr = 0;
bch2_trans_exit(&trans);
return ret; return ret;
} }
static int bch2_gc_reflink_start_initial_fn(struct bch_fs *c, struct bkey_s_c k) static int bch2_gc_reflink_start_initial_fn(struct btree_trans *trans,
struct bkey_s_c k)
{ {
struct bch_fs *c = trans->c;
struct reflink_gc *r; struct reflink_gc *r;
const __le64 *refcount = bkey_refcount_c(k); const __le64 *refcount = bkey_refcount_c(k);
@ -1528,19 +1538,20 @@ static int bch2_gc_reflink_start(struct bch_fs *c, bool initial,
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct reflink_gc *r; struct reflink_gc *r;
int ret; int ret = 0;
if (metadata_only) if (metadata_only)
return 0; return 0;
bch2_trans_init(&trans, c, 0, 0);
genradix_free(&c->reflink_gc_table); genradix_free(&c->reflink_gc_table);
c->reflink_gc_nr = 0; c->reflink_gc_nr = 0;
if (initial) if (initial) {
return bch2_btree_and_journal_walk(c, BTREE_ID_reflink, ret = bch2_btree_and_journal_walk(&trans, BTREE_ID_reflink,
bch2_gc_reflink_start_initial_fn); bch2_gc_reflink_start_initial_fn);
goto out;
bch2_trans_init(&trans, c, 0, 0); }
for_each_btree_key(&trans, iter, BTREE_ID_reflink, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_reflink, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
@ -1561,9 +1572,9 @@ static int bch2_gc_reflink_start(struct bch_fs *c, bool initial,
r->refcount = 0; r->refcount = 0;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
out:
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
return 0; return ret;
} }
/** /**

View File

@ -659,7 +659,8 @@ static void bch2_btree_path_verify(struct btree_trans *trans,
for (i = 0; i < (!path->cached ? BTREE_MAX_DEPTH : 1); i++) { for (i = 0; i < (!path->cached ? BTREE_MAX_DEPTH : 1); i++) {
if (!path->l[i].b) { if (!path->l[i].b) {
BUG_ON(c->btree_roots[path->btree_id].b->c.level > i); BUG_ON(!path->cached &&
c->btree_roots[path->btree_id].b->c.level > i);
break; break;
} }
@ -2646,6 +2647,7 @@ void bch2_trans_begin(struct btree_trans *trans)
trans_for_each_update(trans, i) trans_for_each_update(trans, i)
__btree_path_put(i->path, true); __btree_path_put(i->path, true);
memset(&trans->journal_res, 0, sizeof(trans->journal_res));
trans->extra_journal_res = 0; trans->extra_journal_res = 0;
trans->nr_updates = 0; trans->nr_updates = 0;
trans->mem_top = 0; trans->mem_top = 0;

View File

@ -524,11 +524,13 @@ 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 int bch2_mark_alloc(struct bch_fs *c, 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,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
bool gc = flags & BTREE_TRIGGER_GC; bool gc = flags & BTREE_TRIGGER_GC;
u64 journal_seq = trans->journal_res.seq;
struct bch_fs *c = trans->c;
struct bkey_alloc_unpacked u; struct bkey_alloc_unpacked u;
struct bch_dev *ca; struct bch_dev *ca;
struct bucket *g; struct bucket *g;
@ -673,7 +675,8 @@ static s64 ptr_disk_sectors(s64 sectors, struct extent_ptr_decoded p)
: sectors; : sectors;
} }
static int check_bucket_ref(struct bch_fs *c, struct bkey_s_c k, static int check_bucket_ref(struct bch_fs *c,
struct bkey_s_c k,
const struct bch_extent_ptr *ptr, const struct bch_extent_ptr *ptr,
s64 sectors, enum bch_data_type ptr_data_type, s64 sectors, enum bch_data_type ptr_data_type,
u8 bucket_gen, u8 bucket_data_type, u8 bucket_gen, u8 bucket_data_type,
@ -747,10 +750,12 @@ static int check_bucket_ref(struct bch_fs *c, struct bkey_s_c k,
return 0; return 0;
} }
static int mark_stripe_bucket(struct bch_fs *c, struct bkey_s_c k, static int mark_stripe_bucket(struct btree_trans *trans,
struct bkey_s_c k,
unsigned ptr_idx, unsigned ptr_idx,
u64 journal_seq, unsigned flags) u64 journal_seq, unsigned flags)
{ {
struct bch_fs *c = trans->c;
const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
unsigned nr_data = s->nr_blocks - s->nr_redundant; unsigned nr_data = s->nr_blocks - s->nr_redundant;
bool parity = ptr_idx >= nr_data; bool parity = ptr_idx >= nr_data;
@ -794,7 +799,8 @@ static int mark_stripe_bucket(struct bch_fs *c, struct bkey_s_c k,
return 0; return 0;
} }
static int __mark_pointer(struct bch_fs *c, struct bkey_s_c k, static int __mark_pointer(struct btree_trans *trans,
struct bkey_s_c k,
const struct bch_extent_ptr *ptr, const struct bch_extent_ptr *ptr,
s64 sectors, enum bch_data_type ptr_data_type, s64 sectors, enum bch_data_type ptr_data_type,
u8 bucket_gen, u8 *bucket_data_type, u8 bucket_gen, u8 *bucket_data_type,
@ -803,7 +809,7 @@ static int __mark_pointer(struct bch_fs *c, struct bkey_s_c k,
u16 *dst_sectors = !ptr->cached u16 *dst_sectors = !ptr->cached
? dirty_sectors ? dirty_sectors
: cached_sectors; : cached_sectors;
int ret = check_bucket_ref(c, k, ptr, sectors, ptr_data_type, int ret = check_bucket_ref(trans->c, k, ptr, sectors, ptr_data_type,
bucket_gen, *bucket_data_type, bucket_gen, *bucket_data_type,
*dirty_sectors, *cached_sectors); *dirty_sectors, *cached_sectors);
@ -816,12 +822,15 @@ static int __mark_pointer(struct bch_fs *c, struct bkey_s_c k,
return 0; return 0;
} }
static int bch2_mark_pointer(struct bch_fs *c, struct bkey_s_c k, static int bch2_mark_pointer(struct btree_trans *trans,
struct bkey_s_c k,
struct extent_ptr_decoded p, struct extent_ptr_decoded p,
s64 sectors, enum bch_data_type data_type, s64 sectors, enum bch_data_type data_type,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
bool gc = flags & BTREE_TRIGGER_GC; bool gc = flags & BTREE_TRIGGER_GC;
u64 journal_seq = trans->journal_res.seq;
struct bch_fs *c = trans->c;
struct bucket_mark old, new; struct bucket_mark old, new;
struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev); struct bch_dev *ca = bch_dev_bkey_exists(c, p.ptr.dev);
struct bucket *g = PTR_BUCKET(ca, &p.ptr, gc); struct bucket *g = PTR_BUCKET(ca, &p.ptr, gc);
@ -834,7 +843,8 @@ static int bch2_mark_pointer(struct bch_fs *c, struct bkey_s_c k,
new.v.counter = old.v.counter = v; new.v.counter = old.v.counter = v;
bucket_data_type = new.data_type; bucket_data_type = new.data_type;
ret = __mark_pointer(c, k, &p.ptr, sectors, data_type, new.gen, ret = __mark_pointer(trans, k, &p.ptr, sectors,
data_type, new.gen,
&bucket_data_type, &bucket_data_type,
&new.dirty_sectors, &new.dirty_sectors,
&new.cached_sectors); &new.cached_sectors);
@ -863,13 +873,14 @@ static int bch2_mark_pointer(struct bch_fs *c, struct bkey_s_c k,
return 0; return 0;
} }
static int bch2_mark_stripe_ptr(struct bch_fs *c, static int bch2_mark_stripe_ptr(struct btree_trans *trans,
struct bch_extent_stripe_ptr p, struct bch_extent_stripe_ptr p,
enum bch_data_type data_type, enum bch_data_type data_type,
s64 sectors, s64 sectors,
unsigned journal_seq, unsigned flags) unsigned flags)
{ {
bool gc = flags & BTREE_TRIGGER_GC; bool gc = flags & BTREE_TRIGGER_GC;
struct bch_fs *c = trans->c;
struct bch_replicas_padded r; struct bch_replicas_padded r;
struct stripe *m; struct stripe *m;
unsigned i, blocks_nonempty = 0; unsigned i, blocks_nonempty = 0;
@ -902,17 +913,19 @@ static int bch2_mark_stripe_ptr(struct bch_fs *c,
spin_unlock(&c->ec_stripes_heap_lock); spin_unlock(&c->ec_stripes_heap_lock);
r.e.data_type = data_type; r.e.data_type = data_type;
update_replicas(c, &r.e, sectors, journal_seq, gc); update_replicas(c, &r.e, sectors, trans->journal_res.seq, gc);
return 0; return 0;
} }
static int bch2_mark_extent(struct bch_fs *c, static int bch2_mark_extent(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 journal_seq, unsigned flags) unsigned flags)
{ {
bool gc = flags & BTREE_TRIGGER_GC; bool gc = flags & BTREE_TRIGGER_GC;
struct bkey_s_c k = flags & BTREE_TRIGGER_INSERT ? new : old; u64 journal_seq = trans->journal_res.seq;
struct bch_fs *c = trans->c;
struct bkey_s_c k = flags & BTREE_TRIGGER_OVERWRITE ? old: new;
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const union bch_extent_entry *entry; const union bch_extent_entry *entry;
struct extent_ptr_decoded p; struct extent_ptr_decoded p;
@ -927,9 +940,6 @@ static int bch2_mark_extent(struct bch_fs *c,
bool stale; bool stale;
int ret; int ret;
BUG_ON((flags & (BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE)) ==
(BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE));
r.e.data_type = data_type; r.e.data_type = data_type;
r.e.nr_devs = 0; r.e.nr_devs = 0;
r.e.nr_required = 1; r.e.nr_required = 1;
@ -940,8 +950,8 @@ static int bch2_mark_extent(struct bch_fs *c,
if (flags & BTREE_TRIGGER_OVERWRITE) if (flags & BTREE_TRIGGER_OVERWRITE)
disk_sectors = -disk_sectors; disk_sectors = -disk_sectors;
ret = bch2_mark_pointer(c, k, p, disk_sectors, data_type, ret = bch2_mark_pointer(trans, k, p, disk_sectors,
journal_seq, flags); data_type, flags);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -959,8 +969,8 @@ static int bch2_mark_extent(struct bch_fs *c,
dirty_sectors += disk_sectors; dirty_sectors += disk_sectors;
r.e.devs[r.e.nr_devs++] = p.ptr.dev; r.e.devs[r.e.nr_devs++] = p.ptr.dev;
} else { } else {
ret = bch2_mark_stripe_ptr(c, p.ec, data_type, ret = bch2_mark_stripe_ptr(trans, p.ec, data_type,
disk_sectors, journal_seq, flags); disk_sectors, flags);
if (ret) if (ret)
return ret; return ret;
@ -986,11 +996,13 @@ static int bch2_mark_extent(struct bch_fs *c,
return 0; return 0;
} }
static int bch2_mark_stripe(struct bch_fs *c, static int bch2_mark_stripe(struct btree_trans *trans,
struct bkey_s_c old, struct bkey_s_c new, struct bkey_s_c old, struct bkey_s_c new,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
bool gc = flags & BTREE_TRIGGER_GC; bool gc = flags & BTREE_TRIGGER_GC;
u64 journal_seq = trans->journal_res.seq;
struct bch_fs *c = trans->c;
size_t idx = new.k->p.offset; size_t idx = new.k->p.offset;
const struct bch_stripe *old_s = old.k->type == KEY_TYPE_stripe const struct bch_stripe *old_s = old.k->type == KEY_TYPE_stripe
? bkey_s_c_to_stripe(old).v : NULL; ? bkey_s_c_to_stripe(old).v : NULL;
@ -1003,8 +1015,13 @@ static int bch2_mark_stripe(struct bch_fs *c,
BUG_ON(gc && old_s); BUG_ON(gc && old_s);
if (!m || (old_s && !m->alive)) { if (!m || (old_s && !m->alive)) {
bch_err_ratelimited(c, "error marking nonexistent stripe %zu", char buf1[200], buf2[200];
idx);
bch2_bkey_val_to_text(&PBUF(buf1), c, old);
bch2_bkey_val_to_text(&PBUF(buf2), c, new);
bch_err_ratelimited(c, "error marking nonexistent stripe %zu while marking\n"
"old %s\n"
"new %s", idx, buf1, buf2);
bch2_inconsistent_error(c); bch2_inconsistent_error(c);
return -1; return -1;
} }
@ -1049,7 +1066,7 @@ static int bch2_mark_stripe(struct bch_fs *c,
m->blocks_nonempty = 0; m->blocks_nonempty = 0;
for (i = 0; i < new_s->nr_blocks; i++) { for (i = 0; i < new_s->nr_blocks; i++) {
ret = mark_stripe_bucket(c, new, i, journal_seq, flags); ret = mark_stripe_bucket(trans, new, i, journal_seq, flags);
if (ret) if (ret)
return ret; return ret;
} }
@ -1068,25 +1085,27 @@ static int bch2_mark_stripe(struct bch_fs *c,
return 0; return 0;
} }
static int bch2_mark_inode(struct bch_fs *c, static int bch2_mark_inode(struct btree_trans *trans,
struct bkey_s_c old, struct bkey_s_c new, struct bkey_s_c old, struct bkey_s_c new,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
struct bch_fs *c = trans->c;
struct bch_fs_usage __percpu *fs_usage; struct bch_fs_usage __percpu *fs_usage;
preempt_disable(); preempt_disable();
fs_usage = fs_usage_ptr(c, journal_seq, flags & BTREE_TRIGGER_GC); fs_usage = fs_usage_ptr(c, trans->journal_res.seq, flags & BTREE_TRIGGER_GC);
fs_usage->nr_inodes += new.k->type == KEY_TYPE_inode; fs_usage->nr_inodes += new.k->type == KEY_TYPE_inode;
fs_usage->nr_inodes -= old.k->type == KEY_TYPE_inode; fs_usage->nr_inodes -= old.k->type == KEY_TYPE_inode;
preempt_enable(); preempt_enable();
return 0; return 0;
} }
static int bch2_mark_reservation(struct bch_fs *c, static int bch2_mark_reservation(struct btree_trans *trans,
struct bkey_s_c old, struct bkey_s_c new, struct bkey_s_c old, struct bkey_s_c new,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
struct bkey_s_c k = flags & BTREE_TRIGGER_INSERT ? new : old; struct bch_fs *c = trans->c;
struct bkey_s_c k = flags & BTREE_TRIGGER_OVERWRITE ? old: new;
struct bch_fs_usage __percpu *fs_usage; struct bch_fs_usage __percpu *fs_usage;
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas; unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
s64 sectors = (s64) k.k->size; s64 sectors = (s64) k.k->size;
@ -1096,7 +1115,7 @@ static int bch2_mark_reservation(struct bch_fs *c,
sectors *= replicas; sectors *= replicas;
preempt_disable(); preempt_disable();
fs_usage = fs_usage_ptr(c, journal_seq, flags & BTREE_TRIGGER_GC); fs_usage = fs_usage_ptr(c, trans->journal_res.seq, flags & BTREE_TRIGGER_GC);
replicas = clamp_t(unsigned, replicas, 1, replicas = clamp_t(unsigned, replicas, 1,
ARRAY_SIZE(fs_usage->persistent_reserved)); ARRAY_SIZE(fs_usage->persistent_reserved));
@ -1154,11 +1173,12 @@ fsck_err:
return ret; return ret;
} }
static int bch2_mark_reflink_p(struct bch_fs *c, static int bch2_mark_reflink_p(struct btree_trans *trans,
struct bkey_s_c old, struct bkey_s_c new, struct bkey_s_c old, struct bkey_s_c new,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
struct bkey_s_c k = flags & BTREE_TRIGGER_INSERT ? new : old; struct bch_fs *c = trans->c;
struct bkey_s_c k = flags & BTREE_TRIGGER_OVERWRITE ? old: new;
struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k); struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
struct reflink_gc *ref; struct reflink_gc *ref;
size_t l, r, m; size_t l, r, m;
@ -1167,9 +1187,6 @@ static int bch2_mark_reflink_p(struct bch_fs *c,
le32_to_cpu(p.v->back_pad); le32_to_cpu(p.v->back_pad);
int ret = 0; int ret = 0;
BUG_ON((flags & (BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE)) ==
(BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE));
l = 0; l = 0;
r = c->reflink_gc_nr; r = c->reflink_gc_nr;
while (l < r) { while (l < r) {
@ -1188,47 +1205,48 @@ static int bch2_mark_reflink_p(struct bch_fs *c,
return ret; return ret;
} }
static int bch2_mark_key_locked(struct bch_fs *c, static int bch2_mark_key_locked(struct btree_trans *trans,
struct bkey_s_c old, struct bkey_s_c old,
struct bkey_s_c new, struct bkey_s_c new,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
struct bkey_s_c k = flags & BTREE_TRIGGER_INSERT ? new : old; struct bkey_s_c k = flags & BTREE_TRIGGER_OVERWRITE ? old: new;
BUG_ON(!(flags & (BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE)));
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_alloc: case KEY_TYPE_alloc:
case KEY_TYPE_alloc_v2: case KEY_TYPE_alloc_v2:
return bch2_mark_alloc(c, old, new, journal_seq, flags); return bch2_mark_alloc(trans, old, new, flags);
case KEY_TYPE_btree_ptr: case KEY_TYPE_btree_ptr:
case KEY_TYPE_btree_ptr_v2: case KEY_TYPE_btree_ptr_v2:
case KEY_TYPE_extent: case KEY_TYPE_extent:
case KEY_TYPE_reflink_v: case KEY_TYPE_reflink_v:
return bch2_mark_extent(c, old, new, journal_seq, flags); return bch2_mark_extent(trans, old, new, flags);
case KEY_TYPE_stripe: case KEY_TYPE_stripe:
return bch2_mark_stripe(c, old, new, journal_seq, flags); return bch2_mark_stripe(trans, old, new, flags);
case KEY_TYPE_inode: case KEY_TYPE_inode:
return bch2_mark_inode(c, old, new, journal_seq, flags); return bch2_mark_inode(trans, old, new, flags);
case KEY_TYPE_reservation: case KEY_TYPE_reservation:
return bch2_mark_reservation(c, old, new, journal_seq, flags); return bch2_mark_reservation(trans, old, new, flags);
case KEY_TYPE_reflink_p: case KEY_TYPE_reflink_p:
return bch2_mark_reflink_p(c, old, new, journal_seq, flags); return bch2_mark_reflink_p(trans, old, new, flags);
case KEY_TYPE_snapshot: case KEY_TYPE_snapshot:
return bch2_mark_snapshot(c, old, new, journal_seq, flags); return bch2_mark_snapshot(trans, old, new, flags);
default: default:
return 0; return 0;
} }
} }
int bch2_mark_key(struct bch_fs *c, struct bkey_s_c new, unsigned flags) int bch2_mark_key(struct btree_trans *trans, struct bkey_s_c new, unsigned flags)
{ {
struct bch_fs *c = trans->c;
struct bkey deleted = KEY(0, 0, 0); struct bkey deleted = KEY(0, 0, 0);
struct bkey_s_c old = (struct bkey_s_c) { &deleted, NULL }; struct bkey_s_c old = (struct bkey_s_c) { &deleted, NULL };
int ret; int ret;
deleted.p = new.k->p;
percpu_down_read(&c->mark_lock); percpu_down_read(&c->mark_lock);
ret = bch2_mark_key_locked(c, old, new, 0, flags); ret = bch2_mark_key_locked(trans, old, new, flags);
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
return ret; return ret;
@ -1237,13 +1255,14 @@ int bch2_mark_key(struct bch_fs *c, struct bkey_s_c new, unsigned flags)
int bch2_mark_update(struct btree_trans *trans, struct btree_path *path, int bch2_mark_update(struct btree_trans *trans, struct btree_path *path,
struct bkey_i *new, unsigned flags) struct bkey_i *new, unsigned flags)
{ {
struct bch_fs *c = trans->c;
struct bkey _deleted = KEY(0, 0, 0); struct bkey _deleted = KEY(0, 0, 0);
struct bkey_s_c deleted = (struct bkey_s_c) { &_deleted, NULL }; struct bkey_s_c deleted = (struct bkey_s_c) { &_deleted, NULL };
struct bkey_s_c old; struct bkey_s_c old;
struct bkey unpacked; struct bkey unpacked;
int ret; int ret;
_deleted.p = path->pos;
if (unlikely(flags & BTREE_TRIGGER_NORUN)) if (unlikely(flags & BTREE_TRIGGER_NORUN))
return 0; return 0;
@ -1254,15 +1273,12 @@ int bch2_mark_update(struct btree_trans *trans, struct btree_path *path,
if (old.k->type == new->k.type && if (old.k->type == new->k.type &&
((1U << old.k->type) & BTREE_TRIGGER_WANTS_OLD_AND_NEW)) { ((1U << old.k->type) & BTREE_TRIGGER_WANTS_OLD_AND_NEW)) {
ret = bch2_mark_key_locked(c, old, bkey_i_to_s_c(new), ret = bch2_mark_key_locked(trans, old, bkey_i_to_s_c(new),
trans->journal_res.seq,
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags); BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
} else { } else {
ret = bch2_mark_key_locked(c, deleted, bkey_i_to_s_c(new), ret = bch2_mark_key_locked(trans, deleted, bkey_i_to_s_c(new),
trans->journal_res.seq,
BTREE_TRIGGER_INSERT|flags) ?: BTREE_TRIGGER_INSERT|flags) ?:
bch2_mark_key_locked(c, old, deleted, bch2_mark_key_locked(trans, old, deleted,
trans->journal_res.seq,
BTREE_TRIGGER_OVERWRITE|flags); BTREE_TRIGGER_OVERWRITE|flags);
} }
@ -1426,7 +1442,8 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
if (IS_ERR(a)) if (IS_ERR(a))
return PTR_ERR(a); return PTR_ERR(a);
ret = __mark_pointer(c, k, &p.ptr, sectors, data_type, u.gen, &u.data_type, ret = __mark_pointer(trans, k, &p.ptr, sectors, data_type,
u.gen, &u.data_type,
&u.dirty_sectors, &u.cached_sectors); &u.dirty_sectors, &u.cached_sectors);
if (ret) if (ret)
goto out; goto out;
@ -1511,9 +1528,6 @@ static int bch2_trans_mark_extent(struct btree_trans *trans,
bool stale; bool stale;
int ret; int ret;
BUG_ON((flags & (BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE)) ==
(BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE));
r.e.data_type = data_type; r.e.data_type = data_type;
r.e.nr_devs = 0; r.e.nr_devs = 0;
r.e.nr_required = 1; r.e.nr_required = 1;
@ -1685,9 +1699,6 @@ static int bch2_trans_mark_reservation(struct btree_trans *trans,
s64 sectors = (s64) k.k->size; s64 sectors = (s64) k.k->size;
struct replicas_delta_list *d; struct replicas_delta_list *d;
BUG_ON((flags & (BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE)) ==
(BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE));
if (flags & BTREE_TRIGGER_OVERWRITE) if (flags & BTREE_TRIGGER_OVERWRITE)
sectors = -sectors; sectors = -sectors;
sectors *= replicas; sectors *= replicas;
@ -1807,9 +1818,7 @@ static int bch2_trans_mark_reflink_p(struct btree_trans *trans,
int bch2_trans_mark_key(struct btree_trans *trans, struct bkey_s_c old, int bch2_trans_mark_key(struct btree_trans *trans, struct bkey_s_c old,
struct bkey_s_c new, unsigned flags) struct bkey_s_c new, unsigned flags)
{ {
struct bkey_s_c k = flags & BTREE_TRIGGER_INSERT ? new : old; struct bkey_s_c k = flags & BTREE_TRIGGER_OVERWRITE ? old: new;
BUG_ON(!(flags & (BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE)));
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_btree_ptr: case KEY_TYPE_btree_ptr:
@ -1841,6 +1850,8 @@ int bch2_trans_mark_update(struct btree_trans *trans,
struct bkey unpacked; struct bkey unpacked;
int ret; int ret;
_deleted.p = path->pos;
if (unlikely(flags & BTREE_TRIGGER_NORUN)) if (unlikely(flags & BTREE_TRIGGER_NORUN))
return 0; return 0;

View File

@ -226,7 +226,7 @@ void bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *,
size_t, enum bch_data_type, unsigned, size_t, enum bch_data_type, unsigned,
struct gc_pos, unsigned); struct gc_pos, unsigned);
int bch2_mark_key(struct bch_fs *, struct bkey_s_c, unsigned); int bch2_mark_key(struct btree_trans *, struct bkey_s_c, unsigned);
int bch2_mark_update(struct btree_trans *, struct btree_path *, int bch2_mark_update(struct btree_trans *, struct btree_path *,
struct bkey_i *, unsigned); struct bkey_i *, unsigned);

View File

@ -837,8 +837,9 @@ static int ec_stripe_update_ptrs(struct bch_fs *c,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
bkey_start_pos(pos), bkey_start_pos(pos),
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
retry:
while ((k = bch2_btree_iter_peek(&iter)).k && while (bch2_trans_begin(&trans),
(k = bch2_btree_iter_peek(&iter)).k &&
!(ret = bkey_err(k)) && !(ret = bkey_err(k)) &&
bkey_cmp(bkey_start_pos(k.k), pos->p) < 0) { bkey_cmp(bkey_start_pos(k.k), pos->p) < 0) {
struct bch_extent_ptr *ptr, *ec_ptr = NULL; struct bch_extent_ptr *ptr, *ec_ptr = NULL;
@ -874,11 +875,11 @@ static int ec_stripe_update_ptrs(struct bch_fs *c,
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
if (!ret) if (!ret)
bch2_btree_iter_set_pos(&iter, next_pos); bch2_btree_iter_set_pos(&iter, next_pos);
if (ret == -EINTR)
ret = 0;
if (ret) if (ret)
break; break;
} }
if (ret == -EINTR)
goto retry;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
@ -1069,16 +1070,14 @@ void *bch2_writepoint_ec_buf(struct bch_fs *c, struct write_point *wp)
return ob->ec->new_stripe.data[ob->ec_idx] + (offset << 9); return ob->ec->new_stripe.data[ob->ec_idx] + (offset << 9);
} }
void bch2_ec_add_backpointer(struct bch_fs *c, struct write_point *wp, void bch2_ob_add_backpointer(struct bch_fs *c, struct open_bucket *ob,
struct bpos pos, unsigned sectors) struct bkey *k)
{ {
struct open_bucket *ob = ec_open_bucket(c, &wp->ptrs); struct ec_stripe_new *ec = ob->ec;
struct ec_stripe_new *ec;
if (!ob) if (!ec)
return; return;
ec = ob->ec;
mutex_lock(&ec->lock); mutex_lock(&ec->lock);
if (bch2_keylist_realloc(&ec->keys, ec->inline_keys, if (bch2_keylist_realloc(&ec->keys, ec->inline_keys,
@ -1088,8 +1087,8 @@ void bch2_ec_add_backpointer(struct bch_fs *c, struct write_point *wp,
} }
bkey_init(&ec->keys.top->k); bkey_init(&ec->keys.top->k);
ec->keys.top->k.p = pos; ec->keys.top->k.p = k->p;
bch2_key_resize(&ec->keys.top->k, sectors); ec->keys.top->k.size = k->size;
bch2_keylist_push(&ec->keys); bch2_keylist_push(&ec->keys);
mutex_unlock(&ec->lock); mutex_unlock(&ec->lock);
@ -1635,14 +1634,14 @@ int bch2_stripes_write(struct bch_fs *c, unsigned flags)
return ret; return ret;
} }
static int bch2_stripes_read_fn(struct bch_fs *c, struct bkey_s_c k) static int bch2_stripes_read_fn(struct btree_trans *trans, struct bkey_s_c k)
{ {
struct bch_fs *c = trans->c;
int ret = 0; int ret = 0;
if (k.k->type == KEY_TYPE_stripe) if (k.k->type == KEY_TYPE_stripe)
ret = __ec_stripe_mem_alloc(c, k.k->p.offset, GFP_KERNEL) ?: ret = __ec_stripe_mem_alloc(c, k.k->p.offset, GFP_KERNEL) ?:
bch2_mark_key(c, k, bch2_mark_key(trans, k,
BTREE_TRIGGER_INSERT|
BTREE_TRIGGER_NOATOMIC); BTREE_TRIGGER_NOATOMIC);
return ret; return ret;
@ -1650,8 +1649,13 @@ static int bch2_stripes_read_fn(struct bch_fs *c, struct bkey_s_c k)
int bch2_stripes_read(struct bch_fs *c) int bch2_stripes_read(struct bch_fs *c)
{ {
int ret = bch2_btree_and_journal_walk(c, BTREE_ID_stripes, struct btree_trans trans;
int ret;
bch2_trans_init(&trans, c, 0, 0);
ret = bch2_btree_and_journal_walk(&trans, BTREE_ID_stripes,
bch2_stripes_read_fn); bch2_stripes_read_fn);
bch2_trans_exit(&trans);
if (ret) if (ret)
bch_err(c, "error reading stripes: %i", ret); bch_err(c, "error reading stripes: %i", ret);

View File

@ -193,8 +193,8 @@ struct ec_stripe_head {
int bch2_ec_read_extent(struct bch_fs *, struct bch_read_bio *); int bch2_ec_read_extent(struct bch_fs *, struct bch_read_bio *);
void *bch2_writepoint_ec_buf(struct bch_fs *, struct write_point *); void *bch2_writepoint_ec_buf(struct bch_fs *, struct write_point *);
void bch2_ec_add_backpointer(struct bch_fs *, struct write_point *, void bch2_ob_add_backpointer(struct bch_fs *, struct open_bucket *,
struct bpos, unsigned); struct bkey *);
void bch2_ec_bucket_written(struct bch_fs *, struct open_bucket *); void bch2_ec_bucket_written(struct bch_fs *, struct open_bucket *);
void bch2_ec_bucket_cancel(struct bch_fs *, struct open_bucket *); void bch2_ec_bucket_cancel(struct bch_fs *, struct open_bucket *);

View File

@ -1184,9 +1184,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
if (fsck_err_on(ret == INT_MAX, c, if (fsck_err_on(ret == INT_MAX, c,
"extent in missing inode:\n %s", "extent in missing inode:\n %s",
(bch2_bkey_val_to_text(&PBUF(buf), c, k), buf))) (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)))
return __bch2_trans_do(trans, NULL, NULL, BTREE_INSERT_LAZY_RW, return bch2_btree_delete_at(trans, iter,
bch2_btree_delete_at(trans, iter, BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE));
if (ret == INT_MAX) if (ret == INT_MAX)
return 0; return 0;
@ -1199,9 +1198,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
"extent in non regular inode mode %o:\n %s", "extent in non regular inode mode %o:\n %s",
i->inode.bi_mode, i->inode.bi_mode,
(bch2_bkey_val_to_text(&PBUF(buf), c, k), buf))) (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)))
return __bch2_trans_do(trans, NULL, NULL, BTREE_INSERT_LAZY_RW, return bch2_btree_delete_at(trans, iter,
bch2_btree_delete_at(trans, iter, BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE));
if (!bch2_snapshot_internal_node(c, k.k->p.snapshot)) { if (!bch2_snapshot_internal_node(c, k.k->p.snapshot)) {
for_each_visible_inode(c, s, inode, k.k->p.snapshot, i) { for_each_visible_inode(c, s, inode, k.k->p.snapshot, i) {
@ -1261,7 +1259,9 @@ static int check_extents(struct bch_fs *c)
BTREE_ITER_ALL_SNAPSHOTS); BTREE_ITER_ALL_SNAPSHOTS);
do { do {
ret = lockrestart_do(&trans, ret = __bch2_trans_do(&trans, NULL, NULL,
BTREE_INSERT_LAZY_RW|
BTREE_INSERT_NOFAIL,
check_extent(&trans, &iter, &w, &s)); check_extent(&trans, &iter, &w, &s));
if (ret) if (ret)
break; break;

View File

@ -460,6 +460,7 @@ int bch2_write_index_default(struct bch_write_op *op)
{ {
struct bch_fs *c = op->c; struct bch_fs *c = op->c;
struct bkey_buf sk; struct bkey_buf sk;
struct open_bucket *ec_ob = ec_open_bucket(c, &op->open_buckets);
struct keylist *keys = &op->insert_keys; struct keylist *keys = &op->insert_keys;
struct bkey_i *k = bch2_keylist_front(keys); struct bkey_i *k = bch2_keylist_front(keys);
struct btree_trans trans; struct btree_trans trans;
@ -503,6 +504,9 @@ int bch2_write_index_default(struct bch_write_op *op)
if (ret) if (ret)
break; break;
if (ec_ob)
bch2_ob_add_backpointer(c, ec_ob, &sk.k->k);
if (bkey_cmp(iter.pos, k->k.p) >= 0) if (bkey_cmp(iter.pos, k->k.p) >= 0)
bch2_keylist_pop_front(&op->insert_keys); bch2_keylist_pop_front(&op->insert_keys);
else else
@ -949,7 +953,6 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
struct bio *src = &op->wbio.bio, *dst = src; struct bio *src = &op->wbio.bio, *dst = src;
struct bvec_iter saved_iter; struct bvec_iter saved_iter;
void *ec_buf; void *ec_buf;
struct bpos ec_pos = op->pos;
unsigned total_output = 0, total_input = 0; unsigned total_output = 0, total_input = 0;
bool bounce = false; bool bounce = false;
bool page_alloc_failed = false; bool page_alloc_failed = false;
@ -1119,9 +1122,6 @@ static int bch2_write_extent(struct bch_write_op *op, struct write_point *wp,
dst->bi_iter.bi_size = total_output; dst->bi_iter.bi_size = total_output;
do_write: do_write:
/* might have done a realloc... */
bch2_ec_add_backpointer(c, wp, ec_pos, total_input >> 9);
*_dst = dst; *_dst = dst;
return more; return more;
csum_err: csum_err:

View File

@ -446,6 +446,7 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
ret = 0; ret = 0;
if ((flags & JOURNAL_RES_GET_RESERVED) || if ((flags & JOURNAL_RES_GET_RESERVED) ||
test_bit(JOURNAL_NOCHANGES, &j->flags) ||
new.reserved + d < new.remaining) { new.reserved + d < new.remaining) {
new.reserved += d; new.reserved += d;
ret = 1; ret = 1;

View File

@ -1515,7 +1515,7 @@ retry_alloc:
w->devs_written = bch2_bkey_devs(bkey_i_to_s_c(&w->key)); w->devs_written = bch2_bkey_devs(bkey_i_to_s_c(&w->key));
if (c->opts.nochanges) if (test_bit(JOURNAL_NOCHANGES, &j->flags))
goto no_io; goto no_io;
for_each_rw_member(ca, c, i) for_each_rw_member(ca, c, i)

View File

@ -34,8 +34,10 @@ unsigned bch2_journal_dev_buckets_available(struct journal *j,
struct journal_device *ja, struct journal_device *ja,
enum journal_space_from from) enum journal_space_from from)
{ {
unsigned available = (journal_space_from(ja, from) - unsigned available = !test_bit(JOURNAL_NOCHANGES, &j->flags)
ja->cur_idx - 1 + ja->nr) % ja->nr; ? ((journal_space_from(ja, from) -
ja->cur_idx - 1 + ja->nr) % ja->nr)
: ja->nr;
/* /*
* Don't use the last bucket unless writing the new last_seq * Don't use the last bucket unless writing the new last_seq

View File

@ -154,6 +154,7 @@ enum {
JOURNAL_NEED_WRITE, JOURNAL_NEED_WRITE,
JOURNAL_MAY_GET_UNRESERVED, JOURNAL_MAY_GET_UNRESERVED,
JOURNAL_MAY_SKIP_FLUSH, JOURNAL_MAY_SKIP_FLUSH,
JOURNAL_NOCHANGES,
}; };
/* Embedded in struct bch_fs */ /* Embedded in struct bch_fs */

View File

@ -8,6 +8,7 @@
#include "btree_update_interior.h" #include "btree_update_interior.h"
#include "buckets.h" #include "buckets.h"
#include "disk_groups.h" #include "disk_groups.h"
#include "ec.h"
#include "inode.h" #include "inode.h"
#include "io.h" #include "io.h"
#include "journal_reclaim.h" #include "journal_reclaim.h"
@ -136,6 +137,7 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
struct btree_iter iter; struct btree_iter iter;
struct migrate_write *m = struct migrate_write *m =
container_of(op, struct migrate_write, op); container_of(op, struct migrate_write, op);
struct open_bucket *ec_ob = ec_open_bucket(c, &op->open_buckets);
struct keylist *keys = &op->insert_keys; struct keylist *keys = &op->insert_keys;
struct bkey_buf _new, _insert; struct bkey_buf _new, _insert;
int ret = 0; int ret = 0;
@ -253,6 +255,8 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
if (!ret) { if (!ret) {
bch2_btree_iter_set_pos(&iter, next_pos); bch2_btree_iter_set_pos(&iter, next_pos);
atomic_long_inc(&c->extent_migrate_done); atomic_long_inc(&c->extent_migrate_done);
if (ec_ob)
bch2_ob_add_backpointer(c, ec_ob, &insert->k);
} }
err: err:
if (ret == -EINTR) if (ret == -EINTR)

View File

@ -337,10 +337,11 @@ static void btree_and_journal_iter_prefetch(struct bch_fs *c, struct btree *b,
bch2_bkey_buf_exit(&tmp, c); bch2_bkey_buf_exit(&tmp, c);
} }
static int bch2_btree_and_journal_walk_recurse(struct bch_fs *c, struct btree *b, static int bch2_btree_and_journal_walk_recurse(struct btree_trans *trans, struct btree *b,
enum btree_id btree_id, enum btree_id btree_id,
btree_walk_key_fn key_fn) btree_walk_key_fn key_fn)
{ {
struct bch_fs *c = trans->c;
struct btree_and_journal_iter iter; struct btree_and_journal_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_buf tmp; struct bkey_buf tmp;
@ -364,11 +365,11 @@ static int bch2_btree_and_journal_walk_recurse(struct bch_fs *c, struct btree *b
btree_and_journal_iter_prefetch(c, b, iter); btree_and_journal_iter_prefetch(c, b, iter);
ret = bch2_btree_and_journal_walk_recurse(c, child, ret = bch2_btree_and_journal_walk_recurse(trans, child,
btree_id, key_fn); btree_id, key_fn);
six_unlock_read(&child->c.lock); six_unlock_read(&child->c.lock);
} else { } else {
ret = key_fn(c, k); ret = key_fn(trans, k);
} }
if (ret) if (ret)
@ -382,9 +383,10 @@ static int bch2_btree_and_journal_walk_recurse(struct bch_fs *c, struct btree *b
return ret; return ret;
} }
int bch2_btree_and_journal_walk(struct bch_fs *c, enum btree_id btree_id, int bch2_btree_and_journal_walk(struct btree_trans *trans, enum btree_id btree_id,
btree_walk_key_fn key_fn) btree_walk_key_fn key_fn)
{ {
struct bch_fs *c = trans->c;
struct btree *b = c->btree_roots[btree_id].b; struct btree *b = c->btree_roots[btree_id].b;
int ret = 0; int ret = 0;
@ -392,7 +394,7 @@ int bch2_btree_and_journal_walk(struct bch_fs *c, enum btree_id btree_id,
return 0; return 0;
six_lock_read(&b->c.lock, NULL, NULL); six_lock_read(&b->c.lock, NULL, NULL);
ret = bch2_btree_and_journal_walk_recurse(c, b, btree_id, key_fn); ret = bch2_btree_and_journal_walk_recurse(trans, b, btree_id, key_fn);
six_unlock_read(&b->c.lock); six_unlock_read(&b->c.lock);
return ret; return ret;

View File

@ -45,9 +45,9 @@ void bch2_btree_and_journal_iter_init_node_iter(struct btree_and_journal_iter *,
struct bch_fs *, struct bch_fs *,
struct btree *); struct btree *);
typedef int (*btree_walk_key_fn)(struct bch_fs *c, struct bkey_s_c k); typedef int (*btree_walk_key_fn)(struct btree_trans *, struct bkey_s_c);
int bch2_btree_and_journal_walk(struct bch_fs *, enum btree_id, btree_walk_key_fn); int bch2_btree_and_journal_walk(struct btree_trans *, enum btree_id, btree_walk_key_fn);
void bch2_journal_keys_free(struct journal_keys *); void bch2_journal_keys_free(struct journal_keys *);
void bch2_journal_entries_free(struct list_head *); void bch2_journal_entries_free(struct list_head *);

View File

@ -61,10 +61,11 @@ const char *bch2_snapshot_invalid(const struct bch_fs *c, struct bkey_s_c k)
return NULL; return NULL;
} }
int bch2_mark_snapshot(struct bch_fs *c, int bch2_mark_snapshot(struct btree_trans *trans,
struct bkey_s_c old, struct bkey_s_c new, struct bkey_s_c old, struct bkey_s_c new,
u64 journal_seq, unsigned flags) unsigned flags)
{ {
struct bch_fs *c = trans->c;
struct snapshot_t *t; struct snapshot_t *t;
t = genradix_ptr_alloc(&c->snapshots, t = genradix_ptr_alloc(&c->snapshots,
@ -308,7 +309,7 @@ int bch2_fs_snapshots_start(struct bch_fs *c)
if (BCH_SNAPSHOT_DELETED(bkey_s_c_to_snapshot(k).v)) if (BCH_SNAPSHOT_DELETED(bkey_s_c_to_snapshot(k).v))
have_deleted = true; have_deleted = true;
ret = bch2_mark_snapshot(c, bkey_s_c_null, k, 0, 0); ret = bch2_mark_snapshot(&trans, bkey_s_c_null, k, 0);
if (ret) if (ret)
break; break;
} }
@ -499,7 +500,7 @@ static int bch2_snapshot_node_create(struct btree_trans *trans, u32 parent,
bch2_trans_update(trans, &iter, &n->k_i, 0); bch2_trans_update(trans, &iter, &n->k_i, 0);
ret = bch2_mark_snapshot(trans->c, bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0, 0); ret = bch2_mark_snapshot(trans, bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
if (ret) if (ret)
break; break;

View File

@ -12,8 +12,8 @@ const char *bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c);
.val_to_text = bch2_snapshot_to_text, \ .val_to_text = bch2_snapshot_to_text, \
} }
int bch2_mark_snapshot(struct bch_fs *, struct bkey_s_c, int bch2_mark_snapshot(struct btree_trans *, struct bkey_s_c,
struct bkey_s_c, u64, unsigned); struct bkey_s_c, unsigned);
static inline struct snapshot_t *snapshot_t(struct bch_fs *c, u32 id) static inline struct snapshot_t *snapshot_t(struct bch_fs *c, u32 id)
{ {

View File

@ -793,6 +793,9 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bch2_fs_fsio_init(c)) bch2_fs_fsio_init(c))
goto err; goto err;
if (c->opts.nochanges)
set_bit(JOURNAL_NOCHANGES, &c->journal.flags);
mi = bch2_sb_get_members(c->disk_sb.sb); mi = bch2_sb_get_members(c->disk_sb.sb);
for (i = 0; i < c->sb.nr_devices; i++) for (i = 0; i < c->sb.nr_devices; i++)
if (bch2_dev_exists(c->disk_sb.sb, mi, i) && if (bch2_dev_exists(c->disk_sb.sb, mi, i) &&