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"
51 "Prepare a disk partition to be used as a swap partition.\n\n"
52 "\t-c\tCheck for read-ability.\n"
53 "\t-v0\tMake version 0 swap [max 128 Megs].\n"
54 "\t-v1\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
55 "\tblock-count\tNumber of block to use (default is entire partition).\n";
60 #define BLKGETSIZE 0x1260
62 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
63 #define BLKGETSIZE _IO(0x12,96)
66 static char * program_name = "mkswap";
67 static char * device_name = NULL;
69 static long PAGES = 0;
71 static int badpages = 0;
72 static int version = -1;
74 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
77 linux_version_code(void) {
78 struct utsname my_utsname;
81 if (uname(&my_utsname) == 0) {
82 p = atoi(strtok(my_utsname.release, "."));
83 q = atoi(strtok(NULL, "."));
84 r = atoi(strtok(NULL, "."));
85 return MAKE_VERSION(p,q,r);
91 * The definition of the union swap_header uses the constant PAGE_SIZE.
92 * Unfortunately, on some architectures this depends on the hardware model,
93 * and can only be found at run time -- we use getpagesize().
97 static int *signature_page;
99 struct swap_header_v1 {
100 char bootbits[1024]; /* Space for disklabel etc. */
101 unsigned int version;
102 unsigned int last_page;
103 unsigned int nr_badpages;
104 unsigned int padding[125];
105 unsigned int badpages[1];
109 init_signature_page() {
110 pagesize = getpagesize();
113 if (pagesize != PAGE_SIZE)
114 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
116 signature_page = (int *) malloc(pagesize);
117 memset(signature_page,0,pagesize);
118 p = (struct swap_header_v1 *) signature_page;
122 write_signature(char *sig) {
123 char *sp = (char *) signature_page;
125 strncpy(sp+pagesize-10, sig, 10);
128 #define V0_MAX_PAGES (8 * (pagesize - 10))
129 /* Before 2.2.0pre9 */
130 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
132 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
134 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
135 #define SWP_OFFSET(entry) ((entry) >> 8)
136 on the various architectures. Below the result - yuk.
138 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
139 i386 2^12 o<<8 e>>8 1<<24 1<<19
140 mips 2^12 o<<15 e>>15 1<<17 1<<19
141 alpha 2^13 o<<40 e>>40 1<<24 1<<18
142 m68k 2^12 o<<12 e>>12 1<<20 1<<19
143 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
144 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
145 ppc 2^12 o<<8 e>>8 1<<24 1<<19
146 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
147 armv 2^12 o<<9 e>>9 1<<23 1<<19
149 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
151 The bad part is that we need to know this since the kernel will
152 refuse a swap space if it is too large.
154 /* patch from jj - why does this differ from the above? */
155 #if defined(__alpha__)
156 #define V1_MAX_PAGES ((1 << 24) - 1)
157 #elif defined(__mips__)
158 #define V1_MAX_PAGES ((1 << 17) - 1)
159 #elif defined(__sparc_v9__)
160 #define V1_MAX_PAGES ((3 << 29) - 1)
161 #elif defined(__sparc__)
162 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
164 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
166 /* man page now says:
167 The maximum useful size of a swap area now depends on the architecture.
168 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
169 128GB on alpha and 3TB on sparc64.
172 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
174 static void bit_set (unsigned int *addr, unsigned int nr)
178 addr += nr / (8 * sizeof(int));
180 m = 1 << (nr & (8 * sizeof(int) - 1));
184 static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
188 addr += nr / (8 * sizeof(int));
190 m = 1 << (nr & (8 * sizeof(int) - 1));
197 die(const char *str) {
198 fprintf(stderr, "%s: %s\n", program_name, str);
205 bit_set(signature_page, page);
211 bit_test_and_clear(signature_page, page);
213 if (badpages == MAX_BADPAGES)
214 die("too many bad pages");
215 p->badpages[badpages] = page;
222 unsigned int current_page;
226 buffer = malloc(pagesize);
228 die("Out of memory");
230 while (current_page < PAGES) {
232 page_ok(current_page++);
235 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
236 current_page*pagesize)
237 die("seek failed in check_blocks");
238 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
239 page_bad(current_page++);
242 page_ok(current_page++);
245 printf("one bad page\n");
246 else if (badpages > 1)
247 printf("%d bad pages\n", badpages);
250 static long valid_offset (int fd, int offset)
254 if (lseek (fd, offset, 0) < 0)
256 if (read (fd, &ch, 1) < 1)
264 unsigned int high, low;
267 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2)
269 while (low < high - 1)
271 const int mid = (low + high) / 2;
273 if (valid_offset (fd, mid))
281 /* return size in pages, to avoid integer overflow */
283 get_size(const char *file)
288 fd = open(file, O_RDONLY);
293 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
294 int sectors_per_page = pagesize/512;
295 size /= sectors_per_page;
297 size = find_size(fd) / pagesize;
303 int mkswap_main(int argc, char ** argv)
314 program_name = *argv;
316 init_signature_page(); /* get pagesize */
320 if (argv[0][0] != '-') {
322 int blocks_per_page = pagesize/1024;
323 PAGES = strtol(argv[0],&tmp,0)/blocks_per_page;
325 usage( mkswap_usage);
327 device_name = argv[0];
329 switch (argv[0][1]) {
337 version=atoi(argv[0]+2);
340 usage( mkswap_usage);
346 "%s: error: Nowhere to set up swap on?\n",
348 usage( mkswap_usage);
350 sz = get_size(device_name);
353 } else if (PAGES > sz && !force) {
356 "size %ld is larger than device size %d\n",
358 PAGES*(pagesize/1024), sz*(pagesize/1024));
363 if (PAGES <= V0_MAX_PAGES)
365 else if (linux_version_code() < MAKE_VERSION(2,1,117))
367 else if (pagesize < 2048)
372 if (version != 0 && version != 1) {
373 fprintf(stderr, "%s: error: unknown version %d\n",
374 program_name, version);
375 usage( mkswap_usage);
379 "%s: error: swap area needs to be at least %ldkB\n",
380 program_name, (long)(10 * pagesize / 1024));
381 usage( mkswap_usage);
384 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
387 maxpages = V0_MAX_PAGES;
388 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
389 maxpages = V1_MAX_PAGES;
391 maxpages = V1_OLD_MAX_PAGES;
392 if (maxpages > V1_MAX_PAGES)
393 maxpages = V1_MAX_PAGES;
396 if (PAGES > maxpages) {
398 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
399 program_name, PAGES * pagesize / 1024);
402 DEV = open(device_name,O_RDWR);
403 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
407 if (!S_ISBLK(statbuf.st_mode))
409 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
410 die("Will not try to make swapdevice on '%s'");
413 if (!force && version == 0) {
414 /* Don't overwrite partition table unless forced */
415 unsigned char *buffer = (unsigned char *)signature_page;
416 unsigned short *q, sum;
418 if (read(DEV, buffer, 512) != 512)
419 die("fatal: first page unreadable");
420 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
421 q = (unsigned short *)(buffer + 510);
422 for (sum = 0; q >= (unsigned short *) buffer;)
426 %s: Device '%s' contains a valid Sun disklabel.\n\
427 This probably means creating v0 swap would destroy your partition table\n\
428 No swap created. If you really want to create swap v0 on that device, use\n\
429 the -f option to force it.\n",
430 program_name, device_name);
437 if (version == 0 || check)
439 if (version == 0 && !bit_test_and_clear(signature_page,0))
440 die("fatal: first page unreadable");
442 p->version = version;
443 p->last_page = PAGES-1;
444 p->nr_badpages = badpages;
447 goodpages = PAGES - badpages - 1;
449 die("Unable to set up swap-space: unreadable");
450 printf("Setting up swapspace version %d, size = %ld bytes\n",
451 version, (long)(goodpages*pagesize));
452 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
454 offset = ((version == 0) ? 0 : 1024);
455 if (lseek(DEV, offset, SEEK_SET) != offset)
456 die("unable to rewind swap-device");
457 if (write(DEV,(char*)signature_page+offset, pagesize-offset)
459 die("unable to write signature page");
462 * A subsequent swapon() will fail if the signature
463 * is not actually on disk. (This is a kernel bug.)