diff options
| author | Tito Ragusa <farmatito@tiscali.it> | 2014-03-31 16:39:26 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-03-31 16:39:26 +0200 |
| commit | a3f326cd6619cadb44cb4bb051b1d4e54bcd3477 (patch) | |
| tree | d14296cbe3ff31c322e825b842d5aac868b92fee /util-linux | |
| parent | faa9e94db619d1110061687278cde93a651e69de (diff) | |
| download | busybox-w32-a3f326cd6619cadb44cb4bb051b1d4e54bcd3477.tar.gz busybox-w32-a3f326cd6619cadb44cb4bb051b1d4e54bcd3477.tar.bz2 busybox-w32-a3f326cd6619cadb44cb4bb051b1d4e54bcd3477.zip | |
swapon/swapoff: size reduction, cleanup, fixes, improvements
1) real swapon/swapoff handles also devices on the commandline with -a;
2) xstat(device) in swap_enable_disable aborts on error when cycling through
fstab so some devices are not handled;
3) duplicated code for ENABLE_FEATURE_SWAPON_DISCARD and
ENABLE_FEATURE_SWAPON_PRI was moved to functions.
4) silence some error messages with -a;
5) minor cleanups and code refactoring reduced the size as per bloat-check:
6) I also added support for /proc/swaps handling to swapoff:
"When the -a flag is given, swapping is disabled on all known swap devices
and files (as found in /proc/swaps or /etc/fstab)."
So now swapoff first cycles through /proc/swaps and then through fstab
to swapoff all devices.
function old new delta
set_discard_flag - 106 +106
swap_enable_disable 147 238 +91
set_priority_flag - 79 +79
retrieve_file_data 470 467 -3
swap_on_off_main 638 418 -220
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 1/2 up/down: 276/-223) Total: 53 bytes
Signed-off-by: Tito Ragusa <farmatito@tiscali.it>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux')
| -rw-r--r-- | util-linux/swaponoff.c | 276 |
1 files changed, 161 insertions, 115 deletions
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index a7ad6db79..acdb67729 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c | |||
| @@ -63,90 +63,142 @@ struct globals { | |||
| 63 | } FIX_ALIASING; | 63 | } FIX_ALIASING; |
| 64 | #define G (*(struct globals*)&bb_common_bufsiz1) | 64 | #define G (*(struct globals*)&bb_common_bufsiz1) |
| 65 | #define g_flags (G.flags) | 65 | #define g_flags (G.flags) |
| 66 | #define save_g_flags() int save_g_flags = g_flags | ||
| 67 | #define restore_g_flags() g_flags = save_g_flags | ||
| 66 | #else | 68 | #else |
| 67 | #define g_flags 0 | 69 | #define g_flags 0 |
| 70 | #define save_g_flags() ((void)0) | ||
| 71 | #define restore_g_flags() ((void)0) | ||
| 68 | #endif | 72 | #endif |
| 69 | #define INIT_G() do { } while (0) | 73 | #define INIT_G() do { } while (0) |
| 70 | 74 | ||
| 75 | #define do_swapoff (applet_name[5] == 'f') | ||
| 76 | |||
| 77 | /* Command line options */ | ||
| 78 | enum { | ||
| 79 | OPTBIT_a, /* -a all */ | ||
| 80 | IF_FEATURE_SWAPON_DISCARD( OPTBIT_d ,) /* -d discard */ | ||
| 81 | IF_FEATURE_SWAPON_PRI ( OPTBIT_p ,) /* -p priority */ | ||
| 82 | OPT_a = 1 << OPTBIT_a, | ||
| 83 | OPT_d = IF_FEATURE_SWAPON_DISCARD((1 << OPTBIT_d)) + 0, | ||
| 84 | OPT_p = IF_FEATURE_SWAPON_PRI ((1 << OPTBIT_p)) + 0, | ||
| 85 | }; | ||
| 86 | |||
| 87 | #define OPT_ALL (option_mask32 & OPT_a) | ||
| 88 | #define OPT_DISCARD (option_mask32 & OPT_d) | ||
| 89 | #define OPT_PRIO (option_mask32 & OPT_p) | ||
| 90 | |||
| 71 | static int swap_enable_disable(char *device) | 91 | static int swap_enable_disable(char *device) |
| 72 | { | 92 | { |
| 73 | int status; | 93 | int err = 0; |
| 94 | int quiet = 0; | ||
| 74 | struct stat st; | 95 | struct stat st; |
| 75 | 96 | ||
| 76 | resolve_mount_spec(&device); | 97 | resolve_mount_spec(&device); |
| 77 | xstat(device, &st); | ||
| 78 | |||
| 79 | #if ENABLE_DESKTOP | ||
| 80 | /* test for holes */ | ||
| 81 | if (S_ISREG(st.st_mode)) | ||
| 82 | if (st.st_blocks * (off_t)512 < st.st_size) | ||
| 83 | bb_error_msg("warning: swap file has holes"); | ||
| 84 | #endif | ||
| 85 | 98 | ||
| 86 | if (applet_name[5] == 'n') | 99 | if (do_swapoff) { |
| 87 | status = swapon(device, g_flags); | 100 | err = swapoff(device); |
| 88 | else | 101 | /* Don't complain on OPT_ALL if not a swap device or if it doesn't exist */ |
| 89 | status = swapoff(device); | 102 | quiet = (OPT_ALL && (errno == EINVAL || errno == ENOENT)); |
| 103 | } else { | ||
| 104 | /* swapon */ | ||
| 105 | err = stat(device, &st); | ||
| 106 | if (!err) { | ||
| 107 | if (ENABLE_DESKTOP && S_ISREG(st.st_mode)) { | ||
| 108 | if (st.st_blocks * (off_t)512 < st.st_size) { | ||
| 109 | bb_error_msg("%s: file has holes", device); | ||
| 110 | return 1; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | err = swapon(device, g_flags); | ||
| 114 | /* Don't complain on swapon -a if device is already in use */ | ||
| 115 | quiet = (OPT_ALL && errno == EBUSY); | ||
| 116 | } | ||
| 117 | } | ||
| 90 | 118 | ||
| 91 | if (status != 0) { | 119 | if (err) { |
| 92 | bb_simple_perror_msg(device); | 120 | if (!quiet) |
| 121 | bb_simple_perror_msg(device); | ||
| 93 | return 1; | 122 | return 1; |
| 94 | } | 123 | } |
| 95 | |||
| 96 | return 0; | 124 | return 0; |
| 97 | } | 125 | } |
| 98 | 126 | ||
| 99 | static int do_em_all(void) | 127 | #if ENABLE_FEATURE_SWAPON_DISCARD |
| 128 | static void set_discard_flag(char *s) | ||
| 100 | { | 129 | { |
| 101 | struct mntent *m; | 130 | /* Unset the flag first to allow fstab options to override */ |
| 102 | FILE *f; | 131 | /* options set on the command line */ |
| 103 | int err; | 132 | g_flags = (g_flags & ~SWAP_FLAG_DISCARD_MASK) | SWAP_FLAG_DISCARD; |
| 104 | #ifdef G | 133 | |
| 105 | int cl_flags = g_flags; | 134 | if (!s) /* No optional policy value on the commandline */ |
| 135 | return; | ||
| 136 | /* Skip prepended '=' */ | ||
| 137 | if (*s == '=') | ||
| 138 | s++; | ||
| 139 | /* For fstab parsing: remove other appended options */ | ||
| 140 | *strchrnul(s, ',') = '\0'; | ||
| 141 | |||
| 142 | if (strcmp(s, "once") == 0) | ||
| 143 | g_flags |= SWAP_FLAG_DISCARD_ONCE; | ||
| 144 | if (strcmp(s, "pages") == 0) | ||
| 145 | g_flags |= SWAP_FLAG_DISCARD_PAGES; | ||
| 146 | } | ||
| 147 | #else | ||
| 148 | #define set_discard_flag(s) ((void)0) | ||
| 149 | #endif | ||
| 150 | |||
| 151 | #if ENABLE_FEATURE_SWAPON_PRI | ||
| 152 | static void set_priority_flag(char *s) | ||
| 153 | { | ||
| 154 | unsigned prio; | ||
| 155 | |||
| 156 | /* For fstab parsing: remove other appended options */ | ||
| 157 | *strchrnul(s, ',') = '\0'; | ||
| 158 | /* Max allowed 32767 (== SWAP_FLAG_PRIO_MASK) */ | ||
| 159 | prio = bb_strtou(s, NULL, 10); | ||
| 160 | if (!errno) { | ||
| 161 | /* Unset the flag first to allow fstab options to override */ | ||
| 162 | /* options set on the command line */ | ||
| 163 | g_flags = (g_flags & ~SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER | | ||
| 164 | MIN(prio, SWAP_FLAG_PRIO_MASK); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | #else | ||
| 168 | #define set_priority_flag(s) ((void)0) | ||
| 106 | #endif | 169 | #endif |
| 107 | 170 | ||
| 108 | f = setmntent("/etc/fstab", "r"); | 171 | static int do_em_all_in_fstab(void) |
| 109 | if (f == NULL) | 172 | { |
| 110 | bb_perror_msg_and_die("/etc/fstab"); | 173 | struct mntent *m; |
| 174 | int err = 0; | ||
| 175 | FILE *f = xfopen_for_read("/etc/fstab"); | ||
| 111 | 176 | ||
| 112 | err = 0; | ||
| 113 | while ((m = getmntent(f)) != NULL) { | 177 | while ((m = getmntent(f)) != NULL) { |
| 114 | if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) { | 178 | if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) { |
| 115 | /* swapon -a should ignore entries with noauto, | 179 | /* swapon -a should ignore entries with noauto, |
| 116 | * but swapoff -a should process them */ | 180 | * but swapoff -a should process them |
| 117 | if (applet_name[5] != 'n' | 181 | */ |
| 118 | || hasmntopt(m, MNTOPT_NOAUTO) == NULL | 182 | if (do_swapoff || hasmntopt(m, MNTOPT_NOAUTO) == NULL) { |
| 119 | ) { | 183 | /* each swap space might have different flags */ |
| 120 | #if ENABLE_FEATURE_SWAPON_DISCARD || ENABLE_FEATURE_SWAPON_PRI | 184 | /* save global flags for the next round */ |
| 121 | char *p; | 185 | save_g_flags(); |
| 122 | g_flags = cl_flags; /* each swap space might have different flags */ | 186 | if (ENABLE_FEATURE_SWAPON_DISCARD) { |
| 123 | #if ENABLE_FEATURE_SWAPON_DISCARD | 187 | char *p = hasmntopt(m, "discard"); |
| 124 | p = hasmntopt(m, "discard"); | 188 | if (p) { |
| 125 | if (p) { | 189 | /* move to '=' or to end of string */ |
| 126 | if (p[7] == '=') { | 190 | p += 7; |
| 127 | if (strncmp(p + 8, "once", 4) == 0 && (p[12] == ',' || p[12] == '\0')) | 191 | set_discard_flag(p); |
| 128 | g_flags = (g_flags & ~SWAP_FLAG_DISCARD_MASK) | SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE; | ||
| 129 | else if (strncmp(p + 8, "pages", 5) == 0 && (p[13] == ',' || p[13] == '\0')) | ||
| 130 | g_flags = (g_flags & ~SWAP_FLAG_DISCARD_MASK) | SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_PAGES; | ||
| 131 | } | 192 | } |
| 132 | else if (p[7] == ',' || p[7] == '\0') | ||
| 133 | g_flags = (g_flags & ~SWAP_FLAG_DISCARD_MASK) | SWAP_FLAG_DISCARD; | ||
| 134 | } | 193 | } |
| 135 | #endif | 194 | if (ENABLE_FEATURE_SWAPON_PRI) { |
| 136 | #if ENABLE_FEATURE_SWAPON_PRI | 195 | char *p = hasmntopt(m, "pri"); |
| 137 | p = hasmntopt(m, "pri"); | 196 | if (p) { |
| 138 | if (p) { | 197 | set_priority_flag(p + 4); |
| 139 | /* Max allowed 32767 (== SWAP_FLAG_PRIO_MASK) */ | ||
| 140 | unsigned prio = bb_strtou(p + 4, NULL, 10); | ||
| 141 | /* We want to allow "NNNN,foo", thus errno == EINVAL is allowed too */ | ||
| 142 | if (errno != ERANGE) { | ||
| 143 | g_flags = (g_flags & ~SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER | | ||
| 144 | MIN(prio, SWAP_FLAG_PRIO_MASK); | ||
| 145 | } | 198 | } |
| 146 | } | 199 | } |
| 147 | #endif | 200 | err |= swap_enable_disable(m->mnt_fsname); |
| 148 | #endif | 201 | restore_g_flags(); |
| 149 | err += swap_enable_disable(m->mnt_fsname); | ||
| 150 | } | 202 | } |
| 151 | } | 203 | } |
| 152 | } | 204 | } |
| @@ -157,74 +209,68 @@ static int do_em_all(void) | |||
| 157 | return err; | 209 | return err; |
| 158 | } | 210 | } |
| 159 | 211 | ||
| 212 | static int do_all_in_proc_swaps(void) | ||
| 213 | { | ||
| 214 | char *line; | ||
| 215 | int err = 0; | ||
| 216 | FILE *f = fopen_for_read("/proc/swaps"); | ||
| 217 | /* Don't complain if missing */ | ||
| 218 | if (f) { | ||
| 219 | while ((line = xmalloc_fgetline(f)) != NULL) { | ||
| 220 | if (line[0] == '/') { | ||
| 221 | *strchrnul(line, ' ') = '\0'; | ||
| 222 | err |= swap_enable_disable(line); | ||
| 223 | } | ||
| 224 | free(line); | ||
| 225 | } | ||
| 226 | if (ENABLE_FEATURE_CLEAN_UP) | ||
| 227 | fclose(f); | ||
| 228 | } | ||
| 229 | |||
| 230 | return err; | ||
| 231 | } | ||
| 232 | |||
| 233 | #define OPTSTR_SWAPON "a" \ | ||
| 234 | IF_FEATURE_SWAPON_DISCARD("d::") \ | ||
| 235 | IF_FEATURE_SWAPON_PRI("p:") | ||
| 236 | |||
| 160 | int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 237 | int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 161 | int swap_on_off_main(int argc UNUSED_PARAM, char **argv) | 238 | int swap_on_off_main(int argc UNUSED_PARAM, char **argv) |
| 162 | { | 239 | { |
| 163 | int ret; | 240 | IF_FEATURE_SWAPON_PRI(char *prio;) |
| 164 | #if ENABLE_FEATURE_SWAPON_DISCARD | 241 | IF_FEATURE_SWAPON_DISCARD(char *discard = NULL;) |
| 165 | char *discard = NULL; | 242 | int ret = 0; |
| 166 | #endif | ||
| 167 | #if ENABLE_FEATURE_SWAPON_PRI | ||
| 168 | unsigned prio; | ||
| 169 | #endif | ||
| 170 | 243 | ||
| 171 | INIT_G(); | 244 | INIT_G(); |
| 172 | 245 | ||
| 173 | #if !ENABLE_FEATURE_SWAPON_DISCARD && !ENABLE_FEATURE_SWAPON_PRI | 246 | getopt32(argv, do_swapoff ? "a" : OPTSTR_SWAPON |
| 174 | ret = getopt32(argv, "a"); | 247 | IF_FEATURE_SWAPON_DISCARD(, &discard) |
| 175 | #else | 248 | IF_FEATURE_SWAPON_PRI(, &prio) |
| 176 | #if ENABLE_FEATURE_SWAPON_PRI | 249 | ); |
| 177 | if (applet_name[5] == 'n') | ||
| 178 | opt_complementary = "p+"; | ||
| 179 | #endif | ||
| 180 | ret = getopt32(argv, (applet_name[5] == 'n') ? | ||
| 181 | #if ENABLE_FEATURE_SWAPON_DISCARD | ||
| 182 | "d::" | ||
| 183 | #endif | ||
| 184 | #if ENABLE_FEATURE_SWAPON_PRI | ||
| 185 | "p:" | ||
| 186 | #endif | ||
| 187 | "a" : "a" | ||
| 188 | #if ENABLE_FEATURE_SWAPON_DISCARD | ||
| 189 | , &discard | ||
| 190 | #endif | ||
| 191 | #if ENABLE_FEATURE_SWAPON_PRI | ||
| 192 | , &prio | ||
| 193 | #endif | ||
| 194 | ); | ||
| 195 | #endif | ||
| 196 | |||
| 197 | #if ENABLE_FEATURE_SWAPON_DISCARD | ||
| 198 | if (ret & 1) { // -d | ||
| 199 | if (!discard) | ||
| 200 | g_flags |= SWAP_FLAG_DISCARD; | ||
| 201 | else if (strcmp(discard, "once") == 0) | ||
| 202 | g_flags |= SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE; | ||
| 203 | else if (strcmp(discard, "pages") == 0) | ||
| 204 | g_flags |= SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_PAGES; | ||
| 205 | else | ||
| 206 | bb_show_usage(); | ||
| 207 | } | ||
| 208 | ret >>= 1; | ||
| 209 | #endif | ||
| 210 | #if ENABLE_FEATURE_SWAPON_PRI | ||
| 211 | if (ret & 1) // -p | ||
| 212 | g_flags |= SWAP_FLAG_PREFER | | ||
| 213 | MIN(prio, SWAP_FLAG_PRIO_MASK); | ||
| 214 | ret >>= 1; | ||
| 215 | #endif | ||
| 216 | |||
| 217 | if (ret /* & 1: not needed */) // -a | ||
| 218 | return do_em_all(); | ||
| 219 | 250 | ||
| 220 | argv += optind; | 251 | argv += optind; |
| 221 | if (!*argv) | ||
| 222 | bb_show_usage(); | ||
| 223 | 252 | ||
| 224 | /* ret = 0; redundant */ | 253 | if (OPT_DISCARD) { |
| 225 | do { | 254 | set_discard_flag(discard); |
| 226 | ret += swap_enable_disable(*argv); | 255 | } |
| 227 | } while (*++argv); | 256 | if (OPT_PRIO) { |
| 257 | set_priority_flag(prio); | ||
| 258 | } | ||
| 228 | 259 | ||
| 260 | if (OPT_ALL) { | ||
| 261 | /* swapoff -a does also /proc/swaps */ | ||
| 262 | if (do_swapoff) | ||
| 263 | ret = do_all_in_proc_swaps(); | ||
| 264 | ret |= do_em_all_in_fstab(); | ||
| 265 | } else if (!*argv) { | ||
| 266 | /* if not -a we need at least one arg */ | ||
| 267 | bb_show_usage(); | ||
| 268 | } | ||
| 269 | /* Unset -a now to allow for more messages in swap_enable_disable */ | ||
| 270 | option_mask32 = option_mask32 & ~OPT_a; | ||
| 271 | /* Now process devices on the commandline if any */ | ||
| 272 | while (*argv) { | ||
| 273 | ret |= swap_enable_disable(*argv++); | ||
| 274 | } | ||
| 229 | return ret; | 275 | return ret; |
| 230 | } | 276 | } |
