aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTito Ragusa <farmatito@tiscali.it>2014-03-31 16:39:26 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2014-03-31 16:39:26 +0200
commita3f326cd6619cadb44cb4bb051b1d4e54bcd3477 (patch)
treed14296cbe3ff31c322e825b842d5aac868b92fee
parentfaa9e94db619d1110061687278cde93a651e69de (diff)
downloadbusybox-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>
-rw-r--r--util-linux/swaponoff.c276
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 */
78enum {
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
71static int swap_enable_disable(char *device) 91static 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
99static int do_em_all(void) 127#if ENABLE_FEATURE_SWAPON_DISCARD
128static 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
152static 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"); 171static 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
212static 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
160int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 237int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
161int swap_on_off_main(int argc UNUSED_PARAM, char **argv) 238int 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}