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...?
> 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? :)
> + 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
>