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
41 #include <sys/ioctl.h> /* for _IO */
42 #include <sys/utsname.h>
45 #ifdef HAVE_LIBSELINUX
46 #include <selinux/selinux.h>
47 #include <selinux/context.h>
50 #include "linux_version.h"
51 #include "swapheader.h"
55 #include "pathnames.h"
57 #include "wholedisk.h"
60 # ifdef HAVE_UUID_UUID_H
61 # include <uuid/uuid.h>
67 static char * program_name = "mkswap";
68 static char * device_name = NULL;
70 static unsigned long long PAGES = 0;
71 static unsigned long badpages = 0;
74 #define SELINUX_SWAPFILE_TYPE "swapfile_t"
78 # define is_sparc64() 1
84 static int sparc64 = -1;
86 if (sparc64 != -1) return sparc64;
89 if (uname(&un) < 0) return 0;
90 if (! strcmp(un.machine, "sparc64")) {
94 if (strcmp(un.machine, "sparc"))
95 return 0; /* Should not happen */
97 #ifdef HAVE_PERSONALITY
99 extern int personality(unsigned long);
101 #define PERS_LINUX 0x00000000
102 #define PERS_LINUX_32BIT 0x00800000
103 #define PERS_LINUX32 0x00000008
105 oldpers = personality(PERS_LINUX_32BIT);
107 if (personality(PERS_LINUX) != -1) {
109 if (! strcmp(un.machine, "sparc64")) {
111 oldpers = PERS_LINUX32;
114 personality(oldpers);
121 # define is_be64() is_sparc64()
122 # endif /* sparc32 */
128 * The definition of the union swap_header uses the kernel constant PAGE_SIZE.
129 * Unfortunately, on some architectures this depends on the hardware model, and
130 * can only be found at run time -- we use getpagesize(), so that we do not
131 * need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
133 * Even more unfortunately, getpagesize() does not always return the right
134 * information. For example, libc4, libc5 and glibc 2.0 do not use the system
135 * call but invent a value themselves (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC),
136 * and thus it may happen that e.g. on a sparc kernel PAGE_SIZE=4096 and
137 * getpagesize() returns 8192.
139 * What to do? Let us allow the user to specify the pagesize explicitly.
142 static int user_pagesize;
144 static unsigned long *signature_page = NULL;
145 struct swap_header_v1 *p;
148 init_signature_page(void) {
150 int kernel_pagesize = pagesize = getpagesize();
153 if ((user_pagesize & (user_pagesize-1)) ||
154 user_pagesize < 1024) {
155 fprintf(stderr, _("Bad user-specified page size %d\n"),
159 pagesize = user_pagesize;
162 if (user_pagesize && user_pagesize != kernel_pagesize)
163 fprintf(stderr, _("Using user-specified page size %d, "
164 "instead of the system value %d\n"),
165 pagesize, kernel_pagesize);
167 signature_page = (unsigned long *) malloc(pagesize);
168 memset(signature_page, 0, pagesize);
169 p = (struct swap_header_v1 *) signature_page;
173 deinit_signature_page(void) {
174 free(signature_page);
178 write_signature(char *sig) {
179 char *sp = (char *) signature_page;
181 strncpy(sp+pagesize-10, sig, 10);
185 write_uuid_and_label(unsigned char *uuid, char *volume_name) {
186 struct swap_header_v1_2 *h;
189 if (sizeof(struct swap_header_v1) !=
190 sizeof(struct swap_header_v1_2)) {
192 _("Bad swap header size, no label written.\n"));
196 h = (struct swap_header_v1_2 *) signature_page;
198 memcpy(h->uuid, uuid, sizeof(h->uuid));
200 xstrncpy(h->volume_name, volume_name, sizeof(h->volume_name));
201 if (strlen(volume_name) > strlen(h->volume_name))
202 fprintf(stderr, _("Label was truncated.\n"));
204 if (uuid || volume_name) {
206 printf("LABEL=%s, ", h->volume_name);
208 printf(_("no label, "));
211 char uuid_string[37];
212 uuid_unparse(uuid, uuid_string);
213 printf("UUID=%s\n", uuid_string);
216 printf(_("no uuid\n"));
221 * Find out what the maximum amount of swap space is that the kernel will
222 * handle. This wouldn't matter if the kernel just used as much of the
223 * swap space as it can handle, but until 2.3.4 it would return an error
224 * to swapon() if the swapspace was too large.
226 /* Before 2.2.0pre9 */
227 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
228 /* Since 2.2.0pre9, before 2.3.4:
229 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
231 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
232 #define SWP_OFFSET(entry) ((entry) >> 8)
233 on the various architectures. Below the result - yuk.
235 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
236 i386 2^12 o<<8 e>>8 1<<24 1<<19
237 mips 2^12 o<<15 e>>15 1<<17 1<<19
238 alpha 2^13 o<<40 e>>40 1<<24 1<<18
239 m68k 2^12 o<<12 e>>12 1<<20 1<<19
240 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
241 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
242 ppc 2^12 o<<8 e>>8 1<<24 1<<19
243 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
244 armv 2^12 o<<9 e>>9 1<<23 1<<19
246 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
248 The bad part is that we need to know this since the kernel will
249 refuse a swap space if it is too large.
251 /* patch from jj - why does this differ from the above? */
252 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
253 the size of virtual address space allocation for vmalloc */
254 #if defined(__alpha__)
255 #define V1_MAX_PAGES ((1 << 24) - 1)
256 #elif defined(__mips__)
257 #define V1_MAX_PAGES ((1 << 17) - 1)
258 #elif defined(__sparc__)
259 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
260 #elif defined(__ia64__)
262 * The actual size will depend on the amount of virtual address space
263 * available to vmalloc the swap map.
265 #define V1_MAX_PAGES ((1UL << 54) - 1)
267 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
269 /* man page now says:
270 The maximum useful size of a swap area now depends on the architecture.
271 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
272 128GB on alpha and 3TB on sparc64.
275 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
276 #define MIN_GOODPAGES 10
281 _("Usage: %s [-c] [-pPAGESZ] [-L label] [-U UUID] /dev/name [blocks]\n"),
287 die(const char *str) {
288 fprintf(stderr, "%s: %s\n", program_name, str);
294 if (badpages == MAX_BADPAGES)
295 die(_("too many bad pages"));
296 p->badpages[badpages] = page;
302 unsigned int current_page;
306 buffer = malloc(pagesize);
308 die(_("Out of memory"));
310 while (current_page < PAGES) {
311 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
312 current_page*pagesize)
313 die(_("seek failed in check_blocks"));
314 if ((do_seek = (pagesize != read(DEV, buffer, pagesize))))
315 page_bad(current_page);
319 printf(_("one bad page\n"));
320 else if (badpages > 1)
321 printf(_("%lu bad pages\n"), badpages);
325 /* return size in pages */
326 static unsigned long long
327 get_size(const char *file) {
329 unsigned long long size;
331 fd = open(file, O_RDONLY);
336 if (blkdev_get_size(fd, &size) == 0)
339 size = blkdev_find_size(fd) / pagesize;
347 return (c >= '1' && c <= '9');
352 * Check to make certain that our new filesystem won't be created on
353 * an already mounted partition. Code adapted from mke2fs, Copyright
354 * (C) 1994 Theodore Ts'o. Also licensed under GPL.
355 * (C) 2006 Karel Zak -- port to mkswap
362 if ((f = setmntent (_PATH_MOUNTED, "r")) == NULL)
364 while ((mnt = getmntent (f)) != NULL)
365 if (strcmp (device_name, mnt->mnt_fsname) == 0)
375 write_all(int fd, const void *buf, size_t count) {
380 tmp = write(fd, buf, count);
385 } else if (errno != EINTR && errno != EAGAIN)
392 zap_bootbits(int fd, const char *devname, int force)
394 const char *type = NULL;
398 if (lseek(fd, 0, SEEK_SET) != 0)
399 die(_("unable to rewind swap-device"));
401 if (is_whole_disk_fd(fd, devname))
402 /* don't zap bootbits on whole disk -- we know nothing
403 * about bootloaders on the device */
406 else if ((type = get_pt_type_fd(fd)))
407 /* don't zap partition table */
414 if (lseek(fd, 0, SEEK_SET) != 0)
415 die(_("unable to rewind swap-device"));
417 memset(buf, 0, sizeof(buf));
418 if (write_all(fd, buf, sizeof(buf)))
419 die(_("unable to erase bootbits sectors"));
423 fprintf(stderr, _("%s: %s: warning: don't erase bootbits sectors\n"),
424 program_name, devname);
426 fprintf(stderr, _(" (%s partition table detected). "), type);
428 fprintf(stderr, _(" on whole disk. "));
429 fprintf(stderr, "Use -f to force.\n");
433 main(int argc, char ** argv) {
436 unsigned long long maxpages;
437 unsigned long long goodpages;
438 unsigned long long sz;
442 char *block_count = 0;
444 char *opt_label = NULL;
445 unsigned char *uuid = NULL;
447 const char *opt_uuid = NULL;
451 program_name = (argc && *argv) ? argv[0] : "mkswap";
452 if ((pp = strrchr(program_name, '/')) != NULL)
455 setlocale(LC_ALL, "");
456 bindtextdomain(PACKAGE, LOCALEDIR);
460 (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
461 printf(_("%s (%s)\n"), program_name, PACKAGE_STRING);
465 for (i=1; i<argc; i++) {
466 if (argv[i][0] == '-') {
467 switch (argv[i][1]) {
476 if (!*pp && i+1 < argc)
479 user_pagesize = atoi(pp);
485 if (!*pp && i+1 < argc)
490 version = atoi(argv[i]+2);
494 opt_uuid = argv[i]+2;
495 if (!*opt_uuid && i+1 < argc)
496 opt_uuid = argv[++i];
498 fprintf(stderr, _("%1$s: warning: ignore -U (UUIDs are unsupported by %1$s)\n"),
505 } else if (!device_name) {
506 device_name = argv[i];
507 } else if (!block_count) {
508 block_count = argv[i];
514 fprintf(stderr, _("%s: does not support swapspace version %d.\n"),
515 program_name, version);
521 if (uuid_parse(opt_uuid, uuid_dat) != 0)
522 die(_("error: UUID parsing failed"));
524 uuid_generate(uuid_dat);
528 init_signature_page(); /* get pagesize */
529 atexit(deinit_signature_page);
533 _("%s: error: Nowhere to set up swap on?\n"),
538 /* this silly user specified the number of blocks
541 int blocks_per_page = pagesize/1024;
542 PAGES = strtoull(block_count,&tmp,0)/blocks_per_page;
546 sz = get_size(device_name);
549 } else if (PAGES > sz && !force) {
552 "size %llu KiB is larger than device size %llu KiB\n"),
554 PAGES*(pagesize/1024), sz*(pagesize/1024));
558 if (PAGES < MIN_GOODPAGES) {
560 _("%s: error: swap area needs to be at least %ld KiB\n"),
561 program_name, (long)(MIN_GOODPAGES * pagesize/1024));
566 if (get_linux_version() >= KERNEL_VERSION(2,3,4))
567 maxpages = UINT_MAX + 1ULL;
568 else if (get_linux_version() >= KERNEL_VERSION(2,2,1))
569 maxpages = V1_MAX_PAGES;
572 maxpages = V1_OLD_MAX_PAGES;
574 if (PAGES > maxpages) {
577 _("%s: warning: truncating swap area to %llu KiB\n"),
578 program_name, PAGES * pagesize / 1024);
581 if (stat(device_name, &statbuf) < 0) {
585 if (S_ISBLK(statbuf.st_mode))
586 DEV = open(device_name, O_RDWR | O_EXCL);
588 DEV = open(device_name, O_RDWR);
595 /* Want a block device. Probably not /dev/hda or /dev/hdb. */
596 if (!S_ISBLK(statbuf.st_mode))
598 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
601 "will not try to make swapdevice on '%s'\n"),
602 program_name, device_name);
604 } else if (check_mount()) {
607 "%s is mounted; will not make swapspace.\n"),
608 program_name, device_name);
615 zap_bootbits(DEV, device_name, force);
618 p->last_page = PAGES-1;
619 p->nr_badpages = badpages;
621 if (badpages > PAGES - MIN_GOODPAGES)
622 die(_("Unable to set up swap-space: unreadable"));
624 goodpages = PAGES - badpages - 1;
625 printf(_("Setting up swapspace version 1, size = %llu KiB\n"),
626 goodpages * pagesize / 1024);
628 write_signature("SWAPSPACE2");
629 write_uuid_and_label(uuid, opt_label);
632 if (lseek(DEV, offset, SEEK_SET) != offset)
633 die(_("unable to rewind swap-device"));
634 if (write_all(DEV, (char *) signature_page + offset,
635 pagesize - offset) == -1) {
636 fprintf(stderr, _("%s: %s: unable to write signature page: %s"),
637 program_name, device_name, strerror(errno));
642 * A subsequent swapon() will fail if the signature
643 * is not actually on disk. (This is a kernel bug.)
647 die(_("fsync failed"));
650 #ifdef HAVE_LIBSELINUX
651 if (S_ISREG(statbuf.st_mode) && is_selinux_enabled() > 0) {
652 security_context_t context_string;
653 security_context_t oldcontext;
654 context_t newcontext;
656 if (fgetfilecon(DEV, &oldcontext) < 0) {
657 if (errno != ENODATA) {
658 fprintf(stderr, _("%s: %s: unable to obtain selinux file label: %s\n"),
659 program_name, device_name,
663 if (matchpathcon(device_name, statbuf.st_mode, &oldcontext))
664 die(_("unable to matchpathcon()"));
666 if (!(newcontext = context_new(oldcontext)))
667 die(_("unable to create new selinux context"));
668 if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE))
669 die(_("couldn't compute selinux context"));
671 context_string = context_str(newcontext);
673 if (strcmp(context_string, oldcontext)!=0) {
674 if (fsetfilecon(DEV, context_string)) {
675 fprintf(stderr, _("%s: unable to relabel %s to %s: %s\n"),
676 program_name, device_name,
682 context_free(newcontext);