Skip to content

Commit 382b67d

Browse files
author
Pearl Dsilva
committed
improve lock host retrieval logic and quicker retrival using db host as first check point and then fanning out
1 parent f4502f1 commit 382b67d

4 files changed

Lines changed: 329 additions & 153 deletions

File tree

core/src/main/java/org/apache/cloudstack/storage/clvm/command/ClvmLockTransferAnswer.java

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,26 @@ public class ClvmLockTransferAnswer extends Answer {
2727

2828
private String currentLockHostname;
2929
private boolean isActive;
30-
private boolean isExclusive;
30+
private boolean isOpen;
3131
private String lvAttributes;
3232

3333
public ClvmLockTransferAnswer(ClvmLockTransferCommand cmd, boolean result, String details) {
3434
super(cmd, result, details);
3535
}
3636

3737
public ClvmLockTransferAnswer(ClvmLockTransferCommand cmd, boolean result, String details,
38-
String currentLockHostname, boolean isActive, boolean isExclusive,
38+
String currentLockHostname, boolean isActive, boolean isOpen,
3939
String lvAttributes) {
4040
super(cmd, result, details);
4141
this.currentLockHostname = currentLockHostname;
4242
this.isActive = isActive;
43-
this.isExclusive = isExclusive;
43+
this.isOpen = isOpen;
4444
this.lvAttributes = lvAttributes;
4545
}
4646

4747
/**
48-
* Get the hostname of the host currently holding the lock (if any).
49-
* This is parsed from the LVM "lv_host" field.
50-
*
51-
* @return hostname or null if no lock is held
48+
* Get the hostname from lv_host. Retained for diagnostics only —
49+
* do NOT use this to determine lock holder identity.
5250
*/
5351
public String getCurrentLockHostname() {
5452
return currentLockHostname;
@@ -59,9 +57,8 @@ public void setCurrentLockHostname(String currentLockHostname) {
5957
}
6058

6159
/**
62-
* Whether the volume is currently active on any host.
63-
*
64-
* @return true if active, false otherwise
60+
* Whether the LV is locally active on the queried host (lv_attr[4]=='a').
61+
* This is the authoritative signal for lock holder discovery via fan-out.
6562
*/
6663
public boolean isActive() {
6764
return isActive;
@@ -72,17 +69,15 @@ public void setActive(boolean active) {
7269
}
7370

7471
/**
75-
* Whether the lock is exclusive (as opposed to shared).
76-
* Only meaningful if isActive() is true.
77-
*
78-
* @return true if exclusive lock, false if shared
72+
* Whether a process has the device file open on the queried host (lv_attr[5]=='o').
73+
* true means a VM is actively doing I/O on this host right now — do NOT deactivate.
7974
*/
80-
public boolean isExclusive() {
81-
return isExclusive;
75+
public boolean isOpen() {
76+
return isOpen;
8277
}
8378

84-
public void setExclusive(boolean exclusive) {
85-
isExclusive = exclusive;
79+
public void setOpen(boolean open) {
80+
isOpen = open;
8681
}
8782

8883
public String getLvAttributes() {

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtClvmLockTransferCommandWrapper.java

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,15 @@ public Answer execute(ClvmLockTransferCommand cmd, LibvirtComputingResource serv
9696
}
9797

9898
/**
99-
* Query which host currently holds the CLVM lock for a volume.
100-
* Executes: lvs -o lv_attr,lv_host --noheadings <lvPath>
99+
* Query whether this host currently has the CLVM LV activated locally.
100+
* Executes: lvs -o lv_attr,lv_host,lv_active --noheadings <lvPath>
101101
*
102-
* This queries the actual CLVM lock state (source of truth).
103-
* The lv_host attribute shows which host currently has the volume activated.
104-
*
105-
* @return ClvmLockTransferAnswer with lock holder hostname
102+
* lv_attr[4]=='a' (isActive) is LOCAL and is the authoritative signal — true only on
103+
* the host where the LV is currently activated. The management server fans out this
104+
* query to all cluster hosts; the one returning isActive=true is the lock holder.
105+
* lv_attr[5]=='o' (isOpen) means a VM has the device open on this host (doing I/O).
106+
* lv_host is retained for diagnostic logging only — do NOT use it to identify the
107+
* lock holder.
106108
*/
107109
private Answer handleQueryLockState(ClvmLockTransferCommand cmd, String lvPath, String volumeUuid) {
108110
try {
@@ -121,14 +123,11 @@ private Answer handleQueryLockState(ClvmLockTransferCommand cmd, String lvPath,
121123
String.format("lvs command failed: %s", result));
122124
}
123125

124-
// We need to find the line that contains the actual lv_attr (starts with '-' or other attr chars)
125126
String[] lines = parser.getLines().split("\n");
126127
String dataLine = null;
127128

128129
for (String line : lines) {
129130
String trimmed = line.trim();
130-
// Skip empty lines and warning messages
131-
// lv_attr always starts with '-', 'w', 'r', etc. and is at least 10 characters
132131
if (!trimmed.isEmpty() &&
133132
trimmed.length() >= 10 &&
134133
(trimmed.charAt(0) == '-' || trimmed.charAt(0) == 'w' ||
@@ -157,23 +156,27 @@ private Answer handleQueryLockState(ClvmLockTransferCommand cmd, String lvPath,
157156
}
158157

159158
String lvAttr = parts[0];
159+
// lv_host: for diagnostics only, unreliable for lock-holder identification
160160
String hostname = parts.length > 1 ? parts[1] : null;
161161

162+
// lv_attr[4]=='a' → LV is active on THIS host (local activation state)
162163
boolean isActive = lvAttr.length() > 4 && lvAttr.charAt(4) == 'a';
163-
boolean isExclusive = lvAttr.length() > 5 && lvAttr.charAt(5) == 'e';
164+
// lv_attr[5]=='o' → a process has the device file open on this host (VM doing I/O)
165+
boolean isOpen = lvAttr.length() > 5 && lvAttr.charAt(5) == 'o';
164166

165-
logger.info("Queried lock state for volume {}: attr={}, hostname={}, active={}, exclusive={}",
166-
volumeUuid, lvAttr, hostname, isActive, isExclusive);
167+
logger.info("Queried lock state for volume {}: attr={}, hostname={}, active={}, open={}",
168+
volumeUuid, lvAttr, hostname, isActive, isOpen);
167169

168170
return new ClvmLockTransferAnswer(cmd, true,
169-
String.format("Lock state: active=%s, exclusive=%s, host=%s",
170-
isActive, isExclusive, hostname != null ? hostname : "none"),
171-
hostname, isActive, isExclusive, lvAttr);
171+
String.format("Lock state: active=%s, open=%s, host=%s",
172+
isActive, isOpen, hostname != null ? hostname : "none"),
173+
hostname, isActive, isOpen, lvAttr);
172174

173175
} catch (Exception e) {
174176
logger.error("Exception during lock state query for volume {}: {}",
175177
volumeUuid, e.getMessage(), e);
176178
return new ClvmLockTransferAnswer(cmd, false, "Exception: " + e.getMessage());
177179
}
178180
}
181+
179182
}

0 commit comments

Comments
 (0)