diff options
-rw-r--r-- | util-linux/Config.in | 10 | ||||
-rw-r--r-- | util-linux/mkswap.c | 152 |
2 files changed, 83 insertions, 79 deletions
diff --git a/util-linux/Config.in b/util-linux/Config.in index 28292bd40..33567d9a9 100644 --- a/util-linux/Config.in +++ b/util-linux/Config.in @@ -288,6 +288,16 @@ config CONFIG_MKSWAP Once you have created swap space using 'mkswap' you need to enable the swap space using the 'swapon' utility. +config CONFIG_FEATURE_MKSWAP_V0 + bool " version 0 support" + default n + depends on CONFIG_MKSWAP +# depends on CONFIG_MKSWAP && CONFIG_DEPRECATED + help + Enable support for the old v0 style. + If your kernel is older than 2.1.117, then v0 support is the + only option. + config CONFIG_MORE bool "more" default n diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 4107329a6..ce123e502 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c @@ -59,9 +59,17 @@ static int DEV = -1; static long PAGES = 0; static int check = 0; static int badpages = 0; +#if ENABLE_FEATURE_MKSWAP_V0 static int version = -1; - #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) +#else +#define version 1 +/* and make sure that we optimize away anything which would deal with checking + * the kernel revision as we have v1 support only anyway. + */ +#define MAKE_VERSION(p,q,r) 1 +#define get_kernel_revision() 1 +#endif /* * The definition of the union swap_header uses the constant PAGE_SIZE. @@ -74,7 +82,7 @@ static unsigned int *signature_page; static struct swap_header_v1 { char bootbits[1024]; /* Space for disklabel etc. */ - unsigned int version; + unsigned int swap_version; unsigned int last_page; unsigned int nr_badpages; unsigned int padding[125]; @@ -172,23 +180,11 @@ static int bit_test_and_clear(unsigned int *addr, unsigned int nr) return (r & m) != 0; } - static void page_ok(int page) { - if (version == 0) + if (ENABLE_FEATURE_MKSWAP_V0) { bit_set(signature_page, page); -} - -static inline void page_bad(int page) -{ - if (version == 0) - bit_test_and_clear(signature_page, page); - else { - if (badpages == MAX_BADPAGES) - bb_error_msg_and_die("too many bad pages"); - p->badpages[badpages] = page; } - badpages++; } static void check_blocks(void) @@ -200,7 +196,7 @@ static void check_blocks(void) buffer = xmalloc(pagesize); current_page = 0; while (current_page < PAGES) { - if (!check) { + if (!check && version == 0) { page_ok(current_page++); continue; } @@ -208,15 +204,23 @@ static void check_blocks(void) current_page * pagesize) bb_error_msg_and_die("seek failed in check_blocks"); if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { - page_bad(current_page++); + current_page++; + if (version == 0) + bit_test_and_clear(signature_page, current_page); + else { + if (badpages == MAX_BADPAGES) + bb_error_msg_and_die("too many bad pages"); + p->badpages[badpages] = current_page; + } + badpages++; continue; } page_ok(current_page++); } - if (badpages == 1) - printf("one bad page\n"); - else if (badpages > 1) - printf("%d bad pages\n", badpages); + if (ENABLE_FEATURE_CLEAN_UP) + free(buffer); + if (badpages > 0) + printf("%d bad page%s\n", badpages, (badpages==1)?"":"s"); } static long valid_offset(int fd, int offset) @@ -249,17 +253,15 @@ static int find_size(int fd) } /* return size in pages, to avoid integer overflow */ -static long get_size(const char *file) +static inline long get_size(const char *file) { int fd; long size; - if ((fd = open(file, O_RDONLY)) < 0) + if ((fd = open(file, O_RDONLY)) < 0) /* TODO: bb_xopen3 */ bb_perror_msg_and_die("%s", file); if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - int sectors_per_page = pagesize / 512; - - size /= sectors_per_page; + size /= pagesize / 512; } else { size = find_size(fd) / pagesize; } @@ -274,66 +276,53 @@ int mkswap_main(int argc, char **argv) int sz; int maxpages; int goodpages; - int offset; +#ifdef __sparc__ int force = 0; +#endif init_signature_page(); /* get pagesize */ - while (argc-- > 1) { - argv++; - if (argv[0][0] != '-') { - if (device_name) { - int blocks_per_page = pagesize / 1024; - - PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page; - if (*tmp) - bb_show_usage(); - } else - device_name = argv[0]; + bb_opt_complementally = "?"; /* call bb_show_usage internally */ + sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp); + if (sz & 1) + check = 1; +#ifdef __sparc__ + if (sz & 2) + force = 1; +#endif +#if ENABLE_FEATURE_MKSWAP_V0 + if (sz & 4) { + version = bb_xgetlarg(tmp, 10, 0, 1); + } else { + if (get_kernel_revision() < MAKE_VERSION(2, 1, 117)) + version = 0; + else + version = 1; + } +#endif + + argv += optind; + argc -= optind; + + goodpages = pagesize / 1024; /* cache division */ + while (argc--) { + if (device_name) { + PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages; + argc = 0; /* ignore any surplus args.. */ } else { - switch (argv[0][1]) { - case 'c': - check = 1; - break; - case 'f': - force = 1; - break; - case 'v': - version = atoi(argv[0] + 2); - break; - default: - bb_show_usage(); - } + device_name = argv[0]; + sz = get_size(device_name); + argv++; } } + if (!device_name) { - bb_error_msg("error: Nowhere to set up swap on?"); - bb_show_usage(); + bb_error_msg_and_die("error: Nowhere to set up swap on?"); } - sz = get_size(device_name); if (!PAGES) { PAGES = sz; - } else if (PAGES > sz && !force) { - bb_error_msg("error: size %ld is larger than device size %d", - PAGES * (pagesize / 1024), sz * (pagesize / 1024)); - return EXIT_FAILURE; } - if (version == -1) { - if (get_kernel_revision() < MAKE_VERSION(2, 1, 117)) - version = 0; - else - version = 1; - } - if (version != 0 && version != 1) { - bb_error_msg("error: unknown version %d", version); - bb_show_usage(); - } - if (PAGES < 10) { - bb_error_msg("error: swap area needs to be at least %ldkB", - (long) (10 * pagesize / 1024)); - bb_show_usage(); - } #if 0 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); #else @@ -350,7 +339,7 @@ int mkswap_main(int argc, char **argv) if (PAGES > maxpages) { PAGES = maxpages; bb_error_msg("warning: truncating swap area to %ldkB", - PAGES * pagesize / 1024); + PAGES * goodpages); } DEV = open(device_name, O_RDWR); @@ -389,7 +378,7 @@ int mkswap_main(int argc, char **argv) if (version == 0 && !bit_test_and_clear(signature_page, 0)) bb_error_msg_and_die("fatal: first page unreadable"); if (version == 1) { - p->version = version; + p->swap_version = version; p->last_page = PAGES - 1; p->nr_badpages = badpages; } @@ -401,11 +390,12 @@ int mkswap_main(int argc, char **argv) version, (long) (goodpages * pagesize)); write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); - offset = ((version == 0) ? 0 : 1024); - if (lseek(DEV, offset, SEEK_SET) != offset) + sz = ((version == 0) ? 0 : 1024); /* offset */ + if (lseek(DEV, sz, SEEK_SET) != sz) bb_error_msg_and_die("unable to rewind swap-device"); - if (write(DEV, (char *) signature_page + offset, pagesize - offset) - != pagesize - offset) + goodpages = pagesize - sz; /* cache substraction */ + if (write(DEV, (char *) signature_page + sz, goodpages) + != goodpages) bb_error_msg_and_die("unable to write signature page"); /* @@ -414,5 +404,9 @@ int mkswap_main(int argc, char **argv) */ if (fsync(DEV)) bb_error_msg_and_die("fsync failed"); + if (ENABLE_FEATURE_CLEAN_UP) { + close(DEV); + free(signature_page); + } return EXIT_SUCCESS; } |