Skip to content

Commit 8d69aae

Browse files
Hugh Dickinstorvalds
authored andcommitted
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 <[email protected]> Reviewed-by: KAMEZAWA Hiroyuki <[email protected]> Cc: Rik van Riel <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 253d553 commit 8d69aae

File tree

2 files changed

+27
-21
lines changed

2 files changed

+27
-21
lines changed

include/linux/swap.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ enum {
151151

152152
#define SWAP_CLUSTER_MAX 32
153153

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. */
157157

158158
/*
159159
* The in-memory structure used to track swap areas.
@@ -167,7 +167,7 @@ struct swap_info_struct {
167167
struct block_device *bdev;
168168
struct swap_extent first_swap_extent;
169169
struct swap_extent *curr_swap_extent;
170-
unsigned short *swap_map;
170+
unsigned char *swap_map;
171171
unsigned int lowest_bit;
172172
unsigned int highest_bit;
173173
unsigned int lowest_alloc; /* while preparing discard cluster */

mm/swapfile.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static struct swap_info_struct *swap_info[MAX_SWAPFILES];
5353

5454
static DEFINE_MUTEX(swapon_mutex);
5555

56-
static inline int swap_count(unsigned short ent)
56+
static inline unsigned char swap_count(unsigned char ent)
5757
{
5858
return ent & ~SWAP_HAS_CACHE;
5959
}
@@ -203,7 +203,7 @@ static int wait_for_discard(void *word)
203203
#define LATENCY_LIMIT 256
204204

205205
static inline unsigned long scan_swap_map(struct swap_info_struct *si,
206-
unsigned short usage)
206+
unsigned char usage)
207207
{
208208
unsigned long offset;
209209
unsigned long scan_base;
@@ -531,12 +531,12 @@ static struct swap_info_struct *swap_info_get(swp_entry_t entry)
531531
return NULL;
532532
}
533533

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)
536536
{
537537
unsigned long offset = swp_offset(entry);
538-
unsigned short count;
539-
unsigned short has_cache;
538+
unsigned char count;
539+
unsigned char has_cache;
540540

541541
count = p->swap_map[offset];
542542
has_cache = count & SWAP_HAS_CACHE;
@@ -591,7 +591,7 @@ void swap_free(swp_entry_t entry)
591591
void swapcache_free(swp_entry_t entry, struct page *page)
592592
{
593593
struct swap_info_struct *p;
594-
unsigned short count;
594+
unsigned char count;
595595

596596
p = swap_info_get(entry);
597597
if (p) {
@@ -975,7 +975,7 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si,
975975
{
976976
unsigned int max = si->max;
977977
unsigned int i = prev;
978-
int count;
978+
unsigned char count;
979979

980980
/*
981981
* No need for swap_lock here: we're just looking
@@ -1013,8 +1013,8 @@ static int try_to_unuse(unsigned int type)
10131013
{
10141014
struct swap_info_struct *si = swap_info[type];
10151015
struct mm_struct *start_mm;
1016-
unsigned short *swap_map;
1017-
unsigned short swcount;
1016+
unsigned char *swap_map;
1017+
unsigned char swcount;
10181018
struct page *page;
10191019
swp_entry_t entry;
10201020
unsigned int i = 0;
@@ -1174,6 +1174,12 @@ static int try_to_unuse(unsigned int type)
11741174
* If that's wrong, then we should worry more about
11751175
* exit_mmap() and do_munmap() cases described above:
11761176
* 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+
*
11771183
* We know "Undead"s can happen, they're okay, so don't
11781184
* report them; but do report if we reset SWAP_MAP_MAX.
11791185
*/
@@ -1492,7 +1498,7 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
14921498
SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
14931499
{
14941500
struct swap_info_struct *p = NULL;
1495-
unsigned short *swap_map;
1501+
unsigned char *swap_map;
14961502
struct file *swap_file, *victim;
14971503
struct address_space *mapping;
14981504
struct inode *inode;
@@ -1762,7 +1768,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
17621768
sector_t span;
17631769
unsigned long maxpages = 1;
17641770
unsigned long swapfilepages;
1765-
unsigned short *swap_map = NULL;
1771+
unsigned char *swap_map = NULL;
17661772
struct page *page = NULL;
17671773
struct inode *inode = NULL;
17681774
int did_down = 0;
@@ -1938,13 +1944,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
19381944
goto bad_swap;
19391945

19401946
/* OK, set up the swap map and apply the bad block list */
1941-
swap_map = vmalloc(maxpages * sizeof(short));
1947+
swap_map = vmalloc(maxpages);
19421948
if (!swap_map) {
19431949
error = -ENOMEM;
19441950
goto bad_swap;
19451951
}
19461952

1947-
memset(swap_map, 0, maxpages * sizeof(short));
1953+
memset(swap_map, 0, maxpages);
19481954
for (i = 0; i < swap_header->info.nr_badpages; i++) {
19491955
int page_nr = swap_header->info.badpages[i];
19501956
if (page_nr <= 0 || page_nr >= swap_header->info.last_page) {
@@ -2082,12 +2088,12 @@ void si_swapinfo(struct sysinfo *val)
20822088
* - swap-cache reference is requested but there is already one. -> EEXIST
20832089
* - swap-cache reference is requested but the entry is not used. -> ENOENT
20842090
*/
2085-
static int __swap_duplicate(swp_entry_t entry, unsigned short usage)
2091+
static int __swap_duplicate(swp_entry_t entry, unsigned char usage)
20862092
{
20872093
struct swap_info_struct *p;
20882094
unsigned long offset, type;
2089-
unsigned short count;
2090-
unsigned short has_cache;
2095+
unsigned char count;
2096+
unsigned char has_cache;
20912097
int err = -EINVAL;
20922098

20932099
if (non_swap_entry(entry))

0 commit comments

Comments
 (0)