diff options
author | Hugh Dickins <hugh.dickins@tiscali.co.uk> | 2009-12-14 20:58:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:53:15 -0500 |
commit | 8d69aaee80c123b460918816cbfa2e83224c3646 (patch) | |
tree | 899a69417dbd81f9b53926d7076629cc9b394ae5 | |
parent | 253d553ba75ab26b3e9e2f70cbf6fbf0813f7e86 (diff) |
swap_info: swap_map of chars not shorts
Halve the vmalloc'ed swap_map array from unsigned shorts to unsigned
chars: it's still very unusual to reach a swap count of 126, and the
next patch allows it to be extended indefinitely.
Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Rik van Riel <riel@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/swap.h | 8 | ||||
-rw-r--r-- | mm/swapfile.c | 40 |
2 files changed, 27 insertions, 21 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index c9d8870892b8..f733deb10748 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -151,9 +151,9 @@ enum { | |||
151 | 151 | ||
152 | #define SWAP_CLUSTER_MAX 32 | 152 | #define SWAP_CLUSTER_MAX 32 |
153 | 153 | ||
154 | #define SWAP_MAP_MAX 0x7ffe | 154 | #define SWAP_MAP_MAX 0x7e |
155 | #define SWAP_MAP_BAD 0x7fff | 155 | #define SWAP_MAP_BAD 0x7f |
156 | #define SWAP_HAS_CACHE 0x8000 /* There is a swap cache of entry. */ | 156 | #define SWAP_HAS_CACHE 0x80 /* There is a swap cache of entry. */ |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * The in-memory structure used to track swap areas. | 159 | * The in-memory structure used to track swap areas. |
@@ -167,7 +167,7 @@ struct swap_info_struct { | |||
167 | struct block_device *bdev; | 167 | struct block_device *bdev; |
168 | struct swap_extent first_swap_extent; | 168 | struct swap_extent first_swap_extent; |
169 | struct swap_extent *curr_swap_extent; | 169 | struct swap_extent *curr_swap_extent; |
170 | unsigned short *swap_map; | 170 | unsigned char *swap_map; |
171 | unsigned int lowest_bit; | 171 | unsigned int lowest_bit; |
172 | unsigned int highest_bit; | 172 | unsigned int highest_bit; |
173 | unsigned int lowest_alloc; /* while preparing discard cluster */ | 173 | unsigned int lowest_alloc; /* while preparing discard cluster */ |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 52497490a7ca..c0d7b9ed0c16 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -53,7 +53,7 @@ static struct swap_info_struct *swap_info[MAX_SWAPFILES]; | |||
53 | 53 | ||
54 | static DEFINE_MUTEX(swapon_mutex); | 54 | static DEFINE_MUTEX(swapon_mutex); |
55 | 55 | ||
56 | static inline int swap_count(unsigned short ent) | 56 | static inline unsigned char swap_count(unsigned char ent) |
57 | { | 57 | { |
58 | return ent & ~SWAP_HAS_CACHE; | 58 | return ent & ~SWAP_HAS_CACHE; |
59 | } | 59 | } |
@@ -203,7 +203,7 @@ static int wait_for_discard(void *word) | |||
203 | #define LATENCY_LIMIT 256 | 203 | #define LATENCY_LIMIT 256 |
204 | 204 | ||
205 | static inline unsigned long scan_swap_map(struct swap_info_struct *si, | 205 | static inline unsigned long scan_swap_map(struct swap_info_struct *si, |
206 | unsigned short usage) | 206 | unsigned char usage) |
207 | { | 207 | { |
208 | unsigned long offset; | 208 | unsigned long offset; |
209 | unsigned long scan_base; | 209 | unsigned long scan_base; |
@@ -531,12 +531,12 @@ out: | |||
531 | return NULL; | 531 | return NULL; |
532 | } | 532 | } |
533 | 533 | ||
534 | static unsigned short swap_entry_free(struct swap_info_struct *p, | 534 | static unsigned char swap_entry_free(struct swap_info_struct *p, |
535 | swp_entry_t entry, unsigned short usage) | 535 | swp_entry_t entry, unsigned char usage) |
536 | { | 536 | { |
537 | unsigned long offset = swp_offset(entry); | 537 | unsigned long offset = swp_offset(entry); |
538 | unsigned short count; | 538 | unsigned char count; |
539 | unsigned short has_cache; | 539 | unsigned char has_cache; |
540 | 540 | ||
541 | count = p->swap_map[offset]; | 541 | count = p->swap_map[offset]; |
542 | has_cache = count & SWAP_HAS_CACHE; | 542 | has_cache = count & SWAP_HAS_CACHE; |
@@ -591,7 +591,7 @@ void swap_free(swp_entry_t entry) | |||
591 | void swapcache_free(swp_entry_t entry, struct page *page) | 591 | void swapcache_free(swp_entry_t entry, struct page *page) |
592 | { | 592 | { |
593 | struct swap_info_struct *p; | 593 | struct swap_info_struct *p; |
594 | unsigned short count; | 594 | unsigned char count; |
595 | 595 | ||
596 | p = swap_info_get(entry); | 596 | p = swap_info_get(entry); |
597 | if (p) { | 597 | if (p) { |
@@ -975,7 +975,7 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si, | |||
975 | { | 975 | { |
976 | unsigned int max = si->max; | 976 | unsigned int max = si->max; |
977 | unsigned int i = prev; | 977 | unsigned int i = prev; |
978 | int count; | 978 | unsigned char count; |
979 | 979 | ||
980 | /* | 980 | /* |
981 | * No need for swap_lock here: we're just looking | 981 | * No need for swap_lock here: we're just looking |
@@ -1013,8 +1013,8 @@ static int try_to_unuse(unsigned int type) | |||
1013 | { | 1013 | { |
1014 | struct swap_info_struct *si = swap_info[type]; | 1014 | struct swap_info_struct *si = swap_info[type]; |
1015 | struct mm_struct *start_mm; | 1015 | struct mm_struct *start_mm; |
1016 | unsigned short *swap_map; | 1016 | unsigned char *swap_map; |
1017 | unsigned short swcount; | 1017 | unsigned char swcount; |
1018 | struct page *page; | 1018 | struct page *page; |
1019 | swp_entry_t entry; | 1019 | swp_entry_t entry; |
1020 | unsigned int i = 0; | 1020 | unsigned int i = 0; |
@@ -1174,6 +1174,12 @@ static int try_to_unuse(unsigned int type) | |||
1174 | * If that's wrong, then we should worry more about | 1174 | * If that's wrong, then we should worry more about |
1175 | * exit_mmap() and do_munmap() cases described above: | 1175 | * exit_mmap() and do_munmap() cases described above: |
1176 | * we might be resetting SWAP_MAP_MAX too early here. | 1176 | * we might be resetting SWAP_MAP_MAX too early here. |
1177 | * | ||
1178 | * Yes, that's wrong: though very unlikely, swap count 0x7ffe | ||
1179 | * could surely occur if pid_max raised from PID_MAX_DEFAULT; | ||
1180 | * and we are now lowering SWAP_MAP_MAX to 0x7e, making it | ||
1181 | * much easier to reach. But the next patch will fix that. | ||
1182 | * | ||
1177 | * We know "Undead"s can happen, they're okay, so don't | 1183 | * We know "Undead"s can happen, they're okay, so don't |
1178 | * report them; but do report if we reset SWAP_MAP_MAX. | 1184 | * report them; but do report if we reset SWAP_MAP_MAX. |
1179 | */ | 1185 | */ |
@@ -1492,7 +1498,7 @@ bad_bmap: | |||
1492 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | 1498 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) |
1493 | { | 1499 | { |
1494 | struct swap_info_struct *p = NULL; | 1500 | struct swap_info_struct *p = NULL; |
1495 | unsigned short *swap_map; | 1501 | unsigned char *swap_map; |
1496 | struct file *swap_file, *victim; | 1502 | struct file *swap_file, *victim; |
1497 | struct address_space *mapping; | 1503 | struct address_space *mapping; |
1498 | struct inode *inode; | 1504 | struct inode *inode; |
@@ -1762,7 +1768,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1762 | sector_t span; | 1768 | sector_t span; |
1763 | unsigned long maxpages = 1; | 1769 | unsigned long maxpages = 1; |
1764 | unsigned long swapfilepages; | 1770 | unsigned long swapfilepages; |
1765 | unsigned short *swap_map = NULL; | 1771 | unsigned char *swap_map = NULL; |
1766 | struct page *page = NULL; | 1772 | struct page *page = NULL; |
1767 | struct inode *inode = NULL; | 1773 | struct inode *inode = NULL; |
1768 | int did_down = 0; | 1774 | int did_down = 0; |
@@ -1938,13 +1944,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1938 | goto bad_swap; | 1944 | goto bad_swap; |
1939 | 1945 | ||
1940 | /* OK, set up the swap map and apply the bad block list */ | 1946 | /* OK, set up the swap map and apply the bad block list */ |
1941 | swap_map = vmalloc(maxpages * sizeof(short)); | 1947 | swap_map = vmalloc(maxpages); |
1942 | if (!swap_map) { | 1948 | if (!swap_map) { |
1943 | error = -ENOMEM; | 1949 | error = -ENOMEM; |
1944 | goto bad_swap; | 1950 | goto bad_swap; |
1945 | } | 1951 | } |
1946 | 1952 | ||
1947 | memset(swap_map, 0, maxpages * sizeof(short)); | 1953 | memset(swap_map, 0, maxpages); |
1948 | for (i = 0; i < swap_header->info.nr_badpages; i++) { | 1954 | for (i = 0; i < swap_header->info.nr_badpages; i++) { |
1949 | int page_nr = swap_header->info.badpages[i]; | 1955 | int page_nr = swap_header->info.badpages[i]; |
1950 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) { | 1956 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) { |
@@ -2082,12 +2088,12 @@ void si_swapinfo(struct sysinfo *val) | |||
2082 | * - swap-cache reference is requested but there is already one. -> EEXIST | 2088 | * - swap-cache reference is requested but there is already one. -> EEXIST |
2083 | * - swap-cache reference is requested but the entry is not used. -> ENOENT | 2089 | * - swap-cache reference is requested but the entry is not used. -> ENOENT |
2084 | */ | 2090 | */ |
2085 | static int __swap_duplicate(swp_entry_t entry, unsigned short usage) | 2091 | static int __swap_duplicate(swp_entry_t entry, unsigned char usage) |
2086 | { | 2092 | { |
2087 | struct swap_info_struct *p; | 2093 | struct swap_info_struct *p; |
2088 | unsigned long offset, type; | 2094 | unsigned long offset, type; |
2089 | unsigned short count; | 2095 | unsigned char count; |
2090 | unsigned short has_cache; | 2096 | unsigned char has_cache; |
2091 | int err = -EINVAL; | 2097 | int err = -EINVAL; |
2092 | 2098 | ||
2093 | if (non_swap_entry(entry)) | 2099 | if (non_swap_entry(entry)) |