diff options
author | Cesar Eduardo Barros <cesarb@cesarb.net> | 2011-03-22 19:33:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 20:44:07 -0400 |
commit | ca8bd38bf6f05481c4155fc444178151884f65d0 (patch) | |
tree | efb917f23834153878a8f9f4c5f784e9cb900f66 /mm/swapfile.c | |
parent | 5de771e41f0fc2243c39585357b73f0ff757b280 (diff) |
sys_swapon: separate parsing of swapfile header
Move the code which parses and checks the swapfile header (except for
the bad block list) to a separate function. Only code movement, no
functional changes.
Signed-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>
Tested-by: Eric B Munson <emunson@mgebm.net>
Acked-by: Eric B Munson <emunson@mgebm.net>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 140 |
1 files changed, 78 insertions, 62 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 4dade515b086..5e13bff1764c 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1918,6 +1918,82 @@ static int claim_swapfile(struct swap_info_struct *p, struct inode *inode) | |||
1918 | return 0; | 1918 | return 0; |
1919 | } | 1919 | } |
1920 | 1920 | ||
1921 | static unsigned long read_swap_header(struct swap_info_struct *p, | ||
1922 | union swap_header *swap_header, | ||
1923 | struct inode *inode) | ||
1924 | { | ||
1925 | int i; | ||
1926 | unsigned long maxpages; | ||
1927 | unsigned long swapfilepages; | ||
1928 | |||
1929 | if (memcmp("SWAPSPACE2", swap_header->magic.magic, 10)) { | ||
1930 | printk(KERN_ERR "Unable to find swap-space signature\n"); | ||
1931 | goto bad_swap; | ||
1932 | } | ||
1933 | |||
1934 | /* swap partition endianess hack... */ | ||
1935 | if (swab32(swap_header->info.version) == 1) { | ||
1936 | swab32s(&swap_header->info.version); | ||
1937 | swab32s(&swap_header->info.last_page); | ||
1938 | swab32s(&swap_header->info.nr_badpages); | ||
1939 | for (i = 0; i < swap_header->info.nr_badpages; i++) | ||
1940 | swab32s(&swap_header->info.badpages[i]); | ||
1941 | } | ||
1942 | /* Check the swap header's sub-version */ | ||
1943 | if (swap_header->info.version != 1) { | ||
1944 | printk(KERN_WARNING | ||
1945 | "Unable to handle swap header version %d\n", | ||
1946 | swap_header->info.version); | ||
1947 | goto bad_swap; | ||
1948 | } | ||
1949 | |||
1950 | p->lowest_bit = 1; | ||
1951 | p->cluster_next = 1; | ||
1952 | p->cluster_nr = 0; | ||
1953 | |||
1954 | /* | ||
1955 | * Find out how many pages are allowed for a single swap | ||
1956 | * device. There are two limiting factors: 1) the number of | ||
1957 | * bits for the swap offset in the swp_entry_t type and | ||
1958 | * 2) the number of bits in the a swap pte as defined by | ||
1959 | * the different architectures. In order to find the | ||
1960 | * largest possible bit mask a swap entry with swap type 0 | ||
1961 | * and swap offset ~0UL is created, encoded to a swap pte, | ||
1962 | * decoded to a swp_entry_t again and finally the swap | ||
1963 | * offset is extracted. This will mask all the bits from | ||
1964 | * the initial ~0UL mask that can't be encoded in either | ||
1965 | * the swp_entry_t or the architecture definition of a | ||
1966 | * swap pte. | ||
1967 | */ | ||
1968 | maxpages = swp_offset(pte_to_swp_entry( | ||
1969 | swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; | ||
1970 | if (maxpages > swap_header->info.last_page) { | ||
1971 | maxpages = swap_header->info.last_page + 1; | ||
1972 | /* p->max is an unsigned int: don't overflow it */ | ||
1973 | if ((unsigned int)maxpages == 0) | ||
1974 | maxpages = UINT_MAX; | ||
1975 | } | ||
1976 | p->highest_bit = maxpages - 1; | ||
1977 | |||
1978 | if (!maxpages) | ||
1979 | goto bad_swap; | ||
1980 | swapfilepages = i_size_read(inode) >> PAGE_SHIFT; | ||
1981 | if (swapfilepages && maxpages > swapfilepages) { | ||
1982 | printk(KERN_WARNING | ||
1983 | "Swap area shorter than signature indicates\n"); | ||
1984 | goto bad_swap; | ||
1985 | } | ||
1986 | if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode)) | ||
1987 | goto bad_swap; | ||
1988 | if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) | ||
1989 | goto bad_swap; | ||
1990 | |||
1991 | return maxpages; | ||
1992 | |||
1993 | bad_swap: | ||
1994 | return 0; | ||
1995 | } | ||
1996 | |||
1921 | SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | 1997 | SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) |
1922 | { | 1998 | { |
1923 | struct swap_info_struct *p; | 1999 | struct swap_info_struct *p; |
@@ -1931,7 +2007,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1931 | int nr_extents = 0; | 2007 | int nr_extents = 0; |
1932 | sector_t span; | 2008 | sector_t span; |
1933 | unsigned long maxpages; | 2009 | unsigned long maxpages; |
1934 | unsigned long swapfilepages; | ||
1935 | unsigned char *swap_map = NULL; | 2010 | unsigned char *swap_map = NULL; |
1936 | struct page *page = NULL; | 2011 | struct page *page = NULL; |
1937 | struct inode *inode = NULL; | 2012 | struct inode *inode = NULL; |
@@ -1989,71 +2064,12 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1989 | } | 2064 | } |
1990 | swap_header = kmap(page); | 2065 | swap_header = kmap(page); |
1991 | 2066 | ||
1992 | if (memcmp("SWAPSPACE2", swap_header->magic.magic, 10)) { | 2067 | maxpages = read_swap_header(p, swap_header, inode); |
1993 | printk(KERN_ERR "Unable to find swap-space signature\n"); | 2068 | if (unlikely(!maxpages)) { |
1994 | error = -EINVAL; | 2069 | error = -EINVAL; |
1995 | goto bad_swap; | 2070 | goto bad_swap; |
1996 | } | 2071 | } |
1997 | 2072 | ||
1998 | /* swap partition endianess hack... */ | ||
1999 | if (swab32(swap_header->info.version) == 1) { | ||
2000 | swab32s(&swap_header->info.version); | ||
2001 | swab32s(&swap_header->info.last_page); | ||
2002 | swab32s(&swap_header->info.nr_badpages); | ||
2003 | for (i = 0; i < swap_header->info.nr_badpages; i++) | ||
2004 | swab32s(&swap_header->info.badpages[i]); | ||
2005 | } | ||
2006 | /* Check the swap header's sub-version */ | ||
2007 | if (swap_header->info.version != 1) { | ||
2008 | printk(KERN_WARNING | ||
2009 | "Unable to handle swap header version %d\n", | ||
2010 | swap_header->info.version); | ||
2011 | error = -EINVAL; | ||
2012 | goto bad_swap; | ||
2013 | } | ||
2014 | |||
2015 | p->lowest_bit = 1; | ||
2016 | p->cluster_next = 1; | ||
2017 | p->cluster_nr = 0; | ||
2018 | |||
2019 | /* | ||
2020 | * Find out how many pages are allowed for a single swap | ||
2021 | * device. There are two limiting factors: 1) the number of | ||
2022 | * bits for the swap offset in the swp_entry_t type and | ||
2023 | * 2) the number of bits in the a swap pte as defined by | ||
2024 | * the different architectures. In order to find the | ||
2025 | * largest possible bit mask a swap entry with swap type 0 | ||
2026 | * and swap offset ~0UL is created, encoded to a swap pte, | ||
2027 | * decoded to a swp_entry_t again and finally the swap | ||
2028 | * offset is extracted. This will mask all the bits from | ||
2029 | * the initial ~0UL mask that can't be encoded in either | ||
2030 | * the swp_entry_t or the architecture definition of a | ||
2031 | * swap pte. | ||
2032 | */ | ||
2033 | maxpages = swp_offset(pte_to_swp_entry( | ||
2034 | swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; | ||
2035 | if (maxpages > swap_header->info.last_page) { | ||
2036 | maxpages = swap_header->info.last_page + 1; | ||
2037 | /* p->max is an unsigned int: don't overflow it */ | ||
2038 | if ((unsigned int)maxpages == 0) | ||
2039 | maxpages = UINT_MAX; | ||
2040 | } | ||
2041 | p->highest_bit = maxpages - 1; | ||
2042 | |||
2043 | error = -EINVAL; | ||
2044 | if (!maxpages) | ||
2045 | goto bad_swap; | ||
2046 | swapfilepages = i_size_read(inode) >> PAGE_SHIFT; | ||
2047 | if (swapfilepages && maxpages > swapfilepages) { | ||
2048 | printk(KERN_WARNING | ||
2049 | "Swap area shorter than signature indicates\n"); | ||
2050 | goto bad_swap; | ||
2051 | } | ||
2052 | if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode)) | ||
2053 | goto bad_swap; | ||
2054 | if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) | ||
2055 | goto bad_swap; | ||
2056 | |||
2057 | /* OK, set up the swap map and apply the bad block list */ | 2073 | /* OK, set up the swap map and apply the bad block list */ |
2058 | swap_map = vzalloc(maxpages); | 2074 | swap_map = vzalloc(maxpages); |
2059 | if (!swap_map) { | 2075 | if (!swap_map) { |