[lvm-devel] Possibility to convert to exclusive active (opened) volume on clustered VG
Raman
rommer at activecloud.com
Fri Dec 6 14:13:40 UTC 2013
Hello,
On 12/06/2013 11:47 AM, Zdenek Kabelac wrote:
> Dne 6.12.2013 05:10, Raman napsal(a):
>> Hello,
>>
>> Currently there is no way to convert opened volume from CR to EX or
>> from EX to CR lock type on clustered volume group. The only way is to
>> deactivate volume and activate it exclusively again. Example:
>>
>> Simple cman cluster:
>> [root at clvmd2 ~]# cat /etc/cluster/cluster.conf
>> <?xml version="1.0"?>
>> <cluster config_version="1" name="clu">
>> <clusternodes>
>> <clusternode name="clvmd1" nodeid="1"/>
>> <clusternode name="clvmd2" nodeid="2"/>
>> </clusternodes>
>> <cman broadcast="yes" port="5501"/>
>> <totem token="60000"/>
>> </cluster>
>>
>> Clustered volume group:
>> [root at clvmd1 ~]# vgs --noheadings
>> vg 1 1 0 wz--nc 9.31g 9.21g
>>
>> Single volume activated on both nodes:
>> [root at clvmd1 ~]# lvs --noheadings
>> lv1 vg -wi-a----- 100.00m
>> [root at clvmd2 ~]# lvs --noheadings
>> lv1 vg -wi-a----- 100.00m
>>
>> Deactivating on second node and trying to acquire volume exclusively on
>> the first node:
>> [root at clvmd2 ~]# lvchange -aln vg/lv1
>> [root at clvmd1 ~]# lvchange -ae vg/lv1
>> Error locking on node clvmd1: Device or resource busy
>> [root at clvmd1 ~]#
>>
>> But works fine with deactivating cycle:
>> [root at clvmd1 ~]# lvchange -aln vg/lv1 && lvs --noheading
>> lv1 vg -wi------- 100.00m
>> [root at clvmd1 ~]# lvchange -ae vg/lv1 && lvs --noheading
>> lv1 vg -wi-a----- 100.00m
>> [root at clvmd1 ~]#
>>
>> Proposed patch tries to solve this problem allowing lock conversion
>> for activated volumes on clustered volume groups.
>
>
> Patch looks mostly good - but has one 'tiny' problem which is
> unfortunately not so easy to resolve.
>
> +#define LCK_CONVERT 0x00000800U /* Try lock conversion */
>
> I do not know how old code are you are patching - but recent upstream
> git has this bit already in use:
>
> #define LCK_REMOTE 0x00000800U /* Propagate to remote nodes only */
>
>
> And the protocol is awkward to extend (all bits are already in use).
>
> So the question is if we are able to find some bit combination
> to use it uniquely for activate_lv_excl_local_convert()?
>
>
> Zdenek
>
> --
> lvm-devel mailing list
> lvm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/lvm-devel
My fail.
LCK_CONVERT can safely use 0x00001000U.
It used only in "flags" which is uint32_t.
cman protocol uses already defined LCK_CONVERT_MODE in args[1]
-------------- next part --------------
diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c
index b15732f..451d286 100644
--- a/daemons/clvmd/lvm-functions.c
+++ b/daemons/clvmd/lvm-functions.c
@@ -137,7 +137,7 @@ static const char *decode_flags(unsigned char flags)
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
flags & LCK_TEST_MODE ? "TEST|" : "",
- flags & LCK_CONVERT ? "CONVERT|" : "",
+ flags & LCK_CONVERT_MODE ? "CONVERT|" : "",
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "");
if (len > 1)
@@ -374,7 +374,7 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l
* of exclusive lock to shared one during activation.
*/
if (command & LCK_CLUSTER_VG) {
- status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
+ status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT_MODE ? LCKF_CONVERT:0));
if (status) {
/* Return an LVM-sensible error for this.
* Forcing EIO makes the upper level return this text
diff --git a/lib/locking/cluster_locking.c b/lib/locking/cluster_locking.c
index 7cbb8f1..c94f92b 100644
--- a/lib/locking/cluster_locking.c
+++ b/lib/locking/cluster_locking.c
@@ -328,6 +328,9 @@ static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd,
if (flags & LCK_REVERT)
args[1] |= LCK_REVERT_MODE;
+ if (flags & LCK_CONVERT)
+ args[1] |= LCK_CONVERT_MODE;
+
if (mirror_in_sync())
args[1] |= LCK_MIRROR_NOSYNC_MODE;
diff --git a/lib/locking/locking.c b/lib/locking/locking.c
index 9433e40..831388e 100644
--- a/lib/locking/locking.c
+++ b/lib/locking/locking.c
@@ -552,8 +552,13 @@ int activate_lv_excl(struct cmd_context *cmd, struct logical_volume *lv)
if (lv_is_active_exclusive_locally(lv))
return 1;
- if (!activate_lv_excl_local(cmd, lv))
- return_0;
+ if (lv_is_active_locally(lv)) {
+ if (!activate_lv_excl_local_convert(cmd, lv))
+ return_0;
+ } else {
+ if (!activate_lv_excl_local(cmd, lv))
+ return_0;
+ }
if (lv_is_active_exclusive(lv))
return 1;
diff --git a/lib/locking/locking.h b/lib/locking/locking.h
index aa42138..cfc7f38 100644
--- a/lib/locking/locking.h
+++ b/lib/locking/locking.h
@@ -103,6 +103,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
#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_CONVERT 0x00001000U /* Try lock conversion */
/*
* Additional lock bits for cluster communication via args[1]
@@ -110,10 +111,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
#define LCK_PARTIAL_MODE 0x01 /* Partial activation? */
#define LCK_MIRROR_NOSYNC_MODE 0x02 /* Mirrors don't require sync */
#define LCK_DMEVENTD_MONITOR_MODE 0x04 /* Register with dmeventd */
-
-/* Not yet used. */
-#define LCK_CONVERT 0x08 /* Convert existing lock */
-
+#define LCK_CONVERT_MODE 0x08 /* Convert existing lock */
#define LCK_TEST_MODE 0x10 /* Test mode: No activation */
#define LCK_ORIGIN_ONLY_MODE 0x20 /* Same as above */
#define LCK_DMEVENTD_MONITOR_IGNORE 0x40 /* Whether to ignore dmeventd */
@@ -183,6 +181,8 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
#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_local_convert(cmd, lv) \
+ lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD | LCK_LOCAL | LCK_CONVERT)
#define activate_lv_excl_remote(cmd, lv) \
lock_lv_vol(cmd, lv, LCK_LV_EXCLUSIVE | LCK_HOLD | LCK_REMOTE)
@@ -191,6 +191,8 @@ int activate_lv_excl(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_convert(cmd, lv) \
+ lock_lv_vol(cmd, lv, LCK_LV_ACTIVATE | LCK_HOLD | LCK_LOCAL | LCK_CONVERT)
#define deactivate_lv_local(cmd, lv) \
lock_lv_vol(cmd, lv, LCK_LV_DEACTIVATE | LCK_LOCAL)
#define drop_cached_metadata(vg) \
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 3e1458c..2cec240 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -773,13 +773,23 @@ deactivate:
if (_lv_is_exclusive(lv)) {
log_verbose("Activating logical volume \"%s\" exclusively locally.",
lv->name);
- if (!activate_lv_excl_local(cmd, lv))
- return_0;
+ if (vg_is_clustered(lv->vg) && lv_is_active_locally(lv)) {
+ if (!activate_lv_excl_local_convert(cmd, lv))
+ return_0;
+ } else {
+ if (!activate_lv_excl_local(cmd, lv))
+ return_0;
+ }
} else {
log_verbose("Activating logical volume \"%s\" locally.",
lv->name);
- if (!activate_lv_local(cmd, lv))
- return_0;
+ if (vg_is_clustered(lv->vg) && lv_is_active_locally(lv)) {
+ if (!activate_lv_local_convert(cmd, lv))
+ return_0;
+ } else {
+ if (!activate_lv_local(cmd, lv))
+ return_0;
+ }
}
break;
case CHANGE_AE:
More information about the lvm-devel
mailing list