diff options
author | Wu Fengguang <fengguang.wu@intel.com> | 2009-10-07 19:32:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-08 10:36:39 -0400 |
commit | a54fed9f70a2765f4476e1ce3d691a2f31df258f (patch) | |
tree | 407b053daa58bc6f6c855cacf5133005c005dcd3 /Documentation/vm | |
parent | 48640d69f5f06fe951a4de065a7f374cb9ee6040 (diff) |
page-types: add hwpoison/unpoison feature
For hwpoison stress testing. The debugfs mount point is assumed to be
/debug/.
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
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.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c index 11b9a03f7b10..3ec4f2a22585 100644 --- a/Documentation/vm/page-types.c +++ b/Documentation/vm/page-types.c | |||
@@ -170,6 +170,13 @@ static int page_size; | |||
170 | static int pagemap_fd; | 170 | static int pagemap_fd; |
171 | static int kpageflags_fd; | 171 | static int kpageflags_fd; |
172 | 172 | ||
173 | static int opt_hwpoison; | ||
174 | static int opt_unpoison; | ||
175 | |||
176 | static char *hwpoison_debug_fs = "/debug/hwpoison"; | ||
177 | static int hwpoison_inject_fd; | ||
178 | static int hwpoison_forget_fd; | ||
179 | |||
173 | #define HASH_SHIFT 13 | 180 | #define HASH_SHIFT 13 |
174 | #define HASH_SIZE (1 << HASH_SHIFT) | 181 | #define HASH_SIZE (1 << HASH_SHIFT) |
175 | #define HASH_MASK (HASH_SIZE - 1) | 182 | #define HASH_MASK (HASH_SIZE - 1) |
@@ -447,6 +454,53 @@ static uint64_t kpageflags_flags(uint64_t flags) | |||
447 | } | 454 | } |
448 | 455 | ||
449 | /* | 456 | /* |
457 | * page actions | ||
458 | */ | ||
459 | |||
460 | static void prepare_hwpoison_fd(void) | ||
461 | { | ||
462 | char buf[100]; | ||
463 | |||
464 | if (opt_hwpoison && !hwpoison_inject_fd) { | ||
465 | sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs); | ||
466 | hwpoison_inject_fd = checked_open(buf, O_WRONLY); | ||
467 | } | ||
468 | |||
469 | if (opt_unpoison && !hwpoison_forget_fd) { | ||
470 | sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs); | ||
471 | hwpoison_forget_fd = checked_open(buf, O_WRONLY); | ||
472 | } | ||
473 | } | ||
474 | |||
475 | static int hwpoison_page(unsigned long offset) | ||
476 | { | ||
477 | char buf[100]; | ||
478 | int len; | ||
479 | |||
480 | len = sprintf(buf, "0x%lx\n", offset); | ||
481 | len = write(hwpoison_inject_fd, buf, len); | ||
482 | if (len < 0) { | ||
483 | perror("hwpoison inject"); | ||
484 | return len; | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int unpoison_page(unsigned long offset) | ||
490 | { | ||
491 | char buf[100]; | ||
492 | int len; | ||
493 | |||
494 | len = sprintf(buf, "0x%lx\n", offset); | ||
495 | len = write(hwpoison_forget_fd, buf, len); | ||
496 | if (len < 0) { | ||
497 | perror("hwpoison forget"); | ||
498 | return len; | ||
499 | } | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | /* | ||
450 | * page frame walker | 504 | * page frame walker |
451 | */ | 505 | */ |
452 | 506 | ||
@@ -485,6 +539,11 @@ static void add_page(unsigned long voffset, | |||
485 | if (!bit_mask_ok(flags)) | 539 | if (!bit_mask_ok(flags)) |
486 | return; | 540 | return; |
487 | 541 | ||
542 | if (opt_hwpoison) | ||
543 | hwpoison_page(offset); | ||
544 | if (opt_unpoison) | ||
545 | unpoison_page(offset); | ||
546 | |||
488 | if (opt_list == 1) | 547 | if (opt_list == 1) |
489 | show_page_range(voffset, offset, flags); | 548 | show_page_range(voffset, offset, flags); |
490 | else if (opt_list == 2) | 549 | else if (opt_list == 2) |
@@ -624,6 +683,8 @@ static void usage(void) | |||
624 | " -l|--list Show page details in ranges\n" | 683 | " -l|--list Show page details in ranges\n" |
625 | " -L|--list-each Show page details one by one\n" | 684 | " -L|--list-each Show page details one by one\n" |
626 | " -N|--no-summary Don't show summay info\n" | 685 | " -N|--no-summary Don't show summay info\n" |
686 | " -X|--hwpoison hwpoison pages\n" | ||
687 | " -x|--unpoison unpoison pages\n" | ||
627 | " -h|--help Show this usage message\n" | 688 | " -h|--help Show this usage message\n" |
628 | "addr-spec:\n" | 689 | "addr-spec:\n" |
629 | " N one page at offset N (unit: pages)\n" | 690 | " N one page at offset N (unit: pages)\n" |
@@ -833,6 +894,8 @@ static struct option opts[] = { | |||
833 | { "list" , 0, NULL, 'l' }, | 894 | { "list" , 0, NULL, 'l' }, |
834 | { "list-each" , 0, NULL, 'L' }, | 895 | { "list-each" , 0, NULL, 'L' }, |
835 | { "no-summary", 0, NULL, 'N' }, | 896 | { "no-summary", 0, NULL, 'N' }, |
897 | { "hwpoison" , 0, NULL, 'X' }, | ||
898 | { "unpoison" , 0, NULL, 'x' }, | ||
836 | { "help" , 0, NULL, 'h' }, | 899 | { "help" , 0, NULL, 'h' }, |
837 | { NULL , 0, NULL, 0 } | 900 | { NULL , 0, NULL, 0 } |
838 | }; | 901 | }; |
@@ -844,7 +907,7 @@ int main(int argc, char *argv[]) | |||
844 | page_size = getpagesize(); | 907 | page_size = getpagesize(); |
845 | 908 | ||
846 | while ((c = getopt_long(argc, argv, | 909 | while ((c = getopt_long(argc, argv, |
847 | "rp:f:a:b:lLNh", opts, NULL)) != -1) { | 910 | "rp:f:a:b:lLNXxh", opts, NULL)) != -1) { |
848 | switch (c) { | 911 | switch (c) { |
849 | case 'r': | 912 | case 'r': |
850 | opt_raw = 1; | 913 | opt_raw = 1; |
@@ -870,6 +933,14 @@ int main(int argc, char *argv[]) | |||
870 | case 'N': | 933 | case 'N': |
871 | opt_no_summary = 1; | 934 | opt_no_summary = 1; |
872 | break; | 935 | break; |
936 | case 'X': | ||
937 | opt_hwpoison = 1; | ||
938 | prepare_hwpoison_fd(); | ||
939 | break; | ||
940 | case 'x': | ||
941 | opt_unpoison = 1; | ||
942 | prepare_hwpoison_fd(); | ||
943 | break; | ||
873 | case 'h': | 944 | case 'h': |
874 | usage(); | 945 | usage(); |
875 | exit(0); | 946 | exit(0); |