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

locking devices and partitions in partman



Hi all,

currently it is possible to:

1) Setup a device which depends on other devices, e.g. a LVM volume group

2) Remove/repartition the underlying devices

3) Watch as things fall apart

Being able to "lock" devices and/or partition which are in use would be a helpful feature to protect from shooting oneself in the foot IMHO and seems to have been a wishlist item for some time.

So, I've made an attempt at this. Attached is the basic outline of my idea. I've implemented the basics (error message when trying to modify a locked partition/device) in partman-base and added support for it to partman-lvm as a proof-of-concept.

I'd love to hear some comments on this approach.

Regards,
David

Index: partman-base/debian/partman-base.templates
===================================================================
--- partman-base/debian/partman-base.templates	(revision 37863)
+++ partman-base/debian/partman-base.templates	(working copy)
@@ -14,6 +14,24 @@
 Type: text
 _Description: Detecting file systems...
 
+Template: partman-base/devicelocked
+Type: error
+_Description: The device is currently in use
+ The device ${DEVICE} is currently in use for the following purpose:
+ ${MESSAGE}
+ .
+ You must first make sure that the device is no longer in use before you 
+ can make any changes to it.
+
+Template: partman-base/partlocked
+Type: error
+_Description: The partition is currently in use
+ Partition #${PARTITION} of device ${DEVICE} is currently in use for the following purpose:
+ ${MESSAGE}
+ .
+ You must first make sure that the partition is no longer in use before you 
+ can make any changes to it or the device which it resides on.
+
 Template: partman/exception_handler
 Type: select
 Choices: ${CHOICES}
Index: partman-base/definitions.sh
===================================================================
--- partman-base/definitions.sh	(revision 37863)
+++ partman-base/definitions.sh	(working copy)
@@ -866,6 +866,65 @@
     esac
 }
 
+lock_device() {
+	local device message dev testdev
+	device="$1"
+	message="$2"
+
+	for dev in $DEVICES/*; do
+		[ -d "$dev" ] || continue
+		cd $dev
+
+		# First check if we should lock a device
+		if [ -e "device" ]; then
+			testdev=$(mapdevfs $(cat device))
+			if [ "$device" = "$testdev" ]; then
+				echo "$message" > locked
+				return 0
+			fi
+		fi
+
+		# Second check if we should lock a partition
+		open_dialog PARTITIONS
+		while { read_line num id size type fs path name; [ "$id" ]; }; do
+			testdev=$(mapdevfs $path)
+			if [ "$device" = "$testdev" ]; then
+				echo "$message" > $id/locked
+			fi
+		done
+		close_dialog
+	done
+}
+
+unlock_device() {
+	local device dev testdev
+	device="$1"
+
+	for dev in $DEVICES/*; do
+		[ -d "$dev" ] || continue
+		cd $dev
+
+		# First check if we should unlock a device
+		if [ -e "device" ]; then
+			testdev=$(mapdevfs $(cat device))
+			if [ "$device" = "$testdev" ]; then
+				rm -f locked
+				return 0
+			fi
+		fi
+
+		# Second check if we should lock a partition
+		open_dialog PARTITIONS
+		while { read_line num id size type fs path name; [ "$id" ]; }; do
+			testdev=$(mapdevfs $path)
+			if [ "$device" = "$testdev" ]; then
+				rm -f $id/locked
+			fi
+		done
+		close_dialog
+	done
+}
+
 log '*******************************************************'
 
 # Local Variables:
Index: partman-base/choose_partition/partition_tree/do_option
===================================================================
--- partman-base/choose_partition/partition_tree/do_option	(revision 37863)
+++ partman-base/choose_partition/partition_tree/do_option	(working copy)
@@ -8,7 +8,44 @@
 id=${1#*//}
 
 cd $dev
+device=$(humandev $(cat device))
 
+# If the user wants to modify a device or partition
+# the device may not be locked
+if [ -e "$dev/locked" ]; then
+	locked=$(cat "$dev/locked")
+	db_subst partman-base/devicelocked DEVICE "$device"
+	db_subst partman-base/devicelocked MESSAGE "$locked"
+	db_set partman-base/devicelocked "false"
+	db_input critical partman-base/devicelocked
+	db_go
+	exit 0
+fi
+
+# Two scenarios to check for here:
+# 1) If the user wants to modify a partition - it may not be locked
+# 2) If the user wants to modify a device - none of its partitions may be locked
+open_dialog PARTITIONS
+while { read_line num tmpid size type fs path name; [ "$tmpid" ]; }; do
+	if [ -n "$id" ]; then
+		[ "$id" = "$tmpid" ] || continue
+	fi
+
+	if [ -e "$dev/$tmpid/locked" ]; then
+		locked=$(cat "$dev/$tmpid/locked")
+		db_subst partman-base/partlocked DEVICE "$device"
+		db_subst partman-base/partlocked PARTITION "$num"
+		db_subst partman-base/partlocked MESSAGE "$locked"
+		db_set partman-base/partlocked "false"
+		db_input critical partman-base/partlocked
+		db_go
+		close_dialog
+		exit 0
+	fi
+done
+close_dialog
+
+
 if [ -z "$id" ]; then
 #    ask_user /lib/partman/storage_device "$dev" "$id" || true
     open_dialog GET_DISK_TYPE
Index: partman-lvm/choose_partition/lvm/do_option
===================================================================
--- partman-lvm/choose_partition/lvm/do_option	(revision 37863)
+++ partman-lvm/choose_partition/lvm/do_option	(working copy)
@@ -65,6 +65,7 @@
 			db_go
 			db_get partman-lvm/activevg
 			[ "$RET" = "true" ] && log-output -t partman-lvm vgchange -a y
+			# TODO: We need to update the devices that LVM just claimed
 		fi
 		# ask only the first time
 		mkdir -p /var/cache/partman-lvm && touch /var/cache/partman-lvm/first
@@ -245,11 +246,15 @@
 		db_set partman-lvm/vgcreate_error "false"
 		db_input high partman-lvm/vgcreate_error
 		db_go
+	else
+		for pv in $pvs; do
+			lock_device "$pv" "In use by LVM VG $vg"
+		done
 	fi
 }
 
 do_vg_delete() {
-	local vgs vg output
+	local vgs vg output pvs
 	vgs=""
 
 	# Look for VGs with no LVs
@@ -287,10 +292,15 @@
 	db_get partman-lvm/vgdelete_confirm
 	[ "$RET" = "true" ] || return
 
+	pvs=$(vg_list_pvs "$vg")
 	if ! vg_delete "$vg"; then 
 		db_set partman-lvm/vgdelete_error "false"
 		db_input high partman-lvm/vgdelete_error
 		db_go
+	else
+		for pv in $pvs; do
+			unlock_device "$pv"
+		done
 	fi
 }
 
@@ -368,6 +378,8 @@
 			db_input high partman-lvm/vgextend_error
 			db_go
 			return
+		else
+			lock_device "$pv" "In use by LVM VG $vg"
 		fi
 	done
 }
@@ -454,6 +466,8 @@
 			db_input high partman-lvm/vgreduce_error
 			db_go
 			return
+		else
+			unlock_device "$pv"
 		fi
 	done
 }

Reply to: