summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-03-16 02:00:21 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-08-28 19:16:12 -0800
commite72438204b9127a36591b46fdb780a51fe5cb39d (patch)
tree18f829cf174e39982d709df38b856f0e960c1cfb
parent698f07c5f146ec48e8df0d96e6acf61b11b03f0a (diff)
bcache: calculate capacity based off member info
-rw-r--r--fs/bcachefs/alloc.c76
-rw-r--r--fs/bcachefs/bcache.h11
-rw-r--r--fs/bcachefs/btree_gc.c2
-rw-r--r--fs/bcachefs/buckets.c28
-rw-r--r--fs/bcachefs/buckets.h2
-rw-r--r--fs/bcachefs/fs.c5
-rw-r--r--fs/bcachefs/request.c2
-rw-r--r--fs/bcachefs/sysfs.c4
-rw-r--r--fs/bcachefs/writeback.c6
-rw-r--r--fs/bcachefs/writeback.h4
10 files changed, 71 insertions, 69 deletions
diff --git a/fs/bcachefs/alloc.c b/fs/bcachefs/alloc.c
index b4975df07a99..1d1d302c84a1 100644
--- a/fs/bcachefs/alloc.c
+++ b/fs/bcachefs/alloc.c
@@ -519,10 +519,8 @@ static void bch_inc_clock_hand(struct io_timer *timer)
mutex_unlock(&c->bucket_lock);
- capacity = READ_ONCE(c->capacity);
-
- if (!capacity)
- return;
+ capacity = READ_ONCE(c->exposed_capacity);
+ BUG_ON(!capacity);
/*
* we only increment when 0.1% of the cache_set has been read
@@ -544,7 +542,7 @@ static void bch_prio_timer_init(struct cache_set *c, int rw)
clock->rw = rw;
timer->fn = bch_inc_clock_hand;
- timer->expire = c->capacity >> 10;
+ timer->expire = c->exposed_capacity >> 10;
}
/*
@@ -1500,11 +1498,13 @@ struct open_bucket *bch_alloc_sectors(struct cache_set *c,
static void bch_recalc_capacity(struct cache_set *c)
{
- struct cache_group *tier = c->cache_tiers + ARRAY_SIZE(c->cache_tiers);
+ struct cache_member_rcu *mi;
+ struct cache_member_cpu *m;
struct cache *ca;
- u64 total_capacity, capacity = 0, reserved_sectors = 0;
+ u64 total_capacity = 0;
unsigned long ra_pages = 0;
- unsigned i, j;
+ unsigned i;
+ int tier;
rcu_read_lock();
for_each_cache_rcu(ca, c, i) {
@@ -1513,62 +1513,28 @@ static void bch_recalc_capacity(struct cache_set *c)
ra_pages += bdi->ra_pages;
}
+ rcu_read_unlock();
c->bdi.ra_pages = ra_pages;
/*
* Capacity of the cache set is the capacity of all the devices in the
- * slowest (highest) tier - we don't include lower tier devices.
+ * slowest (highest) tier that has devices - we don't include lower tier
+ * devices:
*/
- for (tier = c->cache_tiers + ARRAY_SIZE(c->cache_tiers) - 1;
- tier > c->cache_tiers && !tier->nr_devices;
- --tier)
- ;
-
- group_for_each_cache_rcu(ca, tier, i) {
- size_t reserve = 0;
-
- /*
- * We need to reserve buckets (from the number
- * of currently available buckets) against
- * foreground writes so that mainly copygc can
- * make forward progress.
- *
- * We need enough to refill the various reserves
- * from scratch - copygc will use its entire
- * reserve all at once, then run against when
- * its reserve is refilled (from the formerly
- * available buckets).
- *
- * This reserve is just used when considering if
- * allocations for foreground writes must wait -
- * not -ENOSPC calculations.
- */
- for (j = 0; j < RESERVE_NR; j++)
- reserve += ca->free[j].size;
- reserve += ca->free_inc.size;
-
- ca->reserve_buckets_count = reserve;
-
- reserved_sectors += reserve << ca->bucket_bits;
-
- capacity += (ca->mi.nbuckets -
- ca->mi.first_bucket) <<
- ca->bucket_bits;
- }
- rcu_read_unlock();
-
- total_capacity = capacity;
-
- capacity *= (100 - c->opts.gc_reserve_percent);
- capacity = div64_u64(capacity, 100);
-
- BUG_ON(capacity + reserved_sectors > total_capacity);
+ mi = cache_member_info_get(c);
+ for (tier = CACHE_TIERS - 1; tier >= 0 && !total_capacity; --tier)
+ for (m = mi->m; m < mi->m + mi->nr_in_set; m++)
+ if (m->tier == tier && m->state == CACHE_ACTIVE)
+ total_capacity += (m->nbuckets - m->first_bucket) *
+ m->bucket_size;
+ cache_member_info_put();
- c->capacity = capacity;
+ c->exposed_capacity = div64_u64(total_capacity *
+ (100 - c->sector_reserve_percent), 100);
- if (c->capacity) {
+ if (c->exposed_capacity) {
bch_io_timer_add(&c->io_clock[READ],
&c->prio_clock[READ].rescale);
bch_io_timer_add(&c->io_clock[WRITE],
diff --git a/fs/bcachefs/bcache.h b/fs/bcachefs/bcache.h
index 83ee086b60fe..7f856f7fd1aa 100644
--- a/fs/bcachefs/bcache.h
+++ b/fs/bcachefs/bcache.h
@@ -636,7 +636,16 @@ struct cache_set {
struct cache_group cache_all;
struct cache_group cache_tiers[CACHE_TIERS];
- u64 capacity; /* sectors */
+ /*
+ * If we want to be able to run rw without all devices currently
+ * present, we need to track capacity of currently available devices:
+ * but we don't want necessarily visible capacity to jump around as
+ * devices go temporarily offline and come back
+ *
+ * both sectors:
+ */
+ u64 exposed_capacity;
+ u64 online_capacity;
/*
* When capacity _decreases_ (due to a disk being removed), we
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 486c47372458..5e3cb929c8cf 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -765,7 +765,7 @@ static int bch_gc_thread(void *arg)
set_freezable();
while (1) {
- unsigned long next = last + c->capacity / 16;
+ unsigned long next = last + c->exposed_capacity / 16;
while (atomic_long_read(&clock->now) < next) {
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index 35336afd0ab2..596d90034bbd 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -624,7 +624,7 @@ void bch_unmark_open_bucket(struct cache *ca, struct bucket *g)
static u64 __recalc_sectors_available(struct cache_set *c)
{
- return c->capacity - cache_set_sectors_used(c);
+ return c->online_capacity - cache_set_sectors_used(c);
}
/* Used by gc when it's starting: */
@@ -737,3 +737,29 @@ int bch_disk_reservation_get(struct cache_set *c,
return bch_disk_reservation_add(c, res, sectors, flags);
}
+
+void bch_capacity_update(struct cache_set *c, u64 new_capacity)
+{
+ lg_global_lock(&c->bucket_stats_lock);
+
+ if (new_capacity < c->online_capacity) {
+ struct bucket_stats_cache_set *stats;
+ int cpu;
+
+ /* invalidate sectors_available */
+ atomic64_set(&c->sectors_available, 0);
+
+ for_each_possible_cpu(cpu) {
+ stats = per_cpu_ptr(c->bucket_stats_percpu, cpu);
+ stats->sectors_available_cache = 0;
+ }
+
+ c->online_capacity = new_capacity;
+ smp_wmb();
+ c->capacity_gen++;
+ } else {
+ c->online_capacity = new_capacity;
+ }
+
+ lg_global_unlock(&c->bucket_stats_lock);
+}
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h
index c96a398ca7bc..e878ac09a0f2 100644
--- a/fs/bcachefs/buckets.h
+++ b/fs/bcachefs/buckets.h
@@ -213,7 +213,7 @@ static inline u64 __cache_set_sectors_used(struct cache_set *c)
static inline u64 cache_set_sectors_used(struct cache_set *c)
{
- return min(c->capacity, __cache_set_sectors_used(c));
+ return min(c->exposed_capacity, __cache_set_sectors_used(c));
}
/* XXX: kill? */
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 3432269afeeb..fbaad0c35c4d 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -1129,8 +1129,9 @@ static int bch_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_type = BCACHE_STATFS_MAGIC;
buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = c->capacity >> PAGE_SECTOR_SHIFT;
- buf->f_bfree = (c->capacity - cache_set_sectors_used(c)) >> PAGE_SECTOR_SHIFT;
+ buf->f_blocks = c->exposed_capacity >> PAGE_SECTOR_SHIFT;
+ buf->f_bfree = (c->exposed_capacity -
+ cache_set_sectors_used(c)) >> PAGE_SECTOR_SHIFT;
buf->f_bavail = buf->f_bfree;
buf->f_files = atomic_long_read(&c->nr_inodes);
buf->f_ffree = U64_MAX;
diff --git a/fs/bcachefs/request.c b/fs/bcachefs/request.c
index 67c8d3f3d145..5baab9a92e18 100644
--- a/fs/bcachefs/request.c
+++ b/fs/bcachefs/request.c
@@ -99,7 +99,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio, int rw)
struct io *i;
if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
- sectors_available(c) * 100 < c->capacity * CUTOFF_CACHE_ADD ||
+ sectors_available(c) * 100 < c->online_capacity * CUTOFF_CACHE_ADD ||
(bio->bi_rw & REQ_DISCARD))
goto skip;
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index 4df9c72486a7..a901b5d8368a 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -551,7 +551,7 @@ static size_t bch_cache_size(struct cache_set *c)
static unsigned bch_cache_available_percent(struct cache_set *c)
{
return div64_u64((u64) sectors_available(c) * 100,
- c->capacity ?: 1);
+ c->exposed_capacity ?: 1);
}
#if 0
@@ -585,7 +585,7 @@ static ssize_t show_cache_set_alloc_debug(struct cache_set *c, char *buf)
"\tcached:\t\t%llu\n"
"persistent reserved sectors:\t%llu\n"
"online reserved sectors:\t%llu\n",
- c->capacity,
+ c->exposed_capacity,
stats.s[S_COMPRESSED][S_META],
stats.s[S_COMPRESSED][S_DIRTY],
stats.s[S_COMPRESSED][S_CACHED],
diff --git a/fs/bcachefs/writeback.c b/fs/bcachefs/writeback.c
index 846533cd527b..9d4095e5fe12 100644
--- a/fs/bcachefs/writeback.c
+++ b/fs/bcachefs/writeback.c
@@ -28,7 +28,7 @@ static void __update_writeback_rate(struct cached_dev *dc)
{
struct cache_set *c = dc->disk.c;
u64 cache_dirty_target =
- div_u64(c->capacity * dc->writeback_percent, 100);
+ div_u64(c->exposed_capacity * dc->writeback_percent, 100);
s64 target = div64_u64(cache_dirty_target *
bdev_sectors(dc->disk_sb.bdev),
c->cached_dev_sectors);
@@ -488,9 +488,9 @@ static int bch_writeback_thread(void *arg)
sectors_written = bch_writeback(dc);
- if (sectors_written < c->capacity >> 4)
+ if (sectors_written < c->exposed_capacity >> 4)
bch_kthread_io_clock_wait(clock,
- last + (c->capacity >> 5));
+ last + (c->exposed_capacity >> 5));
}
return 0;
diff --git a/fs/bcachefs/writeback.h b/fs/bcachefs/writeback.h
index a71a2bfe1b87..58f39d7bf291 100644
--- a/fs/bcachefs/writeback.h
+++ b/fs/bcachefs/writeback.h
@@ -50,7 +50,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
if (cache_mode != CACHE_MODE_WRITEBACK ||
test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
- available * 100 < c->capacity * CUTOFF_WRITEBACK_SYNC)
+ available * 100 < c->online_capacity * CUTOFF_WRITEBACK_SYNC)
return false;
if (dc->partial_stripes_expensive &&
@@ -62,7 +62,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
return false;
return bio->bi_rw & REQ_SYNC ||
- available * 100 < c->capacity * CUTOFF_WRITEBACK;
+ available * 100 < c->online_capacity * CUTOFF_WRITEBACK;
}
static inline void bch_writeback_queue(struct cached_dev *dc)