]>
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@misiek.eu.org>
30 * - added Native Language Support
39 #include <sys/ioctl.h> /* for _IO */
40 #include <sys/utsname.h>
44 #ifdef HAVE_asm_page_h
45 #include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
46 /* we also get PAGE_SIZE via getpagesize() */
47 /* recent glibc systems also define this in <sys/user.h> */
53 #define BLKGETSIZE 0x1260
55 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
56 #define BLKGETSIZE _IO(0x12,96)
59 static char * program_name
= "mkswap";
60 static char * device_name
= NULL
;
62 static long PAGES
= 0;
64 static int badpages
= 0;
65 static int version
= -1;
67 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
70 linux_version_code(void) {
71 struct utsname my_utsname
;
74 if (uname(&my_utsname
) == 0) {
75 p
= atoi(strtok(my_utsname
.release
, "."));
76 q
= atoi(strtok(NULL
, "."));
77 r
= atoi(strtok(NULL
, "."));
78 return MAKE_VERSION(p
,q
,r
);
85 # define is_sparc64() 1
91 static int sparc64
= -1;
93 if (sparc64
!= -1) return sparc64
;
96 if (uname(&un
) < 0) return 0;
97 if (! strcmp(un
.machine
, "sparc64")) {
101 if (strcmp(un
.machine
, "sparc"))
102 return 0; /* Should not happen */
104 #ifdef HAVE_personality
106 extern int personality(unsigned long);
108 #define PERS_LINUX 0x00000000
109 #define PERS_LINUX_32BIT 0x00800000
110 #define PERS_LINUX32 0x00000008
112 oldpers
= personality(PERS_LINUX_32BIT
);
114 if (personality(PERS_LINUX
) != -1) {
116 if (! strcmp(un
.machine
, "sparc64")) {
118 oldpers
= PERS_LINUX32
;
121 personality(oldpers
);
128 # define is_be64() is_sparc64()
129 # endif /* sparc32 */
135 * The definition of the union swap_header uses the constant PAGE_SIZE.
136 * Unfortunately, on some architectures this depends on the hardware model,
137 * and can only be found at run time -- we use getpagesize(), so that
138 * we do not need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
140 * Even more unfortunately, getpagesize() does not always return
141 * the right information. For example, libc4 and libc5 do not use
142 * the system call but invent a value themselves
143 * (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC), and thus it may happen
144 * that e.g. on a sparc PAGE_SIZE=4096 and getpagesize() returns 8192.
145 * What to do? Let us allow the user to specify the pagesize explicitly.
148 static int user_pagesize
= 0;
149 static int kernel_pagesize
; /* obtained via getpagesize(); */
150 static int defined_pagesize
= 0; /* PAGE_SIZE, when that exists */
152 static long *signature_page
;
154 struct swap_header_v1
{
155 char bootbits
[1024]; /* Space for disklabel etc. */
156 unsigned int version
;
157 unsigned int last_page
;
158 unsigned int nr_badpages
;
159 unsigned int padding
[125];
160 unsigned int badpages
[1];
164 init_signature_page(void) {
166 defined_pagesize
= PAGE_SIZE
;
168 kernel_pagesize
= getpagesize();
169 pagesize
= kernel_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 user_pagesize
!= defined_pagesize
)
183 fprintf(stderr
, _("Using user-specified page size %d, "
184 "instead of the system values %d/%d\n"),
185 pagesize
, kernel_pagesize
, defined_pagesize
);
186 else if (defined_pagesize
&& pagesize
!= defined_pagesize
)
187 fprintf(stderr
, _("Assuming pages of size %d (not %d)\n"),
188 pagesize
, defined_pagesize
);
190 signature_page
= (long *) malloc(pagesize
);
191 memset(signature_page
,0,pagesize
);
192 p
= (struct swap_header_v1
*) signature_page
;
196 write_signature(char *sig
) {
197 char *sp
= (char *) signature_page
;
199 strncpy(sp
+pagesize
-10, sig
, 10);
202 #define V0_MAX_PAGES (8 * (pagesize - 10))
203 /* Before 2.2.0pre9 */
204 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
206 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
208 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
209 #define SWP_OFFSET(entry) ((entry) >> 8)
210 on the various architectures. Below the result - yuk.
212 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
213 i386 2^12 o<<8 e>>8 1<<24 1<<19
214 mips 2^12 o<<15 e>>15 1<<17 1<<19
215 alpha 2^13 o<<40 e>>40 1<<24 1<<18
216 m68k 2^12 o<<12 e>>12 1<<20 1<<19
217 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
218 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
219 ppc 2^12 o<<8 e>>8 1<<24 1<<19
220 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
221 armv 2^12 o<<9 e>>9 1<<23 1<<19
223 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
225 The bad part is that we need to know this since the kernel will
226 refuse a swap space if it is too large.
228 /* patch from jj - why does this differ from the above? */
229 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
230 the size of virtual address space allocation for vmalloc */
231 #if defined(__alpha__)
232 #define V1_MAX_PAGES ((1 << 24) - 1)
233 #elif defined(__mips__)
234 #define V1_MAX_PAGES ((1 << 17) - 1)
235 #elif defined(__sparc__)
236 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
238 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
240 /* man page now says:
241 The maximum useful size of a swap area now depends on the architecture.
242 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
243 128GB on alpha and 3TB on sparc64.
246 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
249 * One more point of lossage - Linux swapspace really is a mess.
250 * The definition of the bitmap used is architecture dependent,
251 * and requires one to know whether the machine is bigendian,
252 * and if so, whether it will use 32-bit or 64-bit units in
254 * davem writes: "... is based upon an unsigned long type of
255 * the cpu and the native endianness".
256 * So, it seems we can write `unsigned long' below.
257 * However, sparc64 uses 64-bit units in the kernel, while
258 * mkswap may have been translated with 32-bit longs. Thus,
259 * we need an explicit test for version 0 swap on sparc64.
263 bit_set (unsigned long *addr
, unsigned int nr
) {
267 unsigned long long *bitmap
= (unsigned long long *) addr
;
268 unsigned long long bitnum
= (unsigned long long) nr
;
269 unsigned long long rl
, ml
;
271 bitmap
+= bitnum
/ (8 * sizeof(long long));
273 ml
= 1ULL << (bitnum
&
274 (8ULL * (unsigned long long)sizeof(long long) - 1ULL));
279 addr
+= nr
/ (8 * sizeof(unsigned long));
281 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
286 bit_test_and_clear (unsigned long *addr
, unsigned int nr
) {
290 unsigned long long *bitmap
= (unsigned long long *) addr
;
291 unsigned long long bitnum
= (unsigned long long) nr
;
292 unsigned long long rl
, ml
;
294 bitmap
+= bitnum
/ (8 * sizeof(long long));
296 ml
= 1ULL << (bitnum
&
297 (8ULL * (unsigned long long)sizeof(long long) - 1ULL));
299 return ((rl
& ml
) != 0ULL);
302 addr
+= nr
/ (8 * sizeof(unsigned long));
304 m
= 1 << (nr
& (8 * sizeof(unsigned long) - 1));
312 _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] /dev/name [blocks]\n"),
318 die(const char *str
) {
319 fprintf(stderr
, "%s: %s\n", program_name
, str
);
326 bit_set(signature_page
, page
);
332 bit_test_and_clear(signature_page
, page
);
334 if (badpages
== MAX_BADPAGES
)
335 die(_("too many bad pages"));
336 p
->badpages
[badpages
] = page
;
343 unsigned int current_page
;
347 buffer
= malloc(pagesize
);
349 die(_("Out of memory"));
351 while (current_page
< PAGES
) {
353 page_ok(current_page
++);
356 if (do_seek
&& lseek(DEV
,current_page
*pagesize
,SEEK_SET
) !=
357 current_page
*pagesize
)
358 die(_("seek failed in check_blocks"));
359 if ((do_seek
= (pagesize
!= read(DEV
, buffer
, pagesize
)))) {
360 page_bad(current_page
++);
363 page_ok(current_page
++);
366 printf(_("one bad page\n"));
367 else if (badpages
> 1)
368 printf(_("%d bad pages\n"), badpages
);
372 valid_offset (int fd
, int offset
) {
375 if (lseek (fd
, offset
, 0) < 0)
377 if (read (fd
, &ch
, 1) < 1)
384 unsigned int high
, low
;
387 for (high
= 1; high
> 0 && valid_offset (fd
, high
); high
*= 2)
389 while (low
< high
- 1)
391 const int mid
= (low
+ high
) / 2;
393 if (valid_offset (fd
, mid
))
401 /* return size in pages, to avoid integer overflow */
403 get_size(const char *file
) {
407 fd
= open(file
, O_RDONLY
);
412 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) {
413 int sectors_per_page
= pagesize
/512;
414 size
/= sectors_per_page
;
416 size
= find_size(fd
) / pagesize
;
424 return (c
>= '1' && c
<= '9');
428 main(int argc
, char ** argv
) {
435 char *block_count
= 0;
438 program_name
= (argc
&& *argv
) ? argv
[0] : "fsck.minix";
439 if ((pp
= strrchr(program_name
, '/')) != NULL
)
442 setlocale(LC_ALL
, "");
443 bindtextdomain(PACKAGE
, LOCALEDIR
);
447 (!strcmp(argv
[1], "-V") || !strcmp(argv
[1], "--version"))) {
448 printf(_("%s from %s\n"), program_name
, util_linux_version
);
452 for (i
=1; i
<argc
; i
++) {
453 if (argv
[i
][0] == '-') {
454 switch (argv
[i
][1]) {
463 if (!*pp
&& i
+1 < argc
)
466 user_pagesize
=atoi(pp
);
471 version
= atoi(argv
[i
]+2);
476 } else if (!device_name
) {
477 device_name
= argv
[i
];
478 } else if (!block_count
) {
479 block_count
= argv
[i
];
484 init_signature_page(); /* get pagesize */
488 _("%s: error: Nowhere to set up swap on?\n"),
493 /* this silly user specified the number of blocks
496 int blocks_per_page
= pagesize
/1024;
497 PAGES
= strtol(block_count
,&tmp
,0)/blocks_per_page
;
501 sz
= get_size(device_name
);
504 } else if (PAGES
> sz
&& !force
) {
507 "size %ld is larger than device size %d\n"),
509 PAGES
*(pagesize
/1024), sz
*(pagesize
/1024));
514 /* use version 1 as default, if possible */
515 if (PAGES
<= V0_MAX_PAGES
&& PAGES
> V1_MAX_PAGES
)
517 else if (linux_version_code() < MAKE_VERSION(2,1,117))
519 else if (pagesize
< 2048)
524 if (version
!= 0 && version
!= 1) {
525 fprintf(stderr
, _("%s: error: unknown version %d\n"),
526 program_name
, version
);
531 _("%s: error: swap area needs to be at least %ldkB\n"),
532 program_name
, (long)(10 * pagesize
/ 1024));
536 maxpages
= ((version
== 0) ? V0_MAX_PAGES
: V1_MAX_PAGES
);
539 maxpages
= V0_MAX_PAGES
;
540 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
541 maxpages
= V1_MAX_PAGES
;
543 maxpages
= V1_OLD_MAX_PAGES
;
544 if (maxpages
> V1_MAX_PAGES
)
545 maxpages
= V1_MAX_PAGES
;
548 if (PAGES
> maxpages
) {
550 fprintf(stderr
, _("%s: warning: truncating swap area to %ldkB\n"),
551 program_name
, PAGES
* pagesize
/ 1024);
554 DEV
= open(device_name
,O_RDWR
);
555 if (DEV
< 0 || fstat(DEV
, &statbuf
) < 0) {
559 if (!S_ISBLK(statbuf
.st_mode
))
561 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340)
562 die(_("Will not try to make swapdevice on '%s'"));
565 if (!force
&& version
== 0) {
566 /* Don't overwrite partition table unless forced */
567 unsigned char *buffer
= (unsigned char *)signature_page
;
568 unsigned short *q
, sum
;
570 if (read(DEV
, buffer
, 512) != 512)
571 die(_("fatal: first page unreadable"));
572 if (buffer
[508] == 0xDA && buffer
[509] == 0xBE) {
573 q
= (unsigned short *)(buffer
+ 510);
574 for (sum
= 0; q
>= (unsigned short *) buffer
;)
578 %s: Device '%s' contains a valid Sun disklabel.\n\
579 This probably means creating v0 swap would destroy your partition table\n\
580 No swap created. If you really want to create swap v0 on that device, use\n\
581 the -f option to force it.\n"),
582 program_name
, device_name
);
589 if (version
== 0 || check
)
591 if (version
== 0 && !bit_test_and_clear(signature_page
,0))
592 die(_("fatal: first page unreadable"));
594 p
->version
= version
;
595 p
->last_page
= PAGES
-1;
596 p
->nr_badpages
= badpages
;
599 goodpages
= PAGES
- badpages
- 1;
601 die(_("Unable to set up swap-space: unreadable"));
602 printf(_("Setting up swapspace version %d, size = %ld bytes\n"),
603 version
, (long)(goodpages
*pagesize
));
604 write_signature((version
== 0) ? "SWAP-SPACE" : "SWAPSPACE2");
606 offset
= ((version
== 0) ? 0 : 1024);
607 if (lseek(DEV
, offset
, SEEK_SET
) != offset
)
608 die(_("unable to rewind swap-device"));
609 if (write(DEV
,(char*)signature_page
+offset
, pagesize
-offset
)
611 die(_("unable to write signature page"));
614 * A subsequent swapon() will fail if the signature
615 * is not actually on disk. (This is a kernel bug.)
619 die(_("fsync failed"));