diff options
author | David Teigland <teigland@redhat.com> | 2012-08-29 16:47:58 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2012-08-29 16:47:58 -0500 |
commit | 52a93f9d621deabac7d0d686c527771317d2ded9 (patch) | |
tree | 5f323cfb64db527927150e06f0b986ed2125fa76 | |
parent | c5e56956ea89a06644f17c24eb105e4273294c89 (diff) | |
download | dct-stuff-52a93f9d621deabac7d0d686c527771317d2ded9.tar.gz dct-stuff-52a93f9d621deabac7d0d686c527771317d2ded9.tar.xz dct-stuff-52a93f9d621deabac7d0d686c527771317d2ded9.zip |
sanlvm: update
Signed-off-by: David Teigland <teigland@redhat.com>
-rwxr-xr-x | lvm/sanlvm | 271 |
1 files changed, 206 insertions, 65 deletions
@@ -2,6 +2,7 @@ host_id=0 cmd= +glpath= vgname= lvname= lock_mode= @@ -9,38 +10,76 @@ active_mode= no_active= offset= +# sanlvmd is only needed when sanlvm is used with lv +# activation leases. When sanlvm is only used to +# serialize vg metadata changes, it's not needed. +# +# sanlvmd is a process that sanlock views as owning the lv +# activation leases. When a vg disappears/fails, sanlock +# will notify the owner of the leases in that vg; in this +# case, it sends SIGTERM to sanlvmd. When sanlvmd gets +# this SIGTERM, it knows that its leases will be disappearing +# soon, and that another host would be able to acquire them. +# So, it needs to force the local host to stop using the +# lv's it has locked, since they won't be locked much longer. +# +# To do this, it could: +# - forcibly deactivate the sanlvm lvs in the failed vgs +# - suspend the lv's in the failed vgs +# - or suspend lv's, replace with the error target and resume +# and once done, it can release the leases on those lvs. +# +# (If the sanlock watchdog is enabled, it will fire to reset +# the host if sanlvmd is not able to release the leases +# before another host could acquire them.) +# +# If the lv's are suspended, sanlvmd could monitor and wait +# for the vg to reappear. When it does, it could reacquire +# the leases for the suspended lv's and then resume the lv's. +# (Unless the leases have been acquired by another host since +# they were released, in which case they cannot be reacquired +# by the oringal host, and the lv's will not be resumed.) + help() { vg="\$vg" host_id="\$host_id" echo "" - echo "1. /etc/sanlvm.conf" + echo "/etc/sanlvm.conf" echo " must contain unique host_id definition from 1 to 2000, e.g." echo " host_id 1" echo "" - echo "2. sanlvm vgcreate [options] $vg <devs>" + echo "sanlvm vgcreate [options] $vg <devs>" echo " create vg, unprotected by sanlock," echo " create and initialize storage in $vg for sanlock to use" - echo " vgcreate [options] $vg <devs>" - echo " lvcreate -n leases -L 1G $vg" - echo " sanlock direct init -s $vg:0:/dev/$vg/leases:0" - echo " sanlock direct init -r $vg:vglk:/dev/$vg/leases:1048576" - echo " vgchange --addtag @sanlvm $vg" + echo " . vgcreate [options] $vg <devs>" + echo " . lvcreate -n leases -L 1G $vg" + echo " . sanlock direct init -s $vg:0:/dev/$vg/leases:0" + echo " . sanlock direct init -r $vg:vglk:/dev/$vg/leases:1048576" + echo " . vgchange --addtag @sanlvm $vg" echo "" - echo "3. sanlvm start" + echo "sanlvm start" echo " start lockspaces for vgs @sanlvm, created above" - echo " sanlock add_lockspace -s $vg:$host_id:/dev/$vg/leases:0" + echo " . sanlock add_lockspace -s $vg:$host_id:/dev/$vg/leases:0" echo "" - echo "4. sanlvm <lvmcmd> ..." + echo "sanlvm <lvmcmd> ..." echo " lvm commands within $vg are serialized by sanlock" - echo " sanlock command -r $vg:vglk:/dev/$vg/leases:1048576 -c /sbin/lvm <lvmcmd> ..." + echo " . sanlock command -r $vg:vglk:/dev/$vg/leases:1048576 -c /sbin/lvm <lvmcmd> ..." echo "" - - echo "sanlvm vgcreate [options] $vg <devs>" - echo "sanlvm start" echo "sanlvm [--na] lvcreate ..." - echo "sanlvm lvextend|lvreduce|lvremove ..." + echo " create an lv with or without (--na) an associated lv" + echo " activation lease. without an activation lease, the" + echo " the activation state among hosts is ignored." + echo "" echo "sanlvm --sh|ex lvchange -ay ..." + echo " acquire a shared or exclusive lease, then activate the lv." + echo " an exclusive lease prevents more than one host from activating" + echo " the lv at once, a shared lease allows multiple hosts to" + echo " activate the lv at once, and prevents any from activating" + echo " it exclusively." + echo "" echo "sanlvm lvchange -an ..." + echo " deactivate the lv, then release its lease" + echo "" exit 0 } @@ -71,7 +110,7 @@ fi get_vg_name() { prev=$2 - for i in $args + for i in $get_args do first=`expr substr $i 1 1` if [[ "$first" == "/" ]]; then @@ -82,7 +121,7 @@ get_vg_name() { prev=$i done - for i in $args + for i in $get_args do vgname=$i done @@ -94,7 +133,7 @@ get_vg_name() { get_lv_name() { save_next=0 - for i in $args + for i in $get_args do if [[ $save_next == 1 ]]; then lvname=$i @@ -112,7 +151,7 @@ get_lv_name() { # first arg containing '/' get_vg_lv_name() { - for i in $args + for i in $get_args do ind=`expr index $i /` if [ $ind -gt 0 ]; then @@ -133,12 +172,20 @@ get_host_id() { fi } +get_global_lease() { + glpath=`awk '/^global_lease_path/ { print $2 }' < /etc/sanlvm.conf` + + if [[ $? -ne 0 ]]; then + echo "no global_lease_path found in /etc/sanlvm.conf" + fi +} + # search lvchange args for -a, ---available # if there's a "y" anywhere after the option, then active_mode="y" # if there's a "n" anywhere after the option, then active_mode="n" get_active_mode() { - for i in $args + for i in $get_args do if [[ "$i" == "-ay" ]] || [[ "$i" == "-aly" ]] || [[ "$i" == "-aey" ]]; then active_mode="y" @@ -181,21 +228,54 @@ get_lease_offset() { offset=`echo $tags | cut --delimiter=_ --fields=3` } -if [[ "$cmd" == "start" ]]; then +if [[ "$cmd" == "global_init" ]]; then + get_global_lease + + if [[ "$glpath" == "" ]]; then + exit 1 + fi + + sanlock direct init -s sanlvm_global:0:$glpath:0 + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + sanlock direct init -r sanlvm_global:lease:$glpath:1048576 + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +elif [[ "$cmd" == "start" ]]; then + get_global_lease get_host_id + if [[ "$glpath" != "" ]]; then + lvm lvchange -a y $glpath + sanlock add_lockspace -s sanlvm_global:$host_id:$glpath:0 + fi + for vgname in `vgs @sanlvm --noheadings -o vg_name`; do + # FIXME: do something to prevent sanlvm lv's from + # automatically being activated by the system at + # startup; then this vgchange -an is not needed. + vgchange -an $vgname + lvm lvchange -a y /dev/$vgname/leases echo adding lockspace $vgname, this may take minutes... sanlock add_lockspace -s $vgname:$host_id:/dev/$vgname/leases:0 done exit 0 -fi -if [[ "$cmd" == "vgcreate" ]]; then - args=$* +elif [[ "$cmd" == "vgcreate" ]]; then + # FIXME: wrap this function in sanlvm_global:lease + + get_args=$* get_vg_name lvm "$@" @@ -230,20 +310,94 @@ if [[ "$cmd" == "vgcreate" ]]; then exit 0 +elif [[ "$cmd" == "vgextend" ]]; then + + get_args=$* + get_vg_name + get_glpath + + # FIXME: take both global lease and vglk, e.g. + # sanlock command -r sanlvm_global:lease:$glpath:1048576 -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@" + + sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +elif [[ "$cmd" == "vgremove" ]]; then + + + get_args=$* + get_vg_name + get_glpath + + # It doesn't work to hold the vglk around vgremove, because + # the vglk requires the leases lv to be open, which causes + # the vgremove to fail. This is similar to the reason we can't + # hold the vglk around vgcreate: the leases area for vglk doesn't + # exist yet because it's inside the vg being created. + + # FIXME: we could do the lvremoves automatically, + # but it looks messy + + found=0 + + for lvname in `lvs $vgname --noheadings -o lv_name`; do + if [[ "$lvname" != "leases" ]]; then + echo "run sanlvm lvremove $vgname/$lvname before vgremove" + found=1 + fi + done + + if [[ $found -eq 1 ]]; then + exit 1 + fi + + # FIXME: wrap vgremove in sanlvm_global:lease + + lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + +elif [[ "$cmd" == "vgchange" ]]; then + + # FIXME: catch variations of vgchange -ay / -an + # and either prohibit (require sanlvm lvchange), or + # translate into sanlvm lvchange here. + + lvm "$@" + + if [[ $? -ne 0 ]]; then + exit 1 + fi + + exit 0 + elif [[ "$cmd" == "_lvcreate" ]]; then # wrapped by vglk - shift - args=$* - + get_args=$* get_vg_name get_lv_name - # FIXME: get offset by searching leases lv for unused lease area - offset=2097152 + offset=`sanlock direct next_free /dev/$vgname/leases` + + if [[ $? -ne 0 ]]; then + echo "no space for new lease on /dev/$vgname/leases" + exit 1 + fi + + # FIXME: if we use recent lvcreate arg to disable activation, + # on creation, then we can remove the lvchange -an that follows. - # FIXME: use recent lvcreate arg to disable activation # lvcreate lvm "$@" @@ -251,7 +405,6 @@ elif [[ "$cmd" == "_lvcreate" ]]; then exit 1 fi - # FIXME: can remove this once lvcreate doesn't activate lvm lvchange -an $vgname/$lvname if [[ $? -ne 0 ]]; then @@ -275,8 +428,7 @@ elif [[ "$cmd" == "_lvcreate" ]]; then elif [[ "$cmd" == "lvcreate" ]]; then # we need the multiple steps in _lvcreate to all be wrapped in vglk - args=$* - + get_args=$* get_vg_name if [[ "$no_active" == "--na" ]]; then @@ -295,17 +447,13 @@ elif [[ "$cmd" == "lvcreate" ]]; then elif [[ "$cmd" == "_lvremove" ]]; then # wrapped by vglk - shift - args=$* - vgname=$SANLVM_VGNAME lvname=$SANLVM_LVNAME offset=$SANLVM_OFFSET - # refuse to remove the lv if the local - # host has the lv activated + # refuse to remove the lv if the local host has the lv activated status=`sanlock client status | grep "r $vgname:$lvname"` @@ -314,9 +462,8 @@ elif [[ "$cmd" == "_lvremove" ]]; then exit 1 fi - # acquire ex activation lock on the lv so - # we know that no hosts have it active - # FIXME: I don't think sanlock client acquire success/fail exit codes are always correct + # acquire ex activation lock on the lv so we know that no hosts have it active + # FIXME: I don't think sanlock acquire success/fail exit codes are always correct sanlock client acquire -r $vgname:$lvname:/dev/$vgname/leases:$offset -p `pidof sanlvmd` @@ -336,8 +483,8 @@ elif [[ "$cmd" == "_lvremove" ]]; then exit 0 elif [[ "$cmd" == "lvremove" ]]; then - args=$* + get_args=$* get_vg_lv_name get_lease_offset @@ -357,18 +504,15 @@ elif [[ "$cmd" == "lvremove" ]]; then exit 0 -elif [[ "$cmd" == "_lvextend" ]] || [[ "$cmd" == "_lvreduce" ]]; then +elif [[ "$cmd" == "_lvextend" ]] || [[ "$cmd" == "_lvreduce" ]] || [[ "$cmd" == "_lvconvert" ]] || [[ "$cmd" == "_lvresize" ]]; then # wrapped by vglk - shift - args=$* - vgname=$SANLVM_VGNAME lvname=$SANLVM_LVNAME offset=$SANLVM_OFFSET - # refuse to extend/reduce the lv if the local + # refuse to extend/reduce/convert the lv if the local # host has the lv activated # FIXME: allow extend of active lv, not reduce @@ -389,7 +533,7 @@ elif [[ "$cmd" == "_lvextend" ]] || [[ "$cmd" == "_lvreduce" ]]; then exit 1 fi - # lvextend/lvreduce + # lvextend/lvreduce/lvconvert lvm "$@" sanlock client release -r $vgname:$lvname:/dev/$vgname/leases:$offset -p `pidof sanlvmd` @@ -397,9 +541,9 @@ elif [[ "$cmd" == "_lvextend" ]] || [[ "$cmd" == "_lvreduce" ]]; then exit 0; -elif [[ "$cmd" == "lvextend" ]] || [[ "$cmd" == "lvreduce" ]]; then - args=$* +elif [[ "$cmd" == "lvextend" ]] || [[ "$cmd" == "lvreduce" ]] || [[ "$cmd" == "lvconvert" ]] || [[ "$cmd" == "lvresize" ]]; then + get_args=$* get_vg_lv_name get_lease_offset @@ -420,15 +564,8 @@ elif [[ "$cmd" == "lvextend" ]] || [[ "$cmd" == "lvreduce" ]]; then exit 0 elif [[ "$cmd" == "lvchange" ]]; then - # sanlvmd is a process that sanlock views as owning the lv - # activation leases. sanlvmd should restrict sigkill, and - # on sigterm from sanlock, it should try to forcibly deactivate - # the sanlvm lvs, or suspend the lv's or suspend lv's, replace - # with the error target and resume. - # (what about handling different vg lockspaces separately?) - - args=$* + get_args=$* get_vg_lv_name get_active_mode get_lease_offset @@ -439,7 +576,6 @@ elif [[ "$cmd" == "lvchange" ]]; then fi if [[ "$active_mode" == "y" ]]; then - # acquire lease, then activate if [[ "$lock_mode" == "--sh" ]]; then suffix=":SH" @@ -457,10 +593,9 @@ elif [[ "$cmd" == "lvchange" ]]; then lvm "$@" elif [[ "$active_mode" == "n" ]]; then - # deactivate, then release lease - # lock mode is not used for lvchange -an, and shouldn't be - # provided, but ignore it if it is + # lock mode is not used for lvchange -an, + # ignore it if one was provided if [[ "$lock_mode" != "" ]]; then shift @@ -474,7 +609,6 @@ elif [[ "$cmd" == "lvchange" ]]; then # non-activation related change to lv # I don't know of any lv changes that would require either # vglk or the lv lock - # sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@ echo "no locks needed for this command" lvm "$@" @@ -482,14 +616,21 @@ elif [[ "$cmd" == "lvchange" ]]; then exit 0 +elif [[ "$cmd" == "vgmerge" ]] || [[ "$cmd" == "vgsplit" ]] || [[ "$cmd" == "vgrename" ]] || [[ "$cmd" == "lvrename" ]]; then + + # FIXME: the vg commands could be implemented by combining + # a global lease and vglk's + + echo "command not supported with sanlvm" + exit 1 + else if [[ $# -lt 2 ]]; then echo vg name required exit 1 fi - args=$* - + get_args=$* get_vg_name sanlock command -r $vgname:vglk:/dev/$vgname/leases:1048576 -c /sbin/lvm "$@" |