summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/btree_gc.c46
-rw-r--r--fs/bcachefs/buckets.c112
-rw-r--r--fs/bcachefs/buckets_types.h19
-rw-r--r--fs/bcachefs/chardev.c2
-rw-r--r--fs/bcachefs/sysfs.c2
5 files changed, 97 insertions, 84 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 75ea243d4bbc..c353fbbed975 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -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:
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index c53d7a030832..16aafe8502a0 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -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;
diff --git a/fs/bcachefs/buckets_types.h b/fs/bcachefs/buckets_types.h
index f451a96f432c..196f07f41728 100644
--- a/fs/bcachefs/buckets_types.h
+++ b/fs/bcachefs/buckets_types.h
@@ -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 {
diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c
index c11f8f4d24cf..7f79f020d904 100644
--- a/fs/bcachefs/chardev.c
+++ b/fs/bcachefs/chardev.c
@@ -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++) {
diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c
index 7e46b254da38..a423159b6ed5 100644
--- a/fs/bcachefs/sysfs.c
+++ b/fs/bcachefs/sysfs.c
@@ -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;
}