[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [PATCH] pvcreate: conditionally wipe swap signatures



Hi,

this should address https://bugzilla.redhat.com/show_bug.cgi?id=443062 -- the
first patch implements the actual check, in the spirit of dev_is_md (it also
gets a check in the testsuite). The code is based on swap signature detection
in swapon implementation of util-linux-ng:
http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git;a=blob_plain;f=mount/swapon.c

The latter patch just throws in some checks that the old code misses. They
might as well be redundant (or not, depends on how you look at it). Personally,
I am ambivalent -- advice about (non-)inclusion sought.

Mon Mar 16 19:45:02 CET 2009  Petr Rockai <me mornfall net>
  * Detect and wipe swap signatures in pvcreate.
diff -rN -u -p old-swap-check/lib/device/device.h new-swap-check/lib/device/device.h
--- old-swap-check/lib/device/device.h	2009-03-16 19:51:08.067884748 +0100
+++ new-swap-check/lib/device/device.h	2009-03-16 19:51:08.231882756 +0100
@@ -93,6 +93,7 @@ const char *dev_name_confirmed(struct de
 
 /* Does device contain md superblock?  If so, where? */
 int dev_is_md(struct device *dev, uint64_t *sb);
+int dev_is_swap(struct device *dev, uint64_t *signature);
 unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev);
 
 int is_partitioned_dev(struct device *dev);
diff -rN -u -p old-swap-check/lib/device/dev-swap.c new-swap-check/lib/device/dev-swap.c
--- old-swap-check/lib/device/dev-swap.c	1970-01-01 01:00:00.000000000 +0100
+++ new-swap-check/lib/device/dev-swap.c	2009-03-16 19:51:08.227882596 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "metadata.h"
+#include "xlate.h"
+#include "filter.h"
+
+#ifdef linux
+
+#define MAX_PAGESIZE	(64 * 1024)
+#define SIGNATURE_SIZE  10
+
+static int
+_swap_detect_signature(const char *buf)
+{
+	if (memcmp(buf, "SWAP-SPACE", 10) == 0 ||
+            memcmp(buf, "SWAPSPACE2", 10) == 0)
+		return 1;
+
+	if (memcmp(buf, "S1SUSPEND", 9) == 0 ||
+	    memcmp(buf, "S2SUSPEND", 9) == 0 ||
+	    memcmp(buf, "ULSUSPEND", 9) == 0 ||
+	    memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0)
+		return 1;
+
+	return 0;
+}
+
+int dev_is_swap(struct device *dev, uint64_t *signature)
+{
+	char buf[10];
+	uint64_t size;
+	int page;
+
+	if (!dev_get_size(dev, &size)) {
+		stack;
+		return -1;
+	}
+
+	if (!dev_open(dev)) {
+		stack;
+		return -1;
+	}
+
+	*signature = 0;
+
+	for (page = 0x1000; page <= MAX_PAGESIZE; page <<= 1) {
+		/*
+		 * skip 32k pagesize since this does not seem to be supported
+		 */
+		if (page == 0x8000)
+			continue;
+		if (size < page)
+			break;
+		if (!dev_read(dev, page - SIGNATURE_SIZE,
+			      SIGNATURE_SIZE, buf)) {
+			stack;
+			return -1;
+		}
+		if (_swap_detect_signature(buf)) {
+			*signature = page - SIGNATURE_SIZE;
+			break;
+		}
+	}
+
+	if (!dev_close(dev))
+		stack;
+
+	if (*signature)
+		return 1;
+
+	return 0;
+}
+
+#endif
diff -rN -u -p old-swap-check/lib/Makefile.in new-swap-check/lib/Makefile.in
--- old-swap-check/lib/Makefile.in	2009-03-16 19:51:08.067884748 +0100
+++ new-swap-check/lib/Makefile.in	2009-03-16 19:51:08.211882309 +0100
@@ -42,6 +42,7 @@ SOURCES =\
 	device/dev-cache.c \
 	device/dev-io.c \
 	device/dev-md.c \
+	device/dev-swap.c \
 	device/device.c \
 	display/display.c \
 	error/errseg.c \
diff -rN -u -p old-swap-check/test/t-pvcreate-operation.sh new-swap-check/test/t-pvcreate-operation.sh
--- old-swap-check/test/t-pvcreate-operation.sh	2009-03-16 19:51:08.067884748 +0100
+++ new-swap-check/test/t-pvcreate-operation.sh	2009-03-16 19:51:08.423884253 +0100
@@ -108,3 +108,10 @@ not pvcreate --uuid $uuid1 --restorefile
 pvcreate --uuid $uuid1 $dev1
 vgcfgbackup -f $backupfile
 not pvcreate --uuid $uuid2 --restorefile $backupfile $dev2
+
+# pvcreate wipes swap signature when forced
+dd if=/dev/zero of=$dev1 bs=1024 count=64
+mkswap $dev1
+file -s $dev1 | grep "swap file"
+pvcreate -f $dev1
+file -s $dev1 | not grep "swap file"
diff -rN -u -p old-swap-check/tools/pvcreate.c new-swap-check/tools/pvcreate.c
--- old-swap-check/tools/pvcreate.c	2009-03-16 19:51:08.067884748 +0100
+++ new-swap-check/tools/pvcreate.c	2009-03-16 19:51:08.523885580 +0100
@@ -45,7 +45,7 @@ static int pvcreate_check(struct cmd_con
 {
 	struct physical_volume *pv;
 	struct device *dev;
-	uint64_t md_superblock;
+	uint64_t md_superblock, swap_signature;
 
 	/* FIXME Check partition type is LVM unless --force is given */
 
@@ -129,6 +129,17 @@ static int pvcreate_check(struct cmd_con
 		}
 	}
 
+	if (dev_is_swap(dev, &swap_signature) &&
+	    ((!pp->idp && !pp->restorefile) || pp->yes ||
+	     (yes_no_prompt("Swap signature detected on %s. Wipe it? [y/n] ",
+			    name) == 'y'))) {
+		log_print("Wiping swap signature on %s", name);
+		if (!dev_set(dev, swap_signature, 10, 0)) {
+			log_error("Failed to wipe swap signature on %s", name);
+			return 0;
+		}
+	}
+
 	if (sigint_caught())
 		return 0;
 
Mon Mar 16 19:49:33 CET 2009  Petr Rockai <me mornfall net>
  * Some extra (paranoid) checks on dev_is_{md,swap} result.
diff -rN -u -p old-swap-check/tools/pvcreate.c new-swap-check/tools/pvcreate.c
--- old-swap-check/tools/pvcreate.c	2009-03-16 19:51:15.095886212 +0100
+++ new-swap-check/tools/pvcreate.c	2009-03-16 19:51:15.471884837 +0100
@@ -46,6 +46,7 @@ static int pvcreate_check(struct cmd_con
 	struct physical_volume *pv;
 	struct device *dev;
 	uint64_t md_superblock, swap_signature;
+	int wipe_md, wipe_swap;
 
 	/* FIXME Check partition type is LVM unless --force is given */
 
@@ -117,7 +118,7 @@ static int pvcreate_check(struct cmd_con
 	}
 
 	/* Wipe superblock? */
-	if (dev_is_md(dev, &md_superblock) &&
+	if ((wipe_md = dev_is_md(dev, &md_superblock)) == 1 &&
 	    ((!pp->idp && !pp->restorefile) || pp->yes ||
 	     (yes_no_prompt("Software RAID md superblock "
 			    "detected on %s. Wipe it? [y/n] ", name) == 'y'))) {
@@ -129,7 +130,13 @@ static int pvcreate_check(struct cmd_con
 		}
 	}
 
-	if (dev_is_swap(dev, &swap_signature) &&
+	if (wipe_md == -1) {
+		log_error("Fatal error while trying to detect software "
+			  "RAID md superblock on %s", name);
+		return 0;
+	}
+
+	if ((wipe_swap = dev_is_swap(dev, &swap_signature)) == 1 &&
 	    ((!pp->idp && !pp->restorefile) || pp->yes ||
 	     (yes_no_prompt("Swap signature detected on %s. Wipe it? [y/n] ",
 			    name) == 'y'))) {
@@ -140,6 +147,12 @@ static int pvcreate_check(struct cmd_con
 		}
 	}
 
+	if (wipe_swap == -1) {
+		log_error("Fatal error while trying to detect swap "
+			  "signature on %s", name);
+		return 0;
+	}
+
 	if (sigint_caught())
 		return 0;
 
Yours,
   Petr.

-- 
Peter Rockai | me()mornfall!net | prockai()redhat!com
 http://blog.mornfall.net | http://web.mornfall.net

"In My Egotistical Opinion, most people's C programs should be
 indented six feet downward and covered with dirt."
     -- Blair P. Houghton on the subject of C program indentation

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]