]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - disk-utils/mkswap.c
2 * mkswap.c - set up a linux swap device
4 * (C) 1991 Linus Torvalds. This file may be redistributed as per
9 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
11 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
13 * -c for readability checking. (Use it unless you are SURE!)
14 * -vN for swap areas version N. (Only N=0,1 known today.)
15 * -f for forcing swap creation even if it would smash partition table.
17 * The device may be a block device or an image of one, but this isn't
18 * enforced (but it's not much fun on a character device :-).
20 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
21 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
23 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
25 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
26 * V1_MAX_PAGES fixes, jj, 990325.
28 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
29 * - added Native Language Support
38 #include <sys/ioctl.h> /* for _IO */
39 #include <sys/utsname.h>
41 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
42 /* we also get PAGE_SIZE via getpagesize() */
47 #define BLKGETSIZE 0x1260
49 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
50 #define BLKGETSIZE _IO(0x12,96)
53 static char * program_name
= "mkswap";
54 static char * device_name
= NULL
;
56 static long PAGES
= 0;
58 static int badpages
= 0;
59 static int version
= -1;
61 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
64 linux_version_code(void) {
65 struct utsname my_utsname
;
68 if (uname(&my_utsname
) == 0) {
69 p
= atoi(strtok(my_utsname
.release
, "."));
70 q
= atoi(strtok(NULL
, "."));
71 r
= atoi(strtok(NULL
, "."));
72 return MAKE_VERSION(p
,q
,r
);
78 * The definition of the union swap_header uses the constant PAGE_SIZE.
79 * Unfortunately, on some architectures this depends on the hardware model,
80 * and can only be found at run time -- we use getpagesize().
84 static int *signature_page
;
86 struct swap_header_v1
{
87 char bootbits
[1024]; /* Space for disklabel etc. */
89 unsigned int last_page
;
90 unsigned int nr_badpages
;
91 unsigned int padding
[125];
92 unsigned int badpages
[1];
96 init_signature_page() {
97 pagesize
= getpagesize();
100 if (pagesize
!= PAGE_SIZE
)
101 fprintf(stderr
, _("Assuming pages of size %d\n"), pagesize
);
103 signature_page
= (int *) malloc(pagesize
);
104 memset(signature_page
,0,pagesize
);
105 p
= (struct swap_header_v1
*) signature_page
;
109 write_signature(char *sig
) {
110 char *sp
= (char *) signature_page
;
112 strncpy(sp
+pagesize
-10, sig
, 10);
115 #define V0_MAX_PAGES (8 * (pagesize - 10))
116 /* Before 2.2.0pre9 */
117 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
119 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
121 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
122 #define SWP_OFFSET(entry) ((entry) >> 8)
123 on the various architectures. Below the result - yuk.
125 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
126 i386 2^12 o<<8 e>>8 1<<24 1<<19
127 mips 2^12 o<<15 e>>15 1<<17 1<<19
128 alpha 2^13 o<<40 e>>40 1<<24 1<<18
129 m68k 2^12 o<<12 e>>12 1<<20 1<<19
130 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
131 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
132 ppc 2^12 o<<8 e>>8 1<<24 1<<19
133 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
134 armv 2^12 o<<9 e>>9 1<<23 1<<19
136 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
138 The bad part is that we need to know this since the kernel will
139 refuse a swap space if it is too large.
141 /* patch from jj - why does this differ from the above? */
142 #if defined(__alpha__)
143 #define V1_MAX_PAGES ((1 << 24) - 1)
144 #elif defined(__mips__)
145 #define V1_MAX_PAGES ((1 << 17) - 1)
146 #elif defined(__sparc_v9__)
147 #define V1_MAX_PAGES ((3 << 29) - 1)
148 #elif defined(__sparc__)
149 #define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
151 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
153 /* man page now says:
154 The maximum useful size of a swap area now depends on the architecture.
155 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
156 128GB on alpha and 3TB on sparc64.
159 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
161 static void bit_set (unsigned int *addr
, unsigned int nr
)
165 addr
+= nr
/ (8 * sizeof(int));
167 m
= 1 << (nr
& (8 * sizeof(int) - 1));
171 static int bit_test_and_clear (unsigned int *addr
, unsigned int nr
)
175 addr
+= nr
/ (8 * sizeof(int));
177 m
= 1 << (nr
& (8 * sizeof(int) - 1));
182 void fatal_error(const char * fmt_string
)
184 fprintf(stderr
,fmt_string
,program_name
,device_name
);
188 #define usage() fatal_error(_("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n"))
189 #define die(str) fatal_error(_("%s: " str "\n"))
194 bit_set(signature_page
, page
);
200 bit_test_and_clear(signature_page
, page
);
202 if (badpages
== MAX_BADPAGES
)
203 die("too many bad pages");
204 p
->badpages
[badpages
] = page
;
211 unsigned int current_page
;
215 buffer
= malloc(pagesize
);
217 die("Out of memory");
219 while (current_page
< PAGES
) {
221 page_ok(current_page
++);
224 if (do_seek
&& lseek(DEV
,current_page
*pagesize
,SEEK_SET
) !=
225 current_page
*pagesize
)
226 die("seek failed in check_blocks");
227 if ((do_seek
= (pagesize
!= read(DEV
, buffer
, pagesize
)))) {
228 page_bad(current_page
++);
231 page_ok(current_page
++);
234 printf(_("one bad page\n"));
235 else if (badpages
> 1)
236 printf(_("%d bad pages\n"), badpages
);
239 static long valid_offset (int fd
, int offset
)
243 if (lseek (fd
, offset
, 0) < 0)
245 if (read (fd
, &ch
, 1) < 1)
253 unsigned int high
, low
;
256 for (high
= 1; high
> 0 && valid_offset (fd
, high
); high
*= 2)
258 while (low
< high
- 1)
260 const int mid
= (low
+ high
) / 2;
262 if (valid_offset (fd
, mid
))
270 /* return size in pages, to avoid integer overflow */
272 get_size(const char *file
)
277 fd
= open(file
, O_RDONLY
);
282 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) {
283 int sectors_per_page
= pagesize
/512;
284 size
/= sectors_per_page
;
286 size
= find_size(fd
) / pagesize
;
292 int main(int argc
, char ** argv
)
302 setlocale(LC_ALL
, "");
303 bindtextdomain(PACKAGE
, LOCALEDIR
);
308 program_name
= *argv
;
310 init_signature_page(); /* get pagesize */
314 if (argv
[0][0] != '-') {
316 int blocks_per_page
= pagesize
/1024;
317 PAGES
= strtol(argv
[0],&tmp
,0)/blocks_per_page
;
321 device_name
= argv
[0];
323 switch (argv
[0][1]) {
331 version
=atoi(argv
[0]+2);
340 _("%s: error: Nowhere to set up swap on?\n"),
344 sz
= get_size(device_name
);
347 } else if (PAGES
> sz
&& !force
) {
350 "size %ld is larger than device size %d\n"),
352 PAGES
*(pagesize
/1024), sz
*(pagesize
/1024));
357 if (PAGES
<= V0_MAX_PAGES
)
359 else if (linux_version_code() < MAKE_VERSION(2,1,117))
361 else if (pagesize
< 2048)
366 if (version
!= 0 && version
!= 1) {
367 fprintf(stderr
, _("%s: error: unknown version %d\n"),
368 program_name
, version
);
373 _("%s: error: swap area needs to be at least %ldkB\n"),
374 program_name
, (long)(10 * pagesize
/ 1024));
378 maxpages
= ((version
== 0) ? V0_MAX_PAGES
: V1_MAX_PAGES
);
381 maxpages
= V0_MAX_PAGES
;
382 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
383 maxpages
= V1_MAX_PAGES
;
385 maxpages
= V1_OLD_MAX_PAGES
;
386 if (maxpages
> V1_MAX_PAGES
)
387 maxpages
= V1_MAX_PAGES
;
390 if (PAGES
> maxpages
) {
392 fprintf(stderr
, _("%s: warning: truncating swap area to %ldkB\n"),
393 program_name
, PAGES
* pagesize
/ 1024);
396 DEV
= open(device_name
,O_RDWR
);
397 if (DEV
< 0 || fstat(DEV
, &statbuf
) < 0) {
401 if (!S_ISBLK(statbuf
.st_mode
))
403 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340)
404 die("Will not try to make swapdevice on '%s'");
407 if (!force
&& version
== 0) {
408 /* Don't overwrite partition table unless forced */
409 unsigned char *buffer
= (unsigned char *)signature_page
;
410 unsigned short *q
, sum
;
412 if (read(DEV
, buffer
, 512) != 512)
413 die("fatal: first page unreadable");
414 if (buffer
[508] == 0xDA && buffer
[509] == 0xBE) {
415 q
= (unsigned short *)(buffer
+ 510);
416 for (sum
= 0; q
>= (unsigned short *) buffer
;)
420 %s: Device '%s' contains a valid Sun disklabel.\n\
421 This probably means creating v0 swap would destroy your partition table\n\
422 No swap created. If you really want to create swap v0 on that device, use\n\
423 the -f option to force it.\n"),
424 program_name
, device_name
);
431 if (version
== 0 || check
)
433 if (version
== 0 && !bit_test_and_clear(signature_page
,0))
434 die("fatal: first page unreadable");
436 p
->version
= version
;
437 p
->last_page
= PAGES
-1;
438 p
->nr_badpages
= badpages
;
441 goodpages
= PAGES
- badpages
- 1;
443 die("Unable to set up swap-space: unreadable");
444 printf(_("Setting up swapspace version %d, size = %ld bytes\n"),
445 version
, (long)(goodpages
*pagesize
));
446 write_signature((version
== 0) ? "SWAP-SPACE" : "SWAPSPACE2");
448 offset
= ((version
== 0) ? 0 : 1024);
449 if (lseek(DEV
, offset
, SEEK_SET
) != offset
)
450 die("unable to rewind swap-device");
451 if (write(DEV
,(char*)signature_page
+offset
, pagesize
-offset
)
453 die("unable to write signature page");
456 * A subsequent swapon() will fail if the signature
457 * is not actually on disk. (This is a kernel bug.)