swapoff: cleanup EXIT STATUS
The current code hides details about reason why swapoff(8) and swapoff(2) failed. For example ENOMEM from swapoff(2) is important as it indicates OOM. The patch also clean ups --all return codes to be more compatible for example with [u]mount --all, etc. Addresses: https://github.com/karelzak/util-linux/issues/1050 Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
c7fce443b1
commit
ecfa4dad6f
|
@ -25,6 +25,14 @@ static int all;
|
|||
#define QUIET 1
|
||||
#define CANONIC 1
|
||||
|
||||
#define SWAPOFF_EX_OK 0 /* no errors */
|
||||
#define SWAPOFF_EX_ENOMEM 1 /* swapoff(2) failed due to OOM */
|
||||
#define SWAPOFF_EX_FAILURE 2 /* swapoff(2) failed due to another reason */
|
||||
#define SWAPOFF_EX_SYSERR 4 /* non-swaoff() errors */
|
||||
#define SWAPOFF_EX_USAGE 16 /* usage, permissions or syntax error */
|
||||
#define SWAPOFF_EX_ALLERR 32 /* --all all failed */
|
||||
#define SWAPOFF_EX_SOMEOK 64 /* --all some failed some OK */
|
||||
|
||||
/*
|
||||
* This function works like mnt_resolve_tag(), but it's able to read UUID/LABEL
|
||||
* from regular swap files too (according to entries in /proc/swaps). Note that
|
||||
|
@ -52,7 +60,7 @@ static char *swapoff_resolve_tag(const char *name, const char *value,
|
|||
|
||||
itr = mnt_new_iter(MNT_ITER_BACKWARD);
|
||||
if (!itr)
|
||||
err(EXIT_FAILURE, _("failed to initialize libmount iterator"));
|
||||
err(SWAPOFF_EX_SYSERR, _("failed to initialize libmount iterator"));
|
||||
|
||||
while (tb && mnt_table_next_fs(tb, itr, &fs) == 0) {
|
||||
blkid_probe pr = NULL;
|
||||
|
@ -80,6 +88,7 @@ static char *swapoff_resolve_tag(const char *name, const char *value,
|
|||
static int do_swapoff(const char *orig_special, int quiet, int canonic)
|
||||
{
|
||||
const char *special = orig_special;
|
||||
int rc = SWAPOFF_EX_OK;
|
||||
|
||||
if (verbose)
|
||||
printf(_("swapoff %s\n"), orig_special);
|
||||
|
@ -98,15 +107,25 @@ static int do_swapoff(const char *orig_special, int quiet, int canonic)
|
|||
}
|
||||
|
||||
if (swapoff(special) == 0)
|
||||
return 0; /* success */
|
||||
rc = SWAPOFF_EX_OK; /* success */
|
||||
else {
|
||||
switch (errno) {
|
||||
case EPERM:
|
||||
errx(SWAPOFF_EX_USAGE, _("Not superuser."));
|
||||
break;
|
||||
case ENOMEM:
|
||||
warn(_("%s: swapoff failed"), orig_special);
|
||||
rc = SWAPOFF_EX_ENOMEM;
|
||||
break;
|
||||
default:
|
||||
if (!quiet)
|
||||
warn(_("%s: swapoff failed"), orig_special);
|
||||
rc = SWAPOFF_EX_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno == EPERM)
|
||||
errx(EXIT_FAILURE, _("Not superuser."));
|
||||
|
||||
if (!quiet || errno == ENOMEM)
|
||||
warn(_("%s: swapoff failed"), orig_special);
|
||||
|
||||
return -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int swapoff_by(const char *name, const char *value, int quiet)
|
||||
|
@ -140,18 +159,18 @@ static void __attribute__((__noreturn__)) usage(void)
|
|||
" <file> name of file to be used\n"), out);
|
||||
|
||||
printf(USAGE_MAN_TAIL("swapoff(8)"));
|
||||
exit(EXIT_SUCCESS);
|
||||
exit(SWAPOFF_EX_OK);
|
||||
}
|
||||
|
||||
static int swapoff_all(void)
|
||||
{
|
||||
int status = 0;
|
||||
int nerrs = 0, nsucc = 0;
|
||||
struct libmnt_table *tb;
|
||||
struct libmnt_fs *fs;
|
||||
struct libmnt_iter *itr = mnt_new_iter(MNT_ITER_BACKWARD);
|
||||
|
||||
if (!itr)
|
||||
err(EXIT_FAILURE, _("failed to initialize libmount iterator"));
|
||||
err(SWAPOFF_EX_SYSERR, _("failed to initialize libmount iterator"));
|
||||
|
||||
/*
|
||||
* In case /proc/swaps exists, unswap stuff listed there. We are quiet
|
||||
|
@ -161,8 +180,12 @@ static int swapoff_all(void)
|
|||
*/
|
||||
tb = get_swaps();
|
||||
|
||||
while (tb && mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0)
|
||||
status |= do_swapoff(mnt_fs_get_source(fs), QUIET, CANONIC);
|
||||
while (tb && mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) {
|
||||
if (do_swapoff(mnt_fs_get_source(fs), QUIET, CANONIC) == SWAPOFF_EX_OK)
|
||||
nsucc++;
|
||||
else
|
||||
nerrs++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unswap stuff mentioned in /etc/fstab. Probably it was unmounted
|
||||
|
@ -178,7 +201,13 @@ static int swapoff_all(void)
|
|||
}
|
||||
|
||||
mnt_free_iter(itr);
|
||||
return status;
|
||||
|
||||
if (nerrs == 0)
|
||||
return SWAPOFF_EX_OK; /* all success */
|
||||
else if (nsucc == 0)
|
||||
return SWAPOFF_EX_ALLERR; /* all failed */
|
||||
|
||||
return SWAPOFF_EX_SOMEOK; /* some success, some failed */
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -218,16 +247,16 @@ int main(int argc, char *argv[])
|
|||
case 'h': /* help */
|
||||
usage();
|
||||
case 'V': /* version */
|
||||
print_version(EXIT_SUCCESS);
|
||||
print_version(SWAPOFF_EX_OK);
|
||||
default:
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
errtryhelp(SWAPOFF_EX_USAGE);
|
||||
}
|
||||
}
|
||||
argv += optind;
|
||||
|
||||
if (!all && !numof_labels() && !numof_uuids() && *argv == NULL) {
|
||||
warnx(_("bad usage"));
|
||||
errtryhelp(EXIT_FAILURE);
|
||||
errtryhelp(SWAPOFF_EX_USAGE);
|
||||
}
|
||||
|
||||
mnt_init_debug(0);
|
||||
|
|
|
@ -187,6 +187,34 @@ Be verbose.
|
|||
.TP
|
||||
.BR \-V , " \-\-version"
|
||||
Display version information and exit.
|
||||
.SH EXIT STATUS
|
||||
.B swapoff
|
||||
has the following exit status values:
|
||||
.TP
|
||||
.B 0
|
||||
success
|
||||
.TP
|
||||
.B 1
|
||||
system has insufficient memory to stop swapping (OOM)
|
||||
.TP
|
||||
.B 2
|
||||
swapoff syscall failed for another reason
|
||||
.TP
|
||||
.B 4
|
||||
non-swapoff syscall system error (out of memory, ...)
|
||||
.TP
|
||||
.B 16
|
||||
usage or syntax error
|
||||
.TP
|
||||
.B 32
|
||||
all swapoff failed on \fB\-\-all\fR
|
||||
.TP
|
||||
.B 64
|
||||
some swapoff succeeded on \fB\-\-all\fR
|
||||
|
||||
The command \fBswapoff \-\-all\fR returns 0 (all succeeded), 32 (all failed), or 64 (some
|
||||
failed, some succeeded).
|
||||
|
||||
.SH ENVIRONMENT
|
||||
.IP LIBMOUNT_DEBUG=all
|
||||
enables libmount debug output.
|
||||
|
|
Loading…
Reference in New Issue