From: Matteo Croce <teknora...@meta.com> Under Linux, add a --memory flag which allows to show cache memory usage of files:
$ truncate -s100M file $ du file 0 file $ dd status=none bs=1M count=5 if=file of=/dev/null $ du --memory --human file 10M file $ dd status=none bs=1M skip=30 count=5 if=file of=/dev/null $ du --memory --human file 21M file $ cat file >/dev/null $ du --memory --human file 100M file --- src/du.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/du.c b/src/du.c index 0e5d860a9..de8dfde1e 100644 --- a/src/du.c +++ b/src/du.c @@ -43,6 +43,26 @@ #include "xstrtol.h" #include "xstrtol-error.h" +#ifdef __linux__ + +#include <sys/syscall.h> + +#ifdef __NR_cachestat + +#include <linux/mman.h> + +static long page_size; + +static int +cachestat(int fd, struct cachestat_range *cstat_range, + struct cachestat *cstat, unsigned int flags) +{ + return syscall(__NR_cachestat, fd, cstat_range, cstat, flags); +} + +#endif +#endif + extern bool fts_debug; /* The official name of this program (e.g., no 'g' prefix). */ @@ -165,6 +185,9 @@ static bool opt_inodes = false; /* If true, print most recently modified date, using the specified format. */ static bool opt_time = false; +/* If true, print memory usage. */ +static bool opt_memory = false; + /* Type of time to display. controlled by --time. */ enum time_type @@ -229,6 +252,9 @@ static struct option const long_options[] = {"inodes", no_argument, nullptr, INODES_OPTION}, {"si", no_argument, nullptr, HUMAN_SI_OPTION}, {"max-depth", required_argument, nullptr, 'd'}, +#ifdef __NR_cachestat + {"memory", no_argument, nullptr, 'M'}, +#endif {"null", no_argument, nullptr, '0'}, {"no-dereference", no_argument, nullptr, 'P'}, {"one-file-system", no_argument, nullptr, 'x'}, @@ -321,6 +347,13 @@ Summarize device usage of the set of FILEs, recursively for directories.\n\ \n\ --inodes list inode usage information instead of block usage\n\ "), stdout); + +#ifdef __NR_cachestat + fputs (_("\ + -M, --memory print cache usage instead of block usage\n\ +"), stdout); +#endif + fputs (_("\ -k like --block-size=1K\n\ -L, --dereference dereference all symbolic links\n\ @@ -465,6 +498,35 @@ mount_point_in_fts_cycle (FTSENT const *ent) return false; } +static long get_cacheinfo (MAYBE_UNUSED const char *file) +{ +#ifdef __NR_cachestat + struct cachestat_range cstat_range = { 0 }; + struct cachestat cstat; + int fd = open (file, O_RDONLY | O_CLOEXEC); + int ret; + + if (fd == -1) + { + error (0, errno, _("cannot open %s"), quoteaf (file)); + return 0; + } + + ret = cachestat(fd, &cstat_range, &cstat, 0); + close (fd); + + if (ret == -1) + { + error (0, errno, _("cannot get memory usage")); + return 0; + } + + return cstat.nr_cache * page_size; +#else + return 0; +#endif +} + /* This function is called once for every file system object that fts encounters. fts does a depth-first traversal. This function knows that and accumulates per-directory totals based on changes in @@ -571,6 +633,7 @@ process_file (FTS *fts, FTSENT *ent) } duinfo_set (&dui, + opt_memory ? get_cacheinfo (file) : (apparent_size ? (usable_st_size (sb) ? MAX (0, sb->st_size) : 0) : (uintmax_t) STP_NBLOCKS (sb) * ST_NBLOCKSIZE), @@ -738,7 +801,11 @@ main (int argc, char **argv) while (true) { int oi = -1; - int c = getopt_long (argc, argv, "0abd:chHklmst:xB:DLPSX:", + int c = getopt_long (argc, argv, "0abd:chHklmst:xB:DLPSX:" +#ifdef __NR_cachestat + "M" +#endif + , long_options, &oi); if (c == -1) break; @@ -856,6 +923,13 @@ main (int argc, char **argv) symlink_deref_bits = FTS_LOGICAL; break; +#ifdef __NR_cachestat + case 'M': + opt_memory = true; + page_size = sysconf(_SC_PAGE_SIZE); + break; +#endif + case 'P': /* --no-dereference */ symlink_deref_bits = FTS_PHYSICAL; break; -- 2.49.0