struct bch_dev_usage stats = bch2_dev_usage_read(ca);
free += bucket_to_sector(ca,
- __dev_buckets_free(ca, stats)) << 9;
+ __dev_buckets_available(ca, stats)) << 9;
/*
* Bytes of internal fragmentation, which can be
* reclaimed by copy GC
{
unsigned long gc_count = c->gc_count;
s64 available;
- unsigned i;
int ret = 0;
ca->allocator_state = ALLOCATOR_BLOCKED;
if (gc_count != c->gc_count)
ca->inc_gen_really_needs_gc = 0;
- available = dev_buckets_available(ca);
+ available = dev_buckets_reclaimable(ca);
available -= ca->inc_gen_really_needs_gc;
- spin_lock(&c->freelist_lock);
- for (i = 0; i < RESERVE_NR; i++)
- available -= fifo_used(&ca->free[i]);
- spin_unlock(&c->freelist_lock);
-
available = max(available, 0LL);
- if (available > fifo_free(&ca->free_inc) ||
- (available &&
- !fifo_full(&ca->free[RESERVE_MOVINGGC])))
+ if (available)
break;
up_read(&c->gc_lock);
void bch2_recalc_capacity(struct bch_fs *c)
{
struct bch_dev *ca;
- u64 capacity = 0, reserved_sectors = 0, gc_reserve, copygc_threshold = 0;
+ u64 capacity = 0, reserved_sectors = 0, gc_reserve;
unsigned bucket_size_max = 0;
unsigned long ra_pages = 0;
unsigned i, j;
dev_reserve *= ca->mi.bucket_size;
- copygc_threshold += dev_reserve;
-
capacity += bucket_to_sector(ca, ca->mi.nbuckets -
ca->mi.first_bucket);
reserved_sectors = min(reserved_sectors, capacity);
- c->copygc_threshold = copygc_threshold;
c->capacity = capacity - reserved_sectors;
c->bucket_size_max = bucket_size_max;
spin_lock(&c->freelist_lock);
ob->freelist = c->open_buckets_freelist;
c->open_buckets_freelist = ob - c->open_buckets;
+
c->open_buckets_nr_free++;
+ ca->nr_open_buckets--;
spin_unlock(&c->freelist_lock);
closure_wake_up(&c->open_buckets_wait);
c->blocked_allocate = 0;
}
+ ca->nr_open_buckets++;
spin_unlock(&c->freelist_lock);
bch2_wake_allocator(ca);
struct dev_stripe_state *stripe)
{
u64 *v = stripe->next_alloc + ca->dev_idx;
- u64 free_space = dev_buckets_free(ca);
+ u64 free_space = dev_buckets_available(ca);
u64 free_space_inv = free_space
? div64_u64(1ULL << 48, free_space)
: 1ULL << 48;
*/
alloc_fifo free[RESERVE_NR];
alloc_fifo free_inc;
+ unsigned nr_open_buckets;
open_bucket_idx_t open_buckets_partial[OPEN_BUCKETS_COUNT];
open_bucket_idx_t open_buckets_partial_nr;
copygc_heap copygc_heap;
struct bch_pd_controller copygc_pd;
struct write_point copygc_write_point;
- u64 copygc_threshold;
/* STRIPES: */
GENRADIX(struct stripe) stripes[2];
return total - stats.buckets_unavailable;
}
-/*
- * Number of reclaimable buckets - only for use by the allocator thread:
- */
static inline u64 dev_buckets_available(struct bch_dev *ca)
{
return __dev_buckets_available(ca, bch2_dev_usage_read(ca));
}
-static inline u64 __dev_buckets_free(struct bch_dev *ca,
- struct bch_dev_usage stats)
+static inline u64 __dev_buckets_reclaimable(struct bch_dev *ca,
+ struct bch_dev_usage stats)
{
- return __dev_buckets_available(ca, stats) +
- fifo_used(&ca->free[RESERVE_NONE]) +
- fifo_used(&ca->free_inc);
+ struct bch_fs *c = ca->fs;
+ s64 available = __dev_buckets_available(ca, stats);
+ unsigned i;
+
+ spin_lock(&c->freelist_lock);
+ for (i = 0; i < RESERVE_NR; i++)
+ available -= fifo_used(&ca->free[i]);
+ available -= fifo_used(&ca->free_inc);
+ available -= ca->nr_open_buckets;
+ spin_unlock(&c->freelist_lock);
+
+ return max(available, 0LL);
}
-static inline u64 dev_buckets_free(struct bch_dev *ca)
+static inline u64 dev_buckets_reclaimable(struct bch_dev *ca)
{
- return __dev_buckets_free(ca, bch2_dev_usage_read(ca));
+ return __dev_buckets_reclaimable(ca, bch2_dev_usage_read(ca));
}
/* Filesystem usage: */
{
struct bch_dev *ca;
unsigned dev_idx;
- u64 fragmented_allowed = c->copygc_threshold;
- u64 fragmented = 0;
+ u64 fragmented_allowed = 0, fragmented = 0;
for_each_rw_member(ca, c, dev_idx) {
struct bch_dev_usage usage = bch2_dev_usage_read(ca);
- fragmented_allowed += ((__dev_buckets_available(ca, usage) *
+ fragmented_allowed += ((__dev_buckets_reclaimable(ca, usage) *
ca->mi.bucket_size) >> 1);
fragmented += usage.d[BCH_DATA_user].fragmented;
}
"free[RESERVE_MOVINGGC]\t%zu/%zu\n"
"free[RESERVE_NONE]\t%zu/%zu\n"
"freelist_wait\t\t%s\n"
- "open buckets\t\t%u/%u (reserved %u)\n"
+ "open buckets allocated\t%u\n"
+ "open buckets this dev\t%u\n"
+ "open buckets total\t%u\n"
"open_buckets_wait\t%s\n"
"open_buckets_btree\t%u\n"
"open_buckets_user\t%u\n"
fifo_used(&ca->free[RESERVE_MOVINGGC]), ca->free[RESERVE_MOVINGGC].size,
fifo_used(&ca->free[RESERVE_NONE]), ca->free[RESERVE_NONE].size,
c->freelist_wait.list.first ? "waiting" : "empty",
- c->open_buckets_nr_free, OPEN_BUCKETS_COUNT,
- BTREE_NODE_OPEN_BUCKET_RESERVE,
+ OPEN_BUCKETS_COUNT - c->open_buckets_nr_free,
+ ca->nr_open_buckets,
+ OPEN_BUCKETS_COUNT,
c->open_buckets_wait.list.first ? "waiting" : "empty",
nr[BCH_DATA_btree],
nr[BCH_DATA_user],