From 62c02b4169d24678ab32f1fe6203afc32b9c9365 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Mon, 28 Jul 2014 12:43:54 +0000 Subject: main/busybox: fix top fixes #3234 --- ...-fix-and-merge-code-to-parse-proc-meminfo.patch | 288 +++++++++++++++++++++ main/busybox/APKBUILD | 10 +- main/busybox/fix-top.patch | 14 + 3 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 main/busybox/0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch create mode 100644 main/busybox/fix-top.patch diff --git a/main/busybox/0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch b/main/busybox/0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch new file mode 100644 index 0000000000..86fa9707aa --- /dev/null +++ b/main/busybox/0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch @@ -0,0 +1,288 @@ +From 7df1f1dda1f997c44800d16a9a12cf6cae2ed7e7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= +Date: Mon, 21 Jul 2014 14:14:24 +0300 +Subject: [PATCH] top: fix and merge code to parse /proc/meminfo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +display_header() code to parse meminfo as is was buggy: +- uninitialized variables were used if meminfo was not as expected +- meminfo parsing failed on new kernels (3.14+) as new field 'MemAvailable' + was introduced between MemFree and Buffers +- shared memory was handled only for ancient kernels (2.4.x and earlier) + +as result Buffers and shared memory fields were shown with bogus values +on current kernels. + +The new code does not try to parse the old style summary header, as the +separated fields are always present (it saves code size). Additionally, +both Shmem (2.6+) and MemShared (2.4 and earlier) fields are now parsed +and summed for shared memory usage; as only one of them exists depending +on kernel version. + +display_topmem_header() parses also meminfo so this makes it use the +same code for code shrink. + +function old new delta +display_header - 681 +681 +display_topmem_process_list 465 684 +219 +parse_meminfo - 189 +189 +static.fields - 106 +106 +static.match 132 - -132 +.rodata 120254 120117 -137 +display_topmem_header 513 - -513 +display_process_list 1705 667 -1038 +------------------------------------------------------------------------------ +(add/remove: 3/2 grow/shrink: 1/2 up/down: 1195/-1820) Total: -625 bytes + +Signed-off-by: Timo Teräs +Signed-off-by: Denys Vlasenko +--- + procps/top.c | 196 ++++++++++++++++++++++++++--------------------------------- + 1 file changed, 86 insertions(+), 110 deletions(-) + +diff --git a/procps/top.c b/procps/top.c +index 530f45f..62f9421 100644 +--- a/procps/top.c ++++ b/procps/top.c +@@ -499,85 +499,94 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p) + # define display_cpus(scr_width, scrbuf, lines_rem) ((void)0) + #endif + +-static unsigned long display_header(int scr_width, int *lines_rem_p) +-{ +- FILE *fp; +- char buf[80]; +- char scrbuf[80]; +- unsigned long total, used, mfree, shared, buffers, cached; ++enum { ++ MI_MEMTOTAL, ++ MI_MEMFREE, ++ MI_MEMSHARED, ++ MI_SHMEM, ++ MI_BUFFERS, ++ MI_CACHED, ++ MI_SWAPTOTAL, ++ MI_SWAPFREE, ++ MI_DIRTY, ++ MI_WRITEBACK, ++ MI_ANONPAGES, ++ MI_MAPPED, ++ MI_SLAB, ++ MI_MAX ++}; + +- /* read memory info */ +- fp = xfopen_for_read("meminfo"); ++static void parse_meminfo(unsigned long meminfo[MI_MAX]) ++{ ++ static const char fields[] = ++ "MemTotal\0" ++ "MemFree\0" ++ "MemShared\0" ++ "Shmem\0" ++ "Buffers\0" ++ "Cached\0" ++ "SwapTotal\0" ++ "SwapFree\0" ++ "Dirty\0" ++ "Writeback\0" ++ "AnonPages\0" ++ "Mapped\0" ++ "Slab\0"; ++ char buf[60]; /* actual lines we expect are ~30 chars or less */ ++ FILE *f; ++ int i; + +- /* +- * Old kernels (such as 2.4.x) had a nice summary of memory info that +- * we could parse, however this is gone entirely in 2.6. Try parsing +- * the old way first, and if that fails, parse each field manually. +- * +- * First, we read in the first line. Old kernels will have bogus +- * strings we don't care about, whereas new kernels will start right +- * out with MemTotal: +- * -- PFM. +- */ +- if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) { +- fgets(buf, sizeof(buf), fp); /* skip first line */ +- +- fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu", +- &total, &used, &mfree, &shared, &buffers, &cached); +- /* convert to kilobytes */ +- used /= 1024; +- mfree /= 1024; +- shared /= 1024; +- buffers /= 1024; +- cached /= 1024; +- total /= 1024; +- } else { +- /* +- * Revert to manual parsing, which incidentally already has the +- * sizes in kilobytes. This should be safe for both 2.4 and +- * 2.6. +- */ +- fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); ++ memset(meminfo, 0, sizeof(meminfo)); ++ f = xfopen_for_read("meminfo"); ++ while (fgets(buf, sizeof(buf), f) != NULL) { ++ char *c = strchr(buf, ':'); ++ if (!c) ++ continue; ++ *c = '\0'; ++ i = index_in_strings(fields, buf); ++ if (i >= 0) ++ meminfo[i] = strtoul(c+1, NULL, 10); ++ } ++ fclose(f); ++} + +- /* +- * MemShared: is no longer present in 2.6. Report this as 0, +- * to maintain consistent behavior with normal procps. +- */ +- if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) +- shared = 0; + +- fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); +- fscanf(fp, "Cached: %lu %s\n", &cached, buf); ++static unsigned long display_header(int scr_width, int *lines_rem_p) ++{ ++ char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */ ++ char *buf; ++ unsigned long meminfo[MI_MAX]; + +- used = total - mfree; +- } +- fclose(fp); ++ parse_meminfo(meminfo); + +- /* output memory info */ ++ /* Output memory info */ + if (scr_width > (int)sizeof(scrbuf)) + scr_width = sizeof(scrbuf); + snprintf(scrbuf, scr_width, + "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", +- used, mfree, shared, buffers, cached); +- /* go to top & clear to the end of screen */ ++ meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE], ++ meminfo[MI_MEMFREE], ++ meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM], ++ meminfo[MI_BUFFERS], ++ meminfo[MI_CACHED]); ++ /* Go to top & clear to the end of screen */ + printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); + (*lines_rem_p)--; + +- /* Display CPU time split as percentage of total time +- * This displays either a cumulative line or one line per CPU ++ /* Display CPU time split as percentage of total time. ++ * This displays either a cumulative line or one line per CPU. + */ + display_cpus(scr_width, scrbuf, lines_rem_p); + +- /* read load average as a string */ +- buf[0] = '\0'; +- open_read_close("loadavg", buf, sizeof(buf) - 1); +- buf[sizeof(buf) - 1] = '\n'; +- *strchr(buf, '\n') = '\0'; +- snprintf(scrbuf, scr_width, "Load average: %s", buf); ++ /* Read load average as a string */ ++ buf = stpcpy(scrbuf, "Load average: "); ++ open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: ")); ++ scrbuf[scr_width - 1] = '\0'; ++ strchrnul(buf, '\n')[0] = '\0'; + puts(scrbuf); + (*lines_rem_p)--; + +- return total; ++ return meminfo[MI_MEMTOTAL]; + } + + static NOINLINE void display_process_list(int lines_rem, int scr_width) +@@ -781,64 +790,31 @@ static int topmem_sort(char *a, char *b) + /* display header info (meminfo / loadavg) */ + static void display_topmem_header(int scr_width, int *lines_rem_p) + { +- enum { +- TOTAL = 0, MFREE, BUF, CACHE, +- SWAPTOTAL, SWAPFREE, DIRTY, +- MWRITE, ANON, MAP, SLAB, +- NUM_FIELDS +- }; +- static const char match[NUM_FIELDS][12] = { +- "\x09" "MemTotal:", // TOTAL +- "\x08" "MemFree:", // MFREE +- "\x08" "Buffers:", // BUF +- "\x07" "Cached:", // CACHE +- "\x0a" "SwapTotal:", // SWAPTOTAL +- "\x09" "SwapFree:", // SWAPFREE +- "\x06" "Dirty:", // DIRTY +- "\x0a" "Writeback:", // MWRITE +- "\x0a" "AnonPages:", // ANON +- "\x07" "Mapped:", // MAP +- "\x05" "Slab:", // SLAB +- }; +- char meminfo_buf[4 * 1024]; +- const char *Z[NUM_FIELDS]; +- unsigned i; +- int sz; +- +- for (i = 0; i < NUM_FIELDS; i++) +- Z[i] = "?"; +- +- /* read memory info */ +- sz = open_read_close("meminfo", meminfo_buf, sizeof(meminfo_buf) - 1); +- if (sz >= 0) { +- char *p = meminfo_buf; +- meminfo_buf[sz] = '\0'; +- /* Note that fields always appear in the match[] order */ +- for (i = 0; i < NUM_FIELDS; i++) { +- char *found = strstr(p, match[i] + 1); +- if (found) { +- /* Cut "NNNN" out of " NNNN kb" */ +- char *s = skip_whitespace(found + match[i][0]); +- p = skip_non_whitespace(s); +- *p++ = '\0'; +- Z[i] = s; +- } +- } +- } ++ unsigned long meminfo[MI_MAX]; ++ ++ parse_meminfo(meminfo); + + snprintf(line_buf, LINE_BUF_SIZE, +- "Mem total:%s anon:%s map:%s free:%s", +- Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]); ++ "Mem total:%lu anon:%lu map:%lu free:%lu", ++ meminfo[MI_MEMTOTAL], ++ meminfo[MI_ANONPAGES], ++ meminfo[MI_MAPPED], ++ meminfo[MI_MEMFREE]); + printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf); + + snprintf(line_buf, LINE_BUF_SIZE, +- " slab:%s buf:%s cache:%s dirty:%s write:%s", +- Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]); ++ " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu", ++ meminfo[MI_SLAB], ++ meminfo[MI_BUFFERS], ++ meminfo[MI_CACHED], ++ meminfo[MI_DIRTY], ++ meminfo[MI_WRITEBACK]); + printf("%.*s\n", scr_width, line_buf); + + snprintf(line_buf, LINE_BUF_SIZE, +- "Swap total:%s free:%s", // TODO: % used? +- Z[SWAPTOTAL], Z[SWAPFREE]); ++ "Swap total:%lu free:%lu", // TODO: % used? ++ meminfo[MI_SWAPTOTAL], ++ meminfo[MI_SWAPFREE]); + printf("%.*s\n", scr_width, line_buf); + + (*lines_rem_p) -= 3; +-- +2.0.3 + diff --git a/main/busybox/APKBUILD b/main/busybox/APKBUILD index bba47bd8ac..ed207c23d5 100644 --- a/main/busybox/APKBUILD +++ b/main/busybox/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa pkgname=busybox pkgver=1.22.1 -pkgrel=7 +pkgrel=8 pkgdesc="Size optimized toolbox of many common UNIX utilities" url=http://busybox.net arch="all" @@ -31,6 +31,8 @@ source="http://busybox.net/downloads/$pkgname-$pkgver.tar.bz2 0001-sendmail-make-f-optional-document-its-default-value.patch 0002-sendmail-use-FQDN-in-default-envelope-sender.patch 0001-linedit-deluser-use-POSIX-getpwent-instead-of-getpwe.patch + 0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch + fix-top.patch busyboxconfig glibc.patch" @@ -127,6 +129,8 @@ b15c67be5ccb3e523f540d8e218d5c85 0001-ifupdown-support-link-address-family.patc d372d376820957fd5f2aee158af9867e 0001-sendmail-make-f-optional-document-its-default-value.patch 9d83db6173fe5b0fb8ee6ce741d5bb18 0002-sendmail-use-FQDN-in-default-envelope-sender.patch 239dbe5dae5d36bbf73548b2749a22b1 0001-linedit-deluser-use-POSIX-getpwent-instead-of-getpwe.patch +7cadebb1071d648b947cfbcca9839721 0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch +f2821edec523aadb36c3973d14386c1c fix-top.patch 5d64c6dc25648854034684b7a15d9a7f busyboxconfig befaac2c59c380e36a452b3f1c1d4a3a glibc.patch" sha256sums="ae0b029d0a9e4dd71a077a790840e496dd838998e4571b87b60fed7462b6678b busybox-1.22.1.tar.bz2 @@ -146,6 +150,8 @@ a31ce8bcb8b81b20e80ffa407600a530d085806c6471f4e4249fcb3a491b79ef busybox-uname- 422ce68917dadf1a49085df2a00ffab670e2d0866dcdb7209ee49318ad195fca 0001-sendmail-make-f-optional-document-its-default-value.patch 7c88ef1d837ec8efb7c21e5b1b16e4ac3060ccde7ad5f698e9e6ef630d412593 0002-sendmail-use-FQDN-in-default-envelope-sender.patch ac2cd5fed91bfaec22ed1f2766396d0feb29b9b96f20b2c12d5d8ac8769afae9 0001-linedit-deluser-use-POSIX-getpwent-instead-of-getpwe.patch +79c6e19853a4ceecfec65311e5f8e66033243b8250829c06420d27d8240f1775 0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch +d4673907d58ce80e78a3bfe3c2414b15e7a2b072cfea0c87c2ae9f709744b9ec fix-top.patch 4bbfc462e0455f82f0850e788c53ca36eaf6aec24b285024d3baee8c36533c69 busyboxconfig c604ef791c31d35a8c5ee4558d21428a46f37a6d762c4a7e29864f4037fc44a0 glibc.patch" sha512sums="3e99fe373d638f714c3a61e1b02493d85ca532f472df038f7557db518ded38347072882ed568852941be7aac46fc34007257b4287375335ff5a09b60b295ce80 busybox-1.22.1.tar.bz2 @@ -165,5 +171,7 @@ b1a1cc2ada657a3d3364c8c96853575d73784e769cd8768c170c27a3e59abd2beace75dff6d5047c 7fde27b1742f641ad1da376d5cf7a96e1f60fef70fb9d382ca47b062df76d1c35d7a7f08cba5350484f818383eb897c772d5469fd515e648023d0a85d0ed640e 0001-sendmail-make-f-optional-document-its-default-value.patch d466676cd2779ff33f288bb073aa2baa4f3606cf8b96ec514e624a7acb46442a2839ef18c47e19cc18a8234a485de39596773b44e4be2eff39617d7cf677dd38 0002-sendmail-use-FQDN-in-default-envelope-sender.patch 6781b10ca078296b243373d2c3f2bca2507a9df18a6b06d051e9ce84ed31a238aef3b2bb085daf12b145550be68c07c854272bd78a6f77da9197779b9c7cd9e9 0001-linedit-deluser-use-POSIX-getpwent-instead-of-getpwe.patch +fa5f7f43bf8030f4bfcdf09d85e2e314014d5a083a24de95ac2e78c15e0dfebc14e410088e7f8eaeb8cdf24dea64e3b665b99afb8f96259e9908eebce81745bc 0001-top-fix-and-merge-code-to-parse-proc-meminfo.patch +2dea81509f73621e60d95db1b04186056add15fb24d1f9f7b32bb50aee99733d3cf45404c33b7ca6993cff23d76f31c0bcf38c04ac741dcdd2baaf3bc2afd707 fix-top.patch ee5221f756efe4d0b3c1296ba94fb14acaeafee49bd49c96fa1f3e4f64abe7902cedf0dd0c2c531e7d9287d8743804284f9e30e569525d16a46e4252da7c0e1b busyboxconfig 1d2739379dab1deb3eae7cffd4845300eb7d30f7343b4a1209b21a5680860d55080ad45fdefe098b249ce3040c01951fa7f0a79cd447b2d7b260eb000099d9dc glibc.patch" diff --git a/main/busybox/fix-top.patch b/main/busybox/fix-top.patch new file mode 100644 index 0000000000..7d1cd4a364 --- /dev/null +++ b/main/busybox/fix-top.patch @@ -0,0 +1,14 @@ +diff --git a/procps/top.c b/procps/top.c +index 62f9421..119c32b 100644 +--- a/procps/top.c ++++ b/procps/top.c +@@ -536,7 +536,7 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX]) + FILE *f; + int i; + +- memset(meminfo, 0, sizeof(meminfo)); ++ memset(meminfo, 0, MI_MAX*sizeof(unsigned long)); + f = xfopen_for_read("meminfo"); + while (fgets(buf, sizeof(buf), f) != NULL) { + char *c = strchr(buf, ':'); + -- cgit v1.2.3