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 <andersen@codepoet.org>. I ripped out Native Language
34 * Support, made some stuff smaller, and fitted for life in busybox.
43 #include <sys/ioctl.h> /* for _IO */
44 #include <sys/utsname.h>
45 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
46 /* we also get PAGE_SIZE via getpagesize() */
51 enum { BLKGETSIZE = 0x1260 };
53 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
54 #define BLKGETSIZE _IO(0x12,96)
57 static char *device_name = NULL;
59 static long PAGES = 0;
61 static int badpages = 0;
62 #if ENABLE_FEATURE_MKSWAP_V0
63 static int version = -1;
64 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
67 /* and make sure that we optimize away anything which would deal with checking
68 * the kernel revision as we have v1 support only anyway.
70 #define MAKE_VERSION(p,q,r) 1
71 #define get_kernel_revision() 1
75 * The definition of the union swap_header uses the constant PAGE_SIZE.
76 * Unfortunately, on some architectures this depends on the hardware model,
77 * and can only be found at run time -- we use getpagesize().
81 static unsigned int *signature_page;
83 static struct swap_header_v1 {
84 char bootbits[1024]; /* Space for disklabel etc. */
85 unsigned int swap_version;
86 unsigned int last_page;
87 unsigned int nr_badpages;
88 unsigned int padding[125];
89 unsigned int badpages[1];
92 static inline void init_signature_page(void)
94 pagesize = getpagesize();
97 if (pagesize != PAGE_SIZE)
98 bb_error_msg("Assuming pages of size %d", pagesize);
100 signature_page = (unsigned int *) xmalloc(pagesize);
101 memset(signature_page, 0, pagesize);
102 p = (struct swap_header_v1 *) signature_page;
105 static inline void write_signature(char *sig)
107 char *sp = (char *) signature_page;
109 strncpy(sp + pagesize - 10, sig, 10);
112 #define V0_MAX_PAGES (8 * (pagesize - 10))
113 /* Before 2.2.0pre9 */
114 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
116 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
118 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
119 #define SWP_OFFSET(entry) ((entry) >> 8)
120 on the various architectures. Below the result - yuk.
122 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
123 i386 2^12 o<<8 e>>8 1<<24 1<<19
124 mips 2^12 o<<15 e>>15 1<<17 1<<19
125 alpha 2^13 o<<40 e>>40 1<<24 1<<18
126 m68k 2^12 o<<12 e>>12 1<<20 1<<19
127 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
128 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
129 ppc 2^12 o<<8 e>>8 1<<24 1<<19
130 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
131 armv 2^12 o<<9 e>>9 1<<23 1<<19
133 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
135 The bad part is that we need to know this since the kernel will
136 refuse a swap space if it is too large.
138 /* patch from jj - why does this differ from the above? */
139 #if defined(__alpha__)
140 #define V1_MAX_PAGES ((1 << 24) - 1)
141 #elif defined(__mips__)
142 #define V1_MAX_PAGES ((1 << 17) - 1)
143 #elif defined(__sparc_v9__)
144 #define V1_MAX_PAGES ((3 << 29) - 1)
145 #elif defined(__sparc__)
146 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
148 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
150 /* man page now says:
151 The maximum useful size of a swap area now depends on the architecture.
152 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
153 128GB on alpha and 3TB on sparc64.
156 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
158 static inline void bit_set(unsigned int *addr, unsigned int nr)
162 addr += nr / (8 * sizeof(int));
165 m = 1 << (nr & (8 * sizeof(int) - 1));
170 static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
174 addr += nr / (8 * sizeof(int));
177 m = 1 << (nr & (8 * sizeof(int) - 1));
183 static void page_ok(int page)
185 if (ENABLE_FEATURE_MKSWAP_V0) {
186 bit_set(signature_page, page);
190 static void check_blocks(void)
192 unsigned int current_page;
196 buffer = xmalloc(pagesize);
198 while (current_page < PAGES) {
199 if (!check && version == 0) {
200 page_ok(current_page++);
203 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
204 current_page * pagesize)
205 bb_error_msg_and_die("seek failed in check_blocks");
206 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
209 bit_test_and_clear(signature_page, current_page);
211 if (badpages == MAX_BADPAGES)
212 bb_error_msg_and_die("too many bad pages");
213 p->badpages[badpages] = current_page;
218 page_ok(current_page++);
220 if (ENABLE_FEATURE_CLEAN_UP)
223 printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
226 static long valid_offset(int fd, int offset)
230 if (lseek(fd, offset, 0) < 0)
232 if (read(fd, &ch, 1) < 1)
237 static int find_size(int fd)
239 unsigned int high, low;
242 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
244 while (low < high - 1) {
245 const int mid = (low + high) / 2;
247 if (valid_offset(fd, mid))
255 /* return size in pages, to avoid integer overflow */
256 static inline long get_size(const char *file)
261 if ((fd = open(file, O_RDONLY)) < 0) /* TODO: bb_xopen3 */
262 bb_perror_msg_and_die("%s", file);
263 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
264 size /= pagesize / 512;
266 size = find_size(fd) / pagesize;
272 int mkswap_main(int argc, char **argv)
283 init_signature_page(); /* get pagesize */
285 bb_opt_complementally = "?"; /* call bb_show_usage internally */
286 sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
293 #if ENABLE_FEATURE_MKSWAP_V0
295 version = bb_xgetlarg(tmp, 10, 0, 1);
297 if (get_kernel_revision() < MAKE_VERSION(2, 1, 117))
307 goodpages = pagesize / 1024; /* cache division */
310 PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
311 argc = 0; /* ignore any surplus args.. */
313 device_name = argv[0];
314 sz = get_size(device_name);
320 bb_error_msg_and_die("error: Nowhere to set up swap on?");
327 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
330 maxpages = V0_MAX_PAGES;
331 else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1))
332 maxpages = V1_MAX_PAGES;
334 maxpages = V1_OLD_MAX_PAGES;
335 if (maxpages > V1_MAX_PAGES)
336 maxpages = V1_MAX_PAGES;
339 if (PAGES > maxpages) {
341 bb_error_msg("warning: truncating swap area to %ldkB",
345 DEV = open(device_name, O_RDWR);
346 if (DEV < 0 || fstat(DEV, &statbuf) < 0)
347 bb_perror_msg_and_die("%s", device_name);
348 if (!S_ISBLK(statbuf.st_mode))
350 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
351 bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
354 if (!force && version == 0) {
355 /* Don't overwrite partition table unless forced */
356 unsigned char *buffer = (unsigned char *) signature_page;
357 unsigned short *q, sum;
359 if (read(DEV, buffer, 512) != 512)
360 bb_error_msg_and_die("fatal: first page unreadable");
361 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
362 q = (unsigned short *) (buffer + 510);
363 for (sum = 0; q >= (unsigned short *) buffer;)
366 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
367 "This probably means creating v0 swap would destroy your partition table\n"
368 "No swap created. If you really want to create swap v0 on that device, use\n"
369 "the -f option to force it.", device_name);
376 if (version == 0 || check)
378 if (version == 0 && !bit_test_and_clear(signature_page, 0))
379 bb_error_msg_and_die("fatal: first page unreadable");
381 p->swap_version = version;
382 p->last_page = PAGES - 1;
383 p->nr_badpages = badpages;
386 goodpages = PAGES - badpages - 1;
388 bb_error_msg_and_die("Unable to set up swap-space: unreadable");
389 printf("Setting up swapspace version %d, size = %ld bytes\n",
390 version, (long) (goodpages * pagesize));
391 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
393 sz = ((version == 0) ? 0 : 1024); /* offset */
394 if (lseek(DEV, sz, SEEK_SET) != sz)
395 bb_error_msg_and_die("unable to rewind swap-device");
396 goodpages = pagesize - sz; /* cache substraction */
397 if (write(DEV, (char *) signature_page + sz, goodpages)
399 bb_error_msg_and_die("unable to write signature page");
402 * A subsequent swapon() will fail if the signature
403 * is not actually on disk. (This is a kernel bug.)
406 bb_error_msg_and_die("fsync failed");
407 if (ENABLE_FEATURE_CLEAN_UP) {
409 free(signature_page);