Commit d6a511de authored by Suresh K C's avatar Suresh K C Committed by Andrew Morton
Browse files

selftests: cachestat: add tests for mmap, refactor and enhance mmap test for cachestat validation

Add a cohesive test case that verifies cachestat behavior with
memory-mapped files using mmap().  Also refactor the test logic to reduce
redundancy, improve error reporting, and clarify failure messages for both
shmem and mmap file types.

[akpm@linux-foundation.org: coding-style cleanups]
Link: https://lkml.kernel.org/r/20250709174657.6916-1-suresh.k.chandrappa@gmail.com


Signed-off-by: default avatarSuresh K C <suresh.k.chandrappa@gmail.com>
Reviewed-by: default avatarJoshua Hahn <joshua.hahnjy@gmail.com>
Tested-by: default avatarNhat Pham <nphamcs@gmail.com>
Acked-by: default avatarNhat Pham <nphamcs@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 881388f3
Loading
Loading
Loading
Loading
+54 −8
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@ void print_cachestat(struct cachestat *cs)
	cs->nr_evicted, cs->nr_recently_evicted);
}

enum file_type {
	FILE_MMAP,
	FILE_SHMEM
};

bool write_exactly(int fd, size_t filesize)
{
	int random_fd = open("/dev/urandom", O_RDONLY);
@@ -201,8 +206,20 @@ static int test_cachestat(const char *filename, bool write_random, bool create,
out:
	return ret;
}
const char *file_type_str(enum file_type type)
{
	switch (type) {
	case FILE_SHMEM:
		return "shmem";
	case FILE_MMAP:
		return "mmap";
	default:
		return "unknown";
	}
}

bool test_cachestat_shmem(void)

bool run_cachestat_test(enum file_type type)
{
	size_t PS = sysconf(_SC_PAGESIZE);
	size_t filesize = PS * 512 * 2; /* 2 2MB huge pages */
@@ -212,27 +229,50 @@ bool test_cachestat_shmem(void)
	char *filename = "tmpshmcstat";
	struct cachestat cs;
	bool ret = true;
	int fd;
	unsigned long num_pages = compute_len / PS;
	int fd = shm_open(filename, O_CREAT | O_RDWR, 0600);
	if (type == FILE_SHMEM)
		fd = shm_open(filename, O_CREAT | O_RDWR, 0600);
	else
		fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);

	if (fd < 0) {
		ksft_print_msg("Unable to create shmem file.\n");
		ksft_print_msg("Unable to create %s file.\n",
				file_type_str(type));
		ret = false;
		goto out;
	}

	if (ftruncate(fd, filesize)) {
		ksft_print_msg("Unable to truncate shmem file.\n");
		ksft_print_msg("Unable to truncate %s file.\n",file_type_str(type));
		ret = false;
		goto close_fd;
	}

	switch (type) {
	case FILE_SHMEM:
		if (!write_exactly(fd, filesize)) {
		ksft_print_msg("Unable to write to shmem file.\n");
			ksft_print_msg("Unable to write to file.\n");
			ret = false;
			goto close_fd;
		}
		break;
	case FILE_MMAP:
		char *map = mmap(NULL, filesize, PROT_READ | PROT_WRITE,
				 MAP_SHARED, fd, 0);

		if (map == MAP_FAILED) {
			ksft_print_msg("mmap failed.\n");
			ret = false;
			goto close_fd;
		}
		for (int i = 0; i < filesize; i++)
			map[i] = 'A';
		break;
	default:
		ksft_print_msg("Unsupported file type.\n");
		ret = false;
		goto close_fd;
	}
	syscall_ret = syscall(__NR_cachestat, fd, &cs_range, &cs, 0);

	if (syscall_ret) {
@@ -308,12 +348,18 @@ int main(void)
		break;
	}

	if (test_cachestat_shmem())
	if (run_cachestat_test(FILE_SHMEM))
		ksft_test_result_pass("cachestat works with a shmem file\n");
	else {
		ksft_test_result_fail("cachestat fails with a shmem file\n");
		ret = 1;
	}

	if (run_cachestat_test(FILE_MMAP))
		ksft_test_result_pass("cachestat works with a mmap file\n");
	else {
		ksft_test_result_fail("cachestat fails with a mmap file\n");
		ret = 1;
	}
	return ret;
}