Commit 6548d364 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'cgroup-for-6.18-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup fixes from Tejun Heo:

 - Fix seqcount lockdep assertion failure in cgroup freezer on
   PREEMPT_RT.

   Plain seqcount_t expects preemption disabled, but PREEMPT_RT
   spinlocks don't disable preemption. Switch to seqcount_spinlock_t to
   properly associate css_set_lock with the freeze timing seqcount.

 - Misc changes including kernel-doc warning fix for misc_res_type enum
   and improved selftest diagnostics.

* tag 'cgroup-for-6.18-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  cgroup/misc: fix misc_res_type kernel-doc warning
  selftests: cgroup: Use values_close_report in test_cpu
  selftests: cgroup: add values_close_report helper
  cgroup: Fix seqcount lockdep assertion in cgroup freezer
parents 380cb5d3 0fbbcab7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -452,7 +452,7 @@ struct cgroup_freezer_state {
	int nr_frozen_tasks;

	/* Freeze time data consistency protection */
	seqcount_t freeze_seq;
	seqcount_spinlock_t freeze_seq;

	/*
	 * Most recent time the cgroup was requested to freeze.
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ enum misc_res_type {
	MISC_CG_RES_SEV_ES,
#endif
#ifdef CONFIG_INTEL_TDX_HOST
	/* Intel TDX HKIDs resource */
	/** @MISC_CG_RES_TDX: Intel TDX HKIDs resource */
	MISC_CG_RES_TDX,
#endif
	/** @MISC_CG_RES_TYPES: count of enum misc_res_type constants */
+1 −1
Original line number Diff line number Diff line
@@ -5892,7 +5892,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
	 * if the parent has to be frozen, the child has too.
	 */
	cgrp->freezer.e_freeze = parent->freezer.e_freeze;
	seqcount_init(&cgrp->freezer.freeze_seq);
	seqcount_spinlock_init(&cgrp->freezer.freeze_seq, &css_set_lock);
	if (cgrp->freezer.e_freeze) {
		/*
		 * Set the CGRP_FREEZE flag, so when a process will be
+20 −0
Original line number Diff line number Diff line
@@ -25,6 +25,26 @@ static inline int values_close(long a, long b, int err)
	return labs(a - b) <= (a + b) / 100 * err;
}

/*
 * Checks if two given values differ by less than err% of their sum and assert
 * with detailed debug info if not.
 */
static inline int values_close_report(long a, long b, int err)
{
	long diff  = labs(a - b);
	long limit = (a + b) / 100 * err;
	double actual_err = (a + b) ? (100.0 * diff / (a + b)) : 0.0;
	int close = diff <= limit;

	if (!close)
		fprintf(stderr,
			"[FAIL] actual=%ld expected=%ld | diff=%ld | limit=%ld | "
			"tolerance=%d%% | actual_error=%.2f%%\n",
			a, b, diff, limit, err, actual_err);

	return close;
}

extern ssize_t read_text(const char *path, char *buf, size_t max_len);
extern ssize_t write_text(const char *path, char *buf, ssize_t len);

+9 −9
Original line number Diff line number Diff line
@@ -219,7 +219,7 @@ static int test_cpucg_stats(const char *root)
	if (user_usec <= 0)
		goto cleanup;

	if (!values_close(usage_usec, expected_usage_usec, 1))
	if (!values_close_report(usage_usec, expected_usage_usec, 1))
		goto cleanup;

	ret = KSFT_PASS;
@@ -291,7 +291,7 @@ static int test_cpucg_nice(const char *root)

		user_usec = cg_read_key_long(cpucg, "cpu.stat", "user_usec");
		nice_usec = cg_read_key_long(cpucg, "cpu.stat", "nice_usec");
		if (!values_close(nice_usec, expected_nice_usec, 1))
		if (!values_close_report(nice_usec, expected_nice_usec, 1))
			goto cleanup;

		ret = KSFT_PASS;
@@ -404,7 +404,7 @@ overprovision_validate(const struct cpu_hogger *children, int num_children)
			goto cleanup;

		delta = children[i + 1].usage - children[i].usage;
		if (!values_close(delta, children[0].usage, 35))
		if (!values_close_report(delta, children[0].usage, 35))
			goto cleanup;
	}

@@ -444,7 +444,7 @@ underprovision_validate(const struct cpu_hogger *children, int num_children)
	int ret = KSFT_FAIL, i;

	for (i = 0; i < num_children - 1; i++) {
		if (!values_close(children[i + 1].usage, children[0].usage, 15))
		if (!values_close_report(children[i + 1].usage, children[0].usage, 15))
			goto cleanup;
	}

@@ -573,16 +573,16 @@ run_cpucg_nested_weight_test(const char *root, bool overprovisioned)

	nested_leaf_usage = leaf[1].usage + leaf[2].usage;
	if (overprovisioned) {
		if (!values_close(leaf[0].usage, nested_leaf_usage, 15))
		if (!values_close_report(leaf[0].usage, nested_leaf_usage, 15))
			goto cleanup;
	} else if (!values_close(leaf[0].usage * 2, nested_leaf_usage, 15))
	} else if (!values_close_report(leaf[0].usage * 2, nested_leaf_usage, 15))
		goto cleanup;


	child_usage = cg_read_key_long(child, "cpu.stat", "usage_usec");
	if (child_usage <= 0)
		goto cleanup;
	if (!values_close(child_usage, nested_leaf_usage, 1))
	if (!values_close_report(child_usage, nested_leaf_usage, 1))
		goto cleanup;

	ret = KSFT_PASS;
@@ -691,7 +691,7 @@ static int test_cpucg_max(const char *root)
	expected_usage_usec
		= n_periods * quota_usec + MIN(remainder_usec, quota_usec);

	if (!values_close(usage_usec, expected_usage_usec, 10))
	if (!values_close_report(usage_usec, expected_usage_usec, 10))
		goto cleanup;

	ret = KSFT_PASS;
@@ -762,7 +762,7 @@ static int test_cpucg_max_nested(const char *root)
	expected_usage_usec
		= n_periods * quota_usec + MIN(remainder_usec, quota_usec);

	if (!values_close(usage_usec, expected_usage_usec, 10))
	if (!values_close_report(usage_usec, expected_usage_usec, 10))
		goto cleanup;

	ret = KSFT_PASS;