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

Bug#396023: LVM removal will not work properly with the applied patch



Hi!

On Mon, Jul 02, 2007 at 02:30:55PM +0200, Fabio Massimo Di Nitto wrote:
> I am seeing different issues such as:
> 
> 1) take a fresh disk with no lvm
> 2) install using automatic lvm setup and it will work
> 3) install on it again this time not using lvm and it will work
> 4) install again this time using lvm and it will fail
> 
> The problem is that at #4 the disk has no partitions type LVM but the lvm
> metadata from #2 are still there.
> 
> pvscan still works but all other lvm operations will correctly report that there
> is an error.
> 
> Basically #3 did not wipe the disk properly.
> [...]
> I have different ideas on how to approach the problem but in one way or another
> they might hit other kinds of installations (Colin Watson mentioned low-mem as
> one of them).
> 
> My suggestion is:
> - Make partman-auto depends on the proper bits that it is actually using.
> - Add code to modprobe/verify that dm-mod is available.
> - Fix dm_wipe_lvm to not require dmsetup to detect the volumes and use lvm2
>   tools instead (I am not happy to execute vgchanges if we can avoid it).

The attached patch partially implements these suggestions and removes
bits of duplicated code in partman-partitioning and partman-auto.
Here's the details:

The creation of a new label for a disk (thus wiping any partitions) has
been factored out in create_new_label() in partman-base.
    
This function is then used by :
 * partman-partinioning/storage_device/label/do_option ;
 * partman-auto/auto-shared:wipe_disk().

create_new_label() uses dm_wipe_disk() when applicable and falls back to
lvm_wipe_disk() if dm_mod is not loaded.  The later does not require
dmsetup or the activation of the devices.

Both dm_wipe_disk() and lvm_wipe_disk() might require partman to be
restarted in order to get its state properly refreshed.  This has been
factored out in partman-base/definitions.sh:updated_parted().

In order to keep some modularity, dm_wipe_disk() has been moved from
partman-auto to partman-crypto:crypto_tools.sh.  In a similar fashion,
lvm_wipe_disk() has been added to partman-lvm:lvm_tools.sh.

The value added by the refactoring is less than it could possibly be,
though: once LVM has been configured, the devices are "locked" for
partman and the creation of a new label will prevented.  This check
could probably be relaxed with these new changes.

I have tested various cases and this patch will make d-i work correctly
with Fabio's scenario.  I would like some reviews though as I am far
from being a partman guru.

Cheers,
-- 
Jérémy Bobbio                        .''`. 
lunar@debian.org                    : :Ⓐ  :  # apt-get install anarchism
                                    `. `'` 
                                      `-   
commit e0a88b79f0933e561028b9c48a6ed2f6004fac40
Author: Jérémy Bobbio <lunar@debian.org>
Date:   Wed Oct 24 21:13:56 2007 +0200

    Fix the creation of a new partition label when crypto or LVM are used
    
    In order to make the creation of a new partition label (manually or
    through guided partitioning) correctly remove LVM and crypto metadata
    (see #396023 and #425829) the operation has been factored out in
    create_new_label() in partman-base.
    
    This function is then used by :
     * partman-partinioning/storage_device/label/do_option ;
     * partman-auto/auto-shared:wipe_disk().
    
    create_new_label() uses dm_wipe_disk() when applicable and falls back to
    lvm_wipe_disk() if dm_mod is not loaded.  The later does not require
    dmsetup or the activation of the devices.

    Both dm_wipe_disk() and lvm_wipe_disk() might require partman to be
    restarted in order to get its state properly refreshed.  This has been
    factored out in partman-base/definitions.sh:updated_parted().
    
    In order to keep some modularity, dm_wipe_disk() has been moved from
    partman-auto to partman-crypto:crypto_tools.sh.  In a similar fashion,
    lvm_wipe_disk() has been added to partman-lvm:lvm_tools.sh.
    
    The value added by the refactoring is less than it could possibly be,
    though: once LVM has been configured, the devices are "locked" for
    partman and the creation of a new label will prevented.  This check
    could probably be relaxed with these new changes.

diff --git a/packages/partman/partman-auto/auto-shared.sh b/packages/partman/partman-auto/auto-shared.sh
index dc63eee..ec38c7a 100644
--- a/packages/partman/partman-auto/auto-shared.sh
+++ b/packages/partman/partman-auto/auto-shared.sh
@@ -1,303 +1,13 @@
 ## this file contains a bunch of shared code between partman-auto
 ## and partman-auto-lvm.
 
-# Gets the major and minor device numbers of a device passed as $1
-# and puts them in $MAJOR and $MINOR.
-dev_get_major_minor() {
-	local dev stats
-	dev="$1"
-
-	if [ -z "$dev" ]; then
-		return 1
-	fi
-
-	stats=$(ls -al "$dev" | sed -e 's/[[:space:],]\+/ /g')
-	MAJOR=$(echo "$stats" | cut -d' ' -f5)
-	MINOR=$(echo "$stats" | cut -d' ' -f6)
-
-	if [ -z "$MAJOR" ] || [ -z "$MINOR" ]; then
-		return 1
-	fi
-
-	return 0
-}
-
-# Makes sure that parted has no stale info
-dm_update_parted() {
-	local restart tmpdev tmppart realdev
-
-	restart="0"
-	for tmpdev in $DEVICES/*; do
-		for tmppart in $tmpdev/*; do
-			if [ ! -d "$tmppart" ]; then
-				continue
-			fi
-
-			if [ ! -e "$tmppart/crypt_active" ]; then
-				continue
-			fi
-
-			if [ ! -e "$(cat "$tmppart/crypt_active")" ]; then
-				rm -f "$tmppart/crypt_active"
-				rm -f "$tmppart/locked"
-				restart="1"
-			fi
-		done
-
-		realdev=$(cat $tmpdev/device)
-		if ! $(echo "$realdev" | grep -q "/dev/mapper/"); then
-			continue
-		fi
-
-		if [ -b "$realdev" ]; then
-			continue
-		fi
-
-		rm -rf $tmpdev
-		restart="1"
-	done
-
-	if [ $restart ]; then
-		stop_parted_server
-		restart_partman || return 1
-	fi
-
-	return 0
-}
-
-# Given a lvm device (excluding the /dev/mapper/ part), will gather data on
-# the LVM config, prompt the user and then remove the VG along with all the
-# LV's and PV's which belong to that VG.
-dm_wipe_lvm() {
-	local dev vg pv pvs lv lvs vgtext lvtext pvtext
-	dev="$1"
-
-	# First check that the device exists, it's not an error if it doesn't
-	# since one call to this function can wipe several LV's
-	if [ ! -b "/dev/mapper/$dev" ]; then
-		return 0
-	fi
-
-	if [ ! -e /lib/partman/lvm_tools.sh ]; then
-		return 1
-	fi
-
-	. /lib/partman/lvm_tools.sh
-
-	# We get a device like mainvg-swaplv as $1, let's figure out the VG
-
-	# Make sure that the device includes at least one dash
-        if [ "$(echo -n "$dev" | tr -d -)" = "$dev" ]; then
-                return 1
-	fi
-
-        # Split volume group from logical volume.
-        vg=$(echo ${dev} | sed -e 's#\(.*\)\([^-]\)-[^-].*#\1\2#')
-        # Reduce padded --'s to -'s
-        vg=$(echo ${vg} | sed -e 's#--#-#g')
-	if [ -z "$vg" ]; then
-		return 1
-	fi
-	pvs=$(vg_list_pvs $vg)
-	lvs=$(vg_list_lvs $vg)
-
-	# Ask for permission to erase LVM volumes 
-	vgtext="$vg"
-	pvtext=""
-	for pv in $pvs; do
-		pvtext="${pvtext:+$pvtext, }$pv"
-	done
-	lvtext=""
-	for lv in $lvs; do
-		lvtext="${lvtext:+$lvtext, }$lv"
-	done
-
-	db_subst partman-auto/purge_lvm_from_device VGTARGETS "$vgtext"
-	db_subst partman-auto/purge_lvm_from_device LVTARGETS "$lvtext"
-	db_subst partman-auto/purge_lvm_from_device PVTARGETS "$pvtext"
-	db_input critical partman-auto/purge_lvm_from_device
-	db_go || return 1
-	db_get partman-auto/purge_lvm_from_device
-	if [ "$RET" != "true" ]; then
-		return 1
-	fi
-
-	# Remove the LV's
-	for lv in $lvs; do
-		lv_delete $vg $lv
-	done
-
-	# Remove the VG
-	vg_delete $vg
-
-	# Remove the PV's
-	for pv in $pvs; do
-		pv_delete $pv
-		partman_unlock_unit $pv
-	done
-
-	return 0
-}
-
-# Given a cryptodev (minus the /dev/mapper/ part), will prompt the user and
-# then remove the device.
-dm_wipe_crypto() {
-	local dev
-	dev="$1"
-
-	# Ask for permission to erase crypto volumes 
-	db_subst partman-auto/purge_crypto_from_device TARGET "$dev"
-	db_input critical partman-auto/purge_crypto_from_device
-	db_go || return 1
-	db_get partman-auto/purge_crypto_from_device
-	if [ "$RET" != "true" ]; then
-		return 1
-	fi
-
-	dmsetup remove "$dev"
-	return $?
-}
-
-# Given a dm device (minus the /dev/mapper/ part), will recursively remove
-# all devices which depend on it and then the device itself.
-dm_wipe_dev() {
-	local dev deps dep name type
-	dev="$1"
-
-	if [ ! -e "/dev/mapper/$dev" ]; then
-		return 0
-	fi
-
-	dev_get_major_minor "/dev/mapper/$dev" || return 1
-	deps=$(dmsetup deps | grep "($MAJOR, $MINOR)" | cut -d: -f1)
-	for dep in $deps; do
-		if [ ! -e "/dev/mapper/$dep" ]; then
-			continue
-		fi
-
-		dev_get_major_minor "/dev/mapper/$dep" || return 1
-		name=$(dmsetup info -j$MAJOR -m$MINOR | grep "Name:" | \
-			cut -d: -f2 | sed -e 's/[[:space:]]//g')
-		if [ -z "$name" ]; then
-			return 1
-		fi
-
-		dm_wipe_dev "$name" || return 1
-	done
-
-	type=$(dmsetup table | grep "^$dev:" | cut -d' ' -f4)
-	if [ -z "$type" ]; then
-		return 1
-	elif [ "$type" = crypt ]; then
-		dm_wipe_crypto "$dev" || return 1
-	else
-		dm_wipe_lvm "$dev" || return 1
-	fi
-
-	return 0
-}
-
-# Wipes any dm devices from a disk (LVM and/or crypto)
-# Given an argument like /dev/hda, /dev/hda1 and /dev/hda2 are also wiped...
-# Normally you wouldn't want to use this function, 
-# but wipe_disk() which will also call this function.
-dm_wipe_disk() {
-	local dev realdev devs check checkdev provide provides restart tmpdev tmppart
-	dev="$1"
-
-	if [ -z "$dev" ]; then
-		return 1
-	fi
-
-	realdev=$(mapdevfs "$(cat $dev/device)")
-	devs=$(ls ${realdev}* 2>/dev/null)
-
-	# Given e.g. /dev/hda we check /dev/hda, /dev/hda1, etc...
-	for check in $devs; do
-		checkdev=$(readlink -f "$check")
-		if [ ! -e "$checkdev" ]; then
-			continue
-		fi
-
-		dev_get_major_minor "$checkdev" || return 1
-
-		provides=$(dmsetup deps | grep "($MAJOR, $MINOR)" | cut -d: -f1)
-
-		if [ -z "$provides" ]; then
-			continue
-		fi
-
-		for provide in $provides; do
-			dm_wipe_dev $provide || return 1
-		done
-	done
-	
-	dm_update_parted || return 1
-	return 0
-}
-
 wipe_disk() {
 	local dev
 	dev="$1"
 
-	if [ -z "$dev" ]; then
-		return 1
-	fi
-
-	dm_wipe_disk "$dev" || return 1
+	create_new_label "$dev" || return 1
 
 	cd $dev || return 1
-	open_dialog LABEL_TYPES
-	types=$(read_list)
-	close_dialog
-
-	label_type=$(default_disk_label)
-
-	if ! expr "$types" : ".*${label_type}.*" >/dev/null; then
-		label_type=msdos # most widely used
-	fi
-	
-	# Use gpt instead of msdos disklabel for disks larger than 2TB
-	if expr "$types" : ".*gpt.*" >/dev/null; then
-		if [ "$label_type" = msdos ] ; then
-			disksize=$(cat size)
-			if $(longint_le $(human2longint 2TB) $disksize) ; then
-				label_type=gpt
-			fi
-		fi
-	fi
-
-	if [ "$label_type" = sun ]; then
-		db_input critical partman/confirm_write_new_label
-		db_go || exit 0
-		db_get partman/confirm_write_new_label
-		if [ "$RET" = false ]; then
-			db_reset partman/confirm_write_new_label
-			exit 1
-		fi
-		db_reset partman/confirm_write_new_label
-	fi
-	
-	open_dialog NEW_LABEL "$label_type"
-	close_dialog
-	
-	if [ "$label_type" = sun ]; then
-		# write the partition table to the disk
-		disable_swap
-		open_dialog COMMIT
-		close_dialog
-		sync
-		# reread it from there
-		open_dialog UNDO
-		close_dialog
-		enable_swap
-	fi
-
-	# Different types partition tables support different visuals.  Some
-	# have partition names other don't have, some have extended and
-	# logical partitions, others don't.  Hence we have to regenerate the
-	# list of the visuals
-	rm -f visuals
 
 	free_space=''
 	open_dialog PARTITIONS
diff --git a/packages/partman/partman-auto/debian/changelog b/packages/partman/partman-auto/debian/changelog
index 0a0a6a6..874186c 100644
--- a/packages/partman/partman-auto/debian/changelog
+++ b/packages/partman/partman-auto/debian/changelog
@@ -1,3 +1,13 @@
+partman-auto (71) UNRELEASED; urgency=low
+
+  * Use create_new_label() in wipe_disk().  Requires partman-base (>> 110).
+    (Closes: #425829)
+  * Move dm_update_parted to partman-base.
+  * Move dm_wipe_disk and its dependencies to partman-crypto.
+  * Remove unused partman-auto/cannot_purge_lvm_from_device template.
+
+ -- Jérémy Bobbio <lunar@debian.org>  Wed, 24 Oct 2007 18:49:04 +0200
+
 partman-auto (70) unstable; urgency=low
 
   [ Frans Pop ]
diff --git a/packages/partman/partman-auto/debian/control b/packages/partman/partman-auto/debian/control
index 7eeced1..d730deb 100644
--- a/packages/partman/partman-auto/debian/control
+++ b/packages/partman/partman-auto/debian/control
@@ -9,5 +9,5 @@ Vcs-Svn: svn://svn.debian.org/d-i/trunk/packages/partman/partman-auto
 Package: partman-auto
 XC-Package-Type: udeb
 Architecture: any
-Depends: ${misc:Depends}, di-utils, partman-base (>= 99), partman-basicfilesystems, partman-ext3
+Depends: ${misc:Depends}, di-utils, partman-base (>> 110), partman-basicfilesystems, partman-ext3
 Description: Automatically partition storage devices (partman)
diff --git a/packages/partman/partman-auto/debian/partman-auto.templates b/packages/partman/partman-auto/debian/partman-auto.templates
index d7b28c8..c734a24 100644
--- a/packages/partman/partman-auto/debian/partman-auto.templates
+++ b/packages/partman/partman-auto/debian/partman-auto.templates
@@ -59,13 +59,6 @@ _Description: Remove existing crypto volume data?
  Note that this will also permanently erase any data currently on the
  crypto volume.
 
-Template: partman-auto/cannot_purge_lvm_from_device
-Type: error
-_Description: LVM physical volume already exists on the selected device
- The selected device already contains one or more LVM physical
- volumes which cannot be removed. It is therefore not possible to
- automatically partition this device.
-
 Template: partman-auto/disk
 Type: string
 Description: for internal use; can be preseeded
diff --git a/packages/partman/partman-base/debian/changelog b/packages/partman/partman-base/debian/changelog
index 9854522..0498250 100644
--- a/packages/partman/partman-base/debian/changelog
+++ b/packages/partman/partman-base/debian/changelog
@@ -1,3 +1,12 @@
+partman-base (111) UNRELEASED; urgency=low
+
+  * Add update_parted() (from partman-auto) to definitions.sh.
+  * Add create_new_label() in definitions.sh.  This function is used to create
+    a new label on a disk and wipes its content (e.g. LVM and crypto)
+    accordingly.  Require partman-partitining (>> 0.52) to make use of it.
+
+ -- Jérémy Bobbio <lunar@debian.org>  Wed, 24 Oct 2007 18:52:19 +0200
+
 partman-base (110) unstable; urgency=low
 
   [ Colin Watson ]
diff --git a/packages/partman/partman-base/debian/control b/packages/partman/partman-base/debian/control
index cd875d3..1c0eb16 100644
--- a/packages/partman/partman-base/debian/control
+++ b/packages/partman/partman-base/debian/control
@@ -9,7 +9,7 @@ Vcs-Svn: svn://svn.debian.org/d-i/trunk/packages/partman/partman-base
 Package: partman-base
 XC-Package-Type: udeb
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, partman-utils, partman-partitioning, partman-target, archdetect, harddrive-detection, di-utils-mapdevfs, di-utils (>= 1.15)
+Depends: ${shlibs:Depends}, ${misc:Depends}, partman-utils, partman-partitioning (>> 0.52), partman-target, archdetect, harddrive-detection, di-utils-mapdevfs, di-utils (>= 1.15)
 Provides: ${provides}
 XB-Installer-Menu-Item: ${menuitemnum}
 Description: Partition the storage devices (partman)
diff --git a/packages/partman/partman-base/definitions.sh b/packages/partman/partman-base/definitions.sh
index 3aac718..71a8046 100644
--- a/packages/partman/partman-base/definitions.sh
+++ b/packages/partman/partman-base/definitions.sh
@@ -296,6 +296,50 @@ restart_partman () {
 	db_progress STOP
 }
 
+# Make sure that parted has no stale info
+# (used after crypto/LVM cleanup)
+update_parted() {
+	local restart tmpdev tmppart realdev
+
+	restart="0"
+	for tmpdev in $DEVICES/*; do
+		for tmppart in $tmpdev/*; do
+			if [ ! -d "$tmppart" ]; then
+				continue
+			fi
+
+			if [ ! -e "$tmppart/crypt_active" ]; then
+				continue
+			fi
+
+			if [ ! -e "$(cat "$tmppart/crypt_active")" ]; then
+				rm -f "$tmppart/crypt_active"
+				rm -f "$tmppart/locked"
+				restart="1"
+			fi
+		done
+
+		realdev=$(cat $tmpdev/device)
+		if ! $(echo "$realdev" | grep -q "/dev/mapper/"); then
+			continue
+		fi
+
+		if [ -b "$realdev" ]; then
+			continue
+		fi
+
+		rm -rf $tmpdev
+		restart="1"
+	done
+
+	if [ $restart ]; then
+		stop_parted_server
+		restart_partman || return 1
+	fi
+
+	return 0
+}
+
 update_partition () {
 	local u
 	cd $1
@@ -1001,6 +1045,91 @@ partman_lock_unit() {
 	done
 }
 
+create_new_label() {
+	local dev default_type chosen_type types
+	dev="$1"
+
+	if [ -z "$dev" ]; then
+		return 1
+	fi
+
+	# If we have dm-mod, use dmsetup to cleanup LVM and crypto partitions
+	if lsmod | grep -q '^dm_mod ' && [ -f /lib/partman/crypto_tools.sh ]; then
+		. /lib/partman/crypto_tools.sh
+		dm_wipe_disk "$dev" || return 1
+	elif [ -f /lib/partman/lvm_tools.sh ]; then
+		# Remove LVM devices using plain LVM tools
+		. /lib/partman/lvm_tools.sh
+		lvm_wipe_disk "$dev" || return 1
+	fi
+
+	cd "$dev" || return 1
+	open_dialog LABEL_TYPES
+	types=$(read_list)
+	close_dialog
+
+	db_subst partman-partitioning/choose_label CHOICES "$types"
+	PRIORITY=critical
+
+	default_type=$(default_disk_label)
+
+	# Use gpt instead of msdos disklabel for disks larger than 2TB
+	if expr "$types" : ".*gpt.*" >/dev/null; then
+		if [ "$default_type" = msdos ] ; then
+			disksize=$(cat size)
+			if $(longint_le $(human2longint 2TB) $disksize) ; then
+				default_type=gpt
+			fi
+		fi
+	fi
+
+	if expr "$types" : ".*${default_type}.*" >/dev/null; then
+		PRIORITY=low
+	else
+		default_type="msdos" # most widely used
+		PRIORITY=medium
+	fi
+	db_set partman-partitioning/choose_label "$default_type"
+	db_input $PRIORITY partman-partitioning/choose_label || true
+	db_go || exit 1
+	db_get partman-partitioning/choose_label
+
+	chosen_type="$RET"
+
+	if [ "$chosen_type" = sun ]; then
+		db_input critical partman/confirm_write_new_label
+		db_go || exit 0
+		db_get partman/confirm_write_new_label
+		if [ "$RET" = false ]; then
+			db_reset partman/confirm_write_new_label
+			exit 1
+		fi
+		db_reset partman/confirm_write_new_label
+	fi
+
+	open_dialog NEW_LABEL "$chosen_type"
+	close_dialog
+
+	if [ "$chosen_type" = sun ]; then
+		# write the partition table to the disk
+		disable_swap
+		open_dialog COMMIT
+		close_dialog
+		sync
+		# reread it from there
+		open_dialog UNDO
+		close_dialog
+		enable_swap
+	fi
+
+	# Different types partition tables support different visuals.  Some
+	# have partition names other don't have, some have extended and
+	# logical partitions, others don't.  Hence we have to regenerate the
+	# list of the visuals
+	rm -f visuals
+
+}
+
 # Unlock a device or partition to allow further modifications
 partman_unlock_unit() {
 	local device dev testdev
diff --git a/packages/partman/partman-crypto/crypto_tools.sh b/packages/partman/partman-crypto/crypto_tools.sh
index 61f54bc..feecdbd 100644
--- a/packages/partman/partman-crypto/crypto_tools.sh
+++ b/packages/partman/partman-crypto/crypto_tools.sh
@@ -1,5 +1,197 @@
 . /lib/partman/definitions.sh
 
+# Gets the major and minor device numbers of a device passed as $1
+# and puts them in $MAJOR and $MINOR.
+dev_get_major_minor() {
+	local dev stats
+	dev="$1"
+
+	if [ -z "$dev" ]; then
+		return 1
+	fi
+
+	stats=$(ls -al "$dev" | sed -e 's/[[:space:],]\+/ /g')
+	MAJOR=$(echo "$stats" | cut -d' ' -f5)
+	MINOR=$(echo "$stats" | cut -d' ' -f6)
+
+	if [ -z "$MAJOR" ] || [ -z "$MINOR" ]; then
+		return 1
+	fi
+
+	return 0
+}
+
+# Given a lvm device (excluding the /dev/mapper/ part), will gather data on
+# the LVM config, prompt the user and then remove the VG along with all the
+# LV's and PV's which belong to that VG.
+dm_wipe_lvm() {
+	local dev vg pv pvs lv lvs vgtext lvtext pvtext
+	dev="$1"
+
+	# First check that the device exists, it's not an error if it doesn't
+	# since one call to this function can wipe several LV's
+	if [ ! -b "/dev/mapper/$dev" ]; then
+		return 0
+	fi
+
+	if [ ! -e /lib/partman/lvm_tools.sh ]; then
+		return 1
+	fi
+
+	. /lib/partman/lvm_tools.sh
+
+	# We get a device like mainvg-swaplv as $1, let's figure out the VG
+
+	# Make sure that the device includes at least one dash
+        if [ "$(echo -n "$dev" | tr -d -)" = "$dev" ]; then
+                return 1
+	fi
+
+        # Split volume group from logical volume.
+        vg=$(echo ${dev} | sed -e 's#\(.*\)\([^-]\)-[^-].*#\1\2#')
+        # Reduce padded --'s to -'s
+        vg=$(echo ${vg} | sed -e 's#--#-#g')
+	if [ -z "$vg" ]; then
+		return 1
+	fi
+	pvs=$(vg_list_pvs $vg)
+	lvs=$(vg_list_lvs $vg)
+
+	# Ask for permission to erase LVM volumes
+	vgtext="$vg"
+	pvtext=""
+	for pv in $pvs; do
+		pvtext="${pvtext:+$pvtext, }$pv"
+	done
+	lvtext=""
+	for lv in $lvs; do
+		lvtext="${lvtext:+$lvtext, }$lv"
+	done
+
+	db_subst partman-auto/purge_lvm_from_device VGTARGETS "$vgtext"
+	db_subst partman-auto/purge_lvm_from_device LVTARGETS "$lvtext"
+	db_subst partman-auto/purge_lvm_from_device PVTARGETS "$pvtext"
+	db_input critical partman-auto/purge_lvm_from_device
+	db_go || return 1
+	db_get partman-auto/purge_lvm_from_device
+	if [ "$RET" != "true" ]; then
+		return 1
+	fi
+
+	# Remove the LV's
+	for lv in $lvs; do
+		lv_delete $vg $lv
+	done
+
+	# Remove the VG
+	vg_delete $vg
+
+	# Remove the PV's
+	for pv in $pvs; do
+		pv_delete $pv
+		partman_unlock_unit $pv
+	done
+
+	return 0
+}
+
+# Given a cryptodev (minus the /dev/mapper/ part), will prompt the user and
+# then remove the device.
+dm_wipe_crypto() {
+	local dev
+	dev="$1"
+
+	# Ask for permission to erase crypto volumes
+	db_subst partman-auto/purge_crypto_from_device TARGET "$dev"
+	db_input critical partman-auto/purge_crypto_from_device
+	db_go || return 1
+	db_get partman-auto/purge_crypto_from_device
+	if [ "$RET" != "true" ]; then
+		return 1
+	fi
+
+	dmsetup remove "$dev"
+	return $?
+}
+
+# Given a dm device (minus the /dev/mapper/ part), will recursively remove
+# all devices which depend on it and then the device itself.
+dm_wipe_dev() {
+	local dev deps dep name type
+	dev="$1"
+
+	if [ ! -e "/dev/mapper/$dev" ]; then
+		return 0
+	fi
+
+	dev_get_major_minor "/dev/mapper/$dev" || return 1
+	deps=$(dmsetup deps | grep "($MAJOR, $MINOR)" | cut -d: -f1)
+	for dep in $deps; do
+		if [ ! -e "/dev/mapper/$dep" ]; then
+			continue
+		fi
+
+		dev_get_major_minor "/dev/mapper/$dep" || return 1
+		name=$(dmsetup info -j$MAJOR -m$MINOR | grep "Name:" | \
+			cut -d: -f2 | sed -e 's/[[:space:]]//g')
+		if [ -z "$name" ]; then
+			return 1
+		fi
+
+		dm_wipe_dev "$name" || return 1
+	done
+
+	type=$(dmsetup table | grep "^$dev:" | cut -d' ' -f4)
+	if [ -z "$type" ]; then
+		return 1
+	elif [ "$type" = crypt ]; then
+		dm_wipe_crypto "$dev" || return 1
+	else
+		dm_wipe_lvm "$dev" || return 1
+	fi
+
+	return 0
+}
+
+# Wipes any dm devices from a disk (LVM and/or crypto)
+# Given an argument like /dev/hda, /dev/hda1 and /dev/hda2 are also wiped...
+# Normally you wouldn't want to use this function,
+# but wipe_disk() which will also call this function.
+dm_wipe_disk() {
+	local dev realdev devs check checkdev provide provides restart tmpdev tmppart
+	dev="$1"
+
+	if [ -z "$dev" ]; then
+		return 1
+	fi
+
+	realdev=$(mapdevfs "$(cat $dev/device)")
+	devs=$(ls ${realdev}* 2>/dev/null)
+
+	# Given e.g. /dev/hda we check /dev/hda, /dev/hda1, etc...
+	for check in $devs; do
+		checkdev=$(readlink -f "$check")
+		if [ ! -e "$checkdev" ]; then
+			continue
+		fi
+
+		dev_get_major_minor "$checkdev" || return 1
+
+		provides=$(dmsetup deps | grep "($MAJOR, $MINOR)" | cut -d: -f1)
+
+		if [ -z "$provides" ]; then
+			continue
+		fi
+
+		for provide in $provides; do
+			dm_wipe_dev $provide || return 1
+		done
+	done
+
+	update_parted || return 1
+	return 0
+}
+
 dm_dev_is_safe() {
 	local maj min dminfo deps
 	maj="$1"
diff --git a/packages/partman/partman-crypto/debian/changelog b/packages/partman/partman-crypto/debian/changelog
index ebcad60..0dec16f 100644
--- a/packages/partman/partman-crypto/debian/changelog
+++ b/packages/partman/partman-crypto/debian/changelog
@@ -1,7 +1,13 @@
 partman-crypto (23) UNRELEASED; urgency=low
 
+  [ Colin Watson ]
   * Reduce noise from repeated 'debian/rules clean' runs.
 
+  [ Jérémy Bobbio ]
+  * Add dm_wipe_disk and its dependencies to crypto_tools.sh from partman-auto.
+    This function is used by create_new_label() introduced in partman-base
+    (>> 0.110).
+
  -- Colin Watson <cjwatson@debian.org>  Tue, 02 Oct 2007 16:30:15 +0100
 
 partman-crypto (22) unstable; urgency=low
diff --git a/packages/partman/partman-lvm/debian/changelog b/packages/partman/partman-lvm/debian/changelog
index 7658cc3..a0f8e15 100644
--- a/packages/partman/partman-lvm/debian/changelog
+++ b/packages/partman/partman-lvm/debian/changelog
@@ -1,3 +1,12 @@
+partman-lvm (56) UNRELEASED; urgency=low
+
+  * Add lvm_wipe_disk() to lvm_tools.sh.  This function is used by
+    create_new_label() introduced in partman-base (>> 110).
+    (Closes: #396023)
+  * Add pv_list_vgs() to lvm_tools.sh.
+
+ -- Jérémy Bobbio <lunar@debian.org>  Wed, 24 Oct 2007 19:03:08 +0200
+
 partman-lvm (55) unstable; urgency=low
 
   [ Frans Pop ]
diff --git a/packages/partman/partman-lvm/lvm_tools.sh b/packages/partman/partman-lvm/lvm_tools.sh
index 96f33a5..1143255 100644
--- a/packages/partman/partman-lvm/lvm_tools.sh
+++ b/packages/partman/partman-lvm/lvm_tools.sh
@@ -10,6 +10,69 @@ export LVM_SUPPRESS_FD_WARNINGS=1
 #
 ###############################################################################
 
+# Wipes any traces of LVM from a disk
+# Used by create_new_label() if dmsetup is not usable
+lvm_wipe_disk() {
+	local dev realdev vg pvs pv lv tmpdev
+	dev="$1"
+
+	# Check if the device already contains any physical volumes
+	realdev=$(mapdevfs "$(cat $dev/device)")
+	if ! pv_on_device "$realdev"; then
+		return 0
+	fi
+
+        vgs="$(for pv in $(pvs --noheadings --nosuffix -o pv_name |
+				grep "$realdev"); do
+			pv_list_vgs "$pv"
+		done | uniq)"
+	pvs="$(for vg in $vgs; do vg_list_pvs $vg; done | uniq)"
+	lvs="$(for vg in $vgs; do vg_list_lvs $vg; done | uniq)"
+
+	# Ask for permission to erase LVM volumes
+	vgtext=""
+	for vg in $vgs; do
+		vgtext="${vgtext:+$vgtext, }$vg"
+	done
+	pvtext=""
+	for pv in $pvs; do
+		pvtext="${pvtext:+$pvtext, }$pv"
+	done
+	lvtext=""
+	for lv in $lvs; do
+		lvtext="${lvtext:+$lvtext, }$lv"
+	done
+
+	db_subst partman-auto/purge_lvm_from_device VGTARGETS "$vgtext"
+	db_subst partman-auto/purge_lvm_from_device LVTARGETS "$lvtext"
+	db_subst partman-auto/purge_lvm_from_device PVTARGETS "$pvtext"
+	db_input critical partman-auto/purge_lvm_from_device
+	db_go || return 1
+	db_get partman-auto/purge_lvm_from_device
+	if [ "$RET" != "true" ]; then
+		return 1
+	fi
+
+	# Remove the LV's
+	for lv in $lvs; do
+		lv_delete $vg $lv
+	done
+
+	# Remove the VG's
+	for vg in $vgs; do
+		vg_delete $vg
+	done
+
+	# Remove the PV's
+	for pv in $pvs; do
+		pv_delete $pv
+		partman_unlock_unit $pv
+	done
+
+	update_parted || return 1
+	return 0
+}
+
 # Convert common terms for disk sizes into something LVM understands.
 #  e.g. "200 gb" -> "200G"
 lvm_size_from_human() {
@@ -243,6 +306,19 @@ pv_list_free() {
 	done
 }
 
+# Get all VGs from a PV
+pv_list_vgs() {
+	local line vg pv
+
+	for line in $(lvm_get_info pvs vg_name,pv_name ""); do
+		vg=$(echo "$line" | cut -d':' -f1)
+		pv=$(echo "$line" | cut -d':' -f2)
+		if [ "$pv" = "$1" ]; then
+			echo "$vg"
+		fi
+	done
+}
+
 # Initialize a PV
 pv_create() {
 	local pv
diff --git a/packages/partman/partman-partitioning/debian/changelog b/packages/partman/partman-partitioning/debian/changelog
index 768d4ea..7081e1f 100644
--- a/packages/partman/partman-partitioning/debian/changelog
+++ b/packages/partman/partman-partitioning/debian/changelog
@@ -1,3 +1,10 @@
+partman-partitioning (53) UNRELEASED; urgency=low
+
+  * Use create_new_label() from partman-base (>> 110) in
+    storage_device/label/do_option. 
+
+ -- Jérémy Bobbio <lunar@debian.org>  Wed, 24 Oct 2007 19:07:23 +0200
+
 partman-partitioning (52) unstable; urgency=low
 
   * Use 'mkdir -p' rather than more awkward test-then-create constructions.
diff --git a/packages/partman/partman-partitioning/storage_device/label/do_option b/packages/partman/partman-partitioning/storage_device/label/do_option
index 7676b3f..25740d3 100755
--- a/packages/partman/partman-partitioning/storage_device/label/do_option
+++ b/packages/partman/partman-partitioning/storage_device/label/do_option
@@ -14,68 +14,12 @@ if [ "$RET" = false ]; then
 	db_reset partman/confirm_new_label
 	exit 1
 fi
-db_reset partman/confirm_new_label
-
-open_dialog LABEL_TYPES
-types=$(read_list)
-close_dialog
-
-db_subst partman-partitioning/choose_label CHOICES "$types"
-PRIORITY=critical
-
-default_label=$(default_disk_label)
-
-# Use gpt instead of msdos disklabel for disks larger than 2TB
-if expr "$types" : ".*gpt.*" >/dev/null; then
-	if [ "$default_label" = msdos ] ; then
-		disksize=$(cat size)
-		if $(longint_le $(human2longint 2TB) $disksize) ; then
-			default_label=gpt
-		fi
-	fi
-fi
-
-if expr "$types" : ".*${default_label}.*" >/dev/null; then
-	db_set partman-partitioning/choose_label "$default_label"
-	PRIORITY=low
-fi
-db_input $PRIORITY partman-partitioning/choose_label || true
-db_go || exit 1
-db_get partman-partitioning/choose_label
+# We do not reset partman/confirm_new_label here as users of "sun" label
+# gets another confirmation screen as changes needs to be done immediately.
 
-chosen_type="$RET"
+create_new_label "$dev"
 
-if [ "$chosen_type" = sun ]; then
-	db_input critical partman/confirm_write_new_label
-	db_go || exit 0
-	db_get partman/confirm_write_new_label
-	if [ "$RET" = false ]; then
-		db_reset partman/confirm_write_new_label
-		exit 1
-	fi
-	db_reset partman/confirm_write_new_label
-fi
-
-open_dialog NEW_LABEL "$chosen_type"
-close_dialog
-
-if [ "$chosen_type" = sun ]; then
-	# write the partition table to the disk
-	disable_swap
-	open_dialog COMMIT
-	close_dialog
-	sync
-	# reread it from there
-	open_dialog UNDO
-	close_dialog
-	enable_swap
-fi
-
-# Different types partition tables support different visuals.  Some
-# have partition names other don't have, some have extended and
-# logical partitions, others don't.  Hence we have to regenerate the
-# list of the visuals
-rm -f visuals
+db_reset partman/confirm_new_label
 
 partitions=''
 open_dialog PARTITIONS
@@ -88,7 +32,11 @@ for id in $partitions; do
 	update_partition $dev $id
 done
 
-if [ "$chosen_type" = sun ]; then
+open_dialog GET_LABEL_TYPE
+read_line label_type
+close_dialog
+
+if [ "$label_type" = sun ]; then
 	backupdir=../../backup/`basename $dev`
 	rm -rf "$backupdir"
 	cp -a . "$backupdir"

Attachment: signature.asc
Description: Digital signature


Reply to: