tools/testing/selftests/mm/ksm_functional_tests.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/ksm_functional_tests.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/ksm_functional_tests.c
Extension
.c
Size
18403 bytes
Lines
763
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ret < 0 && errno == EINVAL) {
			ksft_print_msg("PR_SET_MEMORY_MERGE not supported\n");
			err_map = MAP_MERGE_SKIP;
			goto unmap;
		} else if (ret) {
			ksft_print_msg("PR_SET_MEMORY_MERGE=1 failed\n");
			goto unmap;
		}
		break;
	case KSM_MERGE_MADVISE:
		if (madvise(map, size, MADV_MERGEABLE)) {
			ksft_print_msg("MADV_MERGEABLE failed\n");
			goto unmap;
		}
		break;
	case KSM_MERGE_NONE:
		break;
	}

	/* Run KSM to trigger merging and wait. */
	if (ksm_start() < 0) {
		ksft_print_msg("Running KSM failed\n");
		goto unmap;
	}

	/*
	 * Check if anything was merged at all. Ignore the zero page that is
	 * accounted differently (depending on kernel support).
	 */
	if (val && !ksm_get_self_merging_pages()) {
		ksft_print_msg("No pages got merged\n");
		goto unmap;
	}

	return map;
unmap:
	munmap(map, size);
	return err_map;
}

static char *mmap_and_merge_range(char val, unsigned long size, int prot,
				  enum ksm_merge_mode mode)
{
	char *map;
	char *ret = MAP_FAILED;

	map = __mmap_and_merge_range(val, size, prot, mode);
	if (map == MAP_MERGE_FAIL)
		ksft_test_result_fail("Merging memory failed");
	else if (map == MAP_MERGE_SKIP)
		ksft_test_result_skip("Merging memory skipped");
	else
		ret = map;

	return ret;
}

static void test_unmerge(void)
{
	const unsigned int size = 2 * MiB;
	char *map;

	ksft_print_msg("[RUN] %s\n", __func__);

	map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE);
	if (map == MAP_FAILED)
		return;

	if (madvise(map, size, MADV_UNMERGEABLE)) {
		ksft_test_result_fail("MADV_UNMERGEABLE failed\n");
		goto unmap;
	}

	ksft_test_result(!range_maps_duplicates(map, size),
			 "Pages were unmerged\n");
unmap:
	ksm_stop();
	munmap(map, size);
}

static void test_unmerge_zero_pages(void)
{
	const unsigned int size = 2 * MiB;
	char *map;
	unsigned int offs;
	unsigned long pages_expected;

	ksft_print_msg("[RUN] %s\n", __func__);

	if (ksm_get_self_zero_pages() < 0) {

Annotation

Implementation Notes