blob: 17866a735324522ab7d439906d8fa2b858860809 [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
Erik Andersen0d068a22000-03-21 22:32:57 +0000119 signature_page = (int *) xmalloc(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
Erik Andersen0d068a22000-03-21 22:32:57 +0000233 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000234 current_page = 0;
235 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000236 if (!check) {
237 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000238 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000239 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000240 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
241 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000242 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000243 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
244 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000245 continue;
246 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000247 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000248 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000249 if (badpages == 1)
250 printf("one bad page\n");
251 else if (badpages > 1)
252 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000253}
254
Erik Andersene49d5ec2000-02-08 19:58:47 +0000255static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000256{
257 char ch;
258
Erik Andersene49d5ec2000-02-08 19:58:47 +0000259 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000260 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000261 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000262 return 0;
263 return 1;
264}
265
Erik Andersene49d5ec2000-02-08 19:58:47 +0000266static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000267{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000268 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000269
270 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000271 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000272 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000273 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000274 const int mid = (low + high) / 2;
275
Erik Andersene49d5ec2000-02-08 19:58:47 +0000276 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000277 low = mid;
278 else
279 high = mid;
280 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000281 return (low + 1);
282}
283
Eric Andersene77ae3a1999-10-19 20:03:34 +0000284/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000285static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000286{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000287 int fd;
288 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000289
Eric Andersene77ae3a1999-10-19 20:03:34 +0000290 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000291 if (fd < 0) {
292 perror(file);
293 exit(1);
294 }
295 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000296 int sectors_per_page = pagesize / 512;
297
Eric Andersene77ae3a1999-10-19 20:03:34 +0000298 size /= sectors_per_page;
299 } else {
300 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000301 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000302 close(fd);
303 return size;
304}
305
Erik Andersene49d5ec2000-02-08 19:58:47 +0000306int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000307{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000308 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000309 struct stat statbuf;
310 int sz;
311 int maxpages;
312 int goodpages;
313 int offset;
314 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000315
316 if (argc && *argv)
317 program_name = *argv;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000318
Erik Andersene49d5ec2000-02-08 19:58:47 +0000319 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000320
321 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000322 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000323 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000324 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000325 int blocks_per_page = pagesize / 1024;
326
327 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000328 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000329 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000330 } else
331 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000332 } else {
333 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000334 case 'c':
335 check = 1;
336 break;
337 case 'f':
338 force = 1;
339 break;
340 case 'v':
341 version = atoi(argv[0] + 2);
342 break;
343 default:
344 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000345 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000346 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000347 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000348 if (!device_name) {
349 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000350 "%s: error: Nowhere to set up swap on?\n", program_name);
351 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000352 }
353 sz = get_size(device_name);
354 if (!PAGES) {
355 PAGES = sz;
356 } else if (PAGES > sz && !force) {
357 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000358 "%s: error: "
359 "size %ld is larger than device size %d\n",
360 program_name,
361 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
362 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000363 }
364
365 if (version == -1) {
366 if (PAGES <= V0_MAX_PAGES)
367 version = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000368 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000369 version = 0;
370 else if (pagesize < 2048)
371 version = 0;
372 else
373 version = 1;
374 }
375 if (version != 0 && version != 1) {
376 fprintf(stderr, "%s: error: unknown version %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000377 program_name, version);
378 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000379 }
380 if (PAGES < 10) {
381 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000382 "%s: error: swap area needs to be at least %ldkB\n",
383 program_name, (long) (10 * pagesize / 1024));
384 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000385 }
386#if 0
387 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
388#else
389 if (!version)
390 maxpages = V0_MAX_PAGES;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000391 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000392 maxpages = V1_MAX_PAGES;
393 else {
394 maxpages = V1_OLD_MAX_PAGES;
395 if (maxpages > V1_MAX_PAGES)
396 maxpages = V1_MAX_PAGES;
397 }
398#endif
399 if (PAGES > maxpages) {
400 PAGES = maxpages;
401 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000402 program_name, PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000403 }
404
Erik Andersene49d5ec2000-02-08 19:58:47 +0000405 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000406 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
407 perror(device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000408 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000409 }
410 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000411 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000412 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
413 die("Will not try to make swapdevice on '%s'");
414
415#ifdef __sparc__
416 if (!force && version == 0) {
417 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000418 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000419 unsigned short *q, sum;
420
421 if (read(DEV, buffer, 512) != 512)
422 die("fatal: first page unreadable");
423 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000424 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000425 for (sum = 0; q >= (unsigned short *) buffer;)
426 sum ^= *q--;
427 if (!sum) {
428 fprintf(stderr, "\
429%s: Device '%s' contains a valid Sun disklabel.\n\
430This probably means creating v0 swap would destroy your partition table\n\
431No swap created. If you really want to create swap v0 on that device, use\n\
Erik Andersene49d5ec2000-02-08 19:58:47 +0000432the -f option to force it.\n", program_name, device_name);
433 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000434 }
435 }
436 }
437#endif
438
439 if (version == 0 || check)
440 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000441 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000442 die("fatal: first page unreadable");
443 if (version == 1) {
444 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000445 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000446 p->nr_badpages = badpages;
447 }
448
449 goodpages = PAGES - badpages - 1;
450 if (goodpages <= 0)
451 die("Unable to set up swap-space: unreadable");
452 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000453 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000454 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
455
456 offset = ((version == 0) ? 0 : 1024);
457 if (lseek(DEV, offset, SEEK_SET) != offset)
458 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000459 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
460 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000461 die("unable to write signature page");
462
463 /*
464 * A subsequent swapon() will fail if the signature
465 * is not actually on disk. (This is a kernel bug.)
466 */
467 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000468 die("fsync failed");
469 exit(TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000470}