summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-12-17 08:44:56 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2018-12-27 11:38:39 -0500
commit8ac80dff71027c044c7244c1f08928123725c510 (patch)
tree27f42be2d71be58b6722c504af63830d11db8fb6
parentd6542a654ce2d4d014721a8ac74885fbb42ae442 (diff)
bcachefs: factor out acc_u64s()bcachefs-v4.19
-rw-r--r--fs/bcachefs/btree_gc.c106
-rw-r--r--fs/bcachefs/buckets.c120
-rw-r--r--fs/bcachefs/buckets.h2
-rw-r--r--fs/bcachefs/util.h17
4 files changed, 79 insertions, 166 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 9f5a79a8c240..c43b2072349b 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -479,25 +479,35 @@ static void bch2_gc_free(struct bch_fs *c)
c->usage[1] = NULL;
}
-static void fs_usage_reset(struct bch_fs_usage *fs_usage)
+/*
+ * Accumulate percpu counters onto one cpu's copy - only valid when access
+ * against any percpu counter is guarded against
+ */
+static u64 *acc_percpu_u64s(u64 __percpu *p, unsigned nr)
{
- memset(&fs_usage->s.gc_start[0], 0,
- sizeof(*fs_usage) - offsetof(typeof(*fs_usage), s.gc_start));
-}
+ u64 *ret;
+ int cpu;
-static void fs_usage_cpy(struct bch_fs_usage *dst,
- struct bch_fs_usage *src)
-{
- memcpy(&dst->s.gc_start[0],
- &src->s.gc_start[0],
- sizeof(*dst) - offsetof(typeof(*dst), s.gc_start));
+ preempt_disable();
+ ret = this_cpu_ptr(p);
+ preempt_enable();
+
+ for_each_possible_cpu(cpu) {
+ u64 *i = per_cpu_ptr(p, cpu);
+
+ if (i != ret) {
+ acc_u64s(ret, i, nr);
+ memset(i, 0, nr * sizeof(u64));
+ }
+ }
+
+ return ret;
}
static void bch2_gc_done_nocheck(struct bch_fs *c)
{
struct bch_dev *ca;
unsigned i;
- int cpu;
{
struct genradix_iter dst_iter = genradix_iter_init(&c->stripes[0], 0);
@@ -527,42 +537,38 @@ static void bch2_gc_done_nocheck(struct bch_fs *c)
};
for_each_member_device(ca, c, i) {
- struct bch_dev_usage *p;
-
- for_each_possible_cpu(cpu) {
- p = per_cpu_ptr(ca->usage[0], cpu);
- memset(p, 0, sizeof(*p));
- }
+ unsigned nr = sizeof(struct bch_dev_usage) / sizeof(u64);
+ struct bch_dev_usage *dst = (void *)
+ acc_percpu_u64s((void *) ca->usage[0], nr);
+ struct bch_dev_usage *src = (void *)
+ acc_percpu_u64s((void *) ca->usage[1], nr);
- preempt_disable();
- *this_cpu_ptr(ca->usage[0]) = __bch2_dev_usage_read(ca, 1);
- preempt_enable();
+ *dst = *src;
}
{
- struct bch_fs_usage src = __bch2_fs_usage_read(c, 1);
-
- for_each_possible_cpu(cpu)
- fs_usage_reset(per_cpu_ptr(c->usage[0], cpu));
-
- preempt_disable();
- fs_usage_cpy(this_cpu_ptr(c->usage[0]), &src);
- preempt_enable();
+ unsigned nr = sizeof(struct bch_fs_usage) / sizeof(u64);
+ struct bch_fs_usage *dst = (void *)
+ acc_percpu_u64s((void *) c->usage[0], nr);
+ struct bch_fs_usage *src = (void *)
+ acc_percpu_u64s((void *) c->usage[1], nr);
+
+ memcpy(&dst->s.gc_start[0],
+ &src->s.gc_start[0],
+ sizeof(*dst) - offsetof(typeof(*dst), s.gc_start));
}
-
}
static void bch2_gc_done(struct bch_fs *c, bool initial)
{
struct bch_dev *ca;
unsigned i;
- int cpu;
#define copy_field(_f, _msg, ...) \
- if (dst._f != src._f) { \
- bch_err(c, _msg ": got %llu, should be %llu, fixing"\
- , ##__VA_ARGS__, dst._f, src._f); \
- dst._f = src._f; \
+ if (dst->_f != src->_f) { \
+ bch_err(c, _msg ": got %llu, should be %llu, fixing" \
+ , ##__VA_ARGS__, dst->_f, src->_f); \
+ dst->_f = src->_f; \
}
#define copy_stripe_field(_f, _msg, ...) \
if (dst->_f != src->_f) { \
@@ -643,9 +649,11 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
};
for_each_member_device(ca, c, i) {
- struct bch_dev_usage dst = __bch2_dev_usage_read(ca, 0);
- struct bch_dev_usage src = __bch2_dev_usage_read(ca, 1);
- struct bch_dev_usage *p;
+ unsigned nr = sizeof(struct bch_dev_usage) / sizeof(u64);
+ struct bch_dev_usage *dst = (void *)
+ acc_percpu_u64s((void *) ca->usage[0], nr);
+ struct bch_dev_usage *src = (void *)
+ acc_percpu_u64s((void *) ca->usage[1], nr);
unsigned b;
for (b = 0; b < BCH_DATA_NR; b++)
@@ -659,21 +667,14 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
"sectors[%s]", bch2_data_types[b]);
copy_dev_field(sectors_fragmented,
"sectors_fragmented");
-
- for_each_possible_cpu(cpu) {
- p = per_cpu_ptr(ca->usage[0], cpu);
- memset(p, 0, sizeof(*p));
- }
-
- preempt_disable();
- p = this_cpu_ptr(ca->usage[0]);
- *p = dst;
- preempt_enable();
}
{
- struct bch_fs_usage dst = __bch2_fs_usage_read(c, 0);
- struct bch_fs_usage src = __bch2_fs_usage_read(c, 1);
+ unsigned nr = sizeof(struct bch_fs_usage) / sizeof(u64);
+ struct bch_fs_usage *dst = (void *)
+ acc_percpu_u64s((void *) c->usage[0], nr);
+ struct bch_fs_usage *src = (void *)
+ acc_percpu_u64s((void *) c->usage[1], nr);
unsigned r, b;
copy_fs_field(s.hidden, "hidden");
@@ -696,13 +697,6 @@ 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]);
-
- for_each_possible_cpu(cpu)
- fs_usage_reset(per_cpu_ptr(c->usage[0], cpu));
-
- preempt_disable();
- fs_usage_cpy(this_cpu_ptr(c->usage[0]), &dst);
- preempt_enable();
}
out:
percpu_up_write(&c->mark_lock);
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index d72e5951615f..bd2a9330cb25 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -77,77 +77,6 @@
static inline u64 __bch2_fs_sectors_used(struct bch_fs *, struct bch_fs_usage);
-#ifdef DEBUG_BUCKETS
-
-#define lg_local_lock lg_global_lock
-#define lg_local_unlock lg_global_unlock
-
-static void bch2_fs_stats_verify(struct bch_fs *c)
-{
- struct bch_fs_usage stats =_bch2_fs_usage_read(c);
- unsigned i, j;
-
- for (i = 0; i < ARRAY_SIZE(stats.replicas); i++) {
- for (j = 0; j < ARRAY_SIZE(stats.replicas[i].data); j++)
- if ((s64) stats.replicas[i].data[j] < 0)
- panic("replicas %u %s sectors underflow: %lli\n",
- i + 1, bch_data_types[j],
- stats.replicas[i].data[j]);
-
- if ((s64) stats.replicas[i].persistent_reserved < 0)
- panic("replicas %u reserved underflow: %lli\n",
- i + 1, stats.replicas[i].persistent_reserved);
- }
-
- for (j = 0; j < ARRAY_SIZE(stats.buckets); j++)
- if ((s64) stats.replicas[i].data_buckets[j] < 0)
- panic("%s buckets underflow: %lli\n",
- bch_data_types[j],
- stats.buckets[j]);
-
- if ((s64) stats.s.online_reserved < 0)
- panic("sectors_online_reserved underflow: %lli\n",
- stats.s.online_reserved);
-}
-
-static void bch2_dev_stats_verify(struct bch_dev *ca)
-{
- struct bch_dev_usage stats =
- __bch2_dev_usage_read(ca);
- u64 n = ca->mi.nbuckets - ca->mi.first_bucket;
- unsigned i;
-
- for (i = 0; i < ARRAY_SIZE(stats.buckets); i++)
- BUG_ON(stats.buckets[i] > n);
- BUG_ON(stats.buckets_alloc > n);
- BUG_ON(stats.buckets_unavailable > n);
-}
-
-static void bch2_disk_reservations_verify(struct bch_fs *c, int flags)
-{
- if (!(flags & BCH_DISK_RESERVATION_NOFAIL)) {
- u64 used = __bch2_fs_sectors_used(c);
- u64 cached = 0;
- u64 avail = atomic64_read(&c->sectors_available);
- int cpu;
-
- for_each_possible_cpu(cpu)
- cached += per_cpu_ptr(c->usage_percpu, cpu)->available_cache;
-
- if (used + avail + cached > c->capacity)
- panic("used %llu avail %llu cached %llu capacity %llu\n",
- used, avail, cached, c->capacity);
- }
-}
-
-#else
-
-static void bch2_fs_stats_verify(struct bch_fs *c) {}
-static void bch2_dev_stats_verify(struct bch_dev *ca) {}
-static void bch2_disk_reservations_verify(struct bch_fs *c, int flags) {}
-
-#endif
-
/*
* Clear journal_seq_valid for buckets for which it's not needed, to prevent
* wraparound:
@@ -185,43 +114,23 @@ void bch2_bucket_seq_cleanup(struct bch_fs *c)
}
}
-#define bch2_usage_add(_acc, _stats) \
-do { \
- typeof(_acc) _a = (_acc), _s = (_stats); \
- unsigned i; \
- \
- for (i = 0; i < sizeof(*_a) / sizeof(u64); i++) \
- ((u64 *) (_a))[i] += ((u64 *) (_s))[i]; \
-} while (0)
-
#define bch2_usage_read_raw(_stats) \
({ \
typeof(*this_cpu_ptr(_stats)) _acc; \
- int cpu; \
\
memset(&_acc, 0, sizeof(_acc)); \
- \
- for_each_possible_cpu(cpu) \
- bch2_usage_add(&_acc, per_cpu_ptr((_stats), cpu)); \
+ acc_u64s_percpu((u64 *) &_acc, \
+ (u64 __percpu *) _stats, \
+ sizeof(_acc) / sizeof(u64)); \
\
_acc; \
})
-struct bch_dev_usage __bch2_dev_usage_read(struct bch_dev *ca, bool gc)
-{
- return bch2_usage_read_raw(ca->usage[gc]);
-}
-
struct bch_dev_usage bch2_dev_usage_read(struct bch_fs *c, struct bch_dev *ca)
{
return bch2_usage_read_raw(ca->usage[0]);
}
-struct bch_fs_usage __bch2_fs_usage_read(struct bch_fs *c, bool gc)
-{
- return bch2_usage_read_raw(c->usage[gc]);
-}
-
struct bch_fs_usage bch2_fs_usage_read(struct bch_fs *c)
{
return bch2_usage_read_raw(c->usage[0]);
@@ -324,12 +233,16 @@ void bch2_fs_usage_apply(struct bch_fs *c,
fs_usage->s.online_reserved -= added;
}
- bch2_usage_add(this_cpu_ptr(c->usage[0]), fs_usage);
-
- if (gc_visited(c, gc_pos))
- bch2_usage_add(this_cpu_ptr(c->usage[1]), fs_usage);
+ acc_u64s((u64 *) this_cpu_ptr(c->usage[0]),
+ (u64 *) fs_usage,
+ sizeof(*fs_usage) / sizeof(u64));
- bch2_fs_stats_verify(c);
+ if (gc_visited(c, gc_pos)) {
+ BUG_ON(!c->usage[1]);
+ acc_u64s((u64 *) this_cpu_ptr(c->usage[1]),
+ (u64 *) fs_usage,
+ sizeof(*fs_usage) / sizeof(u64));
+ }
memset(fs_usage, 0, sizeof(*fs_usage));
}
@@ -387,8 +300,6 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
if (!is_available_bucket(old) && is_available_bucket(new))
bch2_wake_allocator(ca);
-
- bch2_dev_stats_verify(ca);
}
void bch2_dev_usage_from_buckets(struct bch_fs *c, struct bch_dev *ca)
@@ -1003,8 +914,6 @@ void __bch2_disk_reservation_put(struct bch_fs *c, struct disk_reservation *res)
percpu_down_read_preempt_disable(&c->mark_lock);
this_cpu_sub(c->usage[0]->s.online_reserved,
res->sectors);
-
- bch2_fs_stats_verify(c);
percpu_up_read_preempt_enable(&c->mark_lock);
res->sectors = 0;
@@ -1045,8 +954,6 @@ out:
this_cpu_add(c->usage[0]->s.online_reserved, sectors);
res->sectors += sectors;
- bch2_disk_reservations_verify(c, flags);
- bch2_fs_stats_verify(c);
percpu_up_read_preempt_enable(&c->mark_lock);
return 0;
@@ -1078,14 +985,11 @@ recalculate:
this_cpu_add(c->usage[0]->s.online_reserved, sectors);
res->sectors += sectors;
ret = 0;
-
- bch2_disk_reservations_verify(c, flags);
} else {
atomic64_set(&c->sectors_available, sectors_available);
ret = -ENOSPC;
}
- bch2_fs_stats_verify(c);
percpu_up_write(&c->mark_lock);
if (!(flags & BCH_DISK_RESERVATION_GC_LOCK_HELD))
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h
index 84059111c7ca..bc9180ffd5f5 100644
--- a/fs/bcachefs/buckets.h
+++ b/fs/bcachefs/buckets.h
@@ -179,7 +179,6 @@ static inline bool bucket_needs_journal_commit(struct bucket_mark m,
/* Device usage: */
-struct bch_dev_usage __bch2_dev_usage_read(struct bch_dev *, bool);
struct bch_dev_usage bch2_dev_usage_read(struct bch_fs *, struct bch_dev *);
static inline u64 __dev_buckets_available(struct bch_dev *ca,
@@ -218,7 +217,6 @@ static inline u64 dev_buckets_free(struct bch_fs *c, struct bch_dev *ca)
/* Filesystem usage: */
-struct bch_fs_usage __bch2_fs_usage_read(struct bch_fs *, bool);
struct bch_fs_usage bch2_fs_usage_read(struct bch_fs *);
u64 bch2_fs_sectors_used(struct bch_fs *, struct bch_fs_usage);
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index 905b24f29d1d..5ea096ec5738 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.h
@@ -704,4 +704,21 @@ do { \
} \
} while (0)
+static inline void acc_u64s(u64 *acc, const u64 *src, unsigned nr)
+{
+ unsigned i;
+
+ for (i = 0; i < nr; i++)
+ acc[i] += src[i];
+}
+
+static inline void acc_u64s_percpu(u64 *acc, const u64 __percpu *src,
+ unsigned nr)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu)
+ acc_u64s(acc, per_cpu_ptr(src, cpu), nr);
+}
+
#endif /* _BCACHEFS_UTIL_H */