blob: eacd8816cdcc6ddce520eb8f496f6132052caf59 [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 Andersene77ae3a1999-10-19 20:03:34 +000050#ifndef _IO
51/* pre-1.3.45 */
52#define BLKGETSIZE 0x1260
53#else
54/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
55#define BLKGETSIZE _IO(0x12,96)
Eric Andersencc8ed391999-10-05 16:24:54 +000056#endif
57
Erik Andersene49d5ec2000-02-08 19:58:47 +000058static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000059static int DEV = -1;
60static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000061static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000062static int badpages = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000063static int version = -1;
Eric Andersencc8ed391999-10-05 16:24:54 +000064
Eric Andersene77ae3a1999-10-19 20:03:34 +000065#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Eric Andersencc8ed391999-10-05 16:24:54 +000066
Erik Andersene49d5ec2000-02-08 19:58:47 +000067static int linux_version_code(void)
68{
Eric Andersene77ae3a1999-10-19 20:03:34 +000069 struct utsname my_utsname;
70 int p, q, r;
71
72 if (uname(&my_utsname) == 0) {
73 p = atoi(strtok(my_utsname.release, "."));
74 q = atoi(strtok(NULL, "."));
75 r = atoi(strtok(NULL, "."));
Erik Andersene49d5ec2000-02-08 19:58:47 +000076 return MAKE_VERSION(p, q, r);
Eric Andersene77ae3a1999-10-19 20:03:34 +000077 }
78 return 0;
79}
80
81/*
82 * The definition of the union swap_header uses the constant PAGE_SIZE.
83 * Unfortunately, on some architectures this depends on the hardware model,
84 * and can only be found at run time -- we use getpagesize().
85 */
86
87static int pagesize;
88static int *signature_page;
89
90struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +000091 char bootbits[1024]; /* Space for disklabel etc. */
Eric Andersene77ae3a1999-10-19 20:03:34 +000092 unsigned int version;
93 unsigned int last_page;
94 unsigned int nr_badpages;
95 unsigned int padding[125];
96 unsigned int badpages[1];
97} *p;
98
Erik Andersene49d5ec2000-02-08 19:58:47 +000099static void init_signature_page()
100{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000101 pagesize = getpagesize();
102
103#ifdef PAGE_SIZE
104 if (pagesize != PAGE_SIZE)
Matt Kraaid537a952000-07-14 01:51:25 +0000105 errorMsg("Assuming pages of size %d\n", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000106#endif
Erik Andersen0d068a22000-03-21 22:32:57 +0000107 signature_page = (int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000108 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000109 p = (struct swap_header_v1 *) signature_page;
110}
111
Erik Andersene49d5ec2000-02-08 19:58:47 +0000112static void write_signature(char *sig)
113{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000114 char *sp = (char *) signature_page;
115
Erik Andersene49d5ec2000-02-08 19:58:47 +0000116 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000117}
118
119#define V0_MAX_PAGES (8 * (pagesize - 10))
120/* Before 2.2.0pre9 */
121#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
122/* Since 2.2.0pre9:
123 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
124 with variations on
125 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
126 #define SWP_OFFSET(entry) ((entry) >> 8)
127 on the various architectures. Below the result - yuk.
128
129 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
130 i386 2^12 o<<8 e>>8 1<<24 1<<19
131 mips 2^12 o<<15 e>>15 1<<17 1<<19
132 alpha 2^13 o<<40 e>>40 1<<24 1<<18
133 m68k 2^12 o<<12 e>>12 1<<20 1<<19
134 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
135 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
136 ppc 2^12 o<<8 e>>8 1<<24 1<<19
137 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
138 armv 2^12 o<<9 e>>9 1<<23 1<<19
139
140 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
141
142 The bad part is that we need to know this since the kernel will
143 refuse a swap space if it is too large.
144*/
145/* patch from jj - why does this differ from the above? */
146#if defined(__alpha__)
147#define V1_MAX_PAGES ((1 << 24) - 1)
148#elif defined(__mips__)
149#define V1_MAX_PAGES ((1 << 17) - 1)
150#elif defined(__sparc_v9__)
151#define V1_MAX_PAGES ((3 << 29) - 1)
152#elif defined(__sparc__)
153#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
154#else
155#define V1_MAX_PAGES V1_OLD_MAX_PAGES
156#endif
157/* man page now says:
158The maximum useful size of a swap area now depends on the architecture.
159It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
160128GB on alpha and 3TB on sparc64.
161*/
162
163#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
164
Erik Andersene49d5ec2000-02-08 19:58:47 +0000165static void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000166{
167 unsigned int r, m;
168
169 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000170
Eric Andersencc8ed391999-10-05 16:24:54 +0000171 r = *addr;
172 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000173
Eric Andersencc8ed391999-10-05 16:24:54 +0000174 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000175}
176
Erik Andersene49d5ec2000-02-08 19:58:47 +0000177static int bit_test_and_clear(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;
187 return (r & m) != 0;
188}
189
Eric Andersene77ae3a1999-10-19 20:03:34 +0000190
Erik Andersene49d5ec2000-02-08 19:58:47 +0000191void die(const char *str)
192{
Matt Kraaid537a952000-07-14 01:51:25 +0000193 errorMsg("%s\n", str);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000194 exit(FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000195}
196
Erik Andersene49d5ec2000-02-08 19:58:47 +0000197void page_ok(int page)
198{
199 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000200 bit_set(signature_page, page);
201}
Eric Andersencc8ed391999-10-05 16:24:54 +0000202
Erik Andersene49d5ec2000-02-08 19:58:47 +0000203void page_bad(int page)
204{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000205 if (version == 0)
206 bit_test_and_clear(signature_page, page);
207 else {
208 if (badpages == MAX_BADPAGES)
209 die("too many bad pages");
210 p->badpages[badpages] = page;
211 }
212 badpages++;
213}
214
Erik Andersene49d5ec2000-02-08 19:58:47 +0000215void check_blocks(void)
216{
Eric Andersencc8ed391999-10-05 16:24:54 +0000217 unsigned int current_page;
218 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000219 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000220
Erik Andersen0d068a22000-03-21 22:32:57 +0000221 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000222 current_page = 0;
223 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000224 if (!check) {
225 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000226 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000227 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000228 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
229 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000230 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000231 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
232 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000233 continue;
234 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000235 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000236 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000237 if (badpages == 1)
238 printf("one bad page\n");
239 else if (badpages > 1)
240 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000241}
242
Erik Andersene49d5ec2000-02-08 19:58:47 +0000243static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000244{
245 char ch;
246
Erik Andersene49d5ec2000-02-08 19:58:47 +0000247 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000248 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000249 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000250 return 0;
251 return 1;
252}
253
Erik Andersene49d5ec2000-02-08 19:58:47 +0000254static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000255{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000256 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000257
258 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000259 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000260 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000261 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000262 const int mid = (low + high) / 2;
263
Erik Andersene49d5ec2000-02-08 19:58:47 +0000264 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000265 low = mid;
266 else
267 high = mid;
268 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000269 return (low + 1);
270}
271
Eric Andersene77ae3a1999-10-19 20:03:34 +0000272/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000273static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000274{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000275 int fd;
276 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000277
Eric Andersene77ae3a1999-10-19 20:03:34 +0000278 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000279 if (fd < 0) {
280 perror(file);
281 exit(1);
282 }
283 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000284 int sectors_per_page = pagesize / 512;
285
Eric Andersene77ae3a1999-10-19 20:03:34 +0000286 size /= sectors_per_page;
287 } else {
288 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000289 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000290 close(fd);
291 return size;
292}
293
Erik Andersene49d5ec2000-02-08 19:58:47 +0000294int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000295{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000296 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000297 struct stat statbuf;
298 int sz;
299 int maxpages;
300 int goodpages;
301 int offset;
302 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000303
Erik Andersene49d5ec2000-02-08 19:58:47 +0000304 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000305
306 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000307 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000308 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000309 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000310 int blocks_per_page = pagesize / 1024;
311
312 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000313 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000314 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000315 } else
316 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000317 } else {
318 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000319 case 'c':
320 check = 1;
321 break;
322 case 'f':
323 force = 1;
324 break;
325 case 'v':
326 version = atoi(argv[0] + 2);
327 break;
328 default:
329 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000330 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000331 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000332 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000333 if (!device_name) {
Matt Kraaid537a952000-07-14 01:51:25 +0000334 errorMsg("error: Nowhere to set up swap on?\n");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000335 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000336 }
337 sz = get_size(device_name);
338 if (!PAGES) {
339 PAGES = sz;
340 } else if (PAGES > sz && !force) {
Matt Kraaid537a952000-07-14 01:51:25 +0000341 errorMsg("error: size %ld is larger than device size %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000342 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
343 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000344 }
345
346 if (version == -1) {
347 if (PAGES <= V0_MAX_PAGES)
348 version = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000349 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000350 version = 0;
351 else if (pagesize < 2048)
352 version = 0;
353 else
354 version = 1;
355 }
356 if (version != 0 && version != 1) {
Matt Kraaid537a952000-07-14 01:51:25 +0000357 errorMsg("error: unknown version %d\n", version);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000358 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000359 }
360 if (PAGES < 10) {
Matt Kraaid537a952000-07-14 01:51:25 +0000361 errorMsg("error: swap area needs to be at least %ldkB\n",
362 (long) (10 * pagesize / 1024));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000363 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000364 }
365#if 0
366 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
367#else
368 if (!version)
369 maxpages = V0_MAX_PAGES;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000370 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000371 maxpages = V1_MAX_PAGES;
372 else {
373 maxpages = V1_OLD_MAX_PAGES;
374 if (maxpages > V1_MAX_PAGES)
375 maxpages = V1_MAX_PAGES;
376 }
377#endif
378 if (PAGES > maxpages) {
379 PAGES = maxpages;
Matt Kraaid537a952000-07-14 01:51:25 +0000380 errorMsg("warning: truncating swap area to %ldkB\n",
381 PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000382 }
383
Erik Andersene49d5ec2000-02-08 19:58:47 +0000384 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000385 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
386 perror(device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000387 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000388 }
389 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000390 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000391 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
392 die("Will not try to make swapdevice on '%s'");
393
394#ifdef __sparc__
395 if (!force && version == 0) {
396 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000397 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000398 unsigned short *q, sum;
399
400 if (read(DEV, buffer, 512) != 512)
401 die("fatal: first page unreadable");
402 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000403 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000404 for (sum = 0; q >= (unsigned short *) buffer;)
405 sum ^= *q--;
406 if (!sum) {
Matt Kraaid537a952000-07-14 01:51:25 +0000407 errorMsg("Device '%s' contains a valid Sun disklabel.\n"
408"This probably means creating v0 swap would destroy your partition table\n"
409"No swap created. If you really want to create swap v0 on that device, use\n"
410"the -f option to force it.\n", device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000411 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000412 }
413 }
414 }
415#endif
416
417 if (version == 0 || check)
418 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000419 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000420 die("fatal: first page unreadable");
421 if (version == 1) {
422 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000423 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000424 p->nr_badpages = badpages;
425 }
426
427 goodpages = PAGES - badpages - 1;
428 if (goodpages <= 0)
429 die("Unable to set up swap-space: unreadable");
430 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000431 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000432 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
433
434 offset = ((version == 0) ? 0 : 1024);
435 if (lseek(DEV, offset, SEEK_SET) != offset)
436 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000437 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
438 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000439 die("unable to write signature page");
440
441 /*
442 * A subsequent swapon() will fail if the signature
443 * is not actually on disk. (This is a kernel bug.)
444 */
445 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000446 die("fsync failed");
Eric Andersenb6106152000-06-19 17:25:40 +0000447 return(TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000448}