]>
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.
27 * sparc64 fixes, jj, 000219.
29 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
30 * - added Native Language Support
39 #include <sys/ioctl.h> /* for _IO */
40 #include <sys/utsname.h>
42 #include "swapheader.h"
46 #ifdef HAVE_UUID_UUID_H
47 #include <uuid/uuid.h>
50 /* Try to get PAGE_SIZE from libc or kernel includes */
51 #ifdef HAVE_SYS_USER_H
52 /* Note: <sys/user.h> says: for gdb only */
53 #include <sys/user.h> /* for PAGE_SIZE and PAGE_SHIFT */
55 #ifdef HAVE_ASM_PAGE_H
56 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
57 /* we also get PAGE_SIZE via getpagesize() */
63 #define BLKGETSIZE 0x1260
65 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
66 #define BLKGETSIZE _IO(0x12,96)
69 static char * program_name
= "mkswap";
70 static char * device_name
= NULL
;
72 static unsigned long PAGES
= 0;
73 static unsigned long badpages
= 0;
75 static int version
= -1;
77 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
80 linux_version_code(void) {
81 struct utsname my_utsname
;
84 if (uname(&my_utsname
) == 0) {
85 p
= atoi(strtok(my_utsname
.release
, "."));
86 q
= atoi(strtok(NULL
, "."));
87 r
= atoi(strtok(NULL
, "."));
88 return MAKE_VERSION(p
,q
,r
);
95 # define is_sparc64() 1
101 static int sparc64
= -1;
103 if (sparc64
!= -1) return sparc64
;
106 if (uname(&un
) < 0) return 0;
107 if (! strcmp(un
.machine
, "sparc64")) {
111 if (strcmp(un
.machine
, "sparc"))
112 return 0; /* Should not happen */
114 #ifdef HAVE_PERSONALITY
116 extern int personality(unsigned long);
118 #define PERS_LINUX 0x00000000
119 #define PERS_LINUX_32BIT 0x00800000
120 #define PERS_LINUX32 0x00000008
122 oldpers
= personality(PERS_LINUX_32BIT
);
124 if (personality(PERS_LINUX
) != -1) {
126 if (! strcmp(un
.machine
, "sparc64")) {
128 oldpers
= PERS_LINUX32
;
131 personality(oldpers
);
138 # define is_be64() is_sparc64()
139 # endif /* sparc32 */
145 * The definition of the union swap_header uses the constant PAGE_SIZE.
146 * Unfortunately, on some architectures this depends on the hardware model,
147 * and can only be found at run time -- we use getpagesize(), so that
148 * we do not need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
150 * Even more unfortunately, getpagesize() does not always return
151 * the right information. For example, libc4 and libc5 do not use
152 * the system call but invent a value themselves
153 * (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC), and thus it may happen
154 * that e.g. on a sparc PAGE_SIZE=4096 and getpagesize() returns 8192.
155 * What to do? Let us allow the user to specify the pagesize explicitly.
158 static int user_pagesize
= 0;
159 static int kernel_pagesize
; /* obtained via getpagesize(); */
160 static int defined_pagesize
= 0; /* PAGE_SIZE, when that exists */
162 static long *signature_page
;
163 struct swap_header_v1
*p
;
166 init_signature_page(void) {
169 defined_pagesize
= PAGE_SIZE
;
171 kernel_pagesize
= getpagesize();
172 pagesize
= kernel_pagesize
;
175 if ((user_pagesize
& (user_pagesize
-1)) ||
176 user_pagesize
< 1024) {
177 fprintf(stderr
, _("Bad user-specified page size %d\n"),
181 pagesize
= user_pagesize
;
184 if (user_pagesize
&& user_pagesize
!= kernel_pagesize
&&
185 user_pagesize
!= defined_pagesize
)
186 fprintf(stderr
, _("Using user-specified page size %d, "
187 "instead of the system values %d/%d\n"),
188 pagesize
, kernel_pagesize
, defined_pagesize
);
189 else if (defined_pagesize
&& pagesize
!= defined_pagesize
)
190 fprintf(stderr
, _("Assuming pages of size %d (not %d)\n"),
191 pagesize
, defined_pagesize
);
193 signature_page
= (long *) malloc(pagesize
);
194 memset(signature_page
, 0, pagesize
);
195 p
= (struct swap_header_v1
*) signature_page
;
199 write_signature(char *sig
) {
200 char *sp
= (char *) signature_page
;
202 strncpy(sp
+pagesize
-10, sig
, 10);
208 return ((a
< 10) ? '0'+a
: 'a'+a
-10);
212 uuid_unparse(unsigned char *uuid
, char *s
) {
215 for (i
=0; i
<16; i
++) {
216 if (i
== 4 || i
== 6 || i
== 8 || i
== 10)
218 *s
++ = tohex((uuid
[i
] >> 4) & 0xf);
219 *s
++ = tohex(uuid
[i
] & 0xf);
226 write_uuid_and_label(char *uuid
, char *volume_name
) {
227 struct swap_header_v1_2
*h
;
230 if (sizeof(struct swap_header_v1
) !=
231 sizeof(struct swap_header_v1_2
)) {
233 _("Bad swap header size, no label written.\n"));
237 h
= (struct swap_header_v1_2
*) signature_page
;
239 memcpy(h
->uuid
, uuid
, sizeof(h
->uuid
));
241 xstrncpy(h
->volume_name
, volume_name
, sizeof(h
->volume_name
));
242 if (strlen(volume_name
) > strlen(h
->volume_name
))
243 fprintf(stderr
, _("Label was truncated.\n"));
245 if (uuid
|| volume_name
) {
247 printf("LABEL=%s, ", h
->volume_name
);
249 printf(_("no label, "));
250 #ifdef HAVE_UUID_UUID_H
252 char uuid_string
[37];
253 uuid_unparse(uuid
, uuid_string
);
254 printf("UUID=%s\n", uuid_string
);
257 printf(_("no uuid\n"));
262 * Find out what the maximum amount of swap space is that the kernel will
263 * handle. This wouldn't matter if the kernel just used as much of the
264 * swap space as it can handle, but until 2.3.4 it would return an error
265 * to swapon() if the swapspace was too large.
267 #define V0_MAX_PAGES (8 * (pagesize - 10))
268 /* Before 2.2.0pre9 */
269 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
270 /* Since 2.2.0pre9, before 2.3.4:
271 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
273 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
274 #define SWP_OFFSET(entry) ((entry) >> 8)
275 on the various architectures. Below the result - yuk.
277 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
278 i386 2^12 o<<8 e>>8 1<<24 1<<19
279 mips 2^12 o<<15 e>>15 1<<17 1<<19
280 alpha 2^13 o<<40 e>>40 1<<24 1<<18
281 m68k 2^12 o<<12 e>>12 1<<20 1<<19
282 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
283 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
284 ppc 2^12 o<<8 e>>8 1<<24 1<<19
285 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
286 armv 2^12 o<<9 e>>9 1<<23 1<<19
288 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
290 The bad part is that we need to know this since the kernel will
291 refuse a swap space if it is too large.
293 /* patch from jj - why does this differ from the above? */
294 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
295 the size of virtual address space allocation for vmalloc */
296 #if defined(__alpha__)
297 #define V1_MAX_PAGES ((1 << 24) - 1)
298 #elif defined(__mips__)
299 #define V1_MAX_PAGES ((1 << 17) - 1)
300 #elif defined(__sparc__)
301 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
302 #elif defined(__ia64__)
304 * The actual size will depend on the amount of virtual address space
305 * available to vmalloc the swap map.
307 #define V1_MAX_PAGES ((1UL << 54) - 1)
309 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
311 /* man page now says:
312 The maximum useful size of a swap area now depends on the architecture.
313 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
314 128GB on alpha and 3TB on sparc64.
317 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
320 * One more point of lossage - Linux swapspace really is a mess.
321 * The definition of the bitmap used is architecture dependent,
322 * and requires one to know whether the machine is bigendian,
323 * and if so, whether it will use 32-bit or 64-bit units in
325 * davem writes: "... is based upon an unsigned long type of
326 * the cpu and the native endianness".
327 * So, it seems we can write `unsigned long' below.
328 * However, sparc64 uses 64-bit units in the kernel, while
329 * mkswap may have been translated with 32-bit longs. Thus,
330 * we need an explicit test for version 0 swap on sparc64.
334 bit_set (unsigned long *addr
, unsigned int nr
) {
338 unsigned long long *bitmap
= (unsigned long long *) addr
;
339 unsigned long long bitnum
= (unsigned long long) nr
;
340 unsigned long long rl
, ml
;
342 bitmap
+= bitnum
/ (8 * sizeof(long long));
344 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
349 addr
+= nr
/ (8 * sizeof(unsigned long));
351 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
356 bit_test_and_clear (unsigned long *addr
, unsigned int nr
) {
360 unsigned long long *bitmap
= (unsigned long long *) addr
;
361 unsigned long long bitnum
= (unsigned long long) nr
;
362 unsigned long long rl
, ml
;
364 bitmap
+= bitnum
/ (8 * sizeof(long long));
366 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
368 return ((rl
& ml
) != 0ULL);
371 addr
+= nr
/ (8 * sizeof(unsigned long));
373 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
381 _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] [-L label] /dev/name [blocks]\n"),
387 die(const char *str
) {
388 fprintf(stderr
, "%s: %s\n", program_name
, str
);
395 bit_set(signature_page
, page
);
401 bit_test_and_clear(signature_page
, page
);
403 if (badpages
== MAX_BADPAGES
)
404 die(_("too many bad pages"));
405 p
->badpages
[badpages
] = page
;
412 unsigned int current_page
;
416 buffer
= malloc(pagesize
);
418 die(_("Out of memory"));
420 while (current_page
< PAGES
) {
422 page_ok(current_page
++);
425 if (do_seek
&& lseek(DEV
,current_page
*pagesize
,SEEK_SET
) !=
426 current_page
*pagesize
)
427 die(_("seek failed in check_blocks"));
428 if ((do_seek
= (pagesize
!= read(DEV
, buffer
, pagesize
)))) {
429 page_bad(current_page
++);
432 page_ok(current_page
++);
435 printf(_("one bad page\n"));
436 else if (badpages
> 1)
437 printf(_("%lu bad pages\n"), badpages
);
441 valid_offset (int fd
, off_t offset
) {
444 if (lseek (fd
, offset
, 0) < 0)
446 if (read (fd
, &ch
, 1) < 1)
456 for (high
= 1; high
> 0 && valid_offset (fd
, high
); high
*= 2)
458 while (low
< high
- 1) {
459 const off_t mid
= (low
+ high
) / 2;
461 if (valid_offset (fd
, mid
))
469 /* return size in pages, to avoid integer overflow */
471 get_size(const char *file
) {
475 fd
= open(file
, O_RDONLY
);
480 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) {
481 int sectors_per_page
= pagesize
/512;
482 size
/= sectors_per_page
;
484 size
= find_size(fd
) / pagesize
;
492 return (c
>= '1' && c
<= '9');
496 main(int argc
, char ** argv
) {
499 unsigned long maxpages
;
500 unsigned long goodpages
;
504 char *block_count
= 0;
506 char *opt_label
= NULL
;
508 #ifdef HAVE_UUID_UUID_H
512 program_name
= (argc
&& *argv
) ? argv
[0] : "mkswap";
513 if ((pp
= strrchr(program_name
, '/')) != NULL
)
516 setlocale(LC_ALL
, "");
517 bindtextdomain(PACKAGE
, LOCALEDIR
);
521 (!strcmp(argv
[1], "-V") || !strcmp(argv
[1], "--version"))) {
522 printf(_("%s from %s%s\n"), program_name
, "util-linux-", VERSION
);
526 for (i
=1; i
<argc
; i
++) {
527 if (argv
[i
][0] == '-') {
528 switch (argv
[i
][1]) {
537 if (!*pp
&& i
+1 < argc
)
540 user_pagesize
= atoi(pp
);
546 if (!*pp
&& i
+1 < argc
)
551 version
= atoi(argv
[i
]+2);
556 } else if (!device_name
) {
557 device_name
= argv
[i
];
558 } else if (!block_count
) {
559 block_count
= argv
[i
];
564 #ifdef HAVE_UUID_UUID_H
565 uuid_generate(uuid_dat
);
569 init_signature_page(); /* get pagesize */
573 _("%s: error: Nowhere to set up swap on?\n"),
578 /* this silly user specified the number of blocks
581 int blocks_per_page
= pagesize
/1024;
582 PAGES
= strtoul(block_count
,&tmp
,0)/blocks_per_page
;
586 sz
= get_size(device_name
);
589 } else if (PAGES
> sz
&& !force
) {
592 "size %lu is larger than device size %lu\n"),
594 PAGES
*(pagesize
/1024), sz
*(pagesize
/1024));
599 /* labels only for v1 */
603 /* use version 1 as default, if possible */
604 if (PAGES
<= V0_MAX_PAGES
&& PAGES
> V1_MAX_PAGES
)
606 else if (linux_version_code() < MAKE_VERSION(2,1,117))
608 else if (pagesize
< 2048)
613 if (version
!= 0 && version
!= 1) {
614 fprintf(stderr
, _("%s: error: unknown version %d\n"),
615 program_name
, version
);
621 _("%s: error: swap area needs to be at least %ldkB\n"),
622 program_name
, (long)(10 * pagesize
/ 1000));
627 maxpages
= V0_MAX_PAGES
;
628 else if (linux_version_code() >= MAKE_VERSION(2,3,4))
630 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
631 maxpages
= V1_MAX_PAGES
;
633 maxpages
= V1_OLD_MAX_PAGES
;
635 if (PAGES
> maxpages
) {
638 _("%s: warning: truncating swap area to %ldkB\n"),
639 program_name
, PAGES
* pagesize
/ 1000);
642 if (opt_label
&& version
== 0) {
644 _("%s: error: label only with v1 swap area\n"),
649 DEV
= open(device_name
,O_RDWR
);
650 if (DEV
< 0 || fstat(DEV
, &statbuf
) < 0) {
655 /* Want a block device. Probably not /dev/hda or /dev/hdb. */
656 if (!S_ISBLK(statbuf
.st_mode
))
658 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340)
659 die(_("Will not try to make swapdevice on '%s'"));
662 if (!force
&& version
== 0) {
663 /* Don't overwrite partition table unless forced */
664 unsigned char *buffer
= (unsigned char *)signature_page
;
665 unsigned short *q
, sum
;
667 if (read(DEV
, buffer
, 512) != 512)
668 die(_("fatal: first page unreadable"));
669 if (buffer
[508] == 0xDA && buffer
[509] == 0xBE) {
670 q
= (unsigned short *)(buffer
+ 510);
671 for (sum
= 0; q
>= (unsigned short *) buffer
;)
675 %s: Device '%s' contains a valid Sun disklabel.\n\
676 This probably means creating v0 swap would destroy your partition table\n\
677 No swap created. If you really want to create swap v0 on that device, use\n\
678 the -f option to force it.\n"),
679 program_name
, device_name
);
686 if (version
== 0 || check
)
688 if (version
== 0 && !bit_test_and_clear(signature_page
,0))
689 die(_("fatal: first page unreadable"));
691 p
->version
= version
;
692 p
->last_page
= PAGES
-1;
693 p
->nr_badpages
= badpages
;
696 goodpages
= PAGES
- badpages
- 1;
697 if ((long) goodpages
<= 0)
698 die(_("Unable to set up swap-space: unreadable"));
699 printf(_("Setting up swapspace version %d, size = %llu kB\n"),
700 version
, (unsigned long long)goodpages
* pagesize
/ 1000);
701 write_signature((version
== 0) ? "SWAP-SPACE" : "SWAPSPACE2");
704 write_uuid_and_label(uuid
, opt_label
);
706 offset
= ((version
== 0) ? 0 : 1024);
707 if (lseek(DEV
, offset
, SEEK_SET
) != offset
)
708 die(_("unable to rewind swap-device"));
709 if (write(DEV
,(char*)signature_page
+offset
, pagesize
-offset
)
711 die(_("unable to write signature page"));
714 * A subsequent swapon() will fail if the signature
715 * is not actually on disk. (This is a kernel bug.)
719 die(_("fsync failed"));