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 via email to