blob: 8a9767cca5985436790b8072f8b84030f07941bc [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 Andersen3570a342000-09-25 21:45:58 +000038#include "busybox.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>
Erik Andersene49d5ec2000-02-08 19:58:47 +000046#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
Eric Andersene77ae3a1999-10-19 20:03:34 +000047 /* we also get PAGE_SIZE via getpagesize() */
Eric Andersencc8ed391999-10-05 16:24:54 +000048
Eric Andersene77ae3a1999-10-19 20:03:34 +000049#ifndef _IO
50/* pre-1.3.45 */
51#define BLKGETSIZE 0x1260
52#else
53/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
54#define BLKGETSIZE _IO(0x12,96)
Eric Andersencc8ed391999-10-05 16:24:54 +000055#endif
56
Erik Andersene49d5ec2000-02-08 19:58:47 +000057static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000058static int DEV = -1;
59static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000060static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000061static int badpages = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000062static int version = -1;
Eric Andersencc8ed391999-10-05 16:24:54 +000063
Eric Andersene77ae3a1999-10-19 20:03:34 +000064#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Eric Andersencc8ed391999-10-05 16:24:54 +000065
Erik Andersene49d5ec2000-02-08 19:58:47 +000066static int linux_version_code(void)
67{
Eric Andersene77ae3a1999-10-19 20:03:34 +000068 struct utsname my_utsname;
69 int p, q, r;
70
71 if (uname(&my_utsname) == 0) {
72 p = atoi(strtok(my_utsname.release, "."));
73 q = atoi(strtok(NULL, "."));
74 r = atoi(strtok(NULL, "."));
Erik Andersene49d5ec2000-02-08 19:58:47 +000075 return MAKE_VERSION(p, q, r);
Eric Andersene77ae3a1999-10-19 20:03:34 +000076 }
77 return 0;
78}
79
80/*
81 * The definition of the union swap_header uses the constant PAGE_SIZE.
82 * Unfortunately, on some architectures this depends on the hardware model,
83 * and can only be found at run time -- we use getpagesize().
84 */
85
86static int pagesize;
87static int *signature_page;
88
89struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +000090 char bootbits[1024]; /* Space for disklabel etc. */
Eric Andersene77ae3a1999-10-19 20:03:34 +000091 unsigned int version;
92 unsigned int last_page;
93 unsigned int nr_badpages;
94 unsigned int padding[125];
95 unsigned int badpages[1];
96} *p;
97
Erik Andersene49d5ec2000-02-08 19:58:47 +000098static void init_signature_page()
99{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000100 pagesize = getpagesize();
101
102#ifdef PAGE_SIZE
103 if (pagesize != PAGE_SIZE)
Matt Kraaid537a952000-07-14 01:51:25 +0000104 errorMsg("Assuming pages of size %d\n", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000105#endif
Erik Andersen0d068a22000-03-21 22:32:57 +0000106 signature_page = (int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000107 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000108 p = (struct swap_header_v1 *) signature_page;
109}
110
Erik Andersene49d5ec2000-02-08 19:58:47 +0000111static void write_signature(char *sig)
112{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000113 char *sp = (char *) signature_page;
114
Erik Andersene49d5ec2000-02-08 19:58:47 +0000115 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000116}
117
118#define V0_MAX_PAGES (8 * (pagesize - 10))
119/* Before 2.2.0pre9 */
120#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
121/* Since 2.2.0pre9:
122 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
123 with variations on
124 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
125 #define SWP_OFFSET(entry) ((entry) >> 8)
126 on the various architectures. Below the result - yuk.
127
128 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
129 i386 2^12 o<<8 e>>8 1<<24 1<<19
130 mips 2^12 o<<15 e>>15 1<<17 1<<19
131 alpha 2^13 o<<40 e>>40 1<<24 1<<18
132 m68k 2^12 o<<12 e>>12 1<<20 1<<19
133 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
134 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
135 ppc 2^12 o<<8 e>>8 1<<24 1<<19
136 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
137 armv 2^12 o<<9 e>>9 1<<23 1<<19
138
139 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
140
141 The bad part is that we need to know this since the kernel will
142 refuse a swap space if it is too large.
143*/
144/* patch from jj - why does this differ from the above? */
145#if defined(__alpha__)
146#define V1_MAX_PAGES ((1 << 24) - 1)
147#elif defined(__mips__)
148#define V1_MAX_PAGES ((1 << 17) - 1)
149#elif defined(__sparc_v9__)
150#define V1_MAX_PAGES ((3 << 29) - 1)
151#elif defined(__sparc__)
152#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
153#else
154#define V1_MAX_PAGES V1_OLD_MAX_PAGES
155#endif
156/* man page now says:
157The maximum useful size of a swap area now depends on the architecture.
158It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
159128GB on alpha and 3TB on sparc64.
160*/
161
162#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
163
Erik Andersene49d5ec2000-02-08 19:58:47 +0000164static void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000165{
166 unsigned int r, m;
167
168 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000169
Eric Andersencc8ed391999-10-05 16:24:54 +0000170 r = *addr;
171 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000172
Eric Andersencc8ed391999-10-05 16:24:54 +0000173 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000174}
175
Erik Andersene49d5ec2000-02-08 19:58:47 +0000176static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000177{
178 unsigned int r, m;
179
180 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000181
Eric Andersencc8ed391999-10-05 16:24:54 +0000182 r = *addr;
183 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000184
Eric Andersencc8ed391999-10-05 16:24:54 +0000185 *addr = r & ~m;
186 return (r & m) != 0;
187}
188
Eric Andersene77ae3a1999-10-19 20:03:34 +0000189
Erik Andersene49d5ec2000-02-08 19:58:47 +0000190void die(const char *str)
191{
Matt Kraaid537a952000-07-14 01:51:25 +0000192 errorMsg("%s\n", str);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000193 exit(FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000194}
195
Erik Andersene49d5ec2000-02-08 19:58:47 +0000196void page_ok(int page)
197{
198 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000199 bit_set(signature_page, page);
200}
Eric Andersencc8ed391999-10-05 16:24:54 +0000201
Erik Andersene49d5ec2000-02-08 19:58:47 +0000202void page_bad(int page)
203{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000204 if (version == 0)
205 bit_test_and_clear(signature_page, page);
206 else {
207 if (badpages == MAX_BADPAGES)
208 die("too many bad pages");
209 p->badpages[badpages] = page;
210 }
211 badpages++;
212}
213
Erik Andersene49d5ec2000-02-08 19:58:47 +0000214void check_blocks(void)
215{
Eric Andersencc8ed391999-10-05 16:24:54 +0000216 unsigned int current_page;
217 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000218 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000219
Erik Andersen0d068a22000-03-21 22:32:57 +0000220 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000221 current_page = 0;
222 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000223 if (!check) {
224 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000225 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000226 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000227 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
228 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000229 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000230 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
231 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000232 continue;
233 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000234 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000235 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000236 if (badpages == 1)
237 printf("one bad page\n");
238 else if (badpages > 1)
239 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000240}
241
Erik Andersene49d5ec2000-02-08 19:58:47 +0000242static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000243{
244 char ch;
245
Erik Andersene49d5ec2000-02-08 19:58:47 +0000246 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000247 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000248 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000249 return 0;
250 return 1;
251}
252
Erik Andersene49d5ec2000-02-08 19:58:47 +0000253static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000254{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000255 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000256
257 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000258 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000259 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000260 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000261 const int mid = (low + high) / 2;
262
Erik Andersene49d5ec2000-02-08 19:58:47 +0000263 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000264 low = mid;
265 else
266 high = mid;
267 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000268 return (low + 1);
269}
270
Eric Andersene77ae3a1999-10-19 20:03:34 +0000271/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000272static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000273{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000274 int fd;
275 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000276
Eric Andersene77ae3a1999-10-19 20:03:34 +0000277 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000278 if (fd < 0) {
279 perror(file);
280 exit(1);
281 }
282 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000283 int sectors_per_page = pagesize / 512;
284
Eric Andersene77ae3a1999-10-19 20:03:34 +0000285 size /= sectors_per_page;
286 } else {
287 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000288 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000289 close(fd);
290 return size;
291}
292
Erik Andersene49d5ec2000-02-08 19:58:47 +0000293int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000294{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000295 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000296 struct stat statbuf;
297 int sz;
298 int maxpages;
299 int goodpages;
300 int offset;
301 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000302
Erik Andersene49d5ec2000-02-08 19:58:47 +0000303 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000304
305 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000306 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000307 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000308 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000309 int blocks_per_page = pagesize / 1024;
310
311 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000312 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000313 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000314 } else
315 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000316 } else {
317 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000318 case 'c':
319 check = 1;
320 break;
321 case 'f':
322 force = 1;
323 break;
324 case 'v':
325 version = atoi(argv[0] + 2);
326 break;
327 default:
328 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000329 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000330 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000331 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000332 if (!device_name) {
Matt Kraaid537a952000-07-14 01:51:25 +0000333 errorMsg("error: Nowhere to set up swap on?\n");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000334 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000335 }
336 sz = get_size(device_name);
337 if (!PAGES) {
338 PAGES = sz;
339 } else if (PAGES > sz && !force) {
Matt Kraaid537a952000-07-14 01:51:25 +0000340 errorMsg("error: size %ld is larger than device size %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000341 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
342 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000343 }
344
345 if (version == -1) {
346 if (PAGES <= V0_MAX_PAGES)
347 version = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000348 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000349 version = 0;
350 else if (pagesize < 2048)
351 version = 0;
352 else
353 version = 1;
354 }
355 if (version != 0 && version != 1) {
Matt Kraaid537a952000-07-14 01:51:25 +0000356 errorMsg("error: unknown version %d\n", version);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000357 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000358 }
359 if (PAGES < 10) {
Matt Kraaid537a952000-07-14 01:51:25 +0000360 errorMsg("error: swap area needs to be at least %ldkB\n",
361 (long) (10 * pagesize / 1024));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000362 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000363 }
364#if 0
365 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
366#else
367 if (!version)
368 maxpages = V0_MAX_PAGES;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000369 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000370 maxpages = V1_MAX_PAGES;
371 else {
372 maxpages = V1_OLD_MAX_PAGES;
373 if (maxpages > V1_MAX_PAGES)
374 maxpages = V1_MAX_PAGES;
375 }
376#endif
377 if (PAGES > maxpages) {
378 PAGES = maxpages;
Matt Kraaid537a952000-07-14 01:51:25 +0000379 errorMsg("warning: truncating swap area to %ldkB\n",
380 PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000381 }
382
Erik Andersene49d5ec2000-02-08 19:58:47 +0000383 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000384 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
385 perror(device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000386 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000387 }
388 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000389 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000390 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
391 die("Will not try to make swapdevice on '%s'");
392
393#ifdef __sparc__
394 if (!force && version == 0) {
395 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000396 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000397 unsigned short *q, sum;
398
399 if (read(DEV, buffer, 512) != 512)
400 die("fatal: first page unreadable");
401 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000402 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000403 for (sum = 0; q >= (unsigned short *) buffer;)
404 sum ^= *q--;
405 if (!sum) {
Matt Kraaid537a952000-07-14 01:51:25 +0000406 errorMsg("Device '%s' contains a valid Sun disklabel.\n"
407"This probably means creating v0 swap would destroy your partition table\n"
408"No swap created. If you really want to create swap v0 on that device, use\n"
409"the -f option to force it.\n", device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000410 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000411 }
412 }
413 }
414#endif
415
416 if (version == 0 || check)
417 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000418 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000419 die("fatal: first page unreadable");
420 if (version == 1) {
421 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000422 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000423 p->nr_badpages = badpages;
424 }
425
426 goodpages = PAGES - badpages - 1;
427 if (goodpages <= 0)
428 die("Unable to set up swap-space: unreadable");
429 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000430 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000431 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
432
433 offset = ((version == 0) ? 0 : 1024);
434 if (lseek(DEV, offset, SEEK_SET) != offset)
435 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000436 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
437 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000438 die("unable to write signature page");
439
440 /*
441 * A subsequent swapon() will fail if the signature
442 * is not actually on disk. (This is a kernel bug.)
443 */
444 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000445 die("fsync failed");
Eric Andersenb6106152000-06-19 17:25:40 +0000446 return(TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000447}