Re: [PATCH 3/3] selftests/cachestat: add an overlayfs test case
Pavel Tikhomirov <[email protected]> Wed, 24 Jun 2026 14:22:08 +0200
| Newsgroups | org.kernel.vger.linux-unionfs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On 6/23/26 18:13, Nhat Pham wrote: > On Tue, Jun 23, 2026 at 4:15 AM Pavel Tikhomirov > <[email protected]> wrote: >> >> Mount an overlayfs, create and write a file in the merged directory, and >> run cachestat() on it, reusing the existing test_cachestat() helper. >> >> Also bump NR_TESTS to the actual number of tests run: it was 9 while >> ten tests were already executed, and this adds an eleventh. >> >> Signed-off-by: Pavel Tikhomirov <[email protected]> >> --- >> .../selftests/cachestat/test_cachestat.c | 75 ++++++++++++++++++- > > Hmm this looks strange...? That's just how git-format-patch formats it for long path and big change ("++...++") it hides part of the path. > >> 1 file changed, 74 insertions(+), 1 deletion(-) >> >> diff --git a/tools/testing/selftests/cachestat/test_cachestat.c b/tools/testing/selftests/cachestat/test_cachestat.c >> index 542cd09cb4434..1662d9817c50b 100644 >> --- a/tools/testing/selftests/cachestat/test_cachestat.c >> +++ b/tools/testing/selftests/cachestat/test_cachestat.c >> @@ -4,21 +4,25 @@ >> >> #include <stdio.h> >> #include <stdbool.h> >> +#include <stdlib.h> >> #include <linux/kernel.h> >> #include <linux/magic.h> >> #include <linux/mman.h> >> #include <sys/mman.h> >> +#include <sys/mount.h> >> #include <sys/shm.h> >> +#include <sys/stat.h> >> #include <sys/syscall.h> >> #include <sys/vfs.h> >> #include <unistd.h> >> #include <string.h> >> #include <fcntl.h> >> #include <errno.h> >> +#include <limits.h> >> >> #include "kselftest.h" >> >> -#define NR_TESTS 9 >> +#define NR_TESTS 11 >> >> static const char * const dev_files[] = { >> "/dev/zero", "/dev/null", "/dev/urandom", >> @@ -294,6 +298,62 @@ bool run_cachestat_test(enum file_type type) >> return ret; >> } >> >> +/* >> + * Set up an overlayfs mount and run cachestat on a freshly created file in the >> + * merged directory. Overlayfs forwards data I/O to the underlying (upper) >> + * inode, so the page cache lives there and not in the overlay inode's mapping. >> + * This is a regression test for cachestat returning all zeroes on overlayfs. >> + */ >> +static int run_cachestat_overlayfs_test(void) >> +{ >> + char tmpl[] = "/tmp/cachestat_ovl.XXXXXX"; >> + char lower[PATH_MAX], upper[PATH_MAX], work[PATH_MAX]; >> + char merged[PATH_MAX], opts[4 * PATH_MAX], file[PATH_MAX]; >> + char *base; >> + int ret; >> + >> + base = mkdtemp(tmpl); >> + if (!base) { >> + ksft_print_msg("Unable to create overlayfs base dir: %s\n", >> + strerror(errno)); >> + return KSFT_FAIL; >> + } >> + >> + snprintf(lower, sizeof(lower), "%s/lower", base); >> + snprintf(upper, sizeof(upper), "%s/upper", base); >> + snprintf(work, sizeof(work), "%s/work", base); >> + snprintf(merged, sizeof(merged), "%s/merged", base); >> + >> + if (mkdir(lower, 0755) || mkdir(upper, 0755) || >> + mkdir(work, 0755) || mkdir(merged, 0755)) { >> + ksft_print_msg("Unable to create overlayfs dirs: %s\n", >> + strerror(errno)); >> + ret = KSFT_FAIL; >> + goto cleanup; >> + } >> + >> + snprintf(opts, sizeof(opts), "lowerdir=%s,upperdir=%s,workdir=%s", >> + lower, upper, work); >> + >> + if (mount("overlay", merged, "overlay", 0, opts)) { >> + ksft_print_msg("Unable to mount overlayfs (need root?): %s\n", >> + strerror(errno)); >> + ret = KSFT_SKIP; >> + goto cleanup; >> + } >> + >> + snprintf(file, sizeof(file), "%s/merged/cachestat", base); >> + ret = test_cachestat(file, true, true, false, 4, O_CREAT | O_RDWR, 0600); >> + >> + umount(merged); >> +cleanup: >> + /* Best-effort recursive cleanup of the temporary tree. */ >> + snprintf(opts, sizeof(opts), "rm -rf %s", base); >> + if (system(opts)) >> + ksft_print_msg("Unable to clean up %s\n", base); > > nit: no helper for these? :) This is similar to e.g. ./tools/testing/selftests/bpf/prog_tests/test_local_storage.c's cleanup, I didn't find a common selftest helper for temporary directory removal. > >> + return ret; >> +} >> + >> int main(void) >> { >> int ret; >> @@ -361,5 +421,18 @@ int main(void) >> ksft_test_result_fail("cachestat fails with a mmap file\n"); >> ret = 1; >> } >> + >> + switch (run_cachestat_overlayfs_test()) { >> + case KSFT_FAIL: >> + ksft_test_result_fail("cachestat fails with an overlayfs file\n"); >> + ret = 1; >> + break; >> + case KSFT_PASS: >> + ksft_test_result_pass("cachestat works with an overlayfs file\n"); >> + break; >> + case KSFT_SKIP: >> + ksft_test_result_skip("overlayfs not available\n"); >> + break; >> + } >> return ret; >> } >> -- >> 2.54.0 >> -- Best regards, Pavel Tikhomirov Senior Software Developer, Virtuozzo.