@@ -521,6 +521,52 @@ static const char *action_name[] = {
521
521
[RECOVERED ] = "Recovered" ,
522
522
};
523
523
524
+ enum action_page_type {
525
+ MSG_KERNEL ,
526
+ MSG_KERNEL_HIGH_ORDER ,
527
+ MSG_SLAB ,
528
+ MSG_DIFFERENT_COMPOUND ,
529
+ MSG_POISONED_HUGE ,
530
+ MSG_HUGE ,
531
+ MSG_FREE_HUGE ,
532
+ MSG_UNMAP_FAILED ,
533
+ MSG_DIRTY_SWAPCACHE ,
534
+ MSG_CLEAN_SWAPCACHE ,
535
+ MSG_DIRTY_MLOCKED_LRU ,
536
+ MSG_CLEAN_MLOCKED_LRU ,
537
+ MSG_DIRTY_UNEVICTABLE_LRU ,
538
+ MSG_CLEAN_UNEVICTABLE_LRU ,
539
+ MSG_DIRTY_LRU ,
540
+ MSG_CLEAN_LRU ,
541
+ MSG_TRUNCATED_LRU ,
542
+ MSG_BUDDY ,
543
+ MSG_BUDDY_2ND ,
544
+ MSG_UNKNOWN ,
545
+ };
546
+
547
+ static const char * const action_page_types [] = {
548
+ [MSG_KERNEL ] = "reserved kernel page" ,
549
+ [MSG_KERNEL_HIGH_ORDER ] = "high-order kernel page" ,
550
+ [MSG_SLAB ] = "kernel slab page" ,
551
+ [MSG_DIFFERENT_COMPOUND ] = "different compound page after locking" ,
552
+ [MSG_POISONED_HUGE ] = "huge page already hardware poisoned" ,
553
+ [MSG_HUGE ] = "huge page" ,
554
+ [MSG_FREE_HUGE ] = "free huge page" ,
555
+ [MSG_UNMAP_FAILED ] = "unmapping failed page" ,
556
+ [MSG_DIRTY_SWAPCACHE ] = "dirty swapcache page" ,
557
+ [MSG_CLEAN_SWAPCACHE ] = "clean swapcache page" ,
558
+ [MSG_DIRTY_MLOCKED_LRU ] = "dirty mlocked LRU page" ,
559
+ [MSG_CLEAN_MLOCKED_LRU ] = "clean mlocked LRU page" ,
560
+ [MSG_DIRTY_UNEVICTABLE_LRU ] = "dirty unevictable LRU page" ,
561
+ [MSG_CLEAN_UNEVICTABLE_LRU ] = "clean unevictable LRU page" ,
562
+ [MSG_DIRTY_LRU ] = "dirty LRU page" ,
563
+ [MSG_CLEAN_LRU ] = "clean LRU page" ,
564
+ [MSG_TRUNCATED_LRU ] = "already truncated LRU page" ,
565
+ [MSG_BUDDY ] = "free buddy page" ,
566
+ [MSG_BUDDY_2ND ] = "free buddy page (2nd try)" ,
567
+ [MSG_UNKNOWN ] = "unknown page" ,
568
+ };
569
+
524
570
/*
525
571
* XXX: It is possible that a page is isolated from LRU cache,
526
572
* and then kept in swap cache or failed to remove from page cache.
@@ -777,10 +823,10 @@ static int me_huge_page(struct page *p, unsigned long pfn)
777
823
static struct page_state {
778
824
unsigned long mask ;
779
825
unsigned long res ;
780
- char * msg ;
826
+ enum action_page_type type ;
781
827
int (* action )(struct page * p , unsigned long pfn );
782
828
} error_states [] = {
783
- { reserved , reserved , "reserved kernel" , me_kernel },
829
+ { reserved , reserved , MSG_KERNEL , me_kernel },
784
830
/*
785
831
* free pages are specially detected outside this table:
786
832
* PG_buddy pages only make a small fraction of all free pages.
@@ -791,31 +837,31 @@ static struct page_state {
791
837
* currently unused objects without touching them. But just
792
838
* treat it as standard kernel for now.
793
839
*/
794
- { slab , slab , "kernel slab" , me_kernel },
840
+ { slab , slab , MSG_SLAB , me_kernel },
795
841
796
842
#ifdef CONFIG_PAGEFLAGS_EXTENDED
797
- { head , head , "huge" , me_huge_page },
798
- { tail , tail , "huge" , me_huge_page },
843
+ { head , head , MSG_HUGE , me_huge_page },
844
+ { tail , tail , MSG_HUGE , me_huge_page },
799
845
#else
800
- { compound , compound , "huge" , me_huge_page },
846
+ { compound , compound , MSG_HUGE , me_huge_page },
801
847
#endif
802
848
803
- { sc |dirty , sc |dirty , "dirty swapcache" , me_swapcache_dirty },
804
- { sc |dirty , sc , "clean swapcache" , me_swapcache_clean },
849
+ { sc |dirty , sc |dirty , MSG_DIRTY_SWAPCACHE , me_swapcache_dirty },
850
+ { sc |dirty , sc , MSG_CLEAN_SWAPCACHE , me_swapcache_clean },
805
851
806
- { mlock |dirty , mlock |dirty , "dirty mlocked LRU" , me_pagecache_dirty },
807
- { mlock |dirty , mlock , "clean mlocked LRU" , me_pagecache_clean },
852
+ { mlock |dirty , mlock |dirty , MSG_DIRTY_MLOCKED_LRU , me_pagecache_dirty },
853
+ { mlock |dirty , mlock , MSG_CLEAN_MLOCKED_LRU , me_pagecache_clean },
808
854
809
- { unevict |dirty , unevict |dirty , "dirty unevictable LRU" , me_pagecache_dirty },
810
- { unevict |dirty , unevict , "clean unevictable LRU" , me_pagecache_clean },
855
+ { unevict |dirty , unevict |dirty , MSG_DIRTY_UNEVICTABLE_LRU , me_pagecache_dirty },
856
+ { unevict |dirty , unevict , MSG_CLEAN_UNEVICTABLE_LRU , me_pagecache_clean },
811
857
812
- { lru |dirty , lru |dirty , "dirty LRU" , me_pagecache_dirty },
813
- { lru |dirty , lru , "clean LRU" , me_pagecache_clean },
858
+ { lru |dirty , lru |dirty , MSG_DIRTY_LRU , me_pagecache_dirty },
859
+ { lru |dirty , lru , MSG_CLEAN_LRU , me_pagecache_clean },
814
860
815
861
/*
816
862
* Catchall entry: must be at end.
817
863
*/
818
- { 0 , 0 , "unknown page state" , me_unknown },
864
+ { 0 , 0 , MSG_UNKNOWN , me_unknown },
819
865
};
820
866
821
867
#undef dirty
@@ -835,10 +881,10 @@ static struct page_state {
835
881
* "Dirty/Clean" indication is not 100% accurate due to the possibility of
836
882
* setting PG_dirty outside page lock. See also comment above set_page_dirty().
837
883
*/
838
- static void action_result (unsigned long pfn , char * msg , int result )
884
+ static void action_result (unsigned long pfn , enum action_page_type type , int result )
839
885
{
840
- pr_err ("MCE %#lx: %s page recovery : %s\n" ,
841
- pfn , msg , action_name [result ]);
886
+ pr_err ("MCE %#lx: recovery action for %s : %s\n" ,
887
+ pfn , action_page_types [ type ] , action_name [result ]);
842
888
}
843
889
844
890
static int page_action (struct page_state * ps , struct page * p ,
@@ -854,11 +900,11 @@ static int page_action(struct page_state *ps, struct page *p,
854
900
count -- ;
855
901
if (count != 0 ) {
856
902
printk (KERN_ERR
857
- "MCE %#lx: %s page still referenced by %d users\n" ,
858
- pfn , ps -> msg , count );
903
+ "MCE %#lx: %s still referenced by %d users\n" ,
904
+ pfn , action_page_types [ ps -> type ] , count );
859
905
result = FAILED ;
860
906
}
861
- action_result (pfn , ps -> msg , result );
907
+ action_result (pfn , ps -> type , result );
862
908
863
909
/* Could do more checks here if page looks ok */
864
910
/*
@@ -1106,7 +1152,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1106
1152
if (!(flags & MF_COUNT_INCREASED ) &&
1107
1153
!get_page_unless_zero (hpage )) {
1108
1154
if (is_free_buddy_page (p )) {
1109
- action_result (pfn , "free buddy" , DELAYED );
1155
+ action_result (pfn , MSG_BUDDY , DELAYED );
1110
1156
return 0 ;
1111
1157
} else if (PageHuge (hpage )) {
1112
1158
/*
@@ -1123,12 +1169,12 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1123
1169
}
1124
1170
set_page_hwpoison_huge_page (hpage );
1125
1171
res = dequeue_hwpoisoned_huge_page (hpage );
1126
- action_result (pfn , "free huge" ,
1172
+ action_result (pfn , MSG_FREE_HUGE ,
1127
1173
res ? IGNORED : DELAYED );
1128
1174
unlock_page (hpage );
1129
1175
return res ;
1130
1176
} else {
1131
- action_result (pfn , "high order kernel" , IGNORED );
1177
+ action_result (pfn , MSG_KERNEL_HIGH_ORDER , IGNORED );
1132
1178
return - EBUSY ;
1133
1179
}
1134
1180
}
@@ -1150,9 +1196,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1150
1196
*/
1151
1197
if (is_free_buddy_page (p )) {
1152
1198
if (flags & MF_COUNT_INCREASED )
1153
- action_result (pfn , "free buddy" , DELAYED );
1199
+ action_result (pfn , MSG_BUDDY , DELAYED );
1154
1200
else
1155
- action_result (pfn , "free buddy, 2nd try" , DELAYED );
1201
+ action_result (pfn , MSG_BUDDY_2ND ,
1202
+ DELAYED );
1156
1203
return 0 ;
1157
1204
}
1158
1205
}
@@ -1165,7 +1212,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1165
1212
* If this happens just bail out.
1166
1213
*/
1167
1214
if (compound_head (p ) != hpage ) {
1168
- action_result (pfn , "different compound page after locking" , IGNORED );
1215
+ action_result (pfn , MSG_DIFFERENT_COMPOUND , IGNORED );
1169
1216
res = - EBUSY ;
1170
1217
goto out ;
1171
1218
}
@@ -1205,8 +1252,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1205
1252
* on the head page to show that the hugepage is hwpoisoned
1206
1253
*/
1207
1254
if (PageHuge (p ) && PageTail (p ) && TestSetPageHWPoison (hpage )) {
1208
- action_result (pfn , "hugepage already hardware poisoned" ,
1209
- IGNORED );
1255
+ action_result (pfn , MSG_POISONED_HUGE , IGNORED );
1210
1256
unlock_page (hpage );
1211
1257
put_page (hpage );
1212
1258
return 0 ;
@@ -1235,7 +1281,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1235
1281
*/
1236
1282
if (hwpoison_user_mappings (p , pfn , trapno , flags , & hpage )
1237
1283
!= SWAP_SUCCESS ) {
1238
- action_result (pfn , "unmapping failed" , IGNORED );
1284
+ action_result (pfn , MSG_UNMAP_FAILED , IGNORED );
1239
1285
res = - EBUSY ;
1240
1286
goto out ;
1241
1287
}
@@ -1244,7 +1290,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
1244
1290
* Torn down by someone else?
1245
1291
*/
1246
1292
if (PageLRU (p ) && !PageSwapCache (p ) && p -> mapping == NULL ) {
1247
- action_result (pfn , "already truncated LRU" , IGNORED );
1293
+ action_result (pfn , MSG_TRUNCATED_LRU , IGNORED );
1248
1294
res = - EBUSY ;
1249
1295
goto out ;
1250
1296
}
0 commit comments