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 "swapheader.h"
54 #include <uuid/uuid.h>
59 #define BLKGETSIZE 0x1260
61 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
62 #define BLKGETSIZE _IO(0x12,96)
65 static char * program_name
= "mkswap";
66 static char * device_name
= NULL
;
68 static unsigned long PAGES
= 0;
69 static unsigned long badpages
= 0;
71 static int version
= -1;
73 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
75 #define SELINUX_SWAPFILE_TYPE "swapfile_t"
78 linux_version_code(void) {
79 struct utsname my_utsname
;
82 if (uname(&my_utsname
) == 0) {
83 p
= atoi(strtok(my_utsname
.release
, "."));
84 q
= atoi(strtok(NULL
, "."));
85 r
= atoi(strtok(NULL
, "."));
86 return MAKE_VERSION(p
,q
,r
);
93 # define is_sparc64() 1
99 static int sparc64
= -1;
101 if (sparc64
!= -1) return sparc64
;
104 if (uname(&un
) < 0) return 0;
105 if (! strcmp(un
.machine
, "sparc64")) {
109 if (strcmp(un
.machine
, "sparc"))
110 return 0; /* Should not happen */
112 #ifdef HAVE_PERSONALITY
114 extern int personality(unsigned long);
116 #define PERS_LINUX 0x00000000
117 #define PERS_LINUX_32BIT 0x00800000
118 #define PERS_LINUX32 0x00000008
120 oldpers
= personality(PERS_LINUX_32BIT
);
122 if (personality(PERS_LINUX
) != -1) {
124 if (! strcmp(un
.machine
, "sparc64")) {
126 oldpers
= PERS_LINUX32
;
129 personality(oldpers
);
136 # define is_be64() is_sparc64()
137 # endif /* sparc32 */
143 * The definition of the union swap_header uses the kernel constant PAGE_SIZE.
144 * Unfortunately, on some architectures this depends on the hardware model, and
145 * can only be found at run time -- we use getpagesize(), so that we do not
146 * need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
148 * Even more unfortunately, getpagesize() does not always return the right
149 * information. For example, libc4, libc5 and glibc 2.0 do not use the system
150 * call but invent a value themselves (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC),
151 * and thus it may happen that e.g. on a sparc kernel PAGE_SIZE=4096 and
152 * getpagesize() returns 8192.
154 * What to do? Let us allow the user to specify the pagesize explicitly.
156 * Update 05-Feb-2007 (kzak):
157 * - use sysconf(_SC_PAGESIZE) to be consistent with the rest of
158 * util-linux code. It is the standardized and preferred way of
159 * querying page size.
161 static int user_pagesize
;
163 static unsigned long *signature_page
;
164 struct swap_header_v1
*p
;
167 init_signature_page(void) {
169 int kernel_pagesize
= pagesize
= (int) sysconf(_SC_PAGESIZE
);
172 if ((user_pagesize
& (user_pagesize
-1)) ||
173 user_pagesize
< 1024) {
174 fprintf(stderr
, _("Bad user-specified page size %d\n"),
178 pagesize
= user_pagesize
;
181 if (user_pagesize
&& user_pagesize
!= kernel_pagesize
)
182 fprintf(stderr
, _("Using user-specified page size %d, "
183 "instead of the system value %d\n"),
184 pagesize
, kernel_pagesize
);
186 signature_page
= (unsigned long *) malloc(pagesize
);
187 memset(signature_page
, 0, pagesize
);
188 p
= (struct swap_header_v1
*) signature_page
;
192 write_signature(char *sig
) {
193 char *sp
= (char *) signature_page
;
195 strncpy(sp
+pagesize
-10, sig
, 10);
201 return ((a
< 10) ? '0'+a
: 'a'+a
-10);
205 uuid_unparse(unsigned char *uuid
, char *s
) {
208 for (i
=0; i
<16; i
++) {
209 if (i
== 4 || i
== 6 || i
== 8 || i
== 10)
211 *s
++ = tohex((uuid
[i
] >> 4) & 0xf);
212 *s
++ = tohex(uuid
[i
] & 0xf);
219 write_uuid_and_label(char *uuid
, char *volume_name
) {
220 struct swap_header_v1_2
*h
;
223 if (sizeof(struct swap_header_v1
) !=
224 sizeof(struct swap_header_v1_2
)) {
226 _("Bad swap header size, no label written.\n"));
230 h
= (struct swap_header_v1_2
*) signature_page
;
232 memcpy(h
->uuid
, uuid
, sizeof(h
->uuid
));
234 xstrncpy(h
->volume_name
, volume_name
, sizeof(h
->volume_name
));
235 if (strlen(volume_name
) > strlen(h
->volume_name
))
236 fprintf(stderr
, _("Label was truncated.\n"));
238 if (uuid
|| volume_name
) {
240 printf("LABEL=%s, ", h
->volume_name
);
242 printf(_("no label, "));
245 char uuid_string
[37];
246 uuid_unparse(uuid
, uuid_string
);
247 printf("UUID=%s\n", uuid_string
);
250 printf(_("no uuid\n"));
255 * Find out what the maximum amount of swap space is that the kernel will
256 * handle. This wouldn't matter if the kernel just used as much of the
257 * swap space as it can handle, but until 2.3.4 it would return an error
258 * to swapon() if the swapspace was too large.
260 #define V0_MAX_PAGES (8 * (pagesize - 10))
261 /* Before 2.2.0pre9 */
262 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
263 /* Since 2.2.0pre9, before 2.3.4:
264 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
266 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
267 #define SWP_OFFSET(entry) ((entry) >> 8)
268 on the various architectures. Below the result - yuk.
270 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
271 i386 2^12 o<<8 e>>8 1<<24 1<<19
272 mips 2^12 o<<15 e>>15 1<<17 1<<19
273 alpha 2^13 o<<40 e>>40 1<<24 1<<18
274 m68k 2^12 o<<12 e>>12 1<<20 1<<19
275 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
276 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
277 ppc 2^12 o<<8 e>>8 1<<24 1<<19
278 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
279 armv 2^12 o<<9 e>>9 1<<23 1<<19
281 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
283 The bad part is that we need to know this since the kernel will
284 refuse a swap space if it is too large.
286 /* patch from jj - why does this differ from the above? */
287 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
288 the size of virtual address space allocation for vmalloc */
289 #if defined(__alpha__)
290 #define V1_MAX_PAGES ((1 << 24) - 1)
291 #elif defined(__mips__)
292 #define V1_MAX_PAGES ((1 << 17) - 1)
293 #elif defined(__sparc__)
294 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
295 #elif defined(__ia64__)
297 * The actual size will depend on the amount of virtual address space
298 * available to vmalloc the swap map.
300 #define V1_MAX_PAGES ((1UL << 54) - 1)
302 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
304 /* man page now says:
305 The maximum useful size of a swap area now depends on the architecture.
306 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
307 128GB on alpha and 3TB on sparc64.
310 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
313 * One more point of lossage - Linux swapspace really is a mess.
314 * The definition of the bitmap used is architecture dependent,
315 * and requires one to know whether the machine is bigendian,
316 * and if so, whether it will use 32-bit or 64-bit units in
318 * davem writes: "... is based upon an unsigned long type of
319 * the cpu and the native endianness".
320 * So, it seems we can write `unsigned long' below.
321 * However, sparc64 uses 64-bit units in the kernel, while
322 * mkswap may have been translated with 32-bit longs. Thus,
323 * we need an explicit test for version 0 swap on sparc64.
327 bit_set (unsigned long *addr
, unsigned int nr
) {
331 unsigned long long *bitmap
= (unsigned long long *) addr
;
332 unsigned long long bitnum
= (unsigned long long) nr
;
333 unsigned long long rl
, ml
;
335 bitmap
+= bitnum
/ (8 * sizeof(long long));
337 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
342 addr
+= nr
/ (8 * sizeof(unsigned long));
344 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
349 bit_test_and_clear (unsigned long *addr
, unsigned int nr
) {
353 unsigned long long *bitmap
= (unsigned long long *) addr
;
354 unsigned long long bitnum
= (unsigned long long) nr
;
355 unsigned long long rl
, ml
;
357 bitmap
+= bitnum
/ (8 * sizeof(long long));
359 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
361 return ((rl
& ml
) != 0ULL);
364 addr
+= nr
/ (8 * sizeof(unsigned long));
366 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
374 _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] [-L label] /dev/name [blocks]\n"),
380 die(const char *str
) {
381 fprintf(stderr
, "%s: %s\n", program_name
, str
);
388 bit_set(signature_page
, page
);
394 bit_test_and_clear(signature_page
, page
);
396 if (badpages
== MAX_BADPAGES
)
397 die(_("too many bad pages"));
398 p
->badpages
[badpages
] = page
;
405 unsigned int current_page
;
409 buffer
= malloc(pagesize
);
411 die(_("Out of memory"));
413 while (current_page
< PAGES
) {
415 page_ok(current_page
++);
418 if (do_seek
&& lseek(DEV
,current_page
*pagesize
,SEEK_SET
) !=
419 current_page
*pagesize
)
420 die(_("seek failed in check_blocks"));
421 if ((do_seek
= (pagesize
!= read(DEV
, buffer
, pagesize
)))) {
422 page_bad(current_page
++);
425 page_ok(current_page
++);
428 printf(_("one bad page\n"));
429 else if (badpages
> 1)
430 printf(_("%lu bad pages\n"), badpages
);
434 valid_offset (int fd
, off_t offset
) {
437 if (lseek (fd
, offset
, 0) < 0)
439 if (read (fd
, &ch
, 1) < 1)
449 for (high
= 1; high
> 0 && valid_offset (fd
, high
); high
*= 2)
451 while (low
< high
- 1) {
452 const off_t mid
= (low
+ high
) / 2;
454 if (valid_offset (fd
, mid
))
462 /* return size in pages, to avoid integer overflow */
464 get_size(const char *file
) {
468 fd
= open(file
, O_RDONLY
);
473 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) {
474 int sectors_per_page
= pagesize
/512;
475 size
/= sectors_per_page
;
477 size
= find_size(fd
) / pagesize
;
485 return (c
>= '1' && c
<= '9');
490 * Check to make certain that our new filesystem won't be created on
491 * an already mounted partition. Code adapted from mke2fs, Copyright
492 * (C) 1994 Theodore Ts'o. Also licensed under GPL.
493 * (C) 2006 Karel Zak -- port to mkswap
500 if ((f
= setmntent (MOUNTED
, "r")) == NULL
)
502 while ((mnt
= getmntent (f
)) != NULL
)
503 if (strcmp (device_name
, mnt
->mnt_fsname
) == 0)
512 main(int argc
, char ** argv
) {
515 unsigned long maxpages
;
516 unsigned long goodpages
;
520 char *block_count
= 0;
522 char *opt_label
= NULL
;
528 program_name
= (argc
&& *argv
) ? argv
[0] : "mkswap";
529 if ((pp
= strrchr(program_name
, '/')) != NULL
)
532 setlocale(LC_ALL
, "");
533 bindtextdomain(PACKAGE
, LOCALEDIR
);
537 (!strcmp(argv
[1], "-V") || !strcmp(argv
[1], "--version"))) {
538 printf(_("%s (%s)\n"), program_name
, PACKAGE_STRING
);
542 for (i
=1; i
<argc
; i
++) {
543 if (argv
[i
][0] == '-') {
544 switch (argv
[i
][1]) {
553 if (!*pp
&& i
+1 < argc
)
556 user_pagesize
= atoi(pp
);
562 if (!*pp
&& i
+1 < argc
)
567 version
= atoi(argv
[i
]+2);
572 } else if (!device_name
) {
573 device_name
= argv
[i
];
574 } else if (!block_count
) {
575 block_count
= argv
[i
];
581 uuid_generate(uuid_dat
);
585 init_signature_page(); /* get pagesize */
589 _("%s: error: Nowhere to set up swap on?\n"),
594 /* this silly user specified the number of blocks
597 int blocks_per_page
= pagesize
/1024;
598 PAGES
= strtoul(block_count
,&tmp
,0)/blocks_per_page
;
602 sz
= get_size(device_name
);
605 } else if (PAGES
> sz
&& !force
) {
608 "size %lu is larger than device size %lu\n"),
610 PAGES
*(pagesize
/1024), sz
*(pagesize
/1024));
615 /* labels only for v1 */
619 /* use version 1 as default, if possible */
620 if (linux_version_code() < MAKE_VERSION(2,1,117))
622 else if (pagesize
< 2048)
627 if (version
!= 0 && version
!= 1) {
628 fprintf(stderr
, _("%s: error: unknown version %d\n"),
629 program_name
, version
);
635 _("%s: error: swap area needs to be at least %ldkB\n"),
636 program_name
, (long)(10 * pagesize
/ 1000));
641 maxpages
= V0_MAX_PAGES
;
642 else if (linux_version_code() >= MAKE_VERSION(2,3,4))
644 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
645 maxpages
= V1_MAX_PAGES
;
647 maxpages
= V1_OLD_MAX_PAGES
;
649 if (PAGES
> maxpages
) {
652 _("%s: warning: truncating swap area to %ldkB\n"),
653 program_name
, PAGES
* pagesize
/ 1000);
656 if (opt_label
&& version
== 0) {
658 _("%s: error: label only with v1 swap area\n"),
663 DEV
= open(device_name
,O_RDWR
);
664 if (DEV
< 0 || fstat(DEV
, &statbuf
) < 0) {
669 /* Want a block device. Probably not /dev/hda or /dev/hdb. */
670 if (!S_ISBLK(statbuf
.st_mode
))
672 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340) {
675 "will not try to make swapdevice on '%s'\n"),
676 program_name
, device_name
);
678 } else if (check_mount()) {
681 "%s is mounted; will not make swapspace.\n"),
682 program_name
, device_name
);
687 if (!force
&& version
== 0) {
688 /* Don't overwrite partition table unless forced */
689 unsigned char *buffer
= (unsigned char *)signature_page
;
690 unsigned short *q
, sum
;
692 if (read(DEV
, buffer
, 512) != 512)
693 die(_("fatal: first page unreadable"));
694 if (buffer
[508] == 0xDA && buffer
[509] == 0xBE) {
695 q
= (unsigned short *)(buffer
+ 510);
696 for (sum
= 0; q
>= (unsigned short *) buffer
;)
700 %s: Device '%s' contains a valid Sun disklabel.\n\
701 This probably means creating v0 swap would destroy your partition table\n\
702 No swap created. If you really want to create swap v0 on that device, use\n\
703 the -f option to force it.\n"),
704 program_name
, device_name
);
711 if (version
== 0 || check
)
713 if (version
== 0 && !bit_test_and_clear(signature_page
,0))
714 die(_("fatal: first page unreadable"));
716 p
->version
= version
;
717 p
->last_page
= PAGES
-1;
718 p
->nr_badpages
= badpages
;
721 goodpages
= PAGES
- badpages
- 1;
722 if ((long) goodpages
<= 0)
723 die(_("Unable to set up swap-space: unreadable"));
724 printf(_("Setting up swapspace version %d, size = %llu kB\n"),
725 version
, (unsigned long long)goodpages
* pagesize
/ 1000);
726 write_signature((version
== 0) ? "SWAP-SPACE" : "SWAPSPACE2");
729 write_uuid_and_label(uuid
, opt_label
);
731 offset
= ((version
== 0) ? 0 : 1024);
732 if (lseek(DEV
, offset
, SEEK_SET
) != offset
)
733 die(_("unable to rewind swap-device"));
734 if (write(DEV
,(char*)signature_page
+offset
, pagesize
-offset
)
736 die(_("unable to write signature page"));
739 * A subsequent swapon() will fail if the signature
740 * is not actually on disk. (This is a kernel bug.)
744 die(_("fsync failed"));
747 #ifdef HAVE_LIBSELINUX
748 if (S_ISREG(statbuf
.st_mode
) && is_selinux_enabled()) {
749 security_context_t context_string
;
750 security_context_t oldcontext
;
751 context_t newcontext
;
753 if ((fgetfilecon(DEV
, &oldcontext
) < 0) &&
754 (errno
!= ENODATA
)) {
755 fprintf(stderr
, _("%s: %s: unable to obtain selinux file label: %s\n"),
756 program_name
, device_name
,
760 if (!(newcontext
= context_new(oldcontext
)))
761 die(_("unable to create new selinux context"));
762 if (context_type_set(newcontext
, SELINUX_SWAPFILE_TYPE
))
763 die(_("couldn't compute selinux context"));
765 context_string
= context_str(newcontext
);
767 if (strcmp(context_string
, oldcontext
)!=0) {
768 if (fsetfilecon(DEV
, context_string
)) {
769 fprintf(stderr
, _("%s: unable to relabel %s to %s: %s\n"),
770 program_name
, device_name
,
776 context_free(newcontext
);