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: