aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2005-09-03 18:54:34 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:05:40 -0400
commit11d31886dbcb61039ed3789e583d21c6e70960fd (patch)
treeddaebfd35080a530a30c56587707c2c5ef452591
parent4cd3bb10ff0b21b77b5a4cd13b4bd36694e054c4 (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.h2
-rw-r--r--mm/swapfile.c27
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 */
122struct swap_info_struct { 120struct 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 */
867static int 866static int
868add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, 867add_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}