2 * mkswap.c - set up a linux swap device
4 * (C) 1991 Linus Torvalds. This file may be redistributed as per
9 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
11 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
13 * -c for readability checking. (Use it unless you are SURE!)
14 * -vN for swap areas version N. (Only N=0,1 known today.)
15 * -f for forcing swap creation even if it would smash partition table.
17 * The device may be a block device or an image of one, but this isn't
18 * enforced (but it's not much fun on a character device :-).
20 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
21 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
23 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
25 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
26 * V1_MAX_PAGES fixes, jj, 990325.
28 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
29 * - added Native Language Support
31 * from util-linux -- adapted for busybox by
32 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
33 * Support, made some stuff smaller, and fitted for life in busybox.
43 #include <sys/ioctl.h> /* for _IO */
44 #include <sys/utsname.h>
46 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
47 /* we also get PAGE_SIZE via getpagesize() */
50 static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n\n"
51 "Prepare a disk partition to be used as a swap partition.\n\n"
53 "\t-c\t\tCheck for read-ability.\n"
54 "\t-v0\t\tMake version 0 swap [max 128 Megs].\n"
55 "\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
56 "\tblock-count\tNumber of block to use (default is entire partition).\n";
61 #define BLKGETSIZE 0x1260
63 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
64 #define BLKGETSIZE _IO(0x12,96)
67 static char * program_name = "mkswap";
68 static char * device_name = NULL;
70 static long PAGES = 0;
72 static int badpages = 0;
73 static int version = -1;
75 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
78 linux_version_code(void) {
79 struct utsname my_utsname;
82 if (uname(&my_utsname) == 0) {
83 p = atoi(strtok(my_utsname.release, "."));
84 q = atoi(strtok(NULL, "."));
85 r = atoi(strtok(NULL, "."));
86 return MAKE_VERSION(p,q,r);
92 * The definition of the union swap_header uses the constant PAGE_SIZE.
93 * Unfortunately, on some architectures this depends on the hardware model,
94 * and can only be found at run time -- we use getpagesize().
98 static int *signature_page;
100 struct swap_header_v1 {
101 char bootbits[1024]; /* Space for disklabel etc. */
102 unsigned int version;
103 unsigned int last_page;
104 unsigned int nr_badpages;
105 unsigned int padding[125];
106 unsigned int badpages[1];
110 init_signature_page() {
111 pagesize = getpagesize();
114 if (pagesize != PAGE_SIZE)
115 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
117 signature_page = (int *) malloc(pagesize);
118 memset(signature_page,0,pagesize);
119 p = (struct swap_header_v1 *) signature_page;
123 write_signature(char *sig) {
124 char *sp = (char *) signature_page;
126 strncpy(sp+pagesize-10, sig, 10);
129 #define V0_MAX_PAGES (8 * (pagesize - 10))
130 /* Before 2.2.0pre9 */
131 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
133 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
135 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
136 #define SWP_OFFSET(entry) ((entry) >> 8)
137 on the various architectures. Below the result - yuk.
139 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
140 i386 2^12 o<<8 e>>8 1<<24 1<<19
141 mips 2^12 o<<15 e>>15 1<<17 1<<19
142 alpha 2^13 o<<40 e>>40 1<<24 1<<18
143 m68k 2^12 o<<12 e>>12 1<<20 1<<19
144 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
145 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
146 ppc 2^12 o<<8 e>>8 1<<24 1<<19
147 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
148 armv 2^12 o<<9 e>>9 1<<23 1<<19
150 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
152 The bad part is that we need to know this since the kernel will
153 refuse a swap space if it is too large.
155 /* patch from jj - why does this differ from the above? */
156 #if defined(__alpha__)
157 #define V1_MAX_PAGES ((1 << 24) - 1)
158 #elif defined(__mips__)
159 #define V1_MAX_PAGES ((1 << 17) - 1)
160 #elif defined(__sparc_v9__)
161 #define V1_MAX_PAGES ((3 << 29) - 1)
162 #elif defined(__sparc__)
163 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
165 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
167 /* man page now says:
168 The maximum useful size of a swap area now depends on the architecture.
169 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
170 128GB on alpha and 3TB on sparc64.
173 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
175 static void bit_set (unsigned int *addr, unsigned int nr)
179 addr += nr / (8 * sizeof(int));
181 m = 1 << (nr & (8 * sizeof(int) - 1));
185 static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
189 addr += nr / (8 * sizeof(int));
191 m = 1 << (nr & (8 * sizeof(int) - 1));
198 die(const char *str) {
199 fprintf(stderr, "%s: %s\n", program_name, str);
206 bit_set(signature_page, page);
212 bit_test_and_clear(signature_page, page);
214 if (badpages == MAX_BADPAGES)
215 die("too many bad pages");
216 p->badpages[badpages] = page;
223 unsigned int current_page;
227 buffer = malloc(pagesize);
229 die("Out of memory");
231 while (current_page < PAGES) {
233 page_ok(current_page++);
236 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
237 current_page*pagesize)
238 die("seek failed in check_blocks");
239 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
240 page_bad(current_page++);
243 page_ok(current_page++);
246 printf("one bad page\n");
247 else if (badpages > 1)
248 printf("%d bad pages\n", badpages);
251 static long valid_offset (int fd, int offset)
255 if (lseek (fd, offset, 0) < 0)
257 if (read (fd, &ch, 1) < 1)
265 unsigned int high, low;
268 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2)
270 while (low < high - 1)
272 const int mid = (low + high) / 2;
274 if (valid_offset (fd, mid))
282 /* return size in pages, to avoid integer overflow */
284 get_size(const char *file)
289 fd = open(file, O_RDONLY);
294 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
295 int sectors_per_page = pagesize/512;
296 size /= sectors_per_page;
298 size = find_size(fd) / pagesize;
304 int mkswap_main(int argc, char ** argv)
315 program_name = *argv;
317 init_signature_page(); /* get pagesize */
321 if (argv[0][0] != '-') {
323 int blocks_per_page = pagesize/1024;
324 PAGES = strtol(argv[0],&tmp,0)/blocks_per_page;
326 usage( mkswap_usage);
328 device_name = argv[0];
330 switch (argv[0][1]) {
338 version=atoi(argv[0]+2);
341 usage( mkswap_usage);
347 "%s: error: Nowhere to set up swap on?\n",
349 usage( mkswap_usage);
351 sz = get_size(device_name);
354 } else if (PAGES > sz && !force) {
357 "size %ld is larger than device size %d\n",
359 PAGES*(pagesize/1024), sz*(pagesize/1024));
364 if (PAGES <= V0_MAX_PAGES)
366 else if (linux_version_code() < MAKE_VERSION(2,1,117))
368 else if (pagesize < 2048)
373 if (version != 0 && version != 1) {
374 fprintf(stderr, "%s: error: unknown version %d\n",
375 program_name, version);
376 usage( mkswap_usage);
380 "%s: error: swap area needs to be at least %ldkB\n",
381 program_name, (long)(10 * pagesize / 1024));
382 usage( mkswap_usage);
385 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
388 maxpages = V0_MAX_PAGES;
389 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
390 maxpages = V1_MAX_PAGES;
392 maxpages = V1_OLD_MAX_PAGES;
393 if (maxpages > V1_MAX_PAGES)
394 maxpages = V1_MAX_PAGES;
397 if (PAGES > maxpages) {
399 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
400 program_name, PAGES * pagesize / 1024);
403 DEV = open(device_name,O_RDWR);
404 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
408 if (!S_ISBLK(statbuf.st_mode))
410 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
411 die("Will not try to make swapdevice on '%s'");
414 if (!force && version == 0) {
415 /* Don't overwrite partition table unless forced */
416 unsigned char *buffer = (unsigned char *)signature_page;
417 unsigned short *q, sum;
419 if (read(DEV, buffer, 512) != 512)
420 die("fatal: first page unreadable");
421 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
422 q = (unsigned short *)(buffer + 510);
423 for (sum = 0; q >= (unsigned short *) buffer;)
427 %s: Device '%s' contains a valid Sun disklabel.\n\
428 This probably means creating v0 swap would destroy your partition table\n\
429 No swap created. If you really want to create swap v0 on that device, use\n\
430 the -f option to force it.\n",
431 program_name, device_name);
438 if (version == 0 || check)
440 if (version == 0 && !bit_test_and_clear(signature_page,0))
441 die("fatal: first page unreadable");
443 p->version = version;
444 p->last_page = PAGES-1;
445 p->nr_badpages = badpages;
448 goodpages = PAGES - badpages - 1;
450 die("Unable to set up swap-space: unreadable");
451 printf("Setting up swapspace version %d, size = %ld bytes\n",
452 version, (long)(goodpages*pagesize));
453 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
455 offset = ((version == 0) ? 0 : 1024);
456 if (lseek(DEV, offset, SEEK_SET) != offset)
457 die("unable to rewind swap-device");
458 if (write(DEV,(char*)signature_page+offset, pagesize-offset)
460 die("unable to write signature page");
463 * A subsequent swapon() will fail if the signature
464 * is not actually on disk. (This is a kernel bug.)