summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/alloc_foreground.c4
-rw-r--r--fs/bcachefs/ec.c32
-rw-r--r--fs/bcachefs/ec.h36
3 files changed, 49 insertions, 23 deletions
diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c
index 4621ef7f1e50..7c81189bcd62 100644
--- a/fs/bcachefs/alloc_foreground.c
+++ b/fs/bcachefs/alloc_foreground.c
@@ -97,7 +97,7 @@ void __bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob)
struct bch_dev *ca = bch_dev_bkey_exists(c, ob->dev);
if (ob->ec) {
- ec_stripe_new_put(c, ob->ec);
+ ec_stripe_new_put(c, ob->ec, STRIPE_REF_io);
return;
}
@@ -799,7 +799,7 @@ got_bucket:
ob->ec_idx = ec_idx;
ob->ec = h->s;
- ec_stripe_new_get(h->s);
+ ec_stripe_new_get(h->s, STRIPE_REF_io);
ret = add_new_bucket(c, ptrs, devs_may_alloc,
nr_replicas, nr_effective,
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 1fd68d44b90f..0a2e7db6906f 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -1057,6 +1057,13 @@ static void zero_out_rest_of_ec_bucket(struct bch_fs *c,
s->err = ret;
}
+void bch2_ec_stripe_new_free(struct bch_fs *c, struct ec_stripe_new *s)
+{
+ if (s->idx)
+ bch2_stripe_close(c, s);
+ kfree(s);
+}
+
/*
* data buckets of new stripe all written: create the stripe
*/
@@ -1152,13 +1159,11 @@ err:
list_del(&s->list);
mutex_unlock(&c->ec_stripe_new_lock);
- if (s->idx)
- bch2_stripe_close(c, s);
-
ec_stripe_buf_exit(&s->existing_stripe);
ec_stripe_buf_exit(&s->new_stripe);
closure_debug_destroy(&s->iodone);
- kfree(s);
+
+ ec_stripe_new_put(c, s, STRIPE_REF_stripe);
}
static struct ec_stripe_new *get_pending_stripe(struct bch_fs *c)
@@ -1167,7 +1172,7 @@ static struct ec_stripe_new *get_pending_stripe(struct bch_fs *c)
mutex_lock(&c->ec_stripe_new_lock);
list_for_each_entry(s, &c->ec_stripe_new_list, list)
- if (!atomic_read(&s->pin))
+ if (!atomic_read(&s->ref[STRIPE_REF_io]))
goto out;
s = NULL;
out:
@@ -1209,7 +1214,7 @@ static void ec_stripe_set_pending(struct bch_fs *c, struct ec_stripe_head *h)
list_add(&s->list, &c->ec_stripe_new_list);
mutex_unlock(&c->ec_stripe_new_lock);
- ec_stripe_new_put(c, s);
+ ec_stripe_new_put(c, s, STRIPE_REF_io);
}
void bch2_ec_bucket_cancel(struct bch_fs *c, struct open_bucket *ob)
@@ -1321,7 +1326,8 @@ static int ec_new_stripe_alloc(struct bch_fs *c, struct ec_stripe_head *h)
mutex_init(&s->lock);
closure_init(&s->iodone, NULL);
- atomic_set(&s->pin, 1);
+ atomic_set(&s->ref[STRIPE_REF_stripe], 1);
+ atomic_set(&s->ref[STRIPE_REF_io], 1);
s->c = c;
s->h = h;
s->nr_data = min_t(unsigned, h->nr_active_devs,
@@ -1829,13 +1835,16 @@ void bch2_stripes_heap_to_text(struct printbuf *out, struct bch_fs *c)
size_t i;
mutex_lock(&c->ec_stripes_heap_lock);
- for (i = 0; i < min_t(size_t, h->used, 20); i++) {
+ for (i = 0; i < min_t(size_t, h->used, 50); i++) {
m = genradix_ptr(&c->stripes, h->data[i].idx);
- prt_printf(out, "%zu %u/%u+%u\n", h->data[i].idx,
+ prt_printf(out, "%zu %u/%u+%u", h->data[i].idx,
h->data[i].blocks_nonempty,
m->nr_blocks - m->nr_redundant,
m->nr_redundant);
+ if (bch2_stripe_is_open(c, h->data[i].idx))
+ prt_str(out, " open");
+ prt_newline(out);
}
mutex_unlock(&c->ec_stripes_heap_lock);
}
@@ -1860,9 +1869,10 @@ void bch2_new_stripes_to_text(struct printbuf *out, struct bch_fs *c)
mutex_lock(&c->ec_stripe_new_lock);
list_for_each_entry(s, &c->ec_stripe_new_list, list) {
- prt_printf(out, "\tin flight: idx %llu blocks %u+%u pin %u\n",
+ prt_printf(out, "\tin flight: idx %llu blocks %u+%u ref %u %u\n",
s->idx, s->nr_data, s->nr_parity,
- atomic_read(&s->pin));
+ atomic_read(&s->ref[STRIPE_REF_io]),
+ atomic_read(&s->ref[STRIPE_REF_stripe]));
}
mutex_unlock(&c->ec_stripe_new_lock);
}
diff --git a/fs/bcachefs/ec.h b/fs/bcachefs/ec.h
index d112aea9ec56..8f777a37e43d 100644
--- a/fs/bcachefs/ec.h
+++ b/fs/bcachefs/ec.h
@@ -143,6 +143,12 @@ struct ec_stripe_buf {
struct ec_stripe_head;
+enum ec_stripe_ref {
+ STRIPE_REF_io,
+ STRIPE_REF_stripe,
+ STRIPE_REF_NR
+};
+
struct ec_stripe_new {
struct bch_fs *c;
struct ec_stripe_head *h;
@@ -154,8 +160,7 @@ struct ec_stripe_new {
struct closure iodone;
- /* counts in flight writes, stripe is created when pin == 0 */
- atomic_t pin;
+ atomic_t ref[STRIPE_REF_NR];
int err;
@@ -213,19 +218,30 @@ void bch2_stripes_heap_insert(struct bch_fs *, struct stripe *, size_t);
void bch2_do_stripe_deletes(struct bch_fs *);
void bch2_ec_do_stripe_creates(struct bch_fs *);
+void bch2_ec_stripe_new_free(struct bch_fs *, struct ec_stripe_new *);
-static inline void ec_stripe_new_get(struct ec_stripe_new *s)
+static inline void ec_stripe_new_get(struct ec_stripe_new *s,
+ enum ec_stripe_ref ref)
{
- atomic_inc(&s->pin);
+ atomic_inc(&s->ref[ref]);
}
-static inline void ec_stripe_new_put(struct bch_fs *c, struct ec_stripe_new *s)
+static inline void ec_stripe_new_put(struct bch_fs *c, struct ec_stripe_new *s,
+ enum ec_stripe_ref ref)
{
- BUG_ON(atomic_read(&s->pin) <= 0);
- BUG_ON(!s->err && !s->idx);
-
- if (atomic_dec_and_test(&s->pin))
- bch2_ec_do_stripe_creates(c);
+ BUG_ON(atomic_read(&s->ref[ref]) <= 0);
+
+ if (atomic_dec_and_test(&s->ref[ref]))
+ switch (ref) {
+ case STRIPE_REF_stripe:
+ bch2_ec_stripe_new_free(c, s);
+ break;
+ case STRIPE_REF_io:
+ bch2_ec_do_stripe_creates(c);
+ break;
+ default:
+ unreachable();
+ }
}
void bch2_ec_stop_dev(struct bch_fs *, struct bch_dev *);