mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
bcachefs: Include summarized counts in fs_usage
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
5663a41521
commit
06b7345cc2
@ -482,6 +482,24 @@ static void bch2_gc_free(struct bch_fs *c)
|
||||
c->usage[1] = NULL;
|
||||
}
|
||||
|
||||
static void fs_usage_reset(struct bch_fs_usage *fs_usage)
|
||||
{
|
||||
unsigned offset = offsetof(typeof(*fs_usage), s.gc_start);
|
||||
|
||||
memset((void *) fs_usage + offset, 0,
|
||||
sizeof(*fs_usage) - offset);
|
||||
}
|
||||
|
||||
static void fs_usage_cpy(struct bch_fs_usage *dst,
|
||||
struct bch_fs_usage *src)
|
||||
{
|
||||
unsigned offset = offsetof(typeof(*dst), s.gc_start);
|
||||
|
||||
memcpy((void *) dst + offset,
|
||||
(void *) src + offset,
|
||||
sizeof(*dst) - offset);
|
||||
}
|
||||
|
||||
static void bch2_gc_done_nocheck(struct bch_fs *c)
|
||||
{
|
||||
struct bch_dev *ca;
|
||||
@ -530,17 +548,12 @@ static void bch2_gc_done_nocheck(struct bch_fs *c)
|
||||
|
||||
{
|
||||
struct bch_fs_usage src = __bch2_fs_usage_read(c, 1);
|
||||
struct bch_fs_usage *p;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
p = per_cpu_ptr(c->usage[0], cpu);
|
||||
memset(p, 0, offsetof(typeof(*p), online_reserved));
|
||||
}
|
||||
for_each_possible_cpu(cpu)
|
||||
fs_usage_reset(per_cpu_ptr(c->usage[0], cpu));
|
||||
|
||||
preempt_disable();
|
||||
memcpy(this_cpu_ptr(c->usage[0]),
|
||||
&src,
|
||||
offsetof(typeof(*p), online_reserved));
|
||||
fs_usage_cpy(this_cpu_ptr(c->usage[0]), &src);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
@ -668,9 +681,14 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
|
||||
{
|
||||
struct bch_fs_usage dst = __bch2_fs_usage_read(c, 0);
|
||||
struct bch_fs_usage src = __bch2_fs_usage_read(c, 1);
|
||||
struct bch_fs_usage *p;
|
||||
unsigned r, b;
|
||||
|
||||
copy_fs_field(s.hidden, "hidden");
|
||||
copy_fs_field(s.data, "data");
|
||||
copy_fs_field(s.cached, "cached");
|
||||
copy_fs_field(s.reserved, "reserved");
|
||||
copy_fs_field(s.nr_inodes, "nr_inodes");
|
||||
|
||||
for (r = 0; r < BCH_REPLICAS_MAX; r++) {
|
||||
for (b = 0; b < BCH_DATA_NR; b++)
|
||||
copy_fs_field(replicas[r].data[b],
|
||||
@ -685,16 +703,12 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
|
||||
for (b = 0; b < BCH_DATA_NR; b++)
|
||||
copy_fs_field(buckets[b],
|
||||
"buckets[%s]", bch2_data_types[b]);
|
||||
copy_fs_field(nr_inodes, "nr_inodes");
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
p = per_cpu_ptr(c->usage[0], cpu);
|
||||
memset(p, 0, offsetof(typeof(*p), online_reserved));
|
||||
}
|
||||
for_each_possible_cpu(cpu)
|
||||
fs_usage_reset(per_cpu_ptr(c->usage[0], cpu));
|
||||
|
||||
preempt_disable();
|
||||
p = this_cpu_ptr(c->usage[0]);
|
||||
memcpy(p, &dst, offsetof(typeof(*p), online_reserved));
|
||||
fs_usage_cpy(this_cpu_ptr(c->usage[0]), &dst);
|
||||
preempt_enable();
|
||||
}
|
||||
out:
|
||||
|
@ -106,9 +106,9 @@ static void bch2_fs_stats_verify(struct bch_fs *c)
|
||||
bch_data_types[j],
|
||||
stats.buckets[j]);
|
||||
|
||||
if ((s64) stats.online_reserved < 0)
|
||||
if ((s64) stats.s.online_reserved < 0)
|
||||
panic("sectors_online_reserved underflow: %lli\n",
|
||||
stats.online_reserved);
|
||||
stats.s.online_reserved);
|
||||
}
|
||||
|
||||
static void bch2_dev_stats_verify(struct bch_dev *ca)
|
||||
@ -228,38 +228,6 @@ struct bch_fs_usage bch2_fs_usage_read(struct bch_fs *c)
|
||||
return bch2_usage_read_raw(c->usage[0]);
|
||||
}
|
||||
|
||||
struct fs_usage_sum {
|
||||
u64 hidden;
|
||||
u64 data;
|
||||
u64 cached;
|
||||
u64 reserved;
|
||||
};
|
||||
|
||||
static inline struct fs_usage_sum __fs_usage_sum(struct bch_fs_usage stats)
|
||||
{
|
||||
struct fs_usage_sum sum = { 0 };
|
||||
unsigned i;
|
||||
|
||||
/*
|
||||
* For superblock and journal we count bucket usage, not sector usage,
|
||||
* because any internal fragmentation should _not_ be counted as
|
||||
* free space:
|
||||
*/
|
||||
sum.hidden += stats.buckets[BCH_DATA_SB];
|
||||
sum.hidden += stats.buckets[BCH_DATA_JOURNAL];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stats.replicas); i++) {
|
||||
sum.data += stats.replicas[i].data[BCH_DATA_BTREE];
|
||||
sum.data += stats.replicas[i].data[BCH_DATA_USER];
|
||||
sum.data += stats.replicas[i].ec_data;
|
||||
sum.cached += stats.replicas[i].data[BCH_DATA_CACHED];
|
||||
sum.reserved += stats.replicas[i].persistent_reserved;
|
||||
}
|
||||
|
||||
sum.reserved += stats.online_reserved;
|
||||
return sum;
|
||||
}
|
||||
|
||||
#define RESERVE_FACTOR 6
|
||||
|
||||
static u64 reserve_factor(u64 r)
|
||||
@ -274,9 +242,10 @@ static u64 avail_factor(u64 r)
|
||||
|
||||
static inline u64 __bch2_fs_sectors_used(struct bch_fs *c, struct bch_fs_usage fs_usage)
|
||||
{
|
||||
struct fs_usage_sum sum = __fs_usage_sum(fs_usage);
|
||||
|
||||
return sum.hidden + sum.data + reserve_factor(sum.reserved);
|
||||
return fs_usage.s.hidden +
|
||||
fs_usage.s.data +
|
||||
reserve_factor(fs_usage.s.reserved +
|
||||
fs_usage.s.online_reserved);
|
||||
}
|
||||
|
||||
u64 bch2_fs_sectors_used(struct bch_fs *c, struct bch_fs_usage fs_usage)
|
||||
@ -287,13 +256,14 @@ u64 bch2_fs_sectors_used(struct bch_fs *c, struct bch_fs_usage fs_usage)
|
||||
struct bch_fs_usage_short
|
||||
bch2_fs_usage_read_short(struct bch_fs *c)
|
||||
{
|
||||
struct bch_fs_usage usage = bch2_fs_usage_read(c);
|
||||
struct fs_usage_sum sum = __fs_usage_sum(usage);
|
||||
struct bch_fs_usage_summarized usage =
|
||||
bch2_usage_read_raw(&c->usage[0]->s);
|
||||
struct bch_fs_usage_short ret;
|
||||
|
||||
ret.capacity = READ_ONCE(c->capacity) - sum.hidden;
|
||||
ret.used = min(ret.capacity, sum.data +
|
||||
reserve_factor(sum.reserved));
|
||||
ret.capacity = READ_ONCE(c->capacity) - usage.hidden;
|
||||
ret.used = min(ret.capacity, usage.data +
|
||||
reserve_factor(usage.reserved +
|
||||
usage.online_reserved));
|
||||
ret.nr_inodes = usage.nr_inodes;
|
||||
|
||||
return ret;
|
||||
@ -334,8 +304,7 @@ void bch2_fs_usage_apply(struct bch_fs *c,
|
||||
struct disk_reservation *disk_res,
|
||||
struct gc_pos gc_pos)
|
||||
{
|
||||
struct fs_usage_sum sum = __fs_usage_sum(*fs_usage);
|
||||
s64 added = sum.data + sum.reserved;
|
||||
s64 added = fs_usage->s.data + fs_usage->s.reserved;
|
||||
s64 should_not_have_added;
|
||||
|
||||
percpu_rwsem_assert_held(&c->mark_lock);
|
||||
@ -353,7 +322,7 @@ void bch2_fs_usage_apply(struct bch_fs *c,
|
||||
|
||||
if (added > 0) {
|
||||
disk_res->sectors -= added;
|
||||
fs_usage->online_reserved -= added;
|
||||
fs_usage->s.online_reserved -= added;
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
@ -368,6 +337,18 @@ void bch2_fs_usage_apply(struct bch_fs *c,
|
||||
memset(fs_usage, 0, sizeof(*fs_usage));
|
||||
}
|
||||
|
||||
static inline void account_bucket(struct bch_fs_usage *fs_usage,
|
||||
struct bch_dev_usage *dev_usage,
|
||||
enum bch_data_type type,
|
||||
int nr, s64 size)
|
||||
{
|
||||
if (type == BCH_DATA_SB || type == BCH_DATA_JOURNAL)
|
||||
fs_usage->s.hidden += size;
|
||||
|
||||
fs_usage->buckets[type] += size;
|
||||
dev_usage->buckets[type] += nr;
|
||||
}
|
||||
|
||||
static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
|
||||
struct bch_fs_usage *fs_usage,
|
||||
struct bucket_mark old, struct bucket_mark new,
|
||||
@ -386,15 +367,13 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
|
||||
preempt_disable();
|
||||
dev_usage = this_cpu_ptr(ca->usage[gc]);
|
||||
|
||||
if (bucket_type(old)) {
|
||||
fs_usage->buckets[bucket_type(old)] -= ca->mi.bucket_size;
|
||||
dev_usage->buckets[bucket_type(old)]--;
|
||||
}
|
||||
if (bucket_type(old))
|
||||
account_bucket(fs_usage, dev_usage, bucket_type(old),
|
||||
-1, -ca->mi.bucket_size);
|
||||
|
||||
if (bucket_type(new)) {
|
||||
fs_usage->buckets[bucket_type(new)] += ca->mi.bucket_size;
|
||||
dev_usage->buckets[bucket_type(new)]++;
|
||||
}
|
||||
if (bucket_type(new))
|
||||
account_bucket(fs_usage, dev_usage, bucket_type(new),
|
||||
1, ca->mi.bucket_size);
|
||||
|
||||
dev_usage->buckets_alloc +=
|
||||
(int) new.owned_by_allocator - (int) old.owned_by_allocator;
|
||||
@ -460,7 +439,8 @@ static void __bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
new.gen++;
|
||||
}));
|
||||
|
||||
fs_usage->replicas[0].data[BCH_DATA_CACHED] -= old->cached_sectors;
|
||||
fs_usage->replicas[0].data[BCH_DATA_CACHED] -= old->cached_sectors;
|
||||
fs_usage->s.cached -= old->cached_sectors;
|
||||
}
|
||||
|
||||
void bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
@ -528,7 +508,10 @@ static void __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
checked_add(new.dirty_sectors, sectors);
|
||||
}));
|
||||
|
||||
fs_usage->replicas[0].data[type] += sectors;
|
||||
if (type == BCH_DATA_BTREE ||
|
||||
type == BCH_DATA_USER)
|
||||
fs_usage->s.data += sectors;
|
||||
fs_usage->replicas[0].data[type] += sectors;
|
||||
}
|
||||
|
||||
void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
|
||||
@ -755,8 +738,13 @@ static int bch2_mark_extent(struct bch_fs *c, struct bkey_s_c k,
|
||||
ec_redundancy = clamp_t(unsigned, ec_redundancy,
|
||||
1, ARRAY_SIZE(fs_usage->replicas));
|
||||
|
||||
fs_usage->s.cached += cached_sectors;
|
||||
fs_usage->replicas[0].data[BCH_DATA_CACHED] += cached_sectors;
|
||||
|
||||
fs_usage->s.data += dirty_sectors;
|
||||
fs_usage->replicas[replicas - 1].data[data_type] += dirty_sectors;
|
||||
|
||||
fs_usage->s.data += ec_sectors;
|
||||
fs_usage->replicas[ec_redundancy - 1].ec_data += ec_sectors;
|
||||
|
||||
return 0;
|
||||
@ -866,9 +854,9 @@ static int __bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
|
||||
break;
|
||||
case KEY_TYPE_alloc:
|
||||
if (inserting)
|
||||
fs_usage->nr_inodes++;
|
||||
fs_usage->s.nr_inodes++;
|
||||
else
|
||||
fs_usage->nr_inodes--;
|
||||
fs_usage->s.nr_inodes--;
|
||||
break;
|
||||
case KEY_TYPE_reservation: {
|
||||
unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
|
||||
@ -877,7 +865,8 @@ static int __bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
|
||||
replicas = clamp_t(unsigned, replicas,
|
||||
1, ARRAY_SIZE(fs_usage->replicas));
|
||||
|
||||
fs_usage->replicas[replicas - 1].persistent_reserved += sectors;
|
||||
fs_usage->s.reserved += sectors;
|
||||
fs_usage->replicas[replicas - 1].persistent_reserved += sectors;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1021,8 +1010,7 @@ static u64 bch2_recalc_sectors_available(struct bch_fs *c)
|
||||
void __bch2_disk_reservation_put(struct bch_fs *c, struct disk_reservation *res)
|
||||
{
|
||||
percpu_down_read(&c->mark_lock);
|
||||
this_cpu_sub(c->usage[0]->online_reserved,
|
||||
res->sectors);
|
||||
this_cpu_sub(c->usage[0]->s.online_reserved, res->sectors);
|
||||
|
||||
bch2_fs_stats_verify(c);
|
||||
percpu_up_read(&c->mark_lock);
|
||||
@ -1064,7 +1052,7 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
|
||||
|
||||
out:
|
||||
pcpu->sectors_available -= sectors;
|
||||
this_cpu_add(c->usage[0]->online_reserved, sectors);
|
||||
this_cpu_add(c->usage[0]->s.online_reserved, sectors);
|
||||
res->sectors += sectors;
|
||||
|
||||
bch2_disk_reservations_verify(c, flags);
|
||||
@ -1098,7 +1086,7 @@ recalculate:
|
||||
(flags & BCH_DISK_RESERVATION_NOFAIL)) {
|
||||
atomic64_set(&c->sectors_available,
|
||||
max_t(s64, 0, sectors_available - sectors));
|
||||
this_cpu_add(c->usage[0]->online_reserved, sectors);
|
||||
this_cpu_add(c->usage[0]->s.online_reserved, sectors);
|
||||
res->sectors += sectors;
|
||||
ret = 0;
|
||||
|
||||
|
@ -63,6 +63,21 @@ struct bch_dev_usage {
|
||||
struct bch_fs_usage {
|
||||
/* all fields are in units of 512 byte sectors: */
|
||||
|
||||
/* summarized: */
|
||||
struct bch_fs_usage_summarized {
|
||||
u64 online_reserved;
|
||||
|
||||
/* fields after online_reserved are cleared/recalculated by gc: */
|
||||
u64 gc_start[0];
|
||||
|
||||
u64 hidden;
|
||||
u64 data;
|
||||
u64 cached;
|
||||
u64 reserved;
|
||||
u64 nr_inodes;
|
||||
} s;
|
||||
|
||||
/* broken out: */
|
||||
struct {
|
||||
u64 data[BCH_DATA_NR];
|
||||
u64 ec_data;
|
||||
@ -70,10 +85,6 @@ struct bch_fs_usage {
|
||||
} replicas[BCH_REPLICAS_MAX];
|
||||
|
||||
u64 buckets[BCH_DATA_NR];
|
||||
|
||||
u64 nr_inodes;
|
||||
|
||||
u64 online_reserved;
|
||||
};
|
||||
|
||||
struct bch_fs_usage_short {
|
||||
|
@ -398,7 +398,7 @@ static long bch2_ioctl_usage(struct bch_fs *c,
|
||||
struct bch_ioctl_fs_usage dst = {
|
||||
.capacity = c->capacity,
|
||||
.used = bch2_fs_sectors_used(c, src),
|
||||
.online_reserved = src.online_reserved,
|
||||
.online_reserved = src.s.online_reserved,
|
||||
};
|
||||
|
||||
for (i = 0; i < BCH_REPLICAS_MAX; i++) {
|
||||
|
@ -259,7 +259,7 @@ static ssize_t show_fs_alloc_debug(struct bch_fs *c, char *buf)
|
||||
stats.buckets[type]);
|
||||
|
||||
pr_buf(&out, "online reserved:\t%llu\n",
|
||||
stats.online_reserved);
|
||||
stats.s.online_reserved);
|
||||
|
||||
return out.pos - buf;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user