aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2018-01-31 19:21:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 20:18:40 -0500
commitc7905f200225d4257536f19b11d18f598fee5f44 (patch)
tree4eb2efaa0d330e6ed9b53e4f943eb7b776111389 /tools
parente02a9f048ef79a411904bef075fd3ce4204052a9 (diff)
tools, vm: new option to specify kpageflags file
page-types currently hardcodes /proc/kpageflags as the file to parse. This works when using the tool to examine the state of pageflags on the same system, but does not allow storing a snapshot of pageflags at a given time to debug issues nor on a different system. This allows the user to specify a saved version of kpageflags with a new page-types -F option. [akpm@linux-foundation.org: add "filename" to fix usage() string] [rientjes@google.com: fix layout] Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1801301840050.140969@chino.kir.corp.google.com Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1801301458180.153857@chino.kir.corp.google.com Signed-off-by: David Rientjes <rientjes@google.com> Reviewed-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Cc: Vladimir Davydov <vdavydov.dev@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/vm/page-types.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index e92903fc7113..a8783f48f77f 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -169,9 +169,10 @@ static int opt_raw; /* for kernel developers */
169static int opt_list; /* list pages (in ranges) */ 169static int opt_list; /* list pages (in ranges) */
170static int opt_no_summary; /* don't show summary */ 170static int opt_no_summary; /* don't show summary */
171static pid_t opt_pid; /* process to walk */ 171static pid_t opt_pid; /* process to walk */
172const char * opt_file; /* file or directory path */ 172const char *opt_file; /* file or directory path */
173static uint64_t opt_cgroup; /* cgroup inode */ 173static uint64_t opt_cgroup; /* cgroup inode */
174static int opt_list_cgroup;/* list page cgroup */ 174static int opt_list_cgroup;/* list page cgroup */
175static const char *opt_kpageflags;/* kpageflags file to parse */
175 176
176#define MAX_ADDR_RANGES 1024 177#define MAX_ADDR_RANGES 1024
177static int nr_addr_ranges; 178static int nr_addr_ranges;
@@ -258,7 +259,7 @@ static int checked_open(const char *pathname, int flags)
258 * pagemap/kpageflags routines 259 * pagemap/kpageflags routines
259 */ 260 */
260 261
261static unsigned long do_u64_read(int fd, char *name, 262static unsigned long do_u64_read(int fd, const char *name,
262 uint64_t *buf, 263 uint64_t *buf,
263 unsigned long index, 264 unsigned long index,
264 unsigned long count) 265 unsigned long count)
@@ -283,7 +284,7 @@ static unsigned long kpageflags_read(uint64_t *buf,
283 unsigned long index, 284 unsigned long index,
284 unsigned long pages) 285 unsigned long pages)
285{ 286{
286 return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages); 287 return do_u64_read(kpageflags_fd, opt_kpageflags, buf, index, pages);
287} 288}
288 289
289static unsigned long kpagecgroup_read(uint64_t *buf, 290static unsigned long kpagecgroup_read(uint64_t *buf,
@@ -293,7 +294,7 @@ static unsigned long kpagecgroup_read(uint64_t *buf,
293 if (kpagecgroup_fd < 0) 294 if (kpagecgroup_fd < 0)
294 return pages; 295 return pages;
295 296
296 return do_u64_read(kpagecgroup_fd, PROC_KPAGEFLAGS, buf, index, pages); 297 return do_u64_read(kpagecgroup_fd, opt_kpageflags, buf, index, pages);
297} 298}
298 299
299static unsigned long pagemap_read(uint64_t *buf, 300static unsigned long pagemap_read(uint64_t *buf,
@@ -743,7 +744,7 @@ static void walk_addr_ranges(void)
743{ 744{
744 int i; 745 int i;
745 746
746 kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY); 747 kpageflags_fd = checked_open(opt_kpageflags, O_RDONLY);
747 748
748 if (!nr_addr_ranges) 749 if (!nr_addr_ranges)
749 add_addr_range(0, ULONG_MAX); 750 add_addr_range(0, ULONG_MAX);
@@ -790,6 +791,7 @@ static void usage(void)
790" -N|--no-summary Don't show summary info\n" 791" -N|--no-summary Don't show summary info\n"
791" -X|--hwpoison hwpoison pages\n" 792" -X|--hwpoison hwpoison pages\n"
792" -x|--unpoison unpoison pages\n" 793" -x|--unpoison unpoison pages\n"
794" -F|--kpageflags filename kpageflags file to parse\n"
793" -h|--help Show this usage message\n" 795" -h|--help Show this usage message\n"
794"flags:\n" 796"flags:\n"
795" 0x10 bitfield format, e.g.\n" 797" 0x10 bitfield format, e.g.\n"
@@ -1013,7 +1015,7 @@ static void walk_page_cache(void)
1013{ 1015{
1014 struct stat st; 1016 struct stat st;
1015 1017
1016 kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY); 1018 kpageflags_fd = checked_open(opt_kpageflags, O_RDONLY);
1017 pagemap_fd = checked_open("/proc/self/pagemap", O_RDONLY); 1019 pagemap_fd = checked_open("/proc/self/pagemap", O_RDONLY);
1018 sigaction(SIGBUS, &sigbus_action, NULL); 1020 sigaction(SIGBUS, &sigbus_action, NULL);
1019 1021
@@ -1164,6 +1166,11 @@ static void parse_bits_mask(const char *optarg)
1164 add_bits_filter(mask, bits); 1166 add_bits_filter(mask, bits);
1165} 1167}
1166 1168
1169static void parse_kpageflags(const char *name)
1170{
1171 opt_kpageflags = name;
1172}
1173
1167static void describe_flags(const char *optarg) 1174static void describe_flags(const char *optarg)
1168{ 1175{
1169 uint64_t flags = parse_flag_names(optarg, 0); 1176 uint64_t flags = parse_flag_names(optarg, 0);
@@ -1188,6 +1195,7 @@ static const struct option opts[] = {
1188 { "no-summary", 0, NULL, 'N' }, 1195 { "no-summary", 0, NULL, 'N' },
1189 { "hwpoison" , 0, NULL, 'X' }, 1196 { "hwpoison" , 0, NULL, 'X' },
1190 { "unpoison" , 0, NULL, 'x' }, 1197 { "unpoison" , 0, NULL, 'x' },
1198 { "kpageflags", 0, NULL, 'F' },
1191 { "help" , 0, NULL, 'h' }, 1199 { "help" , 0, NULL, 'h' },
1192 { NULL , 0, NULL, 0 } 1200 { NULL , 0, NULL, 0 }
1193}; 1201};
@@ -1199,7 +1207,7 @@ int main(int argc, char *argv[])
1199 page_size = getpagesize(); 1207 page_size = getpagesize();
1200 1208
1201 while ((c = getopt_long(argc, argv, 1209 while ((c = getopt_long(argc, argv,
1202 "rp:f:a:b:d:c:ClLNXxh", opts, NULL)) != -1) { 1210 "rp:f:a:b:d:c:ClLNXxF:h", opts, NULL)) != -1) {
1203 switch (c) { 1211 switch (c) {
1204 case 'r': 1212 case 'r':
1205 opt_raw = 1; 1213 opt_raw = 1;
@@ -1242,6 +1250,9 @@ int main(int argc, char *argv[])
1242 opt_unpoison = 1; 1250 opt_unpoison = 1;
1243 prepare_hwpoison_fd(); 1251 prepare_hwpoison_fd();
1244 break; 1252 break;
1253 case 'F':
1254 parse_kpageflags(optarg);
1255 break;
1245 case 'h': 1256 case 'h':
1246 usage(); 1257 usage();
1247 exit(0); 1258 exit(0);
@@ -1251,6 +1262,9 @@ int main(int argc, char *argv[])
1251 } 1262 }
1252 } 1263 }
1253 1264
1265 if (!opt_kpageflags)
1266 opt_kpageflags = PROC_KPAGEFLAGS;
1267
1254 if (opt_cgroup || opt_list_cgroup) 1268 if (opt_cgroup || opt_list_cgroup)
1255 kpagecgroup_fd = checked_open(PROC_KPAGECGROUP, O_RDONLY); 1269 kpagecgroup_fd = checked_open(PROC_KPAGECGROUP, O_RDONLY);
1256 1270