diff options
author | Chen Gong <gong.chen@linux.intel.com> | 2011-03-22 19:35:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 20:44:17 -0400 |
commit | 12da58b0c89e27617aaedde7dcf99a8690875e91 (patch) | |
tree | 67efcc8e3267e8bdaa07c72ab081d66e2b9cc0c3 /Documentation | |
parent | e06c374400148849cbf496fce7a28680c3604457 (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')
-rw-r--r-- | Documentation/vm/page-types.c | 105 |
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 | ||
167 | static 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; | |||
184 | static int opt_hwpoison; | 202 | static int opt_hwpoison; |
185 | static int opt_unpoison; | 203 | static int opt_unpoison; |
186 | 204 | ||
187 | static const char hwpoison_debug_fs[] = "/debug/hwpoison"; | 205 | static char hwpoison_debug_fs[MAX_PATH+1]; |
188 | static int hwpoison_inject_fd; | 206 | static int hwpoison_inject_fd; |
189 | static int hwpoison_forget_fd; | 207 | static 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 */ | ||
486 | static 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 */ | ||
499 | static 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 | |||
536 | static 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 | ||
471 | static void prepare_hwpoison_fd(void) | 564 | static 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 | } |