Commit 3e154711 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: x-macroize alloc_reserve enum

This makes an array of strings available, like our other enums.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent f13fd87a
...@@ -780,7 +780,7 @@ static int push_invalidated_bucket(struct bch_fs *c, struct bch_dev *ca, u64 b) ...@@ -780,7 +780,7 @@ static int push_invalidated_bucket(struct bch_fs *c, struct bch_dev *ca, u64 b)
* Don't strand buckets on the copygc freelist until * Don't strand buckets on the copygc freelist until
* after recovery is finished: * after recovery is finished:
*/ */
if (i == RESERVE_MOVINGGC && if (i == RESERVE_movinggc &&
!test_bit(BCH_FS_STARTED, &c->flags)) !test_bit(BCH_FS_STARTED, &c->flags))
continue; continue;
...@@ -941,7 +941,7 @@ void bch2_recalc_capacity(struct bch_fs *c) ...@@ -941,7 +941,7 @@ void bch2_recalc_capacity(struct bch_fs *c)
* allocations for foreground writes must wait - * allocations for foreground writes must wait -
* not -ENOSPC calculations. * not -ENOSPC calculations.
*/ */
for (j = 0; j < RESERVE_NONE; j++) for (j = 0; j < RESERVE_none; j++)
dev_reserve += ca->free[j].size; dev_reserve += ca->free[j].size;
dev_reserve += 1; /* btree write point */ dev_reserve += 1; /* btree write point */
......
...@@ -27,6 +27,13 @@ ...@@ -27,6 +27,13 @@
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
const char * const bch2_alloc_reserves[] = {
#define x(t) #t,
BCH_ALLOC_RESERVES()
#undef x
NULL
};
/* /*
* Open buckets represent a bucket that's currently being allocated from. They * Open buckets represent a bucket that's currently being allocated from. They
* serve two purposes: * serve two purposes:
...@@ -168,10 +175,10 @@ long bch2_bucket_alloc_new_fs(struct bch_dev *ca) ...@@ -168,10 +175,10 @@ long bch2_bucket_alloc_new_fs(struct bch_dev *ca)
static inline unsigned open_buckets_reserved(enum alloc_reserve reserve) static inline unsigned open_buckets_reserved(enum alloc_reserve reserve)
{ {
switch (reserve) { switch (reserve) {
case RESERVE_BTREE: case RESERVE_btree:
case RESERVE_BTREE_MOVINGGC: case RESERVE_btree_movinggc:
return 0; return 0;
case RESERVE_MOVINGGC: case RESERVE_movinggc:
return OPEN_BUCKETS_COUNT / 4; return OPEN_BUCKETS_COUNT / 4;
default: default:
return OPEN_BUCKETS_COUNT / 2; return OPEN_BUCKETS_COUNT / 2;
...@@ -219,17 +226,17 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca, ...@@ -219,17 +226,17 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca,
c->blocked_allocate_open_bucket = local_clock(); c->blocked_allocate_open_bucket = local_clock();
spin_unlock(&c->freelist_lock); spin_unlock(&c->freelist_lock);
trace_open_bucket_alloc_fail(ca, reserve); trace_open_bucket_alloc_fail(ca, bch2_alloc_reserves[reserve]);
return ERR_PTR(-OPEN_BUCKETS_EMPTY); return ERR_PTR(-OPEN_BUCKETS_EMPTY);
} }
if (likely(fifo_pop(&ca->free[RESERVE_NONE], b))) if (likely(fifo_pop(&ca->free[RESERVE_none], b)))
goto out; goto out;
switch (reserve) { switch (reserve) {
case RESERVE_BTREE_MOVINGGC: case RESERVE_btree_movinggc:
case RESERVE_MOVINGGC: case RESERVE_movinggc:
if (fifo_pop(&ca->free[RESERVE_MOVINGGC], b)) if (fifo_pop(&ca->free[RESERVE_movinggc], b))
goto out; goto out;
break; break;
default: default:
...@@ -244,7 +251,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca, ...@@ -244,7 +251,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca,
spin_unlock(&c->freelist_lock); spin_unlock(&c->freelist_lock);
trace_bucket_alloc_fail(ca, reserve); trace_bucket_alloc_fail(ca, bch2_alloc_reserves[reserve]);
return ERR_PTR(-FREELIST_EMPTY); return ERR_PTR(-FREELIST_EMPTY);
out: out:
verify_not_on_freelist(c, ca, b); verify_not_on_freelist(c, ca, b);
...@@ -282,7 +289,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca, ...@@ -282,7 +289,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca,
bch2_wake_allocator(ca); bch2_wake_allocator(ca);
trace_bucket_alloc(ca, reserve); trace_bucket_alloc(ca, bch2_alloc_reserves[reserve]);
return ob; return ob;
} }
......
...@@ -12,6 +12,8 @@ struct bch_dev; ...@@ -12,6 +12,8 @@ struct bch_dev;
struct bch_fs; struct bch_fs;
struct bch_devs_List; struct bch_devs_List;
extern const char * const bch2_alloc_reserves[];
struct dev_alloc_list { struct dev_alloc_list {
unsigned nr; unsigned nr;
u8 devs[BCH_SB_MEMBERS_MAX]; u8 devs[BCH_SB_MEMBERS_MAX];
......
...@@ -22,12 +22,17 @@ enum allocator_states { ...@@ -22,12 +22,17 @@ enum allocator_states {
#undef x #undef x
}; };
#define BCH_ALLOC_RESERVES() \
x(btree_movinggc) \
x(btree) \
x(movinggc) \
x(none)
enum alloc_reserve { enum alloc_reserve {
RESERVE_BTREE_MOVINGGC = -2, #define x(name) RESERVE_##name,
RESERVE_BTREE = -1, BCH_ALLOC_RESERVES()
RESERVE_MOVINGGC = 0, #undef x
RESERVE_NONE = 1, RESERVE_NR
RESERVE_NR = 2,
}; };
typedef FIFO(long) alloc_fifo; typedef FIFO(long) alloc_fifo;
......
...@@ -194,10 +194,10 @@ static struct btree *__bch2_btree_node_alloc(struct bch_fs *c, ...@@ -194,10 +194,10 @@ static struct btree *__bch2_btree_node_alloc(struct bch_fs *c,
if (flags & BTREE_INSERT_USE_RESERVE) { if (flags & BTREE_INSERT_USE_RESERVE) {
nr_reserve = 0; nr_reserve = 0;
alloc_reserve = RESERVE_BTREE_MOVINGGC; alloc_reserve = RESERVE_btree_movinggc;
} else { } else {
nr_reserve = BTREE_NODE_RESERVE; nr_reserve = BTREE_NODE_RESERVE;
alloc_reserve = RESERVE_BTREE; alloc_reserve = RESERVE_btree;
} }
mutex_lock(&c->btree_reserve_cache_lock); mutex_lock(&c->btree_reserve_cache_lock);
......
...@@ -2091,9 +2091,9 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) ...@@ -2091,9 +2091,9 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
!(buckets_nouse = kvpmalloc(BITS_TO_LONGS(nbuckets) * !(buckets_nouse = kvpmalloc(BITS_TO_LONGS(nbuckets) *
sizeof(unsigned long), sizeof(unsigned long),
GFP_KERNEL|__GFP_ZERO))) || GFP_KERNEL|__GFP_ZERO))) ||
!init_fifo(&free[RESERVE_MOVINGGC], !init_fifo(&free[RESERVE_movinggc],
copygc_reserve, GFP_KERNEL) || copygc_reserve, GFP_KERNEL) ||
!init_fifo(&free[RESERVE_NONE], reserve_none, GFP_KERNEL) || !init_fifo(&free[RESERVE_none], reserve_none, GFP_KERNEL) ||
!init_fifo(&free_inc, free_inc_nr, GFP_KERNEL) || !init_fifo(&free_inc, free_inc_nr, GFP_KERNEL) ||
!init_heap(&alloc_heap, ALLOC_SCAN_BATCH(ca) << 1, GFP_KERNEL)) !init_heap(&alloc_heap, ALLOC_SCAN_BATCH(ca) << 1, GFP_KERNEL))
goto err; goto err;
......
...@@ -1307,8 +1307,8 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h, ...@@ -1307,8 +1307,8 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h,
&nr_have_parity, &nr_have_parity,
&have_cache, &have_cache,
h->copygc h->copygc
? RESERVE_MOVINGGC ? RESERVE_movinggc
: RESERVE_NONE, : RESERVE_none,
0, 0,
cl); cl);
...@@ -1336,8 +1336,8 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h, ...@@ -1336,8 +1336,8 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h,
&nr_have_data, &nr_have_data,
&have_cache, &have_cache,
h->copygc h->copygc
? RESERVE_MOVINGGC ? RESERVE_movinggc
: RESERVE_NONE, : RESERVE_none,
0, 0,
cl); cl);
......
...@@ -70,7 +70,7 @@ static inline u64 *op_journal_seq(struct bch_write_op *op) ...@@ -70,7 +70,7 @@ static inline u64 *op_journal_seq(struct bch_write_op *op)
static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op) static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op)
{ {
return op->alloc_reserve == RESERVE_MOVINGGC return op->alloc_reserve == RESERVE_movinggc
? op->c->copygc_wq ? op->c->copygc_wq
: op->c->btree_update_wq; : op->c->btree_update_wq;
} }
...@@ -97,7 +97,7 @@ static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c, ...@@ -97,7 +97,7 @@ static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
op->compression_type = bch2_compression_opt_to_type[opts.compression]; op->compression_type = bch2_compression_opt_to_type[opts.compression];
op->nr_replicas = 0; op->nr_replicas = 0;
op->nr_replicas_required = c->opts.data_replicas_required; op->nr_replicas_required = c->opts.data_replicas_required;
op->alloc_reserve = RESERVE_NONE; op->alloc_reserve = RESERVE_none;
op->incompressible = 0; op->incompressible = 0;
op->open_buckets.nr = 0; op->open_buckets.nr = 0;
op->devs_have.nr = 0; op->devs_have.nr = 0;
......
...@@ -817,7 +817,7 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, ...@@ -817,7 +817,7 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr,
} }
} else { } else {
rcu_read_lock(); rcu_read_lock();
ob = bch2_bucket_alloc(c, ca, RESERVE_NONE, ob = bch2_bucket_alloc(c, ca, RESERVE_none,
false, cl); false, cl);
rcu_read_unlock(); rcu_read_unlock();
if (IS_ERR(ob)) { if (IS_ERR(ob)) {
......
...@@ -351,7 +351,7 @@ int bch2_migrate_write_init(struct bch_fs *c, struct migrate_write *m, ...@@ -351,7 +351,7 @@ int bch2_migrate_write_init(struct bch_fs *c, struct migrate_write *m,
} }
if (m->data_opts.btree_insert_flags & BTREE_INSERT_USE_RESERVE) { if (m->data_opts.btree_insert_flags & BTREE_INSERT_USE_RESERVE) {
m->op.alloc_reserve = RESERVE_MOVINGGC; m->op.alloc_reserve = RESERVE_movinggc;
m->op.flags |= BCH_WRITE_ALLOC_NOWAIT; m->op.flags |= BCH_WRITE_ALLOC_NOWAIT;
} else { } else {
/* XXX: this should probably be passed in */ /* XXX: this should probably be passed in */
......
...@@ -30,21 +30,6 @@ ...@@ -30,21 +30,6 @@
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/wait.h> #include <linux/wait.h>
/*
* We can't use the entire copygc reserve in one iteration of copygc: we may
* need the buckets we're freeing up to go back into the copygc reserve to make
* forward progress, but if the copygc reserve is full they'll be available for
* any allocation - and it's possible that in a given iteration, we free up most
* of the buckets we're going to free before we allocate most of the buckets
* we're going to allocate.
*
* If we only use half of the reserve per iteration, then in steady state we'll
* always have room in the reserve for the buckets we're going to need in the
* next iteration:
*/
#define COPYGC_BUCKETS_PER_ITER(ca) \
((ca)->free[RESERVE_MOVINGGC].size / 2)
static int bucket_offset_cmp(const void *_l, const void *_r, size_t size) static int bucket_offset_cmp(const void *_l, const void *_r, size_t size)
{ {
const struct copygc_heap_entry *l = _l; const struct copygc_heap_entry *l = _l;
...@@ -124,7 +109,7 @@ static bool have_copygc_reserve(struct bch_dev *ca) ...@@ -124,7 +109,7 @@ static bool have_copygc_reserve(struct bch_dev *ca)
bool ret; bool ret;
spin_lock(&ca->fs->freelist_lock); spin_lock(&ca->fs->freelist_lock);
ret = fifo_full(&ca->free[RESERVE_MOVINGGC]) || ret = fifo_full(&ca->free[RESERVE_movinggc]) ||
ca->allocator_state != ALLOCATOR_running; ca->allocator_state != ALLOCATOR_running;
spin_unlock(&ca->fs->freelist_lock); spin_unlock(&ca->fs->freelist_lock);
...@@ -265,7 +250,7 @@ static int bch2_copygc(struct bch_fs *c) ...@@ -265,7 +250,7 @@ static int bch2_copygc(struct bch_fs *c)
closure_wait_event(&c->freelist_wait, have_copygc_reserve(ca)); closure_wait_event(&c->freelist_wait, have_copygc_reserve(ca));
spin_lock(&ca->fs->freelist_lock); spin_lock(&ca->fs->freelist_lock);
sectors_reserved += fifo_used(&ca->free[RESERVE_MOVINGGC]) * ca->mi.bucket_size; sectors_reserved += fifo_used(&ca->free[RESERVE_movinggc]) * ca->mi.bucket_size;
spin_unlock(&ca->fs->freelist_lock); spin_unlock(&ca->fs->freelist_lock);
} }
...@@ -281,7 +266,7 @@ static int bch2_copygc(struct bch_fs *c) ...@@ -281,7 +266,7 @@ static int bch2_copygc(struct bch_fs *c)
} }
/* /*
* Our btree node allocations also come out of RESERVE_MOVINGGC: * Our btree node allocations also come out of RESERVE_movingc:
*/ */
sectors_reserved = (sectors_reserved * 3) / 4; sectors_reserved = (sectors_reserved * 3) / 4;
if (!sectors_reserved) { if (!sectors_reserved) {
......
...@@ -758,8 +758,8 @@ static void dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca) ...@@ -758,8 +758,8 @@ static void dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca)
stats.buckets_ec, stats.buckets_ec,
__dev_buckets_available(ca, stats), __dev_buckets_available(ca, stats),
fifo_used(&ca->free_inc), ca->free_inc.size, fifo_used(&ca->free_inc), ca->free_inc.size,
fifo_used(&ca->free[RESERVE_MOVINGGC]), ca->free[RESERVE_MOVINGGC].size, fifo_used(&ca->free[RESERVE_movinggc]), ca->free[RESERVE_movinggc].size,
fifo_used(&ca->free[RESERVE_NONE]), ca->free[RESERVE_NONE].size, fifo_used(&ca->free[RESERVE_none]), ca->free[RESERVE_none].size,
c->freelist_wait.list.first ? "waiting" : "empty", c->freelist_wait.list.first ? "waiting" : "empty",
OPEN_BUCKETS_COUNT - c->open_buckets_nr_free, OPEN_BUCKETS_COUNT - c->open_buckets_nr_free,
ca->nr_open_buckets, ca->nr_open_buckets,
......
...@@ -468,37 +468,37 @@ TRACE_EVENT(invalidate, ...@@ -468,37 +468,37 @@ TRACE_EVENT(invalidate,
); );
DECLARE_EVENT_CLASS(bucket_alloc, DECLARE_EVENT_CLASS(bucket_alloc,
TP_PROTO(struct bch_dev *ca, enum alloc_reserve reserve), TP_PROTO(struct bch_dev *ca, const char *alloc_reserve),
TP_ARGS(ca, reserve), TP_ARGS(ca, alloc_reserve),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(dev_t, dev ) __field(dev_t, dev )
__field(enum alloc_reserve, reserve ) __array(char, reserve, 16 )
), ),
TP_fast_assign( TP_fast_assign(
__entry->dev = ca->dev; __entry->dev = ca->dev;
__entry->reserve = reserve; strlcpy(__entry->reserve, alloc_reserve, sizeof(__entry->reserve));
), ),
TP_printk("%d,%d reserve %d", TP_printk("%d,%d reserve %s",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->reserve) __entry->reserve)
); );
DEFINE_EVENT(bucket_alloc, bucket_alloc, DEFINE_EVENT(bucket_alloc, bucket_alloc,
TP_PROTO(struct bch_dev *ca, enum alloc_reserve reserve), TP_PROTO(struct bch_dev *ca, const char *alloc_reserve),
TP_ARGS(ca, reserve) TP_ARGS(ca, alloc_reserve)
); );
DEFINE_EVENT(bucket_alloc, bucket_alloc_fail, DEFINE_EVENT(bucket_alloc, bucket_alloc_fail,
TP_PROTO(struct bch_dev *ca, enum alloc_reserve reserve), TP_PROTO(struct bch_dev *ca, const char *alloc_reserve),
TP_ARGS(ca, reserve) TP_ARGS(ca, alloc_reserve)
); );
DEFINE_EVENT(bucket_alloc, open_bucket_alloc_fail, DEFINE_EVENT(bucket_alloc, open_bucket_alloc_fail,
TP_PROTO(struct bch_dev *ca, enum alloc_reserve reserve), TP_PROTO(struct bch_dev *ca, const char *alloc_reserve),
TP_ARGS(ca, reserve) TP_ARGS(ca, alloc_reserve)
); );
/* Moving IO */ /* Moving IO */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment