Commit b8ee5575 authored by SeongJae Park's avatar SeongJae Park Committed by Andrew Morton
Browse files

mm/damon/sysfs-test: add a unit test for damon_sysfs_set_targets()

damon_sysfs_set_targets() had a bug that can result in unexpected memory
usage and monitoring overhead increase.  The bug has fixed by a previous
commit.  Add a unit test for avoiding a similar bug of future.

Link: https://lkml.kernel.org/r/20231022210735.46409-3-sj@kernel.org


Signed-off-by: default avatarSeongJae Park <sj@kernel.org>
Cc: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 62f76a7b
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -59,6 +59,18 @@ config DAMON_SYSFS
	  This builds the sysfs interface for DAMON.  The user space can use
	  the interface for arbitrary data access monitoring.

config DAMON_SYSFS_KUNIT_TEST
	bool "Test for damon debugfs interface" if !KUNIT_ALL_TESTS
	depends on DAMON_SYSFS && KUNIT=y
	default KUNIT_ALL_TESTS
	help
	  This builds the DAMON sysfs interface Kunit test suite.

	  For more information on KUnit and unit tests in general, please refer
	  to the KUnit documentation.

	  If unsure, say N.

config DAMON_DBGFS
	bool "DAMON debugfs interface (DEPRECATED!)"
	depends on DAMON_VADDR && DAMON_PADDR && DEBUG_FS

mm/damon/sysfs-test.h

0 → 100644
+86 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Data Access Monitor Unit Tests
 *
 * Author: SeongJae Park <sj@kernel.org>
 */

#ifdef CONFIG_DAMON_SYSFS_KUNIT_TEST

#ifndef _DAMON_SYSFS_TEST_H
#define _DAMON_SYSFS_TEST_H

#include <kunit/test.h>

static unsigned int nr_damon_targets(struct damon_ctx *ctx)
{
	struct damon_target *t;
	unsigned int nr_targets = 0;

	damon_for_each_target(t, ctx)
		nr_targets++;

	return nr_targets;
}

static int __damon_sysfs_test_get_any_pid(int min, int max)
{
	struct pid *pid;
	int i;

	for (i = min; i <= max; i++) {
		pid = find_get_pid(i);
		if (pid) {
			put_pid(pid);
			return i;
		}
	}
	return -1;
}

static void damon_sysfs_test_set_targets(struct kunit *test)
{
	struct damon_sysfs_targets *sysfs_targets;
	struct damon_sysfs_target *sysfs_target;
	struct damon_ctx *ctx;

	sysfs_targets = damon_sysfs_targets_alloc();
	sysfs_targets->nr = 1;
	sysfs_targets->targets_arr = kmalloc_array(1,
			sizeof(*sysfs_targets->targets_arr), GFP_KERNEL);

	sysfs_target = damon_sysfs_target_alloc();
	sysfs_target->pid = __damon_sysfs_test_get_any_pid(12, 100);
	sysfs_target->regions = damon_sysfs_regions_alloc();
	sysfs_targets->targets_arr[0] = sysfs_target;

	ctx = damon_new_ctx();

	damon_sysfs_set_targets(ctx, sysfs_targets);
	KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(ctx));

	sysfs_target->pid = __damon_sysfs_test_get_any_pid(
			sysfs_target->pid + 1, 200);
	damon_sysfs_set_targets(ctx, sysfs_targets);
	KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(ctx));

	damon_destroy_ctx(ctx);
	kfree(sysfs_targets->targets_arr);
	kfree(sysfs_targets);
	kfree(sysfs_target);
}

static struct kunit_case damon_sysfs_test_cases[] = {
	KUNIT_CASE(damon_sysfs_test_set_targets),
	{},
};

static struct kunit_suite damon_sysfs_test_suite = {
	.name = "damon-sysfs",
	.test_cases = damon_sysfs_test_cases,
};
kunit_test_suite(damon_sysfs_test_suite);

#endif /* _DAMON_SYSFS_TEST_H */

#endif /* CONFIG_DAMON_SYSFS_KUNIT_TEST */
+2 −0
Original line number Diff line number Diff line
@@ -1836,3 +1836,5 @@ static int __init damon_sysfs_init(void)
	return err;
}
subsys_initcall(damon_sysfs_init);

#include "sysfs-test.h"