diff options
Diffstat (limited to 'fs/bcachefs/ec.c')
-rw-r--r-- | fs/bcachefs/ec.c | 134 |
1 files changed, 84 insertions, 50 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index dba861111a8d..be2eca0fcdf7 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -162,19 +162,20 @@ static int extent_matches_stripe(struct bch_fs *c, struct bch_stripe *v, struct bkey_s_c k) { - struct bkey_s_c_extent e; - const struct bch_extent_ptr *ptr; - int idx; - if (!bkey_extent_is_data(k.k)) - return -1; - - e = bkey_s_c_to_extent(k); + switch (k.k->type) { + case KEY_TYPE_extent: { + struct bkey_s_c_extent e = bkey_s_c_to_extent(k); + const struct bch_extent_ptr *ptr; + int idx; - extent_for_each_ptr(e, ptr) { - idx = ptr_matches_stripe(c, v, ptr); - if (idx >= 0) - return idx; + extent_for_each_ptr(e, ptr) { + idx = ptr_matches_stripe(c, v, ptr); + if (idx >= 0) + return idx; + } + break; + } } return -1; @@ -182,19 +183,20 @@ static int extent_matches_stripe(struct bch_fs *c, static bool extent_has_stripe_ptr(struct bkey_s_c k, u64 idx) { - struct bkey_s_c_extent e; - const union bch_extent_entry *entry; - - if (!bkey_extent_is_data(k.k)) - return false; + switch (k.k->type) { + case KEY_TYPE_extent: { + struct bkey_s_c_extent e = bkey_s_c_to_extent(k); + const union bch_extent_entry *entry; - e = bkey_s_c_to_extent(k); + extent_for_each_entry(e, entry) + if (extent_entry_type(entry) == + BCH_EXTENT_ENTRY_stripe_ptr && + entry->stripe_ptr.idx == idx) + return true; - extent_for_each_entry(e, entry) - if (extent_entry_type(entry) == - BCH_EXTENT_ENTRY_stripe_ptr && - entry->stripe_ptr.idx == idx) - return true; + break; + } + } return false; } @@ -399,11 +401,10 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf, bio_set_op_attrs(&ec_bio->bio, rw, 0); ec_bio->bio.bi_iter.bi_sector = ptr->offset + buf->offset + (offset >> 9); - ec_bio->bio.bi_iter.bi_size = b; ec_bio->bio.bi_end_io = ec_block_endio; ec_bio->bio.bi_private = cl; - bch2_bio_map(&ec_bio->bio, buf->data[idx] + offset); + bch2_bio_map(&ec_bio->bio, buf->data[idx] + offset, b); closure_get(cl); percpu_ref_get(&ca->io_ref); @@ -576,7 +577,8 @@ static ssize_t stripe_idx_to_delete(struct bch_fs *c) { ec_stripes_heap *h = &c->ec_stripes_heap; - return h->data[0].blocks_nonempty == 0 ? h->data[0].idx : -1; + return h->used && h->data[0].blocks_nonempty == 0 + ? h->data[0].idx : -1; } static inline int ec_stripes_heap_cmp(ec_stripes_heap *h, @@ -627,7 +629,8 @@ void bch2_stripes_heap_update(struct bch_fs *c, bch2_stripes_heap_insert(c, m, idx); } - if (stripe_idx_to_delete(c) >= 0) + if (stripe_idx_to_delete(c) >= 0 && + !percpu_ref_is_dying(&c->writes)) schedule_work(&c->ec_stripe_delete_work); } @@ -685,7 +688,8 @@ static void ec_stripe_delete_work(struct work_struct *work) if (idx < 0) break; - ec_stripe_delete(c, idx); + if (ec_stripe_delete(c, idx)) + break; } mutex_unlock(&c->ec_stripe_create_lock); @@ -700,26 +704,34 @@ static int ec_stripe_bkey_insert(struct bch_fs *c, struct btree_trans trans; struct btree_iter *iter; struct bkey_s_c k; + struct bpos start_pos = POS(0, c->ec_stripe_hint); int ret; bch2_trans_init(&trans, c, 0, 0); retry: bch2_trans_begin(&trans); - /* XXX: start pos hint */ - for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, + for_each_btree_key(&trans, iter, BTREE_ID_EC, start_pos, BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) { - if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0) + if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0) { + if (start_pos.offset) { + start_pos = POS_MIN; + bch2_btree_iter_set_pos(iter, start_pos); + continue; + } + + ret = -ENOSPC; break; + } if (bkey_deleted(k.k)) goto found_slot; } - if (!ret) - ret = -ENOSPC; goto err; found_slot: + start_pos = iter->pos; + ret = ec_stripe_mem_alloc(c, iter); if (ret) goto err; @@ -734,6 +746,8 @@ found_slot: err: if (ret == -EINTR) goto retry; + + c->ec_stripe_hint = ret ? start_pos.offset : start_pos.offset + 1; bch2_trans_exit(&trans); return ret; @@ -1159,12 +1173,8 @@ void bch2_ec_stop_dev(struct bch_fs *c, struct bch_dev *ca) struct ec_stripe_new *s = NULL; mutex_lock(&h->lock); - bch2_open_buckets_stop_dev(c, ca, - &h->blocks, - BCH_DATA_USER); - bch2_open_buckets_stop_dev(c, ca, - &h->parity, - BCH_DATA_USER); + bch2_open_buckets_stop_dev(c, ca, &h->blocks); + bch2_open_buckets_stop_dev(c, ca, &h->parity); if (!h->s) goto unlock; @@ -1265,10 +1275,10 @@ int bch2_stripes_write(struct bch_fs *c, unsigned flags, bool *wrote) int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys) { - struct journal_key *i; struct btree_trans trans; - struct btree_iter *iter; - struct bkey_s_c k; + struct btree_iter *btree_iter; + struct journal_iter journal_iter; + struct bkey_s_c btree_k, journal_k, k; int ret; ret = bch2_fs_ec_start(c); @@ -1277,10 +1287,41 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys) bch2_trans_init(&trans, c, 0, 0); - for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, 0, k, ret) - bch2_mark_key(c, k, 0, NULL, 0, + btree_iter = bch2_trans_get_iter(&trans, BTREE_ID_EC, POS_MIN, 0); + journal_iter = bch2_journal_iter_init(journal_keys, BTREE_ID_EC); + + btree_k = bch2_btree_iter_peek(btree_iter); + journal_k = bch2_journal_iter_peek(&journal_iter); + + while (1) { + if (btree_k.k && journal_k.k) { + int cmp = bkey_cmp(btree_k.k->p, journal_k.k->p); + + if (cmp < 0) { + k = btree_k; + btree_k = bch2_btree_iter_next(btree_iter); + } else if (cmp == 0) { + btree_k = bch2_btree_iter_next(btree_iter); + k = journal_k; + journal_k = bch2_journal_iter_next(&journal_iter); + } else { + k = journal_k; + journal_k = bch2_journal_iter_next(&journal_iter); + } + } else if (btree_k.k) { + k = btree_k; + btree_k = bch2_btree_iter_next(btree_iter); + } else if (journal_k.k) { + k = journal_k; + journal_k = bch2_journal_iter_next(&journal_iter); + } else { + break; + } + + bch2_mark_key(c, k, 0, 0, NULL, 0, BCH_BUCKET_MARK_ALLOC_READ| BCH_BUCKET_MARK_NOATOMIC); + } ret = bch2_trans_exit(&trans) ?: ret; if (ret) { @@ -1288,13 +1329,6 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys) return ret; } - for_each_journal_key(*journal_keys, i) - if (i->btree_id == BTREE_ID_EC) - bch2_mark_key(c, bkey_i_to_s_c(i->k), - 0, NULL, 0, - BCH_BUCKET_MARK_ALLOC_READ| - BCH_BUCKET_MARK_NOATOMIC); - return 0; } |