diff options
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 93 |
1 files changed, 48 insertions, 45 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index e54d60af6b58..c70248aab536 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -86,64 +86,67 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) | |||
86 | 86 | ||
87 | static inline unsigned long scan_swap_map(struct swap_info_struct *si) | 87 | static inline unsigned long scan_swap_map(struct swap_info_struct *si) |
88 | { | 88 | { |
89 | unsigned long offset; | 89 | unsigned long offset, last_in_cluster; |
90 | |||
90 | /* | 91 | /* |
91 | * We try to cluster swap pages by allocating them | 92 | * We try to cluster swap pages by allocating them sequentially |
92 | * sequentially in swap. Once we've allocated | 93 | * in swap. Once we've allocated SWAPFILE_CLUSTER pages this |
93 | * SWAPFILE_CLUSTER pages this way, however, we resort to | 94 | * way, however, we resort to first-free allocation, starting |
94 | * first-free allocation, starting a new cluster. This | 95 | * a new cluster. This prevents us from scattering swap pages |
95 | * prevents us from scattering swap pages all over the entire | 96 | * all over the entire swap partition, so that we reduce |
96 | * swap partition, so that we reduce overall disk seek times | 97 | * overall disk seek times between swap pages. -- sct |
97 | * between swap pages. -- sct */ | 98 | * But we do now try to find an empty cluster. -Andrea |
98 | if (si->cluster_nr) { | 99 | */ |
99 | while (si->cluster_next <= si->highest_bit) { | 100 | |
100 | offset = si->cluster_next++; | 101 | if (unlikely(!si->cluster_nr)) { |
102 | si->cluster_nr = SWAPFILE_CLUSTER - 1; | ||
103 | if (si->pages - si->inuse_pages < SWAPFILE_CLUSTER) | ||
104 | goto lowest; | ||
105 | |||
106 | offset = si->lowest_bit; | ||
107 | last_in_cluster = offset + SWAPFILE_CLUSTER - 1; | ||
108 | |||
109 | /* Locate the first empty (unaligned) cluster */ | ||
110 | for (; last_in_cluster <= si->highest_bit; offset++) { | ||
101 | if (si->swap_map[offset]) | 111 | if (si->swap_map[offset]) |
102 | continue; | 112 | last_in_cluster = offset + SWAPFILE_CLUSTER; |
103 | si->cluster_nr--; | 113 | else if (offset == last_in_cluster) { |
104 | goto got_page; | 114 | si->cluster_next = offset-SWAPFILE_CLUSTER-1; |
105 | } | 115 | goto cluster; |
106 | } | ||
107 | si->cluster_nr = SWAPFILE_CLUSTER; | ||
108 | |||
109 | /* try to find an empty (even not aligned) cluster. */ | ||
110 | offset = si->lowest_bit; | ||
111 | check_next_cluster: | ||
112 | if (offset+SWAPFILE_CLUSTER-1 <= si->highest_bit) | ||
113 | { | ||
114 | unsigned long nr; | ||
115 | for (nr = offset; nr < offset+SWAPFILE_CLUSTER; nr++) | ||
116 | if (si->swap_map[nr]) | ||
117 | { | ||
118 | offset = nr+1; | ||
119 | goto check_next_cluster; | ||
120 | } | 116 | } |
121 | /* We found a completly empty cluster, so start | 117 | } |
122 | * using it. | 118 | goto lowest; |
123 | */ | ||
124 | goto got_page; | ||
125 | } | 119 | } |
126 | /* No luck, so now go finegrined as usual. -Andrea */ | 120 | |
127 | for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) { | 121 | si->cluster_nr--; |
128 | if (si->swap_map[offset]) | 122 | cluster: |
129 | continue; | 123 | offset = si->cluster_next; |
130 | si->lowest_bit = offset+1; | 124 | if (offset > si->highest_bit) |
131 | got_page: | 125 | lowest: offset = si->lowest_bit; |
132 | if (offset == si->lowest_bit) | 126 | if (!si->highest_bit) |
127 | goto no_page; | ||
128 | if (!si->swap_map[offset]) { | ||
129 | got_page: if (offset == si->lowest_bit) | ||
133 | si->lowest_bit++; | 130 | si->lowest_bit++; |
134 | if (offset == si->highest_bit) | 131 | if (offset == si->highest_bit) |
135 | si->highest_bit--; | 132 | si->highest_bit--; |
136 | if (si->lowest_bit > si->highest_bit) { | 133 | si->inuse_pages++; |
134 | if (si->inuse_pages == si->pages) { | ||
137 | si->lowest_bit = si->max; | 135 | si->lowest_bit = si->max; |
138 | si->highest_bit = 0; | 136 | si->highest_bit = 0; |
139 | } | 137 | } |
140 | si->swap_map[offset] = 1; | 138 | si->swap_map[offset] = 1; |
141 | si->inuse_pages++; | 139 | si->cluster_next = offset + 1; |
142 | si->cluster_next = offset+1; | ||
143 | return offset; | 140 | return offset; |
144 | } | 141 | } |
145 | si->lowest_bit = si->max; | 142 | |
146 | si->highest_bit = 0; | 143 | while (++offset <= si->highest_bit) { |
144 | if (!si->swap_map[offset]) | ||
145 | goto got_page; | ||
146 | } | ||
147 | goto lowest; | ||
148 | |||
149 | no_page: | ||
147 | return 0; | 150 | return 0; |
148 | } | 151 | } |
149 | 152 | ||