ia64: Migrate data off physical pages with correctable errors v3
cover ia64: Migrate data off physical pages with correctable errors v3
Migrate data off physical pages with corrected memory errors (Version 3)
Version 3 changes:
page.cleanup.v3:
- Put PAGE_FLAGS definitions back in page-flags.h (per Christoph Lameter's request).
cpe.migrate.v3
- Use putback_lru_pages() when returning an individual page (per Christoph Lameter's request).
- Code style cleanup
(per Pekka Enberg's request).
- Use strict_strtoul()
(per Pekka Enberg's request).
- Added locking
(per Pekka Enberg's request).
- Use /sys/kernel/ instead of /proc
(per Pekka Enberg's request).
Version 2 changes:
Broke the page.discard patch into two patches, per request by Christoph Lameter.
page.cleanup.v2:
- minor clean-up of page flags in page_alloc.c.
page.discard.v2:
- Updated for recent page flag clean-up.
- Removed the change to the sysinfo struct.
cpe.migrate.v2
- Added /proc/badram interface to print page discard information and to free bad pages.
Purpose:
Physical memory with corrected errors may decay over time into uncorrectable errors. The purpose of this patch is to move the data off pages with correctable memory errors before the memory goes bad.
The patches:
[1/3] page.cleanup.v2: Minor clean-up of page flags in mm/page_alloc.c
Minor source code clean-up of page flags in mm/page_alloc.c. No functional change.
[2/3] page.discard.v2: Avoid putting a bad page back on the LRU.
page.discard are the arch independent changes. It adds a new page flag (PG_memerror) to mark the page as bad and prevent it from being put back on the LRU. PG_memerror is only defined on 64 bit architectures.
[3/3] cpe.migrate.v2: Call migration code on correctable errors
cpe.migrate are the IA64 specific changes. It connects the CPE handler to the page migration code. It is implemented as a kernel loadable module, similar to the mca recovery code (mca_recovery.ko), so that it can be removed to turn off the feature. Add /proc/badram to print page discard and to free bad pages.
Comments:
There is always an issue of how agressive the code should be on migrating pages. Should it migrate on the first correctable error, or wait for some threshold? Reasonable people may disagree on the threshold and the "right" answer may be hardware specific. The decision making is confined to the cpe_migrate.c code. It is currently set to migrate on the first correctable error.
Only pages that can be isolated on the LRU are migrated. Other pages, such as compound pages, are not migrated. That functionality could be a future enhancement.
/proc/badram is a way of displaying information about the bad memory and freeing the bad pages. A userspace program (or sysadmin) could determine if a discarded page needs to be freed.
Sample output:
linux> insmod cpe_migrate.ko
linux> cat /proc/badram // This shows no discarded memory
Bad RAM: 0 kB, 0 pages marked bad
List of bad physical pages
linux> ./errsingle -c 6 -s 1 // Inject correctable errors on
// six pages.
linux> cat /proc/badram
Bad RAM: 384 kB, 6 pages marked bad
List of bad physical pages
0x06048e10000 0x06870c40000 0x06870c20000 0x06870c10000 0x06007f00000 0x06042070000
linux> echo 0x06870c20000 > /proc/badram // Free one of the pages
linux> cat /proc/badram // Five pages remain on the list
Bad RAM: 320 kB, 5 pages marked bad
List of bad physical pages
0x06048e10000 0x06870c40000 0x06870c10000 0x06007f00000 0x06042070000
linux> echo 0 > /proc/badram // Free all the bad pages
linux> cat /proc/badram // All the pages are freed
Bad RAM: 0 kB, 0 pages marked bad
List of bad physical pages
Flow of the code description (while testing on IA64):
1) A user level application test program allocates memory and passes the virtual address of the memory to the error injection driver.
2) The error injection driver converts the virtual address to physical, functions the Altix hardware to modify the ECC for the physical page, creating a correctable error, and returns to the user application.
3) The user application reads the memory.
4) The Altix hardware detects the correctable error and interrupts prom. SAL builds a CPU error record, then sends a CPE interrupt to linux.
5) The linux CPE handler calls the cpe_migrate module (if installed).
6) cpe_migrate parses the physical address from the CPE record and adds the address to the migrate list (if not already on the list) and schedules the worker thread (cpe_enable_work).
7) cpe_enable_work calls ia64_mca_cpe_move_page.
8) ia64_mca_cpe_move_page validates the physical address, converts to page, sets PG_memerror flag and calls the migration code (migrate_prep(), isolate_lru_page(), and migrate_pages(). If the page migrates successfully, the bad page is added to badpagelist.
9) Because PG_memerror is set, the bad page is not added back on the LRU due to checks in lru_cache_add() and lru_cache_add_active().
Signature · 2 lines
Russ Anderson, OS RAS/Partitioning Project Lead SGI - Silicon Graphics Inc [email protected]
Quoted 7 lines · Russ Anderson
[2/3] page.discard.v2: Avoid putting a bad page back on the LRU.
page.discard are the arch independent changes. It adds a new page flag (
PG_memerror) to mark the page as bad and prevent it from being put back on the LRU.PG_memerroris only defined on 64 bit architectures.
So I haven't looked at this a lot, but it strikes me that it look to be much simple if you were to just increment the page count instead of playing games in mm/page_alloc.c.
That will make sure that it never goes back on any free lists, and requires no changes to the allocator. Hmm?
I'm also not really seeing why this triggers on lru_cache_add(), since that should only happen to new pages anyway. Who does lru_cache_add() on old pages?
Linus
Quoted 4 lines · Linus Torvalds
Quoted 3 lines · Russ Anderson
[2/3] page.discard.v2: Avoid putting a bad page back on the LRU.
Quoted 8 lines
Quoted 4 lines
page.discard are the arch independent changes. It adds a new page flag (
PG_memerror) to mark the page as bad and prevent it from being put back on the LRU.PG_memerroris only defined on 64 bit architectures.So I haven't looked at this a lot, but it strikes me that it look to be much simple if you were to just increment the page count instead of playing games in
mm/page_alloc.c.
FWIW, that is how the ia64 mca_recovery code prevents pages with uncorrectable errors from getting reused.
Quoted 2 lines
That will make sure that it never goes back on any free lists, and requires no changes to the allocator. Hmm?
I tried incrementing the page count but it did not play well with the migration code (mm/migrate.c). The migration code is used to copy the data off the bad page to a new good page. It currently will try to free the old page after migrating. My attempts to modify that behavior would result in either the migration code not migrating or pages with non zero page counts on a free list.
Quoted 3 lines
I'm also not really seeing why this triggers on
lru_cache_add(), since that should only happen to new pages anyway. Who doeslru_cache_add()on old pages?
unmap_and_move() calls move_to_lru() which calls lru_cache_add(). This code only deals with pages that can be isolated. (isolate_lru_page())
Quoted 2 lines
Linus
Signature · 2 lines
Russ Anderson, OS RAS/Partitioning Project Lead SGI - Silicon Graphics Inc [email protected]
Quoted 3 lines · Linus Torvalds
So I haven't looked at this a lot, but it strikes me that it look to be much simple if you were to just increment the page count instead of playing games in
mm/page_alloc.c.
We are taking a refcount when isolating the page from the LRU. The problem is that the migration code attempts to free the page. That code could be changed to do something else instead like putting the page on the bad list.
Quoted 3 lines
I'm also not really seeing why this triggers on
lru_cache_add(), since that should only happen to new pages anyway. Who doeslru_cache_add()on old pages?
Migration code does the adding back to the LRU when migration is complete. So he hooked into that I guess.
Quoted 4 lines · Linus Torvalds
Quoted 3 lines · Russ Anderson
[2/3] page.discard.v2: Avoid putting a bad page back on the LRU.
Quoted 8 lines
Quoted 4 lines
page.discard are the arch independent changes. It adds a new page flag (
PG_memerror) to mark the page as bad and prevent it from being put back on the LRU.PG_memerroris only defined on 64 bit architectures.So I haven't looked at this a lot, but it strikes me that it look to be much simple if you were to just increment the page count instead of playing games in
mm/page_alloc.c.
Looking closer at the code, it is possible to increment the page count and avoid playing games in mm/page_alloc.c. The page count cannot be directly incremented, due to the way the migration code works, but, as Christoph pointed out, the migration code increments the page count. Preventing the bad pages from being returned to the LRU prevents the reference counts from going to zero. The net effect is as you suggest.
Quoted 2 lines
That will make sure that it never goes back on any free lists, and requires no changes to the allocator. Hmm?
All the pages on the bad page list have a reference count of 1.
Quoted 3 lines
I'm also not really seeing why this triggers on
lru_cache_add(), since that should only happen to new pages anyway. Who doeslru_cache_add()on old pages?
The change to lru_cache_add() is being removed. I'll post the updated patches shortly.
Quoted 1 line
Linus
Signature · 2 lines
Russ Anderson, OS RAS/Partitioning Project Lead SGI - Silicon Graphics Inc [email protected]