diff options
author | Hugh Dickins <hugh@veritas.com> | 2005-09-03 18:54:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:05:40 -0400 |
commit | 11d31886dbcb61039ed3789e583d21c6e70960fd (patch) | |
tree | ddaebfd35080a530a30c56587707c2c5ef452591 | |
parent | 4cd3bb10ff0b21b77b5a4cd13b4bd36694e054c4 (diff) |
[PATCH] swap: swap extent list is ordered
There are several comments that swap's extent_list.prev points to the lowest
extent: that's not so, it's extent_list.next which points to it, as you'd
expect. And a couple of loops in add_swap_extent which go all the way through
the list, when they should just add to the other end.
Fix those up, and let map_swap_page search the list forwards: profiles shows
it to be twice as quick that way - because prefetch works better on how the
structs are typically kmalloc'ed? or because usually more is written to than
read from swap, and swap is allocated ascendingly?
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | include/linux/swap.h | 2 | ||||
-rw-r--r-- | mm/swapfile.c | 27 |
2 files changed, 9 insertions, 20 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index bfe3e763ccf2..38f288475e67 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -116,8 +116,6 @@ enum { | |||
116 | 116 | ||
117 | /* | 117 | /* |
118 | * The in-memory structure used to track swap areas. | 118 | * The in-memory structure used to track swap areas. |
119 | * extent_list.prev points at the lowest-index extent. That list is | ||
120 | * sorted. | ||
121 | */ | 119 | */ |
122 | struct swap_info_struct { | 120 | struct swap_info_struct { |
123 | unsigned int flags; | 121 | unsigned int flags; |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 4b39e9501d44..73521d39e985 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -832,9 +832,9 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset) | |||
832 | offset < (se->start_page + se->nr_pages)) { | 832 | offset < (se->start_page + se->nr_pages)) { |
833 | return se->start_block + (offset - se->start_page); | 833 | return se->start_block + (offset - se->start_page); |
834 | } | 834 | } |
835 | lh = se->list.prev; | 835 | lh = se->list.next; |
836 | if (lh == &sis->extent_list) | 836 | if (lh == &sis->extent_list) |
837 | lh = lh->prev; | 837 | lh = lh->next; |
838 | se = list_entry(lh, struct swap_extent, list); | 838 | se = list_entry(lh, struct swap_extent, list); |
839 | sis->curr_swap_extent = se; | 839 | sis->curr_swap_extent = se; |
840 | BUG_ON(se == start_se); /* It *must* be present */ | 840 | BUG_ON(se == start_se); /* It *must* be present */ |
@@ -859,10 +859,9 @@ static void destroy_swap_extents(struct swap_info_struct *sis) | |||
859 | 859 | ||
860 | /* | 860 | /* |
861 | * Add a block range (and the corresponding page range) into this swapdev's | 861 | * Add a block range (and the corresponding page range) into this swapdev's |
862 | * extent list. The extent list is kept sorted in block order. | 862 | * extent list. The extent list is kept sorted in page order. |
863 | * | 863 | * |
864 | * This function rather assumes that it is called in ascending sector_t order. | 864 | * This function rather assumes that it is called in ascending page order. |
865 | * It doesn't look for extent coalescing opportunities. | ||
866 | */ | 865 | */ |
867 | static int | 866 | static int |
868 | add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | 867 | add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, |
@@ -872,16 +871,15 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
872 | struct swap_extent *new_se; | 871 | struct swap_extent *new_se; |
873 | struct list_head *lh; | 872 | struct list_head *lh; |
874 | 873 | ||
875 | lh = sis->extent_list.next; /* The highest-addressed block */ | 874 | lh = sis->extent_list.prev; /* The highest page extent */ |
876 | while (lh != &sis->extent_list) { | 875 | if (lh != &sis->extent_list) { |
877 | se = list_entry(lh, struct swap_extent, list); | 876 | se = list_entry(lh, struct swap_extent, list); |
878 | if (se->start_block + se->nr_pages == start_block && | 877 | BUG_ON(se->start_page + se->nr_pages != start_page); |
879 | se->start_page + se->nr_pages == start_page) { | 878 | if (se->start_block + se->nr_pages == start_block) { |
880 | /* Merge it */ | 879 | /* Merge it */ |
881 | se->nr_pages += nr_pages; | 880 | se->nr_pages += nr_pages; |
882 | return 0; | 881 | return 0; |
883 | } | 882 | } |
884 | lh = lh->next; | ||
885 | } | 883 | } |
886 | 884 | ||
887 | /* | 885 | /* |
@@ -894,14 +892,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
894 | new_se->nr_pages = nr_pages; | 892 | new_se->nr_pages = nr_pages; |
895 | new_se->start_block = start_block; | 893 | new_se->start_block = start_block; |
896 | 894 | ||
897 | lh = sis->extent_list.prev; /* The lowest block */ | 895 | list_add_tail(&new_se->list, &sis->extent_list); |
898 | while (lh != &sis->extent_list) { | ||
899 | se = list_entry(lh, struct swap_extent, list); | ||
900 | if (se->start_block > start_block) | ||
901 | break; | ||
902 | lh = lh->prev; | ||
903 | } | ||
904 | list_add_tail(&new_se->list, lh); | ||
905 | sis->nr_extents++; | 896 | sis->nr_extents++; |
906 | return 0; | 897 | return 0; |
907 | } | 898 | } |