Commit f5095b9f authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: dev_usage updated by new accounting



Reading disk accounting now requires an eytzinger lookup (see:
bch2_accounting_mem_read()), but the per-device counters are used
frequently enough that we'd like to still be able to read them with just
a percpu sum, as in the old code.

This patch special cases the device counters; when we update in-memory
accounting we also update the old style percpu counters if it's a deice
counter update.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 2e8d686a
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -545,8 +545,7 @@ struct bch_dev {
	unsigned long		*buckets_nouse;
	struct rw_semaphore	bucket_lock;

	struct bch_dev_usage		*usage_base;
	struct bch_dev_usage __percpu	*usage[JOURNAL_BUF_NR];
	struct bch_dev_usage __percpu	*usage;
	struct bch_dev_usage __percpu	*usage_gc;

	/* Allocator: */
+1 −1
Original line number Diff line number Diff line
@@ -773,7 +773,7 @@ static int bch2_gc_done(struct bch_fs *c)
		bch2_fs_usage_acc_to_base(c, i);

	__for_each_member_device(c, ca) {
		struct bch_dev_usage *dst = ca->usage_base;
		struct bch_dev_usage *dst = this_cpu_ptr(ca->usage);
		struct bch_dev_usage *src = (void *)
			bch2_acc_percpu_u64s((u64 __percpu *) ca->usage_gc,
					     dev_usage_u64s());
+5 −31
Original line number Diff line number Diff line
@@ -69,15 +69,8 @@ void bch2_fs_usage_initialize(struct bch_fs *c)

void bch2_dev_usage_read_fast(struct bch_dev *ca, struct bch_dev_usage *usage)
{
	struct bch_fs *c = ca->fs;
	unsigned seq, i, u64s = dev_usage_u64s();

	do {
		seq = read_seqcount_begin(&c->usage_lock);
		memcpy(usage, ca->usage_base, u64s * sizeof(u64));
		for (i = 0; i < ARRAY_SIZE(ca->usage); i++)
			acc_u64s_percpu((u64 *) usage, (u64 __percpu *) ca->usage[i], u64s);
	} while (read_seqcount_retry(&c->usage_lock, seq));
	memset(usage, 0, sizeof(*usage));
	acc_u64s_percpu((u64 *) usage, (u64 __percpu *) ca->usage, dev_usage_u64s());
}

u64 bch2_fs_usage_read_one(struct bch_fs *c, u64 *v)
@@ -147,16 +140,6 @@ void bch2_fs_usage_acc_to_base(struct bch_fs *c, unsigned idx)
			(u64 __percpu *) c->usage[idx], u64s);
	percpu_memset(c->usage[idx], 0, u64s * sizeof(u64));

	rcu_read_lock();
	for_each_member_device_rcu(c, ca, NULL) {
		u64s = dev_usage_u64s();

		acc_u64s_percpu((u64 *) ca->usage_base,
				(u64 __percpu *) ca->usage[idx], u64s);
		percpu_memset(ca->usage[idx], 0, u64s * sizeof(u64));
	}
	rcu_read_unlock();

	write_seqcount_end(&c->usage_lock);
	preempt_enable();
}
@@ -1488,23 +1471,14 @@ void bch2_dev_buckets_free(struct bch_dev *ca)
{
	kvfree(ca->buckets_nouse);
	kvfree(rcu_dereference_protected(ca->bucket_gens, 1));

	for (unsigned i = 0; i < ARRAY_SIZE(ca->usage); i++)
		free_percpu(ca->usage[i]);
	kfree(ca->usage_base);
	free_percpu(ca->usage);
}

int bch2_dev_buckets_alloc(struct bch_fs *c, struct bch_dev *ca)
{
	ca->usage_base = kzalloc(sizeof(struct bch_dev_usage), GFP_KERNEL);
	if (!ca->usage_base)
	ca->usage = alloc_percpu(struct bch_dev_usage);
	if (!ca->usage)
		return -BCH_ERR_ENOMEM_usage_init;

	for (unsigned i = 0; i < ARRAY_SIZE(ca->usage); i++) {
		ca->usage[i] = alloc_percpu(struct bch_dev_usage);
		if (!ca->usage[i])
			return -BCH_ERR_ENOMEM_usage_init;
	}

	return bch2_dev_buckets_resize(c, ca, ca->mi.nbuckets);
}
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ struct bucket_gens {
};

struct bch_dev_usage {
	struct {
	struct bch_dev_usage_type {
		u64		buckets;
		u64		sectors; /* _compressed_ sectors: */
		/*
+15 −0
Original line number Diff line number Diff line
@@ -400,6 +400,21 @@ int bch2_accounting_read(struct bch_fs *c)
		case BCH_DISK_ACCOUNTING_replicas:
			fs_usage_data_type_to_base(usage, k.replicas.data_type, v[0]);
			break;
		case BCH_DISK_ACCOUNTING_dev_data_type:
			rcu_read_lock();
			struct bch_dev *ca = bch2_dev_rcu(c, k.dev_data_type.dev);
			if (ca) {
				struct bch_dev_usage_type __percpu *d = &ca->usage->d[k.dev_data_type.data_type];
				percpu_u64_set(&d->buckets,	v[0]);
				percpu_u64_set(&d->sectors,	v[1]);
				percpu_u64_set(&d->fragmented,	v[2]);

				if (k.dev_data_type.data_type == BCH_DATA_sb ||
				    k.dev_data_type.data_type == BCH_DATA_journal)
					usage->hidden += v[0] * ca->mi.bucket_size;
			}
			rcu_read_unlock();
			break;
		}
	}
	preempt_enable();
Loading