LVM snapshot with Clustered VG
Is there a way to convert an active LV on a clustered VG to an exclusive lock without deactivating it first? Or some way of taking a snapshot of a clustered LVM? I know I have read snapshots are not possible on CLVM, but the information seems outdated.
ha node1: /dev/vg_clus/logvol_clus
ha node2: /dev/vg_clus/logvol_clus
1) I can deactivate the the entire vg on node1 and node2 with 'vgchange -an vg_clus' and activate with -ay. Just stating cluster vg is working.
2) I can deactivate locally on node2 with 'vgchange -aln vg_clus' , it shows inactive on node2 and active still on node1
- After deactivating, I cannot get exclusive lock on node1 with
'vgchange -aey vg_clus'
I get an error locking on node1
3) I can get exclusive an lock if I deactivate the VG on both nodes and then run 'vgchange -aey vg_clus' on either node. The lvcreate snapshop works, but again, it requires deactivating the vg, which isn't an option in production.
Setup:
Centos 6.3 (current)
cman+pacemaker dual primary drbd for HA KVM w/ live migration
disk: lvm -> drbd -> clvm -> kvm virt
Currently I am taking a lvm snapshot of the drbd lvm backing device, but it's not ideal ( as there are other issues )
Thanks for the time!
-Rob
Quoted 17 lines · Rob
Is there a way to convert an active LV on a clustered VG to an exclusive lock without deactivating it first? Or some way of taking a snapshot of a clustered LVM? I know I have read snapshots are not possible on CLVM, but the information seems outdated.
ha node1:
/dev/vg_clus/logvol_clus
ha node2:/dev/vg_clus/logvol_clus1) I can deactivate the the entire vg on node1 and node2 with 'vgchange -an
vg_clus' and activate with -ay. Just stating cluster vg is working.2) I can deactivate locally on node2 with 'vgchange -aln
vg_clus' , it shows inactive on node2 and active still on node1
- After deactivating, I cannot get exclusive lock on node1 with
'vgchange -aeyvg_clus'
I get an error locking on node1
Quoted 4 lines
3) I can get exclusive an lock if I deactivate the VG on both nodes and then run 'vgchange -aey
vg_clus' on either node. The lvcreate snapshop works, but again, it requires deactivating the vg, which isn't an option in production.
You may try (experimental, not-complete) patch attached.
Quoted 12 lines
Setup:
Centos 6.3 (current)
cman+pacemaker dual primary drbd for HA KVM w/ live migration
disk: lvm -> drbd -> clvm -> kvm virtCurrently I am taking a lvm snapshot of the drbd lvm backing device, but it's not ideal ( as there are other issues )
Thanks for the time!
Quoted 7 lines
-Rob
_______________________________________________
linux-lvm mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-lvm
read the LVM HOW-TO at http://tldp.org/HOWTO/LVM-HOWTO/
lib/locking/cluster_locking.c +5 -1
@@ -330,6 +330,9 @@ static int _lock_for_cluster(struct cmd_if (flags &LCK_REVERT ) args[1 ] |=LCK_REVERT_MODE ; +if (flags &LCK_TRY_CONVERT ) + args[1 ] |=LCK_CONVERT ; +if (mirror_in_sync ()) args[1 ] |=LCK_MIRROR_NOSYNC_MODE ;
@@ -491,7 +494,7 @@ int lock_resource(struct cmd_context *cmreturn 0 ; } - log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s%s%s%s) (0x%x)", lock_scope, lockname, + log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s%s%s%s%s) (0x%x)", lock_scope, lockname, lock_type, lock_scope, flags & LCK_NONBLOCK ? "|NONBLOCK" : "", flags & LCK_HOLD ? "|HOLD" : "",
@@ -501,6 +504,7 @@ int lock_resource(struct cmd_context *cm flags &LCK_CACHE ?"|CACHE" :"" , flags &LCK_ORIGIN_ONLY ?"|ORIGIN_ONLY" :"" , flags &LCK_REVERT ?"|REVERT" :"" , + flags &LCK_TRY_CONVERT ?"|CONVERT" :"" , flags);/* Send a message to the cluster manager */
lib/locking/locking.c +32 -0
@@ -540,6 +540,16 @@ int suspend_lvs(struct cmd_context *cmd,return 1 ; } +int deactivate_lv (struct cmd_context *cmd,struct logical_volume *lv) +{ +if (vg_is_clustered (lv->vg)) { +if (lv_is_active_exclusive (lv) && !lv_is_active_exclusive_locally (lv)) { + return_0; + } + } +lock_lv_vol (cmd, lv,LCK_LV_DEACTIVATE ); +} +/* * First try to activate exclusively locally. * Then if the VG is clustered and the LV is not yet active (e.g. due to
@@ -567,6 +577,28 @@ int activate_lv_excl(struct cmd_contextreturn lv_is_active_exclusive (lv); } +int activate_lv_excl_force (struct cmd_context *cmd,struct logical_volume *lv) +{ +/* Non-clustered VGs are only activated locally. */ +if (!vg_is_clustered (lv->vg)) +return activate_lv_excl_local (cmd, lv); + +if (lv_is_active_exclusive_locally (lv)) +return 1 ; + +if (!activate_lv_excl_local_force (cmd, lv)) + return_0; + +if (lv_is_active_exclusive (lv)) +return 1 ; + +/* FIXME Deal with error return codes. */ +if (activate_lv_excl_remote_force (cmd, lv)) + stack; + +return lv_is_active_exclusive (lv); +} +/* Lock a list of LVs */ int activate_lvs (struct cmd_context *cmd,struct dm_list *lvs,unsigned exclusive) {
lib/locking/locking.h +9 -1
@@ -101,6 +101,7 @@ int check_lvm1_vg_inactive(struct cmd_co#define LCK_CACHE 0x00000100U/* Operation on cache only using P_ lock */ #define LCK_ORIGIN_ONLY 0x00000200U/* Operation should bypass any snapshots */ #define LCK_REVERT 0x00000400U/* Revert any incomplete change */ +#define LCK_TRY_CONVERT 0x00004000U/* Convert existing lock */ /* * Additional lock bits for cluster communication via args[1]
@@ -176,19 +177,26 @@ int check_lvm1_vg_inactive(struct cmd_co#define revert_lv (cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_RESUME | LCK_REVERT)#define suspend_lv (cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_SUSPEND | LCK_HOLD)#define suspend_lv_origin (cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_SUSPEND | LCK_HOLD | LCK_ORIGIN_ONLY) -#define deactivate_lv (cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE)#define activate_lv (cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD)#define activate_lv_excl_local (cmd, lv) \ lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD | LCK_LOCAL)#define activate_lv_excl_remote (cmd, lv) \ lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD | LCK_REMOTE) +#define activate_lv_excl_local_force (cmd, lv) \ + lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD | LCK_LOCAL | (lv_is_active(lv) && ! lv_is_active_exclusive(lv) ? LCK_TRY_CONVERT : 0)) +#define activate_lv_excl_remote_force (cmd, lv) \ + lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD | LCK_REMOTE | (lv_is_active(lv) && ! lv_is_active_exclusive(lv) ? LCK_TRY_CONVERT : 0))struct logical_volume ;int activate_lv_excl (struct cmd_context *cmd,struct logical_volume *lv); +int activate_lv_excl_force (struct cmd_context *cmd,struct logical_volume *lv); +int deactivate_lv (struct cmd_context *cmd,struct logical_volume *lv);#define activate_lv_local (cmd, lv) \ lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL) +#define activate_lv_local_force (cmd, lv) \ + lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL | (lv_is_active_exclusive_locally(lv) ? LCK_TRY_CONVERT : 0))#define deactivate_lv_local (cmd, lv) \ lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE | LCK_LOCAL)#define drop_cached_metadata (vg) \
tools/lvchange.c +22 -8
@@ -238,15 +238,29 @@ static int _lvchange_activate(struct cmdif ((activate ==CHANGE_AE ) ||lv_is_origin (lv) ||lv_is_thin_type (lv)) { -log_verbose ("Activating logical volume \"%s\" " -"exclusively" , lv->name); -if (!activate_lv_excl (cmd, lv)) - return_0; +if (arg_count (cmd, force_ARG)) { +log_verbose ("Activating logical volume \"%s\" " +"exclusively (forced)" , lv->name); +if (!activate_lv_excl_force (cmd, lv)) + return_0; + }else { +log_verbose ("Activating logical volume \"%s\" " +"exclusively" , lv->name); +if (!activate_lv_excl (cmd, lv)) + return_0; + } }else if (activate ==CHANGE_ALY ) { -log_verbose ("Activating logical volume \"%s\" locally" , - lv->name); -if (!activate_lv_local (cmd, lv)) - return_0; +if (arg_count (cmd, force_ARG)) { +log_verbose ("Activating logical volume \"%s\" locally (forced)" , + lv->name); +if (!activate_lv_local_force (cmd, lv)) + return_0; + }else { +log_verbose ("Activating logical volume \"%s\" locally" , + lv->name); +if (!activate_lv_local (cmd, lv)) + return_0; + } }else {log_verbose ("Activating logical volume \"%s\"" , lv->name);