On 2025-03-17 00:15:29, Ritesh Harjani (IBM) wrote: > This adds -c "cachestat off len" command which uses cachestat() syscall > [1]. This can provide following pagecache detail for a file. > > - no. of cached pages, > - no. of dirty pages, > - no. of pages marked for writeback, > - no. of evicted pages, > - no. of recently evicted pages > > [1]: https://lore.kernel.org/all/20230503013608.2431726-3-nphamcs@xxxxxxxxx/T/#u > > Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx> > --- > configure.ac | 1 + > include/builddefs.in | 1 + > io/Makefile | 5 +++ > io/cachestat.c | 77 +++++++++++++++++++++++++++++++++++++++++++ > io/init.c | 1 + > io/io.h | 6 ++++ > m4/package_libcdev.m4 | 19 +++++++++++ > 7 files changed, 110 insertions(+) > create mode 100644 io/cachestat.c > > diff --git a/configure.ac b/configure.ac > index 8c76f398..f039bc91 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -154,6 +154,7 @@ AC_PACKAGE_NEED_RCU_INIT > > AC_HAVE_PWRITEV2 > AC_HAVE_COPY_FILE_RANGE > +AC_HAVE_CACHESTAT > AC_NEED_INTERNAL_FSXATTR > AC_NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG > AC_NEED_INTERNAL_FSCRYPT_POLICY_V2 > diff --git a/include/builddefs.in b/include/builddefs.in > index 82840ec7..fe2a7824 100644 > --- a/include/builddefs.in > +++ b/include/builddefs.in > @@ -95,6 +95,7 @@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@ > > HAVE_PWRITEV2 = @have_pwritev2@ > HAVE_COPY_FILE_RANGE = @have_copy_file_range@ > +HAVE_CACHESTAT = @have_cachestat@ > NEED_INTERNAL_FSXATTR = @need_internal_fsxattr@ > NEED_INTERNAL_FSCRYPT_ADD_KEY_ARG = @need_internal_fscrypt_add_key_arg@ > NEED_INTERNAL_FSCRYPT_POLICY_V2 = @need_internal_fscrypt_policy_v2@ > diff --git a/io/Makefile b/io/Makefile > index 14a3fe20..444e2d6a 100644 > --- a/io/Makefile > +++ b/io/Makefile > @@ -61,6 +61,11 @@ CFILES += copy_file_range.c > LCFLAGS += -DHAVE_COPY_FILE_RANGE > endif > > +ifeq ($(HAVE_CACHESTAT),yes) > +CFILES += cachestat.c > +LCFLAGS += -DHAVE_CACHESTAT > +endif > + > ifeq ($(ENABLE_EDITLINE),yes) > LLDLIBS += $(LIBEDITLINE) $(LIBTERMCAP) > endif > diff --git a/io/cachestat.c b/io/cachestat.c > new file mode 100644 > index 00000000..9edf3f9a > --- /dev/null > +++ b/io/cachestat.c > @@ -0,0 +1,77 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include "command.h" > +#include "input.h" > +#include "init.h" > +#include "io.h" > +#include <unistd.h> > +#include <linux/mman.h> > +#include <asm/unistd.h> > + > +static cmdinfo_t cachestat_cmd; > + > +static void print_cachestat(struct cachestat *cs) > +{ > + printf(_("Cached: %llu, Dirty: %llu, Writeback: %llu, Evicted: %llu, Recently Evicted: %llu\n"), > + cs->nr_cache, cs->nr_dirty, cs->nr_writeback, > + cs->nr_evicted, cs->nr_recently_evicted); > +} > + > +static int > +cachestat_f(int argc, char **argv) > +{ > + off_t offset = 0, length = 0; > + size_t blocksize, sectsize; > + struct cachestat_range cs_range; > + struct cachestat cs; > + > + if (argc != 3) { > + exitcode = 1; > + return command_usage(&cachestat_cmd); > + } > + > + init_cvtnum(&blocksize, §size); > + offset = cvtnum(blocksize, sectsize, argv[1]); > + if (offset < 0) { > + printf(_("invalid offset argument -- %s\n"), argv[1]); > + exitcode = 1; > + return 0; > + } > + > + length = cvtnum(blocksize, sectsize, argv[2]); > + if (length < 0) { > + printf(_("invalid length argument -- %s\n"), argv[2]); > + exitcode = 1; > + return 0; > + } > + > + cs_range.off = offset; > + cs_range.len = length; > + > + if (syscall(__NR_cachestat, file->fd, &cs_range, &cs, 0)) { > + perror("cachestat"); > + exitcode = 1; > + return 0; > + } > + > + print_cachestat(&cs); > + > + return 0; > +} > + > +static cmdinfo_t cachestat_cmd = { > + .name = "cachestat", > + .altname = "cs", > + .cfunc = cachestat_f, > + .argmin = 2, > + .argmax = 2, > + .flags = CMD_NOMAP_OK | CMD_FOREIGN_OK, > + .args = "[off len]", I suppose [] aren't needed, as those arguments are mandatory. I can fix while pulling if no v2 > + .oneline = "find page cache pages for a given file", > +}; Otherwise, looks good to me Reviewed-by: Andrey Albershteyn <aalbersh@xxxxxxxxxx> -- - Andrey