(root)/
strace-6.5/
tests/
cachestat.c
       1  /*
       2   * Check decoding of cachestat syscall.
       3   *
       4   * Copyright (c) 2023 Dmitry V. Levin <ldv@strace.io>
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include "scno.h"
      12  #include "cachestat.h"
      13  
      14  #include <stdio.h>
      15  #include <unistd.h>
      16  
      17  #ifndef SKIP_IF_PROC_IS_UNAVAILABLE
      18  # define SKIP_IF_PROC_IS_UNAVAILABLE skip_if_unavailable("/proc/self/fd/")
      19  #endif
      20  
      21  #ifndef FD9_PATH
      22  # define FD9_PATH "</dev/full>"
      23  #endif
      24  
      25  #ifdef RETVAL_INJECTED
      26  # define INJ_STR " (INJECTED)\n"
      27  #else
      28  # define INJ_STR "\n"
      29  #endif
      30  
      31  #ifndef TRACE_FDS
      32  # define TRACE_FDS 0
      33  #endif
      34  #ifndef TRACE_PATH
      35  # define TRACE_PATH 0
      36  #endif
      37  #define TRACE_FILTERED (TRACE_FDS || TRACE_PATH)
      38  
      39  static const char *errstr;
      40  
      41  static long
      42  k_cachestat(const unsigned int fd, const void *crange,
      43  	      const void *cstat, const unsigned int flags)
      44  {
      45  	const kernel_ulong_t fill = (kernel_ulong_t) 0xbadc0ded00000000ULL;
      46  	const kernel_ulong_t arg1 = fill | fd;
      47  	const kernel_ulong_t arg2 = (uintptr_t) crange;
      48  	const kernel_ulong_t arg3 = (uintptr_t) cstat;
      49  	const kernel_ulong_t arg4 = fill | flags;
      50  	const kernel_ulong_t arg5 = fill | 0xdecaffed;
      51  	const kernel_ulong_t arg6 = fill | 0xdeefaced;
      52  	const long rc = syscall(__NR_cachestat,
      53  				arg1, arg2, arg3, arg4, arg5, arg6);
      54  	errstr = sprintrc(rc);
      55  	return rc;
      56  }
      57  
      58  int
      59  main(void)
      60  {
      61  	SKIP_IF_PROC_IS_UNAVAILABLE;
      62  
      63  	k_cachestat(-1, 0, 0, 0);
      64  #if !TRACE_FILTERED
      65  	printf("cachestat(-1, NULL, NULL, 0) = %s" INJ_STR, errstr);
      66  #endif
      67  
      68  	k_cachestat(9, 0, 0, -1U);
      69  	printf("cachestat(9%s, NULL, NULL, %#x) = %s" INJ_STR,
      70  	       FD9_PATH, -1U, errstr);
      71  
      72  	TAIL_ALLOC_OBJECT_CONST_PTR(struct cachestat_range, crange);
      73  	fill_memory(crange, sizeof(*crange));
      74  	const void *const bad_crange = (void *) crange + 1;
      75  
      76  	k_cachestat(9, bad_crange, 0, 0);
      77  	printf("cachestat(9%s, %p, NULL, 0) = %s" INJ_STR,
      78  	       FD9_PATH, bad_crange, errstr);
      79  
      80  	TAIL_ALLOC_OBJECT_CONST_PTR(struct cachestat, cstat);
      81  	fill_memory(cstat, sizeof(*cstat));
      82  	const void *const bad_cstat = (void *) cstat + 1;
      83  
      84  	k_cachestat(9, crange, bad_cstat, 0);
      85  	printf("cachestat(9%s, {off=%#llx, len=%llu}, %p, 0) = %s"
      86  	       INJ_STR, FD9_PATH,
      87  	       (unsigned long long) crange->off,
      88  	       (unsigned long long) crange->len,
      89  	       bad_cstat, errstr);
      90  
      91  	if (k_cachestat(9, 0, cstat, 0) < 0) {
      92  		printf("cachestat(9%s, NULL, %p, 0) = %s" INJ_STR,
      93  		       FD9_PATH, cstat, errstr);
      94  	} else {
      95  		printf("cachestat(9%s, NULL, {nr_cache=%llu"
      96  		       ", nr_dirty=%llu, nr_writeback=%llu, nr_evicted=%llu"
      97  		       ", nr_recently_evicted=%llu}, 0) = %s" INJ_STR, FD9_PATH,
      98  		       (unsigned long long) cstat->nr_cache,
      99  		       (unsigned long long) cstat->nr_dirty,
     100  		       (unsigned long long) cstat->nr_writeback,
     101  		       (unsigned long long) cstat->nr_evicted,
     102  		       (unsigned long long) cstat->nr_recently_evicted,
     103  		       errstr);
     104  	}
     105  
     106  	puts("+++ exited with 0 +++");
     107  	return 0;
     108  }