1 /* vi: set sw=4 ts=4: */
3 * mkswap.c - set up a linux swap device
5 * (C) 1991 Linus Torvalds. This file may be redistributed as per
10 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
12 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
14 * -c for readability checking. (Use it unless you are SURE!)
15 * -vN for swap areas version N. (Only N=0,1 known today.)
16 * -f for forcing swap creation even if it would smash partition table.
18 * The device may be a block device or an image of one, but this isn't
19 * enforced (but it's not much fun on a character device :-).
21 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
22 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
24 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
26 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
27 * V1_MAX_PAGES fixes, jj, 990325.
29 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
30 * - added Native Language Support
32 * from util-linux -- adapted for busybox by
33 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
34 * Support, made some stuff smaller, and fitted for life in busybox.
44 #include <sys/ioctl.h> /* for _IO */
45 #include <sys/utsname.h>
47 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
48 /* we also get PAGE_SIZE via getpagesize() */
51 static const char mkswap_usage[] =
52 "mkswap [-c] [-v0|-v1] device [block-count]\n"
53 #ifndef BB_FEATURE_TRIVIAL_HELP
54 "\nPrepare a disk partition to be used as a swap partition.\n\n"
55 "Options:\n" "\t-c\t\tCheck for read-ability.\n"
56 "\t-v0\t\tMake version 0 swap [max 128 Megs].\n"
57 "\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
59 "\tblock-count\tNumber of block to use (default is entire partition).\n"
66 #define BLKGETSIZE 0x1260
68 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
69 #define BLKGETSIZE _IO(0x12,96)
72 static char *device_name = NULL;
74 static long PAGES = 0;
76 static int badpages = 0;
77 static int version = -1;
79 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
81 static int linux_version_code(void)
83 struct utsname my_utsname;
86 if (uname(&my_utsname) == 0) {
87 p = atoi(strtok(my_utsname.release, "."));
88 q = atoi(strtok(NULL, "."));
89 r = atoi(strtok(NULL, "."));
90 return MAKE_VERSION(p, q, r);
96 * The definition of the union swap_header uses the constant PAGE_SIZE.
97 * Unfortunately, on some architectures this depends on the hardware model,
98 * and can only be found at run time -- we use getpagesize().
102 static int *signature_page;
104 struct swap_header_v1 {
105 char bootbits[1024]; /* Space for disklabel etc. */
106 unsigned int version;
107 unsigned int last_page;
108 unsigned int nr_badpages;
109 unsigned int padding[125];
110 unsigned int badpages[1];
113 static void init_signature_page()
115 pagesize = getpagesize();
118 if (pagesize != PAGE_SIZE)
119 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
121 signature_page = (int *) xmalloc(pagesize);
122 memset(signature_page, 0, pagesize);
123 p = (struct swap_header_v1 *) signature_page;
126 static void write_signature(char *sig)
128 char *sp = (char *) signature_page;
130 strncpy(sp + pagesize - 10, sig, 10);
133 #define V0_MAX_PAGES (8 * (pagesize - 10))
134 /* Before 2.2.0pre9 */
135 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
137 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
139 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
140 #define SWP_OFFSET(entry) ((entry) >> 8)
141 on the various architectures. Below the result - yuk.
143 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
144 i386 2^12 o<<8 e>>8 1<<24 1<<19
145 mips 2^12 o<<15 e>>15 1<<17 1<<19
146 alpha 2^13 o<<40 e>>40 1<<24 1<<18
147 m68k 2^12 o<<12 e>>12 1<<20 1<<19
148 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
149 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
150 ppc 2^12 o<<8 e>>8 1<<24 1<<19
151 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
152 armv 2^12 o<<9 e>>9 1<<23 1<<19
154 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
156 The bad part is that we need to know this since the kernel will
157 refuse a swap space if it is too large.
159 /* patch from jj - why does this differ from the above? */
160 #if defined(__alpha__)
161 #define V1_MAX_PAGES ((1 << 24) - 1)
162 #elif defined(__mips__)
163 #define V1_MAX_PAGES ((1 << 17) - 1)
164 #elif defined(__sparc_v9__)
165 #define V1_MAX_PAGES ((3 << 29) - 1)
166 #elif defined(__sparc__)
167 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
169 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
171 /* man page now says:
172 The maximum useful size of a swap area now depends on the architecture.
173 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
174 128GB on alpha and 3TB on sparc64.
177 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
179 static void bit_set(unsigned int *addr, unsigned int nr)
183 addr += nr / (8 * sizeof(int));
186 m = 1 << (nr & (8 * sizeof(int) - 1));
191 static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
195 addr += nr / (8 * sizeof(int));
198 m = 1 << (nr & (8 * sizeof(int) - 1));
205 void die(const char *str)
207 fprintf(stderr, "%s: %s\n", applet_name, str);
211 void page_ok(int page)
214 bit_set(signature_page, page);
217 void page_bad(int page)
220 bit_test_and_clear(signature_page, page);
222 if (badpages == MAX_BADPAGES)
223 die("too many bad pages");
224 p->badpages[badpages] = page;
229 void check_blocks(void)
231 unsigned int current_page;
235 buffer = xmalloc(pagesize);
237 while (current_page < PAGES) {
239 page_ok(current_page++);
242 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
243 current_page * pagesize)
244 die("seek failed in check_blocks");
245 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
246 page_bad(current_page++);
249 page_ok(current_page++);
252 printf("one bad page\n");
253 else if (badpages > 1)
254 printf("%d bad pages\n", badpages);
257 static long valid_offset(int fd, int offset)
261 if (lseek(fd, offset, 0) < 0)
263 if (read(fd, &ch, 1) < 1)
268 static int find_size(int fd)
270 unsigned int high, low;
273 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
275 while (low < high - 1) {
276 const int mid = (low + high) / 2;
278 if (valid_offset(fd, mid))
286 /* return size in pages, to avoid integer overflow */
287 static long get_size(const char *file)
292 fd = open(file, O_RDONLY);
297 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
298 int sectors_per_page = pagesize / 512;
300 size /= sectors_per_page;
302 size = find_size(fd) / pagesize;
308 int mkswap_main(int argc, char **argv)
318 init_signature_page(); /* get pagesize */
322 if (argv[0][0] != '-') {
324 int blocks_per_page = pagesize / 1024;
326 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
330 device_name = argv[0];
332 switch (argv[0][1]) {
340 version = atoi(argv[0] + 2);
349 "%s: error: Nowhere to set up swap on?\n", applet_name);
352 sz = get_size(device_name);
355 } else if (PAGES > sz && !force) {
358 "size %ld is larger than device size %d\n",
360 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
365 if (PAGES <= V0_MAX_PAGES)
367 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
369 else if (pagesize < 2048)
374 if (version != 0 && version != 1) {
375 fprintf(stderr, "%s: error: unknown version %d\n",
376 applet_name, version);
381 "%s: error: swap area needs to be at least %ldkB\n",
382 applet_name, (long) (10 * pagesize / 1024));
386 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
389 maxpages = V0_MAX_PAGES;
390 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
391 maxpages = V1_MAX_PAGES;
393 maxpages = V1_OLD_MAX_PAGES;
394 if (maxpages > V1_MAX_PAGES)
395 maxpages = V1_MAX_PAGES;
398 if (PAGES > maxpages) {
400 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
401 applet_name, PAGES * pagesize / 1024);
404 DEV = open(device_name, O_RDWR);
405 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
409 if (!S_ISBLK(statbuf.st_mode))
411 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
412 die("Will not try to make swapdevice on '%s'");
415 if (!force && version == 0) {
416 /* Don't overwrite partition table unless forced */
417 unsigned char *buffer = (unsigned char *) signature_page;
418 unsigned short *q, sum;
420 if (read(DEV, buffer, 512) != 512)
421 die("fatal: first page unreadable");
422 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
423 q = (unsigned short *) (buffer + 510);
424 for (sum = 0; q >= (unsigned short *) buffer;)
428 %s: Device '%s' contains a valid Sun disklabel.\n\
429 This probably means creating v0 swap would destroy your partition table\n\
430 No swap created. If you really want to create swap v0 on that device, use\n\
431 the -f option to force it.\n", applet_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)
459 != 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.)