diff options
author | Lukas Rusak <lorusak@gmail.com> | 2019-06-25 18:52:33 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-25 18:53:10 +0200 |
commit | 9663bbd17ba3ab9f7921d7c46f07d177cb4a1435 (patch) | |
tree | 626bf54db7e2a973eacf064c3e0d0f355f0eeb34 | |
parent | 25a871fb402012325654ed82e568c337bc426848 (diff) | |
download | busybox-w32-9663bbd17ba3ab9f7921d7c46f07d177cb4a1435.tar.gz busybox-w32-9663bbd17ba3ab9f7921d7c46f07d177cb4a1435.tar.bz2 busybox-w32-9663bbd17ba3ab9f7921d7c46f07d177cb4a1435.zip |
free: include SReclaimable in cached value
I noticed that the 'used' values from busybox free and
procps-ng free differed so I looked into why. It turns
out that procps-ng uses the "SReclaimable" value as
part of the cached value.
This was changed in
procps-ng commit 05d751c4f076a2f0118b914c5e51cfbb4762ad8e
function old new delta
free_main 633 653 +20
Signed-off-by: Lukas Rusak <lorusak@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | procps/free.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/procps/free.c b/procps/free.c index 3acfc4072..1e5d36742 100644 --- a/procps/free.c +++ b/procps/free.c | |||
@@ -44,6 +44,7 @@ struct globals { | |||
44 | #else | 44 | #else |
45 | # define G_unit_steps 10 | 45 | # define G_unit_steps 10 |
46 | #endif | 46 | #endif |
47 | unsigned long cached_kb, available_kb, reclaimable_kb; | ||
47 | }; | 48 | }; |
48 | /* Because of NOFORK, "globals" are not in global data */ | 49 | /* Because of NOFORK, "globals" are not in global data */ |
49 | 50 | ||
@@ -53,27 +54,30 @@ static unsigned long long scale(struct globals *g, unsigned long d) | |||
53 | } | 54 | } |
54 | 55 | ||
55 | /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ | 56 | /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ |
56 | static NOINLINE unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long *available_kb) | 57 | static NOINLINE unsigned int parse_meminfo(struct globals *g) |
57 | { | 58 | { |
58 | char buf[60]; /* actual lines we expect are ~30 chars or less */ | 59 | char buf[60]; /* actual lines we expect are ~30 chars or less */ |
59 | FILE *fp; | 60 | FILE *fp; |
60 | int seen_cached_and_available; | 61 | int seen_cached_and_available_and_reclaimable; |
61 | 62 | ||
62 | fp = xfopen_for_read("/proc/meminfo"); | 63 | fp = xfopen_for_read("/proc/meminfo"); |
63 | *cached_kb = *available_kb = 0; | 64 | g->cached_kb = g->available_kb = g->reclaimable_kb = 0; |
64 | seen_cached_and_available = 2; | 65 | seen_cached_and_available_and_reclaimable = 3; |
65 | while (fgets(buf, sizeof(buf), fp)) { | 66 | while (fgets(buf, sizeof(buf), fp)) { |
66 | if (sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1) | 67 | if (sscanf(buf, "Cached: %lu %*s\n", &g->cached_kb) == 1) |
67 | if (--seen_cached_and_available == 0) | 68 | if (--seen_cached_and_available_and_reclaimable == 0) |
68 | break; | 69 | break; |
69 | if (sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1) | 70 | if (sscanf(buf, "MemAvailable: %lu %*s\n", &g->available_kb) == 1) |
70 | if (--seen_cached_and_available == 0) | 71 | if (--seen_cached_and_available_and_reclaimable == 0) |
72 | break; | ||
73 | if (sscanf(buf, "SReclaimable: %lu %*s\n", &g->reclaimable_kb) == 1) | ||
74 | if (--seen_cached_and_available_and_reclaimable == 0) | ||
71 | break; | 75 | break; |
72 | } | 76 | } |
73 | /* Have to close because of NOFORK */ | 77 | /* Have to close because of NOFORK */ |
74 | fclose(fp); | 78 | fclose(fp); |
75 | 79 | ||
76 | return seen_cached_and_available == 0; | 80 | return seen_cached_and_available_and_reclaimable == 0; |
77 | } | 81 | } |
78 | 82 | ||
79 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 83 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -82,7 +86,6 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
82 | struct globals G; | 86 | struct globals G; |
83 | struct sysinfo info; | 87 | struct sysinfo info; |
84 | unsigned long long cached, cached_plus_free, available; | 88 | unsigned long long cached, cached_plus_free, available; |
85 | unsigned long cached_kb, available_kb; | ||
86 | int seen_available; | 89 | int seen_available; |
87 | 90 | ||
88 | #if ENABLE_DESKTOP | 91 | #if ENABLE_DESKTOP |
@@ -118,10 +121,11 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
118 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ | 121 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ |
119 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); | 122 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); |
120 | /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ | 123 | /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ |
121 | seen_available = parse_meminfo(&cached_kb, &available_kb); | 124 | seen_available = parse_meminfo(&G); |
122 | available = ((unsigned long long) available_kb * 1024) / G.mem_unit; | 125 | available = ((unsigned long long) G.available_kb * 1024) / G.mem_unit; |
123 | cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit; | 126 | cached = ((unsigned long long) G.cached_kb * 1024) / G.mem_unit; |
124 | cached += info.bufferram; | 127 | cached += info.bufferram; |
128 | cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit; | ||
125 | cached_plus_free = cached + info.freeram; | 129 | cached_plus_free = cached + info.freeram; |
126 | 130 | ||
127 | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" | 131 | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" |