Commit 8d69aaee80c123b460918816cbfa2e83224c3646
Committed by
Linus Torvalds
1 parent
253d553ba7
Exists in
master
and in
4 other branches
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>
Showing 2 changed files with 27 additions and 21 deletions Side-by-side Diff
include/linux/swap.h
... | ... | @@ -151,9 +151,9 @@ |
151 | 151 | |
152 | 152 | #define SWAP_CLUSTER_MAX 32 |
153 | 153 | |
154 | -#define SWAP_MAP_MAX 0x7ffe | |
155 | -#define SWAP_MAP_BAD 0x7fff | |
156 | -#define SWAP_HAS_CACHE 0x8000 /* There is a swap cache of entry. */ | |
154 | +#define SWAP_MAP_MAX 0x7e | |
155 | +#define SWAP_MAP_BAD 0x7f | |
156 | +#define SWAP_HAS_CACHE 0x80 /* There is a swap cache of entry. */ | |
157 | 157 | |
158 | 158 | /* |
159 | 159 | * The in-memory structure used to track swap areas. |
... | ... | @@ -167,7 +167,7 @@ |
167 | 167 | struct block_device *bdev; |
168 | 168 | struct swap_extent first_swap_extent; |
169 | 169 | struct swap_extent *curr_swap_extent; |
170 | - unsigned short *swap_map; | |
170 | + unsigned char *swap_map; | |
171 | 171 | unsigned int lowest_bit; |
172 | 172 | unsigned int highest_bit; |
173 | 173 | unsigned int lowest_alloc; /* while preparing discard cluster */ |
mm/swapfile.c
... | ... | @@ -53,7 +53,7 @@ |
53 | 53 | |
54 | 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 | 58 | return ent & ~SWAP_HAS_CACHE; |
59 | 59 | } |
... | ... | @@ -203,7 +203,7 @@ |
203 | 203 | #define LATENCY_LIMIT 256 |
204 | 204 | |
205 | 205 | static inline unsigned long scan_swap_map(struct swap_info_struct *si, |
206 | - unsigned short usage) | |
206 | + unsigned char usage) | |
207 | 207 | { |
208 | 208 | unsigned long offset; |
209 | 209 | unsigned long scan_base; |
210 | 210 | |
... | ... | @@ -531,12 +531,12 @@ |
531 | 531 | return NULL; |
532 | 532 | } |
533 | 533 | |
534 | -static unsigned short swap_entry_free(struct swap_info_struct *p, | |
535 | - swp_entry_t entry, unsigned short usage) | |
534 | +static unsigned char swap_entry_free(struct swap_info_struct *p, | |
535 | + swp_entry_t entry, unsigned char usage) | |
536 | 536 | { |
537 | 537 | unsigned long offset = swp_offset(entry); |
538 | - unsigned short count; | |
539 | - unsigned short has_cache; | |
538 | + unsigned char count; | |
539 | + unsigned char has_cache; | |
540 | 540 | |
541 | 541 | count = p->swap_map[offset]; |
542 | 542 | has_cache = count & SWAP_HAS_CACHE; |
... | ... | @@ -591,7 +591,7 @@ |
591 | 591 | void swapcache_free(swp_entry_t entry, struct page *page) |
592 | 592 | { |
593 | 593 | struct swap_info_struct *p; |
594 | - unsigned short count; | |
594 | + unsigned char count; | |
595 | 595 | |
596 | 596 | p = swap_info_get(entry); |
597 | 597 | if (p) { |
... | ... | @@ -975,7 +975,7 @@ |
975 | 975 | { |
976 | 976 | unsigned int max = si->max; |
977 | 977 | unsigned int i = prev; |
978 | - int count; | |
978 | + unsigned char count; | |
979 | 979 | |
980 | 980 | /* |
981 | 981 | * No need for swap_lock here: we're just looking |
... | ... | @@ -1013,8 +1013,8 @@ |
1013 | 1013 | { |
1014 | 1014 | struct swap_info_struct *si = swap_info[type]; |
1015 | 1015 | struct mm_struct *start_mm; |
1016 | - unsigned short *swap_map; | |
1017 | - unsigned short swcount; | |
1016 | + unsigned char *swap_map; | |
1017 | + unsigned char swcount; | |
1018 | 1018 | struct page *page; |
1019 | 1019 | swp_entry_t entry; |
1020 | 1020 | unsigned int i = 0; |
... | ... | @@ -1174,6 +1174,12 @@ |
1174 | 1174 | * If that's wrong, then we should worry more about |
1175 | 1175 | * exit_mmap() and do_munmap() cases described above: |
1176 | 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 | 1183 | * We know "Undead"s can happen, they're okay, so don't |
1178 | 1184 | * report them; but do report if we reset SWAP_MAP_MAX. |
1179 | 1185 | */ |
... | ... | @@ -1492,7 +1498,7 @@ |
1492 | 1498 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) |
1493 | 1499 | { |
1494 | 1500 | struct swap_info_struct *p = NULL; |
1495 | - unsigned short *swap_map; | |
1501 | + unsigned char *swap_map; | |
1496 | 1502 | struct file *swap_file, *victim; |
1497 | 1503 | struct address_space *mapping; |
1498 | 1504 | struct inode *inode; |
... | ... | @@ -1762,7 +1768,7 @@ |
1762 | 1768 | sector_t span; |
1763 | 1769 | unsigned long maxpages = 1; |
1764 | 1770 | unsigned long swapfilepages; |
1765 | - unsigned short *swap_map = NULL; | |
1771 | + unsigned char *swap_map = NULL; | |
1766 | 1772 | struct page *page = NULL; |
1767 | 1773 | struct inode *inode = NULL; |
1768 | 1774 | int did_down = 0; |
1769 | 1775 | |
... | ... | @@ -1938,13 +1944,13 @@ |
1938 | 1944 | goto bad_swap; |
1939 | 1945 | |
1940 | 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 | 1948 | if (!swap_map) { |
1943 | 1949 | error = -ENOMEM; |
1944 | 1950 | goto bad_swap; |
1945 | 1951 | } |
1946 | 1952 | |
1947 | - memset(swap_map, 0, maxpages * sizeof(short)); | |
1953 | + memset(swap_map, 0, maxpages); | |
1948 | 1954 | for (i = 0; i < swap_header->info.nr_badpages; i++) { |
1949 | 1955 | int page_nr = swap_header->info.badpages[i]; |
1950 | 1956 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) { |
1951 | 1957 | |
... | ... | @@ -2082,12 +2088,12 @@ |
2082 | 2088 | * - swap-cache reference is requested but there is already one. -> EEXIST |
2083 | 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 | 2093 | struct swap_info_struct *p; |
2088 | 2094 | unsigned long offset, type; |
2089 | - unsigned short count; | |
2090 | - unsigned short has_cache; | |
2095 | + unsigned char count; | |
2096 | + unsigned char has_cache; | |
2091 | 2097 | int err = -EINVAL; |
2092 | 2098 | |
2093 | 2099 | if (non_swap_entry(entry)) |