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
40 #include <sys/ioctl.h> /* for _IO */
41 #include <sys/utsname.h>
44 #ifdef HAVE_LIBSELINUX
45 #include <selinux/selinux.h>
46 #include <selinux/context.h>
49 #include "linux_version.h"
50 #include "swapheader.h"
54 #include "pathnames.h"
57 #include <uuid/uuid.h>
60 static char * program_name
= "mkswap";
61 static char * device_name
= NULL
;
63 static unsigned long PAGES
= 0;
64 static unsigned long badpages
= 0;
66 static int version
= -1;
68 #define SELINUX_SWAPFILE_TYPE "swapfile_t"
72 # define is_sparc64() 1
78 static int sparc64
= -1;
80 if (sparc64
!= -1) return sparc64
;
83 if (uname(&un
) < 0) return 0;
84 if (! strcmp(un
.machine
, "sparc64")) {
88 if (strcmp(un
.machine
, "sparc"))
89 return 0; /* Should not happen */
91 #ifdef HAVE_PERSONALITY
93 extern int personality(unsigned long);
95 #define PERS_LINUX 0x00000000
96 #define PERS_LINUX_32BIT 0x00800000
97 #define PERS_LINUX32 0x00000008
99 oldpers
= personality(PERS_LINUX_32BIT
);
101 if (personality(PERS_LINUX
) != -1) {
103 if (! strcmp(un
.machine
, "sparc64")) {
105 oldpers
= PERS_LINUX32
;
108 personality(oldpers
);
115 # define is_be64() is_sparc64()
116 # endif /* sparc32 */
122 * The definition of the union swap_header uses the kernel constant PAGE_SIZE.
123 * Unfortunately, on some architectures this depends on the hardware model, and
124 * can only be found at run time -- we use getpagesize(), so that we do not
125 * need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
127 * Even more unfortunately, getpagesize() does not always return the right
128 * information. For example, libc4, libc5 and glibc 2.0 do not use the system
129 * call but invent a value themselves (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC),
130 * and thus it may happen that e.g. on a sparc kernel PAGE_SIZE=4096 and
131 * getpagesize() returns 8192.
133 * What to do? Let us allow the user to specify the pagesize explicitly.
136 static int user_pagesize
;
138 static unsigned long *signature_page
;
139 struct swap_header_v1
*p
;
142 init_signature_page(void) {
144 int kernel_pagesize
= pagesize
= getpagesize();
147 if ((user_pagesize
& (user_pagesize
-1)) ||
148 user_pagesize
< 1024) {
149 fprintf(stderr
, _("Bad user-specified page size %d\n"),
153 pagesize
= user_pagesize
;
156 if (user_pagesize
&& user_pagesize
!= kernel_pagesize
)
157 fprintf(stderr
, _("Using user-specified page size %d, "
158 "instead of the system value %d\n"),
159 pagesize
, kernel_pagesize
);
161 signature_page
= (unsigned long *) malloc(pagesize
);
162 memset(signature_page
, 0, pagesize
);
163 p
= (struct swap_header_v1
*) signature_page
;
167 write_signature(char *sig
) {
168 char *sp
= (char *) signature_page
;
170 strncpy(sp
+pagesize
-10, sig
, 10);
174 write_uuid_and_label(unsigned char *uuid
, char *volume_name
) {
175 struct swap_header_v1_2
*h
;
178 if (sizeof(struct swap_header_v1
) !=
179 sizeof(struct swap_header_v1_2
)) {
181 _("Bad swap header size, no label written.\n"));
185 h
= (struct swap_header_v1_2
*) signature_page
;
187 memcpy(h
->uuid
, uuid
, sizeof(h
->uuid
));
189 xstrncpy(h
->volume_name
, volume_name
, sizeof(h
->volume_name
));
190 if (strlen(volume_name
) > strlen(h
->volume_name
))
191 fprintf(stderr
, _("Label was truncated.\n"));
193 if (uuid
|| volume_name
) {
195 printf("LABEL=%s, ", h
->volume_name
);
197 printf(_("no label, "));
200 char uuid_string
[37];
201 uuid_unparse(uuid
, uuid_string
);
202 printf("UUID=%s\n", uuid_string
);
205 printf(_("no uuid\n"));
210 * Find out what the maximum amount of swap space is that the kernel will
211 * handle. This wouldn't matter if the kernel just used as much of the
212 * swap space as it can handle, but until 2.3.4 it would return an error
213 * to swapon() if the swapspace was too large.
215 #define V0_MAX_PAGES (8 * (pagesize - 10))
216 /* Before 2.2.0pre9 */
217 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
218 /* Since 2.2.0pre9, before 2.3.4:
219 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
221 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
222 #define SWP_OFFSET(entry) ((entry) >> 8)
223 on the various architectures. Below the result - yuk.
225 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
226 i386 2^12 o<<8 e>>8 1<<24 1<<19
227 mips 2^12 o<<15 e>>15 1<<17 1<<19
228 alpha 2^13 o<<40 e>>40 1<<24 1<<18
229 m68k 2^12 o<<12 e>>12 1<<20 1<<19
230 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
231 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
232 ppc 2^12 o<<8 e>>8 1<<24 1<<19
233 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
234 armv 2^12 o<<9 e>>9 1<<23 1<<19
236 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
238 The bad part is that we need to know this since the kernel will
239 refuse a swap space if it is too large.
241 /* patch from jj - why does this differ from the above? */
242 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
243 the size of virtual address space allocation for vmalloc */
244 #if defined(__alpha__)
245 #define V1_MAX_PAGES ((1 << 24) - 1)
246 #elif defined(__mips__)
247 #define V1_MAX_PAGES ((1 << 17) - 1)
248 #elif defined(__sparc__)
249 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
250 #elif defined(__ia64__)
252 * The actual size will depend on the amount of virtual address space
253 * available to vmalloc the swap map.
255 #define V1_MAX_PAGES ((1UL << 54) - 1)
257 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
259 /* man page now says:
260 The maximum useful size of a swap area now depends on the architecture.
261 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
262 128GB on alpha and 3TB on sparc64.
265 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
268 * One more point of lossage - Linux swapspace really is a mess.
269 * The definition of the bitmap used is architecture dependent,
270 * and requires one to know whether the machine is bigendian,
271 * and if so, whether it will use 32-bit or 64-bit units in
273 * davem writes: "... is based upon an unsigned long type of
274 * the cpu and the native endianness".
275 * So, it seems we can write `unsigned long' below.
276 * However, sparc64 uses 64-bit units in the kernel, while
277 * mkswap may have been translated with 32-bit longs. Thus,
278 * we need an explicit test for version 0 swap on sparc64.
282 bit_set (unsigned long *addr
, unsigned int nr
) {
286 unsigned long long *bitmap
= (unsigned long long *) addr
;
287 unsigned long long bitnum
= (unsigned long long) nr
;
288 unsigned long long rl
, ml
;
290 bitmap
+= bitnum
/ (8 * sizeof(long long));
292 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
297 addr
+= nr
/ (8 * sizeof(unsigned long));
299 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
304 bit_test_and_clear (unsigned long *addr
, unsigned int nr
) {
308 unsigned long long *bitmap
= (unsigned long long *) addr
;
309 unsigned long long bitnum
= (unsigned long long) nr
;
310 unsigned long long rl
, ml
;
312 bitmap
+= bitnum
/ (8 * sizeof(long long));
314 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
316 return ((rl
& ml
) != 0ULL);
319 addr
+= nr
/ (8 * sizeof(unsigned long));
321 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
329 _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] [-L label] [-U UUID] /dev/name [blocks]\n"),
335 die(const char *str
) {
336 fprintf(stderr
, "%s: %s\n", program_name
, str
);
343 bit_set(signature_page
, page
);
349 bit_test_and_clear(signature_page
, page
);
351 if (badpages
== MAX_BADPAGES
)
352 die(_("too many bad pages"));
353 p
->badpages
[badpages
] = page
;
360 unsigned int current_page
;
364 buffer
= malloc(pagesize
);
366 die(_("Out of memory"));
368 while (current_page
< PAGES
) {
370 page_ok(current_page
++);
373 if (do_seek
&& lseek(DEV
,current_page
*pagesize
,SEEK_SET
) !=
374 current_page
*pagesize
)
375 die(_("seek failed in check_blocks"));
376 if ((do_seek
= (pagesize
!= read(DEV
, buffer
, pagesize
)))) {
377 page_bad(current_page
++);
380 page_ok(current_page
++);
383 printf(_("one bad page\n"));
384 else if (badpages
> 1)
385 printf(_("%lu bad pages\n"), badpages
);
388 /* return size in pages, to avoid integer overflow */
390 get_size(const char *file
) {
392 unsigned long long size
;
394 fd
= open(file
, O_RDONLY
);
399 if (blkdev_get_size(fd
, &size
) == 0)
402 size
= blkdev_find_size(fd
) / pagesize
;
410 return (c
>= '1' && c
<= '9');
415 * Check to make certain that our new filesystem won't be created on
416 * an already mounted partition. Code adapted from mke2fs, Copyright
417 * (C) 1994 Theodore Ts'o. Also licensed under GPL.
418 * (C) 2006 Karel Zak -- port to mkswap
425 if ((f
= setmntent (_PATH_MOUNTED
, "r")) == NULL
)
427 while ((mnt
= getmntent (f
)) != NULL
)
428 if (strcmp (device_name
, mnt
->mnt_fsname
) == 0)
438 write_all(int fd
, const void *buf
, size_t count
) {
443 tmp
= write(fd
, buf
, count
);
448 } else if (errno
!= EINTR
&& errno
!= EAGAIN
)
455 main(int argc
, char ** argv
) {
458 unsigned long maxpages
;
459 unsigned long goodpages
;
463 char *block_count
= 0;
465 char *opt_label
= NULL
;
466 unsigned char *uuid
= NULL
;
468 const char *opt_uuid
= NULL
;
472 program_name
= (argc
&& *argv
) ? argv
[0] : "mkswap";
473 if ((pp
= strrchr(program_name
, '/')) != NULL
)
476 setlocale(LC_ALL
, "");
477 bindtextdomain(PACKAGE
, LOCALEDIR
);
481 (!strcmp(argv
[1], "-V") || !strcmp(argv
[1], "--version"))) {
482 printf(_("%s (%s)\n"), program_name
, PACKAGE_STRING
);
486 for (i
=1; i
<argc
; i
++) {
487 if (argv
[i
][0] == '-') {
488 switch (argv
[i
][1]) {
497 if (!*pp
&& i
+1 < argc
)
500 user_pagesize
= atoi(pp
);
506 if (!*pp
&& i
+1 < argc
)
511 version
= atoi(argv
[i
]+2);
515 opt_uuid
= argv
[i
]+2;
516 if (!*opt_uuid
&& i
+1 < argc
)
517 opt_uuid
= argv
[++i
];
519 fprintf(stderr
, _("%1$s: warning: ignore -U (UUIDs are unsupported by %1$s)\n"),
526 } else if (!device_name
) {
527 device_name
= argv
[i
];
528 } else if (!block_count
) {
529 block_count
= argv
[i
];
536 if (uuid_parse(opt_uuid
, uuid_dat
) != 0)
537 die(_("error: UUID parsing failed"));
539 uuid_generate(uuid_dat
);
543 init_signature_page(); /* get pagesize */
547 _("%s: error: Nowhere to set up swap on?\n"),
552 /* this silly user specified the number of blocks
555 int blocks_per_page
= pagesize
/1024;
556 PAGES
= strtoul(block_count
,&tmp
,0)/blocks_per_page
;
560 sz
= get_size(device_name
);
563 } else if (PAGES
> sz
&& !force
) {
566 "size %lu KiB is larger than device size %lu KiB\n"),
568 PAGES
*(pagesize
/1024), sz
*(pagesize
/1024));
573 /* labels only for v1 */
577 /* use version 1 as default, if possible */
579 if (get_linux_version() < KERNEL_VERSION(2,1,117))
588 if (version
!= 0 && version
!= 1) {
589 fprintf(stderr
, _("%s: error: unknown version %d\n"),
590 program_name
, version
);
596 _("%s: error: swap area needs to be at least %ld KiB\n"),
597 program_name
, (long)(10 * pagesize
/1024));
602 maxpages
= V0_MAX_PAGES
;
604 else if (get_linux_version() >= KERNEL_VERSION(2,3,4))
606 else if (get_linux_version() >= KERNEL_VERSION(2,2,1))
607 maxpages
= V1_MAX_PAGES
;
610 maxpages
= V1_OLD_MAX_PAGES
;
612 if (PAGES
> maxpages
) {
615 _("%s: warning: truncating swap area to %ld KiB\n"),
616 program_name
, PAGES
* pagesize
/ 1024);
619 if (opt_label
&& version
== 0) {
621 _("%s: error: label only with v1 swap area\n"),
626 if (stat(device_name
, &statbuf
) < 0) {
630 if (S_ISBLK(statbuf
.st_mode
))
631 DEV
= open(device_name
, O_RDWR
| O_EXCL
);
633 DEV
= open(device_name
, O_RDWR
);
640 /* Want a block device. Probably not /dev/hda or /dev/hdb. */
641 if (!S_ISBLK(statbuf
.st_mode
))
643 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340) {
646 "will not try to make swapdevice on '%s'\n"),
647 program_name
, device_name
);
649 } else if (check_mount()) {
652 "%s is mounted; will not make swapspace.\n"),
653 program_name
, device_name
);
658 if (!force
&& version
== 0) {
659 /* Don't overwrite partition table unless forced */
660 unsigned char *buffer
= (unsigned char *)signature_page
;
661 unsigned short *q
, sum
;
663 if (read(DEV
, buffer
, 512) != 512)
664 die(_("fatal: first page unreadable"));
665 if (buffer
[508] == 0xDA && buffer
[509] == 0xBE) {
666 q
= (unsigned short *)(buffer
+ 510);
667 for (sum
= 0; q
>= (unsigned short *) buffer
;)
671 %s: Device '%s' contains a valid Sun disklabel.\n\
672 This probably means creating v0 swap would destroy your partition table.\n\
673 No swap was created. If you really want to create v0 swap on that device,\n\
674 use the -f option to force it.\n"),
675 program_name
, device_name
);
682 if (version
== 0 || check
)
684 if (version
== 0 && !bit_test_and_clear(signature_page
,0))
685 die(_("fatal: first page unreadable"));
687 p
->version
= version
;
688 p
->last_page
= PAGES
-1;
689 p
->nr_badpages
= badpages
;
692 goodpages
= PAGES
- badpages
- 1;
693 if ((long) goodpages
<= 0)
694 die(_("Unable to set up swap-space: unreadable"));
695 printf(_("Setting up swapspace version %d, size = %llu KiB\n"),
696 version
, (unsigned long long)goodpages
* pagesize
/ 1024);
697 write_signature((version
== 0) ? "SWAP-SPACE" : "SWAPSPACE2");
700 write_uuid_and_label(uuid
, opt_label
);
702 offset
= ((version
== 0) ? 0 : 1024);
703 if (lseek(DEV
, offset
, SEEK_SET
) != offset
)
704 die(_("unable to rewind swap-device"));
705 if (write_all(DEV
, (char *) signature_page
+ offset
,
706 pagesize
- offset
) == -1) {
707 fprintf(stderr
, _("%s: %s: unable to write signature page: %s"),
708 program_name
, device_name
, strerror(errno
));
713 * A subsequent swapon() will fail if the signature
714 * is not actually on disk. (This is a kernel bug.)
718 die(_("fsync failed"));
721 #ifdef HAVE_LIBSELINUX
722 if (S_ISREG(statbuf
.st_mode
) && is_selinux_enabled() > 0) {
723 security_context_t context_string
;
724 security_context_t oldcontext
;
725 context_t newcontext
;
727 if (fgetfilecon(DEV
, &oldcontext
) < 0) {
728 if (errno
!= ENODATA
) {
729 fprintf(stderr
, _("%s: %s: unable to obtain selinux file label: %s\n"),
730 program_name
, device_name
,
734 if (matchpathcon(device_name
, statbuf
.st_mode
, &oldcontext
))
735 die(_("unable to matchpathcon()"));
737 if (!(newcontext
= context_new(oldcontext
)))
738 die(_("unable to create new selinux context"));
739 if (context_type_set(newcontext
, SELINUX_SWAPFILE_TYPE
))
740 die(_("couldn't compute selinux context"));
742 context_string
= context_str(newcontext
);
744 if (strcmp(context_string
, oldcontext
)!=0) {
745 if (fsetfilecon(DEV
, context_string
)) {
746 fprintf(stderr
, _("%s: unable to relabel %s to %s: %s\n"),
747 program_name
, device_name
,
753 context_free(newcontext
);