aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/vm
diff options
context:
space:
mode:
authorChen Gong <gong.chen@linux.intel.com>2011-03-22 19:35:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-22 20:44:17 -0400
commit12da58b0c89e27617aaedde7dcf99a8690875e91 (patch)
tree67efcc8e3267e8bdaa07c72ab081d66e2b9cc0c3 /Documentation/vm
parente06c374400148849cbf496fce7a28680c3604457 (diff)
Documentation/vm/page-types.c: auto debugfs mount for hwpoison operation
page-types.c doesn't supply a way to specify the debugfs path and the original debugfs path is not usual on most machines. This patch supplies a way to auto mount debugfs if needed. This patch is heavily inspired by tools/perf/utils/debugfs.c [akpm@linux-foundation.org: make functions static] [akpm@linux-foundation.org: fix debugfs_mount() signature] Signed-off-by: Chen Gong <gong.chen@linux.intel.com> Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Reviewed-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'Documentation/vm')
-rw-r--r--Documentation/vm/page-types.c105
1 files changed, 101 insertions, 4 deletions
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index cc96ee2666f2..7445caa26d05 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -32,8 +32,20 @@
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/errno.h> 33#include <sys/errno.h>
34#include <sys/fcntl.h> 34#include <sys/fcntl.h>
35#include <sys/mount.h>
36#include <sys/statfs.h>
37#include "../../include/linux/magic.h"
35 38
36 39
40#ifndef MAX_PATH
41# define MAX_PATH 256
42#endif
43
44#ifndef STR
45# define _STR(x) #x
46# define STR(x) _STR(x)
47#endif
48
37/* 49/*
38 * pagemap kernel ABI bits 50 * pagemap kernel ABI bits
39 */ 51 */
@@ -152,6 +164,12 @@ static const char *page_flag_names[] = {
152}; 164};
153 165
154 166
167static const char *debugfs_known_mountpoints[] = {
168 "/sys/kernel/debug",
169 "/debug",
170 0,
171};
172
155/* 173/*
156 * data structures 174 * data structures
157 */ 175 */
@@ -184,7 +202,7 @@ static int kpageflags_fd;
184static int opt_hwpoison; 202static int opt_hwpoison;
185static int opt_unpoison; 203static int opt_unpoison;
186 204
187static const char hwpoison_debug_fs[] = "/debug/hwpoison"; 205static char hwpoison_debug_fs[MAX_PATH+1];
188static int hwpoison_inject_fd; 206static int hwpoison_inject_fd;
189static int hwpoison_forget_fd; 207static int hwpoison_forget_fd;
190 208
@@ -464,21 +482,100 @@ static uint64_t kpageflags_flags(uint64_t flags)
464 return flags; 482 return flags;
465} 483}
466 484
485/* verify that a mountpoint is actually a debugfs instance */
486static int debugfs_valid_mountpoint(const char *debugfs)
487{
488 struct statfs st_fs;
489
490 if (statfs(debugfs, &st_fs) < 0)
491 return -ENOENT;
492 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
493 return -ENOENT;
494
495 return 0;
496}
497
498/* find the path to the mounted debugfs */
499static const char *debugfs_find_mountpoint(void)
500{
501 const char **ptr;
502 char type[100];
503 FILE *fp;
504
505 ptr = debugfs_known_mountpoints;
506 while (*ptr) {
507 if (debugfs_valid_mountpoint(*ptr) == 0) {
508 strcpy(hwpoison_debug_fs, *ptr);
509 return hwpoison_debug_fs;
510 }
511 ptr++;
512 }
513
514 /* give up and parse /proc/mounts */
515 fp = fopen("/proc/mounts", "r");
516 if (fp == NULL)
517 perror("Can't open /proc/mounts for read");
518
519 while (fscanf(fp, "%*s %"
520 STR(MAX_PATH)
521 "s %99s %*s %*d %*d\n",
522 hwpoison_debug_fs, type) == 2) {
523 if (strcmp(type, "debugfs") == 0)
524 break;
525 }
526 fclose(fp);
527
528 if (strcmp(type, "debugfs") != 0)
529 return NULL;
530
531 return hwpoison_debug_fs;
532}
533
534/* mount the debugfs somewhere if it's not mounted */
535
536static void debugfs_mount(void)
537{
538 const char **ptr;
539
540 /* see if it's already mounted */
541 if (debugfs_find_mountpoint())
542 return;
543
544 ptr = debugfs_known_mountpoints;
545 while (*ptr) {
546 if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) {
547 /* save the mountpoint */
548 strcpy(hwpoison_debug_fs, *ptr);
549 break;
550 }
551 ptr++;
552 }
553
554 if (*ptr == NULL) {
555 perror("mount debugfs");
556 exit(EXIT_FAILURE);
557 }
558}
559
467/* 560/*
468 * page actions 561 * page actions
469 */ 562 */
470 563
471static void prepare_hwpoison_fd(void) 564static void prepare_hwpoison_fd(void)
472{ 565{
473 char buf[100]; 566 char buf[MAX_PATH + 1];
567
568 debugfs_mount();
474 569
475 if (opt_hwpoison && !hwpoison_inject_fd) { 570 if (opt_hwpoison && !hwpoison_inject_fd) {
476 sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs); 571 snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn",
572 hwpoison_debug_fs);
477 hwpoison_inject_fd = checked_open(buf, O_WRONLY); 573 hwpoison_inject_fd = checked_open(buf, O_WRONLY);
478 } 574 }
479 575
480 if (opt_unpoison && !hwpoison_forget_fd) { 576 if (opt_unpoison && !hwpoison_forget_fd) {
481 sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs); 577 snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn",
578 hwpoison_debug_fs);
482 hwpoison_forget_fd = checked_open(buf, O_WRONLY); 579 hwpoison_forget_fd = checked_open(buf, O_WRONLY);
483 } 580 }
484} 581}