diff options
Diffstat (limited to 'libbcachefs/ec.c')
-rw-r--r-- | libbcachefs/ec.c | 131 |
1 files changed, 61 insertions, 70 deletions
diff --git a/libbcachefs/ec.c b/libbcachefs/ec.c index 02c51eaf..c8115f63 100644 --- a/libbcachefs/ec.c +++ b/libbcachefs/ec.c @@ -122,49 +122,39 @@ static void *stripe_csum(struct bch_stripe *s, unsigned dev, unsigned csum_idx) return csums + (dev * stripe_csums_per_device(s) + csum_idx) * csum_bytes; } -const char *bch2_ec_key_invalid(const struct bch_fs *c, struct bkey_s_c k) +const char *bch2_stripe_invalid(const struct bch_fs *c, struct bkey_s_c k) { + const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; + if (k.k->p.inode) return "invalid stripe key"; - switch (k.k->type) { - case BCH_STRIPE: { - const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; - - if (bkey_val_bytes(k.k) < sizeof(*s)) - return "incorrect value size"; + if (bkey_val_bytes(k.k) < sizeof(*s)) + return "incorrect value size"; - if (bkey_val_u64s(k.k) != stripe_val_u64s(s)) - return "incorrect value size"; + if (bkey_val_u64s(k.k) != stripe_val_u64s(s)) + return "incorrect value size"; - return NULL; - } - default: - return "invalid type"; - } + return NULL; } -void bch2_ec_key_to_text(struct printbuf *out, struct bch_fs *c, +void bch2_stripe_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k) { - switch (k.k->type) { - case BCH_STRIPE: { - const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; - unsigned i; - - pr_buf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u", - s->algorithm, - le16_to_cpu(s->sectors), - s->nr_blocks - s->nr_redundant, - s->nr_redundant, - s->csum_type, - 1U << s->csum_granularity_bits); - - for (i = 0; i < s->nr_blocks; i++) - pr_buf(out, " %u:%llu", s->ptrs[i].dev, - (u64) s->ptrs[i].offset); - } - } + const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; + unsigned i; + + pr_buf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u", + s->algorithm, + le16_to_cpu(s->sectors), + s->nr_blocks - s->nr_redundant, + s->nr_redundant, + s->csum_type, + 1U << s->csum_granularity_bits); + + for (i = 0; i < s->nr_blocks; i++) + pr_buf(out, " %u:%llu", s->ptrs[i].dev, + (u64) s->ptrs[i].offset); } static int ptr_matches_stripe(struct bch_fs *c, @@ -453,7 +443,7 @@ int bch2_ec_read_extent(struct bch_fs *c, struct bch_read_bio *rbio) POS(0, stripe_idx), BTREE_ITER_SLOTS); k = bch2_btree_iter_peek_slot(&iter); - if (btree_iter_err(k) || k.k->type != BCH_STRIPE) { + if (btree_iter_err(k) || k.k->type != KEY_TYPE_stripe) { __bcache_io_error(c, "error doing reconstruct read: stripe not found"); kfree(buf); @@ -529,7 +519,7 @@ err: return ret; } -/* ec_stripe bucket accounting: */ +/* stripe bucket accounting: */ static int __ec_stripe_mem_alloc(struct bch_fs *c, size_t idx, gfp_t gfp) { @@ -550,7 +540,11 @@ static int __ec_stripe_mem_alloc(struct bch_fs *c, size_t idx, gfp_t gfp) free_heap(&n); } - if (!genradix_ptr_alloc(&c->ec_stripes, idx, gfp)) + if (!genradix_ptr_alloc(&c->stripes[0], idx, gfp)) + return -ENOMEM; + + if (c->gc_pos.phase != GC_PHASE_NOT_RUNNING && + !genradix_ptr_alloc(&c->stripes[1], idx, gfp)) return -ENOMEM; return 0; @@ -591,27 +585,26 @@ static inline void ec_stripes_heap_set_backpointer(ec_stripes_heap *h, { struct bch_fs *c = container_of(h, struct bch_fs, ec_stripes_heap); - genradix_ptr(&c->ec_stripes, h->data[i].idx)->heap_idx = i; + genradix_ptr(&c->stripes[0], h->data[i].idx)->heap_idx = i; } static void heap_verify_backpointer(struct bch_fs *c, size_t idx) { ec_stripes_heap *h = &c->ec_stripes_heap; - struct ec_stripe *m = genradix_ptr(&c->ec_stripes, idx); + struct stripe *m = genradix_ptr(&c->stripes[0], idx); BUG_ON(!m->alive); BUG_ON(m->heap_idx >= h->used); BUG_ON(h->data[m->heap_idx].idx != idx); } -static inline unsigned stripe_entry_blocks(struct ec_stripe *m) +static inline unsigned stripe_entry_blocks(struct stripe *m) { - return atomic_read(&m->pin) - ? UINT_MAX : atomic_read(&m->blocks_nonempty); + return atomic_read(&m->blocks_nonempty); } void bch2_stripes_heap_update(struct bch_fs *c, - struct ec_stripe *m, size_t idx) + struct stripe *m, size_t idx) { ec_stripes_heap *h = &c->ec_stripes_heap; bool queue_delete; @@ -645,7 +638,7 @@ void bch2_stripes_heap_update(struct bch_fs *c, } void bch2_stripes_heap_del(struct bch_fs *c, - struct ec_stripe *m, size_t idx) + struct stripe *m, size_t idx) { spin_lock(&c->ec_stripes_heap_lock); heap_verify_backpointer(c, idx); @@ -658,7 +651,7 @@ void bch2_stripes_heap_del(struct bch_fs *c, } void bch2_stripes_heap_insert(struct bch_fs *c, - struct ec_stripe *m, size_t idx) + struct stripe *m, size_t idx) { spin_lock(&c->ec_stripes_heap_lock); @@ -677,7 +670,9 @@ void bch2_stripes_heap_insert(struct bch_fs *c, spin_unlock(&c->ec_stripes_heap_lock); } -static void ec_stripe_delete(struct bch_fs *c, unsigned idx) +/* stripe deletion */ + +static void ec_stripe_delete(struct bch_fs *c, size_t idx) { struct btree_iter iter; struct bch_stripe *v = NULL; @@ -689,7 +684,7 @@ static void ec_stripe_delete(struct bch_fs *c, unsigned idx) POS(0, idx), BTREE_ITER_SLOTS|BTREE_ITER_INTENT); k = bch2_btree_iter_peek_slot(&iter); - if (btree_iter_err(k) || k.k->type != BCH_STRIPE) + if (btree_iter_err(k) || k.k->type != KEY_TYPE_stripe) goto out; v = kmalloc(bkey_val_bytes(k.k), GFP_KERNEL); @@ -716,6 +711,7 @@ static void ec_stripe_delete_work(struct work_struct *work) ssize_t idx; down_read(&c->gc_lock); + mutex_lock(&c->ec_stripe_create_lock); while (1) { spin_lock(&c->ec_stripes_heap_lock); @@ -728,13 +724,15 @@ static void ec_stripe_delete_work(struct work_struct *work) ec_stripe_delete(c, idx); } + mutex_unlock(&c->ec_stripe_create_lock); up_read(&c->gc_lock); } +/* stripe creation: */ + static int ec_stripe_bkey_insert(struct bch_fs *c, struct bkey_i_stripe *stripe) { - struct ec_stripe *m; struct btree_iter iter; struct bkey_s_c k; int ret; @@ -754,18 +752,13 @@ retry: return bch2_btree_iter_unlock(&iter) ?: -ENOSPC; found_slot: - mutex_lock(&c->ec_stripes_lock); ret = ec_stripe_mem_alloc(c, &iter); - mutex_unlock(&c->ec_stripes_lock); if (ret == -EINTR) goto retry; if (ret) return ret; - m = genradix_ptr(&c->ec_stripes, iter.pos.offset); - atomic_inc(&m->pin); - stripe->k.p = iter.pos; ret = bch2_btree_insert_at(c, NULL, NULL, @@ -774,14 +767,9 @@ found_slot: BTREE_INSERT_ENTRY(&iter, &stripe->k_i)); bch2_btree_iter_unlock(&iter); - if (ret) - atomic_dec(&m->pin); - return ret; } -/* stripe creation: */ - static void extent_stripe_ptr_add(struct bkey_s_extent e, struct ec_stripe_buf *s, struct bch_extent_ptr *ptr, @@ -857,7 +845,6 @@ static int ec_stripe_update_ptrs(struct bch_fs *c, */ static void ec_stripe_create(struct ec_stripe_new *s) { - struct ec_stripe *ec_stripe; struct bch_fs *c = s->c; struct open_bucket *ob; struct bkey_i *k; @@ -897,10 +884,12 @@ static void ec_stripe_create(struct ec_stripe_new *s) goto err_put_writes; } + mutex_lock(&c->ec_stripe_create_lock); + ret = ec_stripe_bkey_insert(c, &s->stripe.key); if (ret) { bch_err(c, "error creating stripe: error creating stripe key"); - goto err_put_writes; + goto err_unlock; } for_each_keylist_key(&s->keys, k) { @@ -909,12 +898,8 @@ static void ec_stripe_create(struct ec_stripe_new *s) break; } - ec_stripe = genradix_ptr(&c->ec_stripes, s->stripe.key.k.p.offset); - - atomic_dec(&ec_stripe->pin); - bch2_stripes_heap_update(c, ec_stripe, - s->stripe.key.k.p.offset); - +err_unlock: + mutex_unlock(&c->ec_stripe_create_lock); err_put_writes: percpu_ref_put(&c->writes); err: @@ -1221,7 +1206,7 @@ unlock: mutex_unlock(&c->ec_new_stripe_lock); } -int bch2_fs_ec_start(struct bch_fs *c) +int bch2_ec_mem_alloc(struct bch_fs *c, bool gc) { struct btree_iter iter; struct bkey_s_c k; @@ -1237,19 +1222,25 @@ int bch2_fs_ec_start(struct bch_fs *c) if (ret) return ret; - if (!init_heap(&c->ec_stripes_heap, roundup_pow_of_two(idx), + if (!gc && + !init_heap(&c->ec_stripes_heap, roundup_pow_of_two(idx), GFP_KERNEL)) return -ENOMEM; #if 0 - ret = genradix_prealloc(&c->ec_stripes, idx, GFP_KERNEL); + ret = genradix_prealloc(&c->stripes[gc], idx, GFP_KERNEL); #else for (i = 0; i < idx; i++) - if (!genradix_ptr_alloc(&c->ec_stripes, i, GFP_KERNEL)) + if (!genradix_ptr_alloc(&c->stripes[gc], i, GFP_KERNEL)) return -ENOMEM; #endif return 0; } +int bch2_fs_ec_start(struct bch_fs *c) +{ + return bch2_ec_mem_alloc(c, false); +} + void bch2_fs_ec_exit(struct bch_fs *c) { struct ec_stripe_head *h; @@ -1270,7 +1261,7 @@ void bch2_fs_ec_exit(struct bch_fs *c) } free_heap(&c->ec_stripes_heap); - genradix_free(&c->ec_stripes); + genradix_free(&c->stripes[0]); bioset_exit(&c->ec_bioset); } |