summaryrefslogtreecommitdiff
path: root/libbcachefs/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/ec.c')
-rw-r--r--libbcachefs/ec.c131
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);
}