Migration cache
Subsystems (6)
PATCH 1/1 Migration cache
Hi MM fellows,
So as I've said before in my opinion moving pages to the swapcache to migrate them is unnacceptable for several reasons. Not to mention live memory defragmentation.
So the following patch, on top of the v2.6 -memoryhotplug tree, creates a migration cache - which is basically a swapcache without using the swap map - it instead uses a on-memory idr structure.
For that we decrease SWP_TYPE_SHIFT from 5 to 4, and use that now-free bit to indicate pte's which point to pages on the migration cache.
It still needs more testing, but it successfully migrates a zone while "fillmem" runs on it, on an SMP box.
Need more testing for integration into -mhp, its being done.
I think it needs to be able to transform "migration cache pages" (which still exist until all pte's referencing a page fault-in) into "swapcache pages" by going through the reserve mapping and transforming the "migration pte's" into "swapcache pte's" (with allocated swap space).
As soon as we have this working and stable we can go for "nonblocking" version of mmigrate.c work for defragmentation.
Comments are very welcome
Be warned, it contains debug printk's.
include/linux/mm.h +4 -1
@@ -458,12 +458,15 @@#define PAGE_MAPPING_ANON 1extern struct address_space swapper_space; +extern struct address_space migration_space;static inline struct address_space *page_mapping (struct page *page) {struct address_space *mapping = page->mapping;if (unlikely (PageSwapCache (page))) mapping = &swapper_space; +else if (unlikely (PageMigration (page))) + mapping = &migration_space;else if (unlikely ((unsigned long )mapping &PAGE_MAPPING_ANON )) mapping =NULL ;return mapping;
@@ -480,7 +483,7 @@*/ static inline pgoff_t page_index (struct page *page) { -if (unlikely (PageSwapCache (page))) +if (unlikely (PageSwapCache (page)) ||unlikely (PageMigration (page)))return page->private;return page->index; }
include/linux/page-flags.h +5 -0
@@ -83,6 +83,7 @@* -- daveh */ #define PG_capture 19/* Remove page for memory hotplug */ +#define PG_migration 20/* Remove page for memory hotplug */ /* * Global page accounting. One instance per CPU. Only unsigned longs are
@@ -339,6 +340,10 @@#define SetPageUnderCapture (page) set_bit(PG_capture, &(page)->flags)#define ClearPageUnderCapture (page) clear_bit(PG_capture, &(page)->flags) +#define PageMigration (page) test_bit(PG_migration, &(page)->flags) +#define SetPageMigration (page) set_bit(PG_migration, &(page)->flags) +#define ClearPageMigration (page) clear_bit(PG_migration, &(page)->flags) +static inline void set_page_under_capture (struct page *page) {SetPageUnderCapture (page);
include/linux/swap.h +1 -1
@@ -27,7 +27,7 @@* on 32-bit-pgoff_t architectures. And that assumes that the architecture packs * the type/offset into the pte as 5/27 as well. */ -#define MAX_SWAPFILES_SHIFT 5 +#define MAX_SWAPFILES_SHIFT 4#define MAX_SWAPFILES (1 << MAX_SWAPFILES_SHIFT)/*
include/linux/swapops.h +31 -4
@@ -10,7 +10,7 @@* swp_entry_t's are *never* stored anywhere in their arch-dependent format. */ #define SWP_TYPE_SHIFT (e) (sizeof(e.val) * 8 - MAX_SWAPFILES_SHIFT) -#define SWP_OFFSET_MASK (e) ((1UL << SWP_TYPE_SHIFT(e)) - 1) +#define SWP_OFFSET_MASK (e) ((1UL << (SWP_TYPE_SHIFT(e)-1)) - 1)/* * Store a type+offset into a swp_entry_t in an arch-independent format
@@ -19,7 +19,7 @@ {swp_entry_t ret; - ret.val = (type <<SWP_TYPE_SHIFT (ret)) | + ret.val = type <<SWP_TYPE_SHIFT (ret) | (offset &SWP_OFFSET_MASK (ret));return ret; }
@@ -30,8 +30,12 @@*/ static inline unsigned swp_type (swp_entry_t entry) { -return (entry.val >>SWP_TYPE_SHIFT (entry)) & - ((1 <<MAX_SWAPFILES_SHIFT ) -1 ); +return ((entry.val >>SWP_TYPE_SHIFT (entry))); +} + +static inline unsigned migration_type (swp_entry_t entry) +{ +return 1 ; }/*
@@ -68,3 +72,26 @@BUG_ON (pte_file (__swp_entry_to_pte (arch_entry)));return __swp_entry_to_pte (arch_entry); } + +static inline int pte_is_migration (pte_t pte) +{ +unsigned long swp_type; +swp_entry_t arch_entry; + + arch_entry =__pte_to_swp_entry (pte); + + swp_type =__swp_type (arch_entry); + +if (swp_type &1 ) +return 1 ; +else +return 0 ; +} + +static inline pte_t migration_entry_to_pte (swp_entry_t entry) +{ +swp_entry_t arch_entry; + + arch_entry =__swp_entry (migration_type (entry),swp_offset (entry)); +return __swp_entry_to_pte (arch_entry); +}
mm/memory.c +25 -7
@@ -456,8 +456,13 @@*/ if (unlikely (details))continue ; -if (!pte_file (pte)) -free_swap_and_cache (pte_to_swp_entry (pte)); +if (!pte_file (pte)) { +swp_entry_t swp_entry =pte_to_swp_entry (pte); +if (pte_is_migration (pte)) { +migration_remove_entry (swp_entry); + }else +free_swap_and_cache (swp_entry); + }pte_clear (ptep); }pte_unmap (ptep-1 );
@@ -1408,6 +1413,9 @@pte_unmap (page_table);spin_unlock (&mm->page_table_lock); again: +if (pte_is_migration (orig_pte)) { + page =lookup_migration_cache (entry.val &SWP_OFFSET_MASK (entry)); + }else { page =lookup_swap_cache (entry);if (!page) {swapin_readahead (entry, address, vma);
@@ -1433,7 +1441,6 @@inc_page_state (pgmajfault);grab_swap_token (); } -mark_page_accessed (page);lock_page (page);if (!PageSwapCache (page)) {
@@ -1442,6 +1449,13 @@page_cache_release (page); goto again; } + } + + +if (pte_is_migration (orig_pte)) { +mark_page_accessed (page); +lock_page (page); + }/* * Back out if somebody else faulted in this pte while we
@@ -1459,10 +1473,14 @@ }/* The page isn't present yet, go ahead with the fault. */ - -swap_free (entry); -if (vm_swap_full ()) -remove_exclusive_swap_page (page); + +if (!pte_is_migration (orig_pte)) { +swap_free (entry); +if (vm_swap_full ()) +remove_exclusive_swap_page (page); + }else { +migration_remove_reference (page); + } mm->rss++; pte =mk_pte (page, vma->vm_page_prot);
mm/mmigrate.c +183 -5
239 lines not on this page · raw message
mm/rmap.c +29 -15
51 lines not on this page · raw message
mm/vmscan.c +1 -1
@@ -354,7 +354,7 @@* Anonymous process memory has backing store? * Try to allocate it some swap space here. */ -if (PageAnon (page) && !PageSwapCache (page)) { +if (PageAnon (page) && !PageSwapCache (page) && !PageMigration (page)) {if (!add_to_swap (page,GFP_ATOMIC )) goto activate_locked; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Hi, Marcelo,
Give me few days to check it.
Quoted 9 lines
Hi MM fellows,
So as I've said before in my opinion moving pages to the swapcache to migrate them is unnacceptable for several reasons. Not to mention live memory defragmentation.
So the following patch, on top of the v2.6 -memoryhotplug tree, creates a migration cache - which is basically a swapcache without using the swap map - it instead uses a on-memory idr structure.
Thanks,
Hirokazu Takahashi.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Hi, Marcelo,
Quoted 10 lines
So as I've said before in my opinion moving pages to the swapcache to migrate them is unnacceptable for several reasons. Not to mention live memory defragmentation.
So the following patch, on top of the v2.6 -memoryhotplug tree, creates a migration cache - which is basically a swapcache without using the swap map - it instead uses a on-memory idr structure.
For that we decrease
SWP_TYPE_SHIFTfrom 5 to 4, and use that now-free bit to indicate pte's which point to pages on the migration cache.
I guess it would be better to reserve one swap type for the migration cache instead of reserving the bit to reduce the impact of the maximum number of swap types.
However, I think your approach is good enough for the first implementation.
Quoted 1 line
Comments are very welcome
I'll continue to check the code.
include/linux/swapops.h line 22
Quoted 9 lines
diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/include/linux/swapops.hlinux-2.6.9-rc2-mm4.build/include/linux/swapops.hinclude/linux/swapops.h +1
-1@@ -19,7 +19,7 @@ {swp_entry_t ret; - ret.val = (type << SWP_TYPE_SHIFT(ret)) | + ret.val = type << SWP_TYPE_SHIFT(ret) |
I guess it's just for cleanups to remove the brackets, right?
mm/memory.c line 1446
Quoted 11 lines
diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/mm/memory.clinux-2.6.9-rc2-mm4.build/mm/memory.cmm/memory.c +0
-1@@ -1433,7 +1441,6 @@inc_page_state (pgmajfault);grab_swap_token (); } -mark_page_accessed (page);lock_page (page);if (!PageSwapCache (page)) {
I think the previous line should be
if (!PageSwapCache(page) && !PageMigration(page)) {
This line means to redo everything from the beginning if the page is not either in the swap-cache or in the migration-cache.
Quoted 18 lines
mm/memory.c +7
-0@@ -1442,6 +1449,13 @@page_cache_release (page); goto again; } + } + + +if (pte_is_migration (orig_pte)) { +mark_page_accessed (page); +lock_page (page); + }/* * Back out if somebody else faulted in this pte while we diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/mm/mmigrate.clinux-2.6.9-rc2-mm4.build/mm/mmigrate.c
mm/mmigrate.c line 121
Quoted 6 lines
mm/mmigrate.c +5
-0+int migration_remove_entry (swp_entry_t entry) +{ +struct page *page; + + page =find_trylock_page (&migration_space, entry.val);
I guess there exits a race condition here.
If the page is locked unfortunately at this moment, who release it? Another process on another CPU may be handling page-fault against the page if it is shared with other processes.
The following code would be better?
page = find_get_page(&migration_space, entry.val); if (page) lock_page(page);
Quoted 16 lines
mm/mmigrate.c +14
-0+ + +if (printk_ratelimit ()) +printk (KERN_ERR "remove_from_migration_cache!!\n" ); + + +if (page) { +migration_remove_reference (page); +unlock_page (page); +page_cache_release (page); + } + +} +int add_to_migration_cache (struct page *page,int gfp_mask)
mm/mmigrate.c line 169
Quoted 10 lines
mm/mmigrate.c +10
-0+{ +int error, offset; +struct counter *counter; + +BUG_ON (PageSwapCache (page)); +BUG_ON (PagePrivate (page)); +BUG_ON (PageMigration (page)); + +if (idr_pre_get (&migration_idr,GFP_ATOMIC ) ==0 ) +return -ENOMEM ;
GFP_KERNEL would be appropriate for the memory migration code, because the swap-code will make free pages in case of low memory. This is one of the different points from the swap-code, which can't specify such gfp_mask, as no one can prepare free pages for it.
mm/mmigrate.c line 173
Quoted 4 lines
mm/mmigrate.c +4
-0+ + error =radix_tree_preload (gfp_mask); + + counter =kmalloc (sizeof (struct counter ),GFP_KERNEL );
kmalloc() should be called before radix_tree_preload() because radix_tree_preload() disables preemption not to switch other processes during handling radix trees. However kmalloc() with GFP_KERNEL may be blocked to break this assumption.
Quoted 31 lines
mm/mmigrate.c +28
-0+ + counter->i =0 ; + counter->magic =0xdeadbeef ; + +if (!error) { +write_lock_irq (&migration_space.tree_lock); + error =idr_get_new_above (&migration_idr, counter,1 , &offset); + +if (error <0 ) +BUG (); + + error =radix_tree_insert (&migration_space.page_tree, offset, + page); + +if (!error) { +page_cache_get (page); +SetPageLocked (page); + page->private = offset; +// page->mapping = &migration_space; +SetPageMigration (page); + } +write_unlock_irq (&migration_space.tree_lock); +radix_tree_preload_end (); + + } + +return error; +}
mm/mmigrate.c line 574
Quoted 6 lines
mm/mmigrate.c +1
-2@@ -399,11 +571,15 @@* Put the page in a radix tree if it isn't in the tree yet. */ #ifdef CONFIG_SWAP - if (PageAnon(page) && !PageSwapCache(page)) - if (!add_to_swap(page, GFP_KERNEL)) { +if (PageAnon (page) && !PageSwapCache (page) && !PageMigration (page))
I guess calling BUG() would be good if the page is already in the migration cache.
Quoted 16 lines
mm/mmigrate.c +5
-0+if (!add_to_migration_cache (page,GFP_KERNEL )) {unlock_page (page);return ERR_PTR (-ENOSPC ); } +/* if (!add_to_swap(page, GFP_KERNEL)) { +unlock_page(page); +return ERR_PTR(-ENOSPC); +} */ #endif /* CONFIG_SWAP */ if ((mapping =page_mapping (page)) ==NULL ) {/* truncation is in progress */ diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/mm/vmscan.clinux-2.6.9-rc2-mm4.build/mm/vmscan.c
mm/vmscan.c line 357
Quoted 5 lines
mm/vmscan.c +1
-1@@ -354,7 +354,7 @@* Anonymous process memory has backing store? * Try to allocate it some swap space here. */ -if (PageAnon (page) && !PageSwapCache (page)) { +if (PageAnon (page) && !PageSwapCache (page) && !PageMigration (page)) {
BUG_ON(PageMigration(page)) would be better, because it must not exist in the LRU. Target pages to migrate must have been removed from the LRU lists in advance, so that the swap code never grabs them.
mm/vmscan.c line 360
Quoted 3 lines
mm/vmscan.c +0
-0if (!add_to_swap (page,GFP_ATOMIC )) goto activate_locked; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Hi Hirokazu!
Quoted 10 lines · Hirokazu Takahashi
Hi, Marcelo,
Quoted 8 lines
So as I've said before in my opinion moving pages to the swapcache to migrate them is unnacceptable for several reasons. Not to mention live memory defragmentation.
So the following patch, on top of the v2.6 -memoryhotplug tree, creates a migration cache - which is basically a swapcache without using the swap map - it instead uses a on-memory idr structure.
Quoted 7 lines
Quoted 2 lines
For that we decrease
SWP_TYPE_SHIFTfrom 5 to 4, and use that now-free bit to indicate pte's which point to pages on the migration cache.I guess it would be better to reserve one swap type for the migration cache instead of reserving the bit to reduce the impact of the maximum number of swap types.
However, I think your approach is good enough for the first implementation.
By reserving one swap type we would also use a bit. Using a swap type is the same thing as using a bit in the swap pagetableentry. (the swap type has 5 bits reserved for swap devices, 2^5 = 32 swap devices).
?
Quoted 12 lines
Quoted 1 line
Comments are very welcome
I'll continue to check the code.
Quoted 7 lines
diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/include/linux/swapops.hlinux-2.6.9-rc2-mm4.build/include/linux/swapops.hinclude/linux/swapops.h +0
-0@@ -19,7 +19,7 @@ {swp_entry_t ret;
Quoted 4 lines
include/linux/swapops.h line 22
Quoted 2 lines
include/linux/swapops.h +1
-1- ret.val = (type << SWP_TYPE_SHIFT(ret)) | + ret.val = type << SWP_TYPE_SHIFT(ret) |I guess it's just for cleanups to remove the brackets, right?
Actually its just because I've been messing around with this code.
It shouldnt be changed in the final patch :)
Quoted 15 lines
mm/memory.c line 1446
Quoted 11 lines
diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/mm/memory.clinux-2.6.9-rc2-mm4.build/mm/memory.cmm/memory.c +0
-1@@ -1433,7 +1441,6 @@inc_page_state (pgmajfault);grab_swap_token (); } -mark_page_accessed (page);lock_page (page);if (!PageSwapCache (page)) {I think the previous line should be
if (!PageSwapCache(page) && !PageMigration(page)) {
Quoted 2 lines
This line means to redo everything from the beginning if the page is not either in the swap-cache or in the migration-cache.
Right. Added to the todo list.
Quoted 30 lines
Quoted 18 lines
mm/memory.c +7
-0@@ -1442,6 +1449,13 @@page_cache_release (page); goto again; } + } + + +if (pte_is_migration (orig_pte)) { +mark_page_accessed (page); +lock_page (page); + }/* * Back out if somebody else faulted in this pte while we diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/mm/mmigrate.clinux-2.6.9-rc2-mm4.build/mm/mmigrate.cmm/mmigrate.c line 121
Quoted 6 lines
mm/mmigrate.c +5
-0+int migration_remove_entry (swp_entry_t entry) +{ +struct page *page; + + page =find_trylock_page (&migration_space, entry.val);I guess there exits a race condition here.
If the page is locked unfortunately at this moment, who release it? Another process on another CPU may be handling page-fault against the page if it is shared with other processes.
Quoted 4 lines
The following code would be better?
page = find_get_page(&migration_space, entry.val); if (page) lock_page(page);
Correct! Now I also noticed that locking of the IDR structure needs to be done correctly for eg migration_remove_reference does idr_find() without any lock.
Quoted 24 lines
Quoted 24 lines
mm/mmigrate.c +22
-0+ + +if (printk_ratelimit ()) +printk (KERN_ERR "remove_from_migration_cache!!\n" ); + + +if (page) { +migration_remove_reference (page); +unlock_page (page); +page_cache_release (page); + } + +} +int add_to_migration_cache (struct page *page,int gfp_mask) +{ +int error, offset; +struct counter *counter; + +BUG_ON (PageSwapCache (page)); +BUG_ON (PagePrivate (page)); +BUG_ON (PageMigration (page)); +
Quoted 8 lines
mm/mmigrate.c line 169
Quoted 2 lines
mm/mmigrate.c +2
-0+if (idr_pre_get (&migration_idr,GFP_ATOMIC ) ==0 ) +return -ENOMEM ;
GFP_KERNELwould be appropriate for the memory migration code, because the swap-code will make free pages in case of low memory. This is one of the different points from the swap-code, which can't specify suchgfp_mask, as no one can prepare free pages for it.
OK!
Quoted 10 lines
mm/mmigrate.c line 173
Quoted 5 lines
mm/mmigrate.c +4
-0+ + error =radix_tree_preload (gfp_mask); + + counter =kmalloc (sizeof (struct counter ),GFP_KERNEL );
kmalloc()should be called beforeradix_tree_preload()becauseradix_tree_preload()disables preemption not to switch other processes during handling radix trees. Howeverkmalloc()withGFP_KERNELmay be blocked to break this assumption.
OK!
Quoted 30 lines
Quoted 28 lines
mm/mmigrate.c +28
-0+ + counter->i =0 ; + counter->magic =0xdeadbeef ; + +if (!error) { +write_lock_irq (&migration_space.tree_lock); + error =idr_get_new_above (&migration_idr, counter,1 , &offset); + +if (error <0 ) +BUG (); + + error =radix_tree_insert (&migration_space.page_tree, offset, + page); + +if (!error) { +page_cache_get (page); +SetPageLocked (page); + page->private = offset; +// page->mapping = &migration_space; +SetPageMigration (page); + } +write_unlock_irq (&migration_space.tree_lock); +radix_tree_preload_end (); + + } + +return error; +}
Quoted 10 lines
mm/mmigrate.c line 574
Quoted 7 lines
mm/mmigrate.c +1
-2@@ -399,11 +571,15 @@* Put the page in a radix tree if it isn't in the tree yet. */ #ifdef CONFIG_SWAP - if (PageAnon(page) && !PageSwapCache(page)) - if (!add_to_swap(page, GFP_KERNEL)) { +if (PageAnon (page) && !PageSwapCache (page) && !PageMigration (page))I guess calling
BUG()would be good if the page is already in the migration cache.
Sure, can be done.
Quoted 13 lines
Quoted 12 lines
mm/mmigrate.c +5
-0+if (!add_to_migration_cache (page,GFP_KERNEL )) {unlock_page (page);return ERR_PTR (-ENOSPC ); } +/* if (!add_to_swap(page, GFP_KERNEL)) { +unlock_page(page); +return ERR_PTR(-ENOSPC); +} */ #endif /* CONFIG_SWAP */ if ((mapping =page_mapping (page)) ==NULL ) {/* truncation is in progress */
Quoted 13 lines
mm/vmscan.c line 357
Quoted 9 lines
diff -Nur
linux-2.6.9-rc2-mm4.mhp.orig/mm/vmscan.clinux-2.6.9-rc2-mm4.build/mm/vmscan.cmm/vmscan.c +1
-1@@ -354,7 +354,7 @@* Anonymous process memory has backing store? * Try to allocate it some swap space here. */ -if (PageAnon (page) && !PageSwapCache (page)) { +if (PageAnon (page) && !PageSwapCache (page) && !PageMigration (page)) {BUG_ON(PageMigration(page)) would be better, because it must not exist in the LRU. Target pages to migrate must have been removed from the LRU lists in advance, so that the swap code never grabs them.
OK too!
Quoted 3 lines
mm/vmscan.c line 360
Quoted 3 lines
mm/vmscan.c +0
-0if (!add_to_swap (page,GFP_ATOMIC )) goto activate_locked; }
I'm working on something else today and probably tomorrow, later on I'll be making the changes you suggest and find any remaining bugs (I didnt mention but this is still oopsing for some reason in odd places).
So then we do some wider testing and merge it in the mainline -mhp patch!
Thanks for your comments.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 5 lines · Marcelo Tosatti
Quoted 4 lines · Hirokazu Takahashi
I guess it would be better to reserve one swap type for the migration cache instead of reserving the bit to reduce the impact of the maximum number of swap types.
I thought the same ...
Quoted 3 lines
By reserving one swap type we would also use a bit. Using a swap type is the same thing as using a bit in the swap pagetableentry. (the swap type has 5 bits reserved for swap devices, 2^5 = 32 swap devices).
... and don't understand your response.
Reserving a swap type leaves 31 swap devices for normal use, okay; but reserving a bit leaves only 16 swap devices for normal use.
Hugh
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 9 lines · Hugh Dickins
Quoted 5 lines · Marcelo Tosatti
Quoted 4 lines · Hirokazu Takahashi
I guess it would be better to reserve one swap type for the migration cache instead of reserving the bit to reduce the impact of the maximum number of swap types.
I thought the same ...
Quoted 8 lines
Quoted 3 lines
By reserving one swap type we would also use a bit. Using a swap type is the same thing as using a bit in the swap pagetableentry. (the swap type has 5 bits reserved for swap devices, 2^5 = 32 swap devices).
... and don't understand your response.
Reserving a swap type leaves 31 swap devices for normal use, okay; but reserving a bit leaves only 16 swap devices for normal use.
Oh stupid idiot I am! Of course, we can then remove "pte_is_migration" (and all the related pte handling code).
Added to TODO list.
If anyone wants to contribute that it would be cool cause I'm quite busy with other stuff right now.
Thanks guys!
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Hi,
Quoted 19 lines · Hugh Dickins
Quoted 9 lines · Marcelo Tosatti
Quoted 5 lines · Hirokazu Takahashi
Quoted 4 lines
I guess it would be better to reserve one swap type for the migration cache instead of reserving the bit to reduce the impact of the maximum number of swap types.
I thought the same ...
Quoted 8 lines
Quoted 3 lines
By reserving one swap type we would also use a bit. Using a swap type is the same thing as using a bit in the swap pagetableentry. (the swap type has 5 bits reserved for swap devices, 2^5 = 32 swap devices).
... and don't understand your response.
Reserving a swap type leaves 31 swap devices for normal use, okay; but reserving a bit leaves only 16 swap devices for normal use.
Quoted 7 lines
Oh stupid idiot I am! Of course, we can then remove "
pte_is_migration" (and all the related pte handling code).Added to TODO list.
If anyone wants to contribute that it would be cool cause I'm quite busy with other stuff right now.
The following code is my simple idea, which might help you.
#define MIGRATION_TYPE (MAX_SWAPFILES - 1)
static inline int pte_is_migration(pte_t pte)
{
unsigned long swp_type;
swp_entry_t arch_entry;
arch_entry = __pte_to_swp_entry(pte);
swp_type = __swp_type(arch_entry);
return swp_type == MIGRATION_TYPE;
}static inline int PageMigration(page)
{
swp_entry_t entry = { .val = page->private,};
return (PageSwapCache(page) && swp_type(entry) == MIGRATION_TYPE);
}Thanks,
Hirokazu Takahashi.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 35 lines · Hirokazu Takahashi
Hi,
Quoted 19 lines · Hugh Dickins
Quoted 9 lines · Marcelo Tosatti
Quoted 5 lines · Hirokazu Takahashi
Quoted 4 lines
I guess it would be better to reserve one swap type for the migration cache instead of reserving the bit to reduce the impact of the maximum number of swap types.
I thought the same ...
Quoted 8 lines
Quoted 3 lines
By reserving one swap type we would also use a bit. Using a swap type is the same thing as using a bit in the swap pagetableentry. (the swap type has 5 bits reserved for swap devices, 2^5 = 32 swap devices).
... and don't understand your response.
Reserving a swap type leaves 31 swap devices for normal use, okay; but reserving a bit leaves only 16 swap devices for normal use.
Quoted 7 lines
Oh stupid idiot I am! Of course, we can then remove "
pte_is_migration" (and all the related pte handling code).Added to TODO list.
If anyone wants to contribute that it would be cool cause I'm quite busy with other stuff right now.
The following code is my simple idea, which might help you.
#define
MIGRATION_TYPE(MAX_SWAPFILES- 1)static inline int
pte_is_migration(pte_t pte)
Quoted 10 lines
{
unsigned long swp_type;
swp_entry_t arch_entry;
arch_entry = __pte_to_swp_entry(pte);
swp_type = __swp_type(arch_entry);
return swp_type == MIGRATION_TYPE;
}OK thanks this code works fine (just pasted into swapops.h and tested). Thanks.
Quoted 5 lines
static inline int PageMigration(page)
{ swp_entry_t entry = { .val = page->private,}; return (PageSwapCache(page) && swp_type(entry) == MIGRATION_TYPE); }
Oh and with that we no longer need PG_migration bit, but, page->private does not contain swp_type information (MIGRATION_TYPE bit) in it. Its simply an offset counting from 0 increasing sequentially.
ANDing migration type bit into the offset should work. --
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 6 lines · Marcelo Tosatti
Oh and with that we no longer need
PG_migrationbit, but,page->privatedoes not containswp_typeinformation (MIGRATION_TYPEbit) in it. Its simply an offset counting from 0 increasing sequentially.ANDing migration type bit into the offset should work.
I haven't looked, but wouldn't it be a lot easier to use the normal swap allocation code rather than going such a different idr way here?
Hugh
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 10 lines · Hugh Dickins
Quoted 6 lines · Marcelo Tosatti
Oh and with that we no longer need
PG_migrationbit, but,page->privatedoes not containswp_typeinformation (MIGRATION_TYPEbit) in it. Its simply an offset counting from 0 increasing sequentially.ANDing migration type bit into the offset should work.
I haven't looked, but wouldn't it be a lot easier to use the normal swap allocation code rather than going such a different idr way here?
Hi Hugh,
Well, the idr code is quite simple, but yes,
we could probably reuse the swap allocation code.
Would have to create a swap_info_struct, without
the swap extent stuff and no bdev pointer. May
require some modifications but should work.
BTW, while I was reading the code, I wondered:
struct swap_info_struct swap_info[MAX_SWAPFILES];
This array should be created dynamically. Worth
the trouble?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 7 lines · Marcelo Tosatti
BTW, while I was reading the code, I wondered:
struct
swap_info_structswap_info[MAX_SWAPFILES];This array should be created dynamically. Worth
the trouble?
It is rather primitive, but I don't think it's worth the trouble to change it on its own - certainly not worth changing it to allocate the full array at runtime, and if you changed it to allocate slot by slot then quite a few places (within swapfile.c) would need changing. I can imagine someone doing a big cleanup of swapfile.c in which that static array vanished, but I don't think it's worth doing on its own.
Hugh
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>