summaryrefslogtreecommitdiffstats
path: root/mount/swapon.c
diff options
context:
space:
mode:
authorKees Cook2008-03-20 09:24:03 +0100
committerKarel Zak2008-03-20 14:42:59 +0100
commit6274b9877822c9e3ee9eebc5f38fe246ba13197c (patch)
tree35d6376d0c8ec7d876e84be1afffbf9eea960ce0 /mount/swapon.c
parentbuild-sys: cleanup "x$foo" usage (diff)
downloadkernel-qcow2-util-linux-6274b9877822c9e3ee9eebc5f38fe246ba13197c.tar.gz
kernel-qcow2-util-linux-6274b9877822c9e3ee9eebc5f38fe246ba13197c.tar.xz
kernel-qcow2-util-linux-6274b9877822c9e3ee9eebc5f38fe246ba13197c.zip
swapon: Reinitialize software suspend areas to avoid future corruption.
This is based on the earlier swsuspend re-init patch carried by RedHat, SuSE, and Ubuntu. It has been updated to include passing the known UUID to mkswap, and fixing the fstype name. Co-Author: Karel Zak <kzak@redhat.com> Signed-off-by: Kees Cook <kees.cook@canonical.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'mount/swapon.c')
-rw-r--r--mount/swapon.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/mount/swapon.c b/mount/swapon.c
index 37af9ee66..6fce6fd62 100644
--- a/mount/swapon.c
+++ b/mount/swapon.c
@@ -10,6 +10,9 @@
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
#include "xmalloc.h"
#include "swap_constants.h"
#include "nls.h"
@@ -18,6 +21,8 @@
#include "pathnames.h"
#include "sundries.h"
+#define PATH_MKSWAP "/sbin/mkswap"
+
#ifdef HAVE_SYS_SWAP_H
# include <sys/swap.h>
#endif
@@ -175,6 +180,64 @@ display_summary(void)
}
static int
+swap_is_suspend(const char *device) {
+ const char *type = fsprobe_get_fstype_by_devname(device);
+
+ return (type && strcmp(type, "suspend") == 0) ? 1 : 0;
+}
+
+/* calls mkswap */
+static int
+swap_reinitialize(const char *device) {
+ const char *label = fsprobe_get_label_by_devname(device);
+ const char *uuid = fsprobe_get_uuid_by_devname(device);
+ pid_t pid;
+ int status, ret;
+ char *cmd[7];
+ int idx=0;
+
+ switch((pid=fork())) {
+ case -1: /* fork error */
+ fprintf(stderr, _("%s: cannot fork: %s\n"),
+ progname, strerror(errno));
+ return -1;
+
+ case 0: /* child */
+ cmd[idx++] = PATH_MKSWAP;
+ if (label && *label) {
+ cmd[idx++] = "-L";
+ cmd[idx++] = (char *) label;
+ }
+ if (uuid && *uuid) {
+ cmd[idx++] = "-U";
+ cmd[idx++] = (char *) uuid;
+ }
+ cmd[idx++] = (char *) device;
+ cmd[idx++] = NULL;
+ execv(cmd[0], cmd);
+ perror("execv");
+ exit(1); /* error */
+
+ default: /* parent */
+ do {
+ if ((ret = waitpid(pid, &status, 0)) < 0
+ && errno == EINTR)
+ continue;
+ else if (ret < 0) {
+ fprintf(stderr, _("%s: waitpid: %s\n"),
+ progname, strerror(errno));
+ return -1;
+ }
+ } while (0);
+
+ /* mkswap returns: 0=suss, 1=error */
+ if (WIFEXITED(status) && WEXITSTATUS(status)==0)
+ return 0; /* ok */
+ }
+ return -1; /* error */
+}
+
+static int
do_swapon(const char *orig_special, int prio, int canonic) {
int status;
struct stat st;
@@ -196,6 +259,18 @@ do_swapon(const char *orig_special, int prio, int canonic) {
return -1;
}
+ /* We have to reinitialize swap with old (=useless) software suspend
+ * data. The problem is that if we don't do it, then we get data
+ * corruption the next time an attempt at unsuspending is made.
+ */
+ if (swap_is_suspend(special)) {
+ fprintf(stdout, _("%s: %s: software suspend data detected. "
+ "Reinitializing the swap.\n"),
+ progname, special);
+ if (swap_reinitialize(special) < 0)
+ return -1;
+ }
+
/* people generally dislike this warning - now it is printed
only when `verbose' is set */
if (verbose) {