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.
42 #include <sys/ioctl.h> /* for _IO */
43 #include <sys/utsname.h>
44 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
45 /* we also get PAGE_SIZE via getpagesize() */
47 static char *device_name = NULL;
49 static long PAGES = 0;
51 static int badpages = 0;
52 #if ENABLE_FEATURE_MKSWAP_V0
53 static int version = -1;
56 /* and make sure that we optimize away anything which would deal with checking
57 * the kernel revision as we have v1 support only anyway.
60 #define KERNEL_VERSION(p,q,r) 1
61 #define get_linux_version_code() 1
65 * The definition of the union swap_header uses the constant PAGE_SIZE.
66 * Unfortunately, on some architectures this depends on the hardware model,
67 * and can only be found at run time -- we use getpagesize().
71 static unsigned int *signature_page;
73 static struct swap_header_v1 {
74 char bootbits[1024]; /* Space for disklabel etc. */
75 unsigned int swap_version;
76 unsigned int last_page;
77 unsigned int nr_badpages;
78 unsigned int padding[125];
79 unsigned int badpages[1];
82 static inline void init_signature_page(void)
84 pagesize = getpagesize();
87 if (pagesize != PAGE_SIZE)
88 bb_error_msg("Assuming pages of size %d", pagesize);
90 signature_page = (unsigned int *) xmalloc(pagesize);
91 memset(signature_page, 0, pagesize);
92 p = (struct swap_header_v1 *) signature_page;
95 static inline void write_signature(char *sig)
97 char *sp = (char *) signature_page;
99 strncpy(sp + pagesize - 10, sig, 10);
102 #define V0_MAX_PAGES (8 * (pagesize - 10))
103 /* Before 2.2.0pre9 */
104 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
106 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
108 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
109 #define SWP_OFFSET(entry) ((entry) >> 8)
110 on the various architectures. Below the result - yuk.
112 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
113 i386 2^12 o<<8 e>>8 1<<24 1<<19
114 mips 2^12 o<<15 e>>15 1<<17 1<<19
115 alpha 2^13 o<<40 e>>40 1<<24 1<<18
116 m68k 2^12 o<<12 e>>12 1<<20 1<<19
117 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
118 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
119 ppc 2^12 o<<8 e>>8 1<<24 1<<19
120 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
121 armv 2^12 o<<9 e>>9 1<<23 1<<19
123 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
125 The bad part is that we need to know this since the kernel will
126 refuse a swap space if it is too large.
128 /* patch from jj - why does this differ from the above? */
129 #if defined(__alpha__)
130 #define V1_MAX_PAGES ((1 << 24) - 1)
131 #elif defined(__mips__)
132 #define V1_MAX_PAGES ((1 << 17) - 1)
133 #elif defined(__sparc_v9__)
134 #define V1_MAX_PAGES ((3 << 29) - 1)
135 #elif defined(__sparc__)
136 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
138 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
140 /* man page now says:
141 The maximum useful size of a swap area now depends on the architecture.
142 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
143 128GB on alpha and 3TB on sparc64.
146 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
148 static inline void bit_set(unsigned int *addr, unsigned int nr)
152 addr += nr / (8 * sizeof(int));
155 m = 1 << (nr & (8 * sizeof(int) - 1));
160 static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
164 addr += nr / (8 * sizeof(int));
167 m = 1 << (nr & (8 * sizeof(int) - 1));
173 static void page_ok(int page)
175 if (ENABLE_FEATURE_MKSWAP_V0) {
176 bit_set(signature_page, page);
180 static void check_blocks(void)
182 unsigned int current_page;
186 buffer = xmalloc(pagesize);
188 while (current_page < PAGES) {
189 if (!check && version == 0) {
190 page_ok(current_page++);
193 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
194 current_page * pagesize)
195 bb_error_msg_and_die("seek failed in check_blocks");
196 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
199 bit_test_and_clear(signature_page, current_page);
201 if (badpages == MAX_BADPAGES)
202 bb_error_msg_and_die("too many bad pages");
203 p->badpages[badpages] = current_page;
208 page_ok(current_page++);
210 if (ENABLE_FEATURE_CLEAN_UP)
213 printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
216 static long valid_offset(int fd, int offset)
220 if (lseek(fd, offset, 0) < 0)
222 if (read(fd, &ch, 1) < 1)
227 static int find_size(int fd)
229 unsigned int high, low;
232 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
234 while (low < high - 1) {
235 const int mid = (low + high) / 2;
237 if (valid_offset(fd, mid))
245 /* return size in pages, to avoid integer overflow */
246 static inline long get_size(const char *file)
251 fd = bb_xopen3(file, O_RDONLY, 0);
252 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
253 size /= pagesize / 512;
255 size = find_size(fd) / pagesize;
261 int mkswap_main(int argc, char **argv)
272 init_signature_page(); /* get pagesize */
274 bb_opt_complementally = "?"; /* call bb_show_usage internally */
275 sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
282 #if ENABLE_FEATURE_MKSWAP_V0
284 version = bb_xgetlarg(tmp, 10, 0, 1);
286 if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117))
296 goodpages = pagesize / 1024; /* cache division */
299 PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
300 argc = 0; /* ignore any surplus args.. */
302 device_name = argv[0];
303 sz = get_size(device_name);
309 bb_error_msg_and_die("error: Nowhere to set up swap on?");
316 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
319 maxpages = V0_MAX_PAGES;
320 else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1))
321 maxpages = V1_MAX_PAGES;
323 maxpages = V1_OLD_MAX_PAGES;
324 if (maxpages > V1_MAX_PAGES)
325 maxpages = V1_MAX_PAGES;
328 if (PAGES > maxpages) {
330 bb_error_msg("warning: truncating swap area to %ldkB",
334 DEV = bb_xopen3(device_name, O_RDWR, 0);
335 if (fstat(DEV, &statbuf) < 0)
336 bb_perror_msg_and_die("%s", device_name);
337 if (!S_ISBLK(statbuf.st_mode))
339 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
340 bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
343 if (!force && version == 0) {
344 /* Don't overwrite partition table unless forced */
345 unsigned char *buffer = (unsigned char *) signature_page;
346 unsigned short *q, sum;
348 if (read(DEV, buffer, 512) != 512)
349 bb_error_msg_and_die("fatal: first page unreadable");
350 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
351 q = (unsigned short *) (buffer + 510);
352 for (sum = 0; q >= (unsigned short *) buffer;)
355 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
356 "This probably means creating v0 swap would destroy your partition table\n"
357 "No swap created. If you really want to create swap v0 on that device, use\n"
358 "the -f option to force it.", device_name);
365 if (version == 0 || check)
367 if (version == 0 && !bit_test_and_clear(signature_page, 0))
368 bb_error_msg_and_die("fatal: first page unreadable");
370 p->swap_version = version;
371 p->last_page = PAGES - 1;
372 p->nr_badpages = badpages;
375 goodpages = PAGES - badpages - 1;
377 bb_error_msg_and_die("Unable to set up swap-space: unreadable");
378 printf("Setting up swapspace version %d, size = %ld bytes\n",
379 version, (long) (goodpages * pagesize));
380 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
382 sz = ((version == 0) ? 0 : 1024); /* offset */
383 if (lseek(DEV, sz, SEEK_SET) != sz)
384 bb_error_msg_and_die("unable to rewind swap-device");
385 goodpages = pagesize - sz; /* cache substraction */
386 if (write(DEV, (char *) signature_page + sz, goodpages)
388 bb_error_msg_and_die("unable to write signature page");
391 * A subsequent swapon() will fail if the signature
392 * is not actually on disk. (This is a kernel bug.)
395 bb_error_msg_and_die("fsync failed");
396 if (ENABLE_FEATURE_CLEAN_UP) {
398 free(signature_page);