This is a new enhanced version of the sys_swapon bugfix.
I've checked C standard and I cannot find any word about pointer + integer
being promoted first to pointer + long, so I'm pretty sure it is not a
compiler bug to:
static int i = 0, *p;
if (&p[i - 1] >= p) printf("C does not promote in pointer arithmetic\n");
on 64bit archs.
The following patch solves that problem (swapon not allowing new format
swaps with no bad pages) by simply subtracting -1L, which should work just
fine. In addition to that, it makes the 2GB limit be checked on 32bit archs
only, plus it adds a new check which actually tests SWP_* macros on what's
the largest possible SWP_OFFSET in page tables (and the swap size in pages
cannot obviously go beyond that). Without this, a couple of architectures
are broken in the other direction in that they allow swaps larger than they
can hold in page tables, particularly on mips and sparc32.
With this patch, one should be able to use
up to 12TB swaps on sparc64 (it could be 64PB, but the real limit is only 12TB, as
swapfile.c does a vmalloc of size nr_swap_pages * 2
and sparc64 limits VMALLOC area to 3GB at the moment)
up to 128GB swaps on alpha
up to 2GB swaps on arm
up to 2GB swaps on i386
up to 2GB swaps on m68k
up to 2GB swaps on ppc
up to 1GB swaps on sparc (resp. up to 2GB swaps if CONFIG_SUN4)
up to 512MB swaps on mips
Linus, can you please apply this to your tree?
--- linux/mm/swapfile.c.jj Wed Sep 23 15:13:34 1998
+++ linux/mm/swapfile.c Tue Nov 3 09:36:59 1998
@@ -626,8 +626,12 @@
p->highest_bit = swap_header->info.last_page - 1;
p->max = swap_header->info.last_page;
- if (p->max >= 0x7fffffffL/PAGE_SIZE ||
- (void *) &swap_header->info.badpages[swap_header->info.nr_badpages-1] >= (void *) swap_header->magic.magic) {
+ /* Make sure the number of swap pages fits into SWP_OFFSET field
+ in page tables. This depends on the arch macros and thus poses
+ yet another constraint on swap size. */
+ if ((BITS_PER_LONG == 32 && p->max >= 0x7fffffffL/PAGE_SIZE) ||
+ (p->max > SWP_OFFSET(SWP_ENTRY(0,((unsigned long)-1)))) ||
+ (void *) &swap_header->info.badpages[swap_header->info.nr_badpages-1L] >= (void *) swap_header->magic.magic) {
error = -EINVAL;
goto bad_swap;
}
Cheers,
Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
Ultralinux - first 64bit OS to take full power of the UltraSparc
Linux version 2.1.126 on a sparc64 machine (498.80 BogoMips).
___________________________________________________________________
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/