blob: 130d24162cc003b4b753c99df07792433b03066f [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersencc8ed391999-10-05 16:24:54 +00002/*
3 * mkswap.c - set up a linux swap device
4 *
5 * (C) 1991 Linus Torvalds. This file may be redistributed as per
6 * the Linux copyright.
7 */
8
9/*
10 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
11 *
Eric Andersene77ae3a1999-10-19 20:03:34 +000012 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
Eric Andersencc8ed391999-10-05 16:24:54 +000013 *
Eric Andersene77ae3a1999-10-19 20:03:34 +000014 * -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.
Eric Andersencc8ed391999-10-05 16:24:54 +000017 *
Eric Andersene77ae3a1999-10-19 20:03:34 +000018 * The device may be a block device or an image of one, but this isn't
Eric Andersencc8ed391999-10-05 16:24:54 +000019 * enforced (but it's not much fun on a character device :-).
20 *
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.
Eric Andersene77ae3a1999-10-19 20:03:34 +000023 *
24 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
25 *
26 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
27 * V1_MAX_PAGES fixes, jj, 990325.
28 *
29 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
30 * - added Native Language Support
31 *
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.
35 *
Eric Andersencc8ed391999-10-05 16:24:54 +000036 */
37
Eric Andersene77ae3a1999-10-19 20:03:34 +000038#include "internal.h"
Eric Andersencc8ed391999-10-05 16:24:54 +000039#include <stdio.h>
40#include <unistd.h>
41#include <string.h>
42#include <fcntl.h>
43#include <stdlib.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000044#include <sys/ioctl.h> /* for _IO */
Eric Andersene77ae3a1999-10-19 20:03:34 +000045#include <sys/utsname.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000046#include <sys/stat.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000047#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
Eric Andersene77ae3a1999-10-19 20:03:34 +000048 /* we also get PAGE_SIZE via getpagesize() */
Eric Andersencc8ed391999-10-05 16:24:54 +000049
Eric Andersencc8ed391999-10-05 16:24:54 +000050
Erik Andersene49d5ec2000-02-08 19:58:47 +000051static const char mkswap_usage[] =
52 "mkswap [-c] [-v0|-v1] device [block-count]\n\n"
53 "Prepare a disk partition to be used as a swap partition.\n\n"
54 "Options:\n" "\t-c\t\tCheck for read-ability.\n"
55 "\t-v0\t\tMake version 0 swap [max 128 Megs].\n"
56 "\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
57
58 "\tblock-count\tNumber of block to use (default is entire partition).\n";
Eric Andersene77ae3a1999-10-19 20:03:34 +000059
60
61#ifndef _IO
62/* pre-1.3.45 */
63#define BLKGETSIZE 0x1260
64#else
65/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
66#define BLKGETSIZE _IO(0x12,96)
Eric Andersencc8ed391999-10-05 16:24:54 +000067#endif
68
Erik Andersene49d5ec2000-02-08 19:58:47 +000069static char *program_name = "mkswap";
70static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000071static int DEV = -1;
72static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000073static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000074static int badpages = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000075static int version = -1;
Eric Andersencc8ed391999-10-05 16:24:54 +000076
Eric Andersene77ae3a1999-10-19 20:03:34 +000077#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Eric Andersencc8ed391999-10-05 16:24:54 +000078
Erik Andersene49d5ec2000-02-08 19:58:47 +000079static int linux_version_code(void)
80{
Eric Andersene77ae3a1999-10-19 20:03:34 +000081 struct utsname my_utsname;
82 int p, q, r;
83
84 if (uname(&my_utsname) == 0) {
85 p = atoi(strtok(my_utsname.release, "."));
86 q = atoi(strtok(NULL, "."));
87 r = atoi(strtok(NULL, "."));
Erik Andersene49d5ec2000-02-08 19:58:47 +000088 return MAKE_VERSION(p, q, r);
Eric Andersene77ae3a1999-10-19 20:03:34 +000089 }
90 return 0;
91}
92
93/*
94 * The definition of the union swap_header uses the constant PAGE_SIZE.
95 * Unfortunately, on some architectures this depends on the hardware model,
96 * and can only be found at run time -- we use getpagesize().
97 */
98
99static int pagesize;
100static int *signature_page;
101
102struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000103 char bootbits[1024]; /* Space for disklabel etc. */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000104 unsigned int version;
105 unsigned int last_page;
106 unsigned int nr_badpages;
107 unsigned int padding[125];
108 unsigned int badpages[1];
109} *p;
110
Erik Andersene49d5ec2000-02-08 19:58:47 +0000111static void init_signature_page()
112{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000113 pagesize = getpagesize();
114
115#ifdef PAGE_SIZE
116 if (pagesize != PAGE_SIZE)
117 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
118#endif
119 signature_page = (int *) malloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000120 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000121 p = (struct swap_header_v1 *) signature_page;
122}
123
Erik Andersene49d5ec2000-02-08 19:58:47 +0000124static void write_signature(char *sig)
125{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000126 char *sp = (char *) signature_page;
127
Erik Andersene49d5ec2000-02-08 19:58:47 +0000128 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000129}
130
131#define V0_MAX_PAGES (8 * (pagesize - 10))
132/* Before 2.2.0pre9 */
133#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
134/* Since 2.2.0pre9:
135 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
136 with variations on
137 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
138 #define SWP_OFFSET(entry) ((entry) >> 8)
139 on the various architectures. Below the result - yuk.
140
141 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
142 i386 2^12 o<<8 e>>8 1<<24 1<<19
143 mips 2^12 o<<15 e>>15 1<<17 1<<19
144 alpha 2^13 o<<40 e>>40 1<<24 1<<18
145 m68k 2^12 o<<12 e>>12 1<<20 1<<19
146 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
147 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
148 ppc 2^12 o<<8 e>>8 1<<24 1<<19
149 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
150 armv 2^12 o<<9 e>>9 1<<23 1<<19
151
152 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
153
154 The bad part is that we need to know this since the kernel will
155 refuse a swap space if it is too large.
156*/
157/* patch from jj - why does this differ from the above? */
158#if defined(__alpha__)
159#define V1_MAX_PAGES ((1 << 24) - 1)
160#elif defined(__mips__)
161#define V1_MAX_PAGES ((1 << 17) - 1)
162#elif defined(__sparc_v9__)
163#define V1_MAX_PAGES ((3 << 29) - 1)
164#elif defined(__sparc__)
165#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
166#else
167#define V1_MAX_PAGES V1_OLD_MAX_PAGES
168#endif
169/* man page now says:
170The maximum useful size of a swap area now depends on the architecture.
171It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
172128GB on alpha and 3TB on sparc64.
173*/
174
175#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
176
Erik Andersene49d5ec2000-02-08 19:58:47 +0000177static void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000178{
179 unsigned int r, m;
180
181 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000182
Eric Andersencc8ed391999-10-05 16:24:54 +0000183 r = *addr;
184 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000185
Eric Andersencc8ed391999-10-05 16:24:54 +0000186 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000187}
188
Erik Andersene49d5ec2000-02-08 19:58:47 +0000189static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000190{
191 unsigned int r, m;
192
193 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000194
Eric Andersencc8ed391999-10-05 16:24:54 +0000195 r = *addr;
196 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000197
Eric Andersencc8ed391999-10-05 16:24:54 +0000198 *addr = r & ~m;
199 return (r & m) != 0;
200}
201
Eric Andersene77ae3a1999-10-19 20:03:34 +0000202
Erik Andersene49d5ec2000-02-08 19:58:47 +0000203void die(const char *str)
204{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000205 fprintf(stderr, "%s: %s\n", program_name, str);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000206 exit(FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000207}
208
Erik Andersene49d5ec2000-02-08 19:58:47 +0000209void page_ok(int page)
210{
211 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000212 bit_set(signature_page, page);
213}
Eric Andersencc8ed391999-10-05 16:24:54 +0000214
Erik Andersene49d5ec2000-02-08 19:58:47 +0000215void page_bad(int page)
216{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000217 if (version == 0)
218 bit_test_and_clear(signature_page, page);
219 else {
220 if (badpages == MAX_BADPAGES)
221 die("too many bad pages");
222 p->badpages[badpages] = page;
223 }
224 badpages++;
225}
226
Erik Andersene49d5ec2000-02-08 19:58:47 +0000227void check_blocks(void)
228{
Eric Andersencc8ed391999-10-05 16:24:54 +0000229 unsigned int current_page;
230 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000231 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000232
Eric Andersene77ae3a1999-10-19 20:03:34 +0000233 buffer = malloc(pagesize);
234 if (!buffer)
235 die("Out of memory");
Eric Andersencc8ed391999-10-05 16:24:54 +0000236 current_page = 0;
237 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000238 if (!check) {
239 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000240 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000241 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000242 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
243 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000244 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000245 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
246 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000247 continue;
248 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000249 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000250 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000251 if (badpages == 1)
252 printf("one bad page\n");
253 else if (badpages > 1)
254 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000255}
256
Erik Andersene49d5ec2000-02-08 19:58:47 +0000257static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000258{
259 char ch;
260
Erik Andersene49d5ec2000-02-08 19:58:47 +0000261 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000262 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000263 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000264 return 0;
265 return 1;
266}
267
Erik Andersene49d5ec2000-02-08 19:58:47 +0000268static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000269{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000270 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000271
272 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000273 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000274 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000275 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000276 const int mid = (low + high) / 2;
277
Erik Andersene49d5ec2000-02-08 19:58:47 +0000278 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000279 low = mid;
280 else
281 high = mid;
282 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000283 return (low + 1);
284}
285
Eric Andersene77ae3a1999-10-19 20:03:34 +0000286/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000287static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000288{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000289 int fd;
290 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000291
Eric Andersene77ae3a1999-10-19 20:03:34 +0000292 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000293 if (fd < 0) {
294 perror(file);
295 exit(1);
296 }
297 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000298 int sectors_per_page = pagesize / 512;
299
Eric Andersene77ae3a1999-10-19 20:03:34 +0000300 size /= sectors_per_page;
301 } else {
302 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000303 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000304 close(fd);
305 return size;
306}
307
Erik Andersene49d5ec2000-02-08 19:58:47 +0000308int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000309{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000310 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000311 struct stat statbuf;
312 int sz;
313 int maxpages;
314 int goodpages;
315 int offset;
316 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000317
318 if (argc && *argv)
319 program_name = *argv;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000320
Erik Andersene49d5ec2000-02-08 19:58:47 +0000321 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000322
323 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000324 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000325 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000326 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000327 int blocks_per_page = pagesize / 1024;
328
329 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000330 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000331 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000332 } else
333 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000334 } else {
335 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000336 case 'c':
337 check = 1;
338 break;
339 case 'f':
340 force = 1;
341 break;
342 case 'v':
343 version = atoi(argv[0] + 2);
344 break;
345 default:
346 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000347 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000348 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000349 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000350 if (!device_name) {
351 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000352 "%s: error: Nowhere to set up swap on?\n", program_name);
353 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000354 }
355 sz = get_size(device_name);
356 if (!PAGES) {
357 PAGES = sz;
358 } else if (PAGES > sz && !force) {
359 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000360 "%s: error: "
361 "size %ld is larger than device size %d\n",
362 program_name,
363 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
364 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000365 }
366
367 if (version == -1) {
368 if (PAGES <= V0_MAX_PAGES)
369 version = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000370 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000371 version = 0;
372 else if (pagesize < 2048)
373 version = 0;
374 else
375 version = 1;
376 }
377 if (version != 0 && version != 1) {
378 fprintf(stderr, "%s: error: unknown version %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000379 program_name, version);
380 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000381 }
382 if (PAGES < 10) {
383 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000384 "%s: error: swap area needs to be at least %ldkB\n",
385 program_name, (long) (10 * pagesize / 1024));
386 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000387 }
388#if 0
389 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
390#else
391 if (!version)
392 maxpages = V0_MAX_PAGES;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000393 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000394 maxpages = V1_MAX_PAGES;
395 else {
396 maxpages = V1_OLD_MAX_PAGES;
397 if (maxpages > V1_MAX_PAGES)
398 maxpages = V1_MAX_PAGES;
399 }
400#endif
401 if (PAGES > maxpages) {
402 PAGES = maxpages;
403 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000404 program_name, PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000405 }
406
Erik Andersene49d5ec2000-02-08 19:58:47 +0000407 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000408 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
409 perror(device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000410 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000411 }
412 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000413 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000414 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
415 die("Will not try to make swapdevice on '%s'");
416
417#ifdef __sparc__
418 if (!force && version == 0) {
419 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000420 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000421 unsigned short *q, sum;
422
423 if (read(DEV, buffer, 512) != 512)
424 die("fatal: first page unreadable");
425 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000426 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000427 for (sum = 0; q >= (unsigned short *) buffer;)
428 sum ^= *q--;
429 if (!sum) {
430 fprintf(stderr, "\
431%s: Device '%s' contains a valid Sun disklabel.\n\
432This probably means creating v0 swap would destroy your partition table\n\
433No swap created. If you really want to create swap v0 on that device, use\n\
Erik Andersene49d5ec2000-02-08 19:58:47 +0000434the -f option to force it.\n", program_name, device_name);
435 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000436 }
437 }
438 }
439#endif
440
441 if (version == 0 || check)
442 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000443 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000444 die("fatal: first page unreadable");
445 if (version == 1) {
446 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000447 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000448 p->nr_badpages = badpages;
449 }
450
451 goodpages = PAGES - badpages - 1;
452 if (goodpages <= 0)
453 die("Unable to set up swap-space: unreadable");
454 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000455 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000456 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
457
458 offset = ((version == 0) ? 0 : 1024);
459 if (lseek(DEV, offset, SEEK_SET) != offset)
460 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000461 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
462 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000463 die("unable to write signature page");
464
465 /*
466 * A subsequent swapon() will fail if the signature
467 * is not actually on disk. (This is a kernel bug.)
468 */
469 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000470 die("fsync failed");
471 exit(TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000472}