]>
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>
44 /* Try to get PAGE_SIZE from libc or kernel includes */
45 #ifdef HAVE_sys_user_h
46 /* Note: <sys/user.h> says: for gdb only */
47 #include <sys/user.h> /* for PAGE_SIZE and PAGE_SHIFT */
49 #ifdef HAVE_asm_page_h
50 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
51 /* we also get PAGE_SIZE via getpagesize() */
57 #define BLKGETSIZE 0x1260
59 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
60 #define BLKGETSIZE _IO(0x12,96)
63 static char * program_name
= "mkswap";
64 static char * device_name
= NULL
;
66 static long PAGES
= 0;
68 static int badpages
= 0;
69 static int version
= -1;
71 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
74 linux_version_code(void) {
75 struct utsname my_utsname
;
78 if (uname(&my_utsname
) == 0) {
79 p
= atoi(strtok(my_utsname
.release
, "."));
80 q
= atoi(strtok(NULL
, "."));
81 r
= atoi(strtok(NULL
, "."));
82 return MAKE_VERSION(p
,q
,r
);
89 # define is_sparc64() 1
95 static int sparc64
= -1;
97 if (sparc64
!= -1) return sparc64
;
100 if (uname(&un
) < 0) return 0;
101 if (! strcmp(un
.machine
, "sparc64")) {
105 if (strcmp(un
.machine
, "sparc"))
106 return 0; /* Should not happen */
108 #ifdef HAVE_personality
110 extern int personality(unsigned long);
112 #define PERS_LINUX 0x00000000
113 #define PERS_LINUX_32BIT 0x00800000
114 #define PERS_LINUX32 0x00000008
116 oldpers
= personality(PERS_LINUX_32BIT
);
118 if (personality(PERS_LINUX
) != -1) {
120 if (! strcmp(un
.machine
, "sparc64")) {
122 oldpers
= PERS_LINUX32
;
125 personality(oldpers
);
132 # define is_be64() is_sparc64()
133 # endif /* sparc32 */
139 * The definition of the union swap_header uses the constant PAGE_SIZE.
140 * Unfortunately, on some architectures this depends on the hardware model,
141 * and can only be found at run time -- we use getpagesize(), so that
142 * we do not need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
144 * Even more unfortunately, getpagesize() does not always return
145 * the right information. For example, libc4 and libc5 do not use
146 * the system call but invent a value themselves
147 * (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC), and thus it may happen
148 * that e.g. on a sparc PAGE_SIZE=4096 and getpagesize() returns 8192.
149 * What to do? Let us allow the user to specify the pagesize explicitly.
152 static int user_pagesize
= 0;
153 static int kernel_pagesize
; /* obtained via getpagesize(); */
154 static int defined_pagesize
= 0; /* PAGE_SIZE, when that exists */
156 static long *signature_page
;
158 struct swap_header_v1
{
159 char bootbits
[1024]; /* Space for disklabel etc. */
160 unsigned int version
;
161 unsigned int last_page
;
162 unsigned int nr_badpages
;
163 unsigned int padding
[125];
164 unsigned int badpages
[1];
168 init_signature_page(void) {
170 defined_pagesize
= PAGE_SIZE
;
172 kernel_pagesize
= getpagesize();
173 pagesize
= kernel_pagesize
;
176 if ((user_pagesize
& (user_pagesize
-1)) ||
177 user_pagesize
< 1024) {
178 fprintf(stderr
, _("Bad user-specified page size %d\n"),
182 pagesize
= user_pagesize
;
185 if (user_pagesize
&& user_pagesize
!= kernel_pagesize
&&
186 user_pagesize
!= defined_pagesize
)
187 fprintf(stderr
, _("Using user-specified page size %d, "
188 "instead of the system values %d/%d\n"),
189 pagesize
, kernel_pagesize
, defined_pagesize
);
190 else if (defined_pagesize
&& pagesize
!= defined_pagesize
)
191 fprintf(stderr
, _("Assuming pages of size %d (not %d)\n"),
192 pagesize
, defined_pagesize
);
194 signature_page
= (long *) malloc(pagesize
);
195 memset(signature_page
,0,pagesize
);
196 p
= (struct swap_header_v1
*) signature_page
;
200 write_signature(char *sig
) {
201 char *sp
= (char *) signature_page
;
203 strncpy(sp
+pagesize
-10, sig
, 10);
207 * Find out what the maximum amount of swap space is that the kernel will
208 * handle. This wouldn't matter if the kernel just used as much of the
209 * swap space as it can handle, but until 2.3.4 it would return an error
210 * to swapon() if the swapspace was too large.
212 #define V0_MAX_PAGES (8 * (pagesize - 10))
213 /* Before 2.2.0pre9 */
214 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
215 /* Since 2.2.0pre9, before 2.3.4:
216 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
218 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
219 #define SWP_OFFSET(entry) ((entry) >> 8)
220 on the various architectures. Below the result - yuk.
222 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
223 i386 2^12 o<<8 e>>8 1<<24 1<<19
224 mips 2^12 o<<15 e>>15 1<<17 1<<19
225 alpha 2^13 o<<40 e>>40 1<<24 1<<18
226 m68k 2^12 o<<12 e>>12 1<<20 1<<19
227 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
228 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
229 ppc 2^12 o<<8 e>>8 1<<24 1<<19
230 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
231 armv 2^12 o<<9 e>>9 1<<23 1<<19
233 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
235 The bad part is that we need to know this since the kernel will
236 refuse a swap space if it is too large.
238 /* patch from jj - why does this differ from the above? */
239 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
240 the size of virtual address space allocation for vmalloc */
241 #if defined(__alpha__)
242 #define V1_MAX_PAGES ((1 << 24) - 1)
243 #elif defined(__mips__)
244 #define V1_MAX_PAGES ((1 << 17) - 1)
245 #elif defined(__sparc__)
246 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
247 #elif defined(__ia64__)
249 * The actual size will depend on the amount of virtual address space
250 * available to vmalloc the swap map.
252 #define V1_MAX_PAGES ((1UL << 54) - 1)
254 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
256 /* man page now says:
257 The maximum useful size of a swap area now depends on the architecture.
258 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
259 128GB on alpha and 3TB on sparc64.
262 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
265 * One more point of lossage - Linux swapspace really is a mess.
266 * The definition of the bitmap used is architecture dependent,
267 * and requires one to know whether the machine is bigendian,
268 * and if so, whether it will use 32-bit or 64-bit units in
270 * davem writes: "... is based upon an unsigned long type of
271 * the cpu and the native endianness".
272 * So, it seems we can write `unsigned long' below.
273 * However, sparc64 uses 64-bit units in the kernel, while
274 * mkswap may have been translated with 32-bit longs. Thus,
275 * we need an explicit test for version 0 swap on sparc64.
279 bit_set (unsigned long *addr
, unsigned int nr
) {
283 unsigned long long *bitmap
= (unsigned long long *) addr
;
284 unsigned long long bitnum
= (unsigned long long) nr
;
285 unsigned long long rl
, ml
;
287 bitmap
+= bitnum
/ (8 * sizeof(long long));
289 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
294 addr
+= nr
/ (8 * sizeof(unsigned long));
296 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
301 bit_test_and_clear (unsigned long *addr
, unsigned int nr
) {
305 unsigned long long *bitmap
= (unsigned long long *) addr
;
306 unsigned long long bitnum
= (unsigned long long) nr
;
307 unsigned long long rl
, ml
;
309 bitmap
+= bitnum
/ (8 * sizeof(long long));
311 ml
= 1ULL << (bitnum
& (8ULL * sizeof(long long) - 1ULL));
313 return ((rl
& ml
) != 0ULL);
316 addr
+= nr
/ (8 * sizeof(unsigned long));
318 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
326 _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] /dev/name [blocks]\n"),
332 die(const char *str
) {
333 fprintf(stderr
, "%s: %s\n", program_name
, str
);
340 bit_set(signature_page
, page
);
346 bit_test_and_clear(signature_page
, page
);
348 if (badpages
== MAX_BADPAGES
)
349 die(_("too many bad pages"));
350 p
->badpages
[badpages
] = page
;
357 unsigned int current_page
;
361 buffer
= malloc(pagesize
);
363 die(_("Out of memory"));
365 while (current_page
< PAGES
) {
367 page_ok(current_page
++);
370 if (do_seek
&& lseek(DEV
,current_page
*pagesize
,SEEK_SET
) !=
371 current_page
*pagesize
)
372 die(_("seek failed in check_blocks"));
373 if ((do_seek
= (pagesize
!= read(DEV
, buffer
, pagesize
)))) {
374 page_bad(current_page
++);
377 page_ok(current_page
++);
380 printf(_("one bad page\n"));
381 else if (badpages
> 1)
382 printf(_("%d bad pages\n"), badpages
);
386 valid_offset (int fd
, off_t offset
) {
389 if (lseek (fd
, offset
, 0) < 0)
391 if (read (fd
, &ch
, 1) < 1)
401 for (high
= 1; high
> 0 && valid_offset (fd
, high
); high
*= 2)
403 while (low
< high
- 1) {
404 const off_t mid
= (low
+ high
) / 2;
406 if (valid_offset (fd
, mid
))
414 /* return size in pages, to avoid integer overflow */
416 get_size(const char *file
) {
420 fd
= open(file
, O_RDONLY
);
425 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) {
426 int sectors_per_page
= pagesize
/512;
427 size
/= sectors_per_page
;
429 size
= find_size(fd
) / pagesize
;
437 return (c
>= '1' && c
<= '9');
441 main(int argc
, char ** argv
) {
448 char *block_count
= 0;
451 program_name
= (argc
&& *argv
) ? argv
[0] : "fsck.minix";
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 from %s\n"), program_name
, util_linux_version
);
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
);
484 version
= atoi(argv
[i
]+2);
489 } else if (!device_name
) {
490 device_name
= argv
[i
];
491 } else if (!block_count
) {
492 block_count
= argv
[i
];
497 init_signature_page(); /* get pagesize */
501 _("%s: error: Nowhere to set up swap on?\n"),
506 /* this silly user specified the number of blocks
509 int blocks_per_page
= pagesize
/1024;
510 PAGES
= strtol(block_count
,&tmp
,0)/blocks_per_page
;
514 sz
= get_size(device_name
);
517 } else if (PAGES
> sz
&& !force
) {
520 "size %ld is larger than device size %d\n"),
522 PAGES
*(pagesize
/1024), sz
*(pagesize
/1024));
527 /* use version 1 as default, if possible */
528 if (PAGES
<= V0_MAX_PAGES
&& PAGES
> V1_MAX_PAGES
)
530 else if (linux_version_code() < MAKE_VERSION(2,1,117))
532 else if (pagesize
< 2048)
537 if (version
!= 0 && version
!= 1) {
538 fprintf(stderr
, _("%s: error: unknown version %d\n"),
539 program_name
, version
);
545 _("%s: error: swap area needs to be at least %ldkB\n"),
546 program_name
, (long)(10 * pagesize
/ 1000));
551 maxpages
= V0_MAX_PAGES
;
552 else if (linux_version_code() >= MAKE_VERSION(2,3,4))
554 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
555 maxpages
= V1_MAX_PAGES
;
557 maxpages
= V1_OLD_MAX_PAGES
;
559 if (PAGES
> maxpages
) {
562 _("%s: warning: truncating swap area to %ldkB\n"),
563 program_name
, PAGES
* pagesize
/ 1000);
566 DEV
= open(device_name
,O_RDWR
);
567 if (DEV
< 0 || fstat(DEV
, &statbuf
) < 0) {
572 /* Want a block device. Probably not /dev/hda or /dev/hdb. */
573 if (!S_ISBLK(statbuf
.st_mode
))
575 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340)
576 die(_("Will not try to make swapdevice on '%s'"));
579 if (!force
&& version
== 0) {
580 /* Don't overwrite partition table unless forced */
581 unsigned char *buffer
= (unsigned char *)signature_page
;
582 unsigned short *q
, sum
;
584 if (read(DEV
, buffer
, 512) != 512)
585 die(_("fatal: first page unreadable"));
586 if (buffer
[508] == 0xDA && buffer
[509] == 0xBE) {
587 q
= (unsigned short *)(buffer
+ 510);
588 for (sum
= 0; q
>= (unsigned short *) buffer
;)
592 %s: Device '%s' contains a valid Sun disklabel.\n\
593 This probably means creating v0 swap would destroy your partition table\n\
594 No swap created. If you really want to create swap v0 on that device, use\n\
595 the -f option to force it.\n"),
596 program_name
, device_name
);
603 if (version
== 0 || check
)
605 if (version
== 0 && !bit_test_and_clear(signature_page
,0))
606 die(_("fatal: first page unreadable"));
608 p
->version
= version
;
609 p
->last_page
= PAGES
-1;
610 p
->nr_badpages
= badpages
;
613 goodpages
= PAGES
- badpages
- 1;
615 die(_("Unable to set up swap-space: unreadable"));
616 printf(_("Setting up swapspace version %d, size = %llu kB\n"),
617 version
, (unsigned long long)goodpages
* pagesize
/ 1000);
618 write_signature((version
== 0) ? "SWAP-SPACE" : "SWAPSPACE2");
620 offset
= ((version
== 0) ? 0 : 1024);
621 if (lseek(DEV
, offset
, SEEK_SET
) != offset
)
622 die(_("unable to rewind swap-device"));
623 if (write(DEV
,(char*)signature_page
+offset
, pagesize
-offset
)
625 die(_("unable to write signature page"));
628 * A subsequent swapon() will fail if the signature
629 * is not actually on disk. (This is a kernel bug.)
633 die(_("fsync failed"));