Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Source of truth: The actual LVM state is obtained via lvs, not the database.
  • Database as cache: volume_details.clvmLockHostId tracks which host has the lock for debugging purposes, but may be stale.
  • Sequential operations: Lock transfers execute sequentially via executeInSequence() to prevent races.
  • Idempotency: Lock transfer to the same host is a no-op

...

Table: volume_details
Key: clvmLockHostId (constant in {{VolumeInfoClvmPoolManager.java}})
Value: Host ID (Long)

...

          Purpose: Queries actual LVM lock state from KVM hosts

Code Block
1. Resolve hosts for pool:
   ├─ If pool.getClusterId() queryCurrentLockHolder(volumeId, volumeUuid, volumePath, pool, updateDatabase):
├─ lvPath = "/dev/{vgName}/{volumePath}"
│
├─ [Fast path] dbHostId = DB lookup (volume_details.clvmLockHostId)
│  └─ If dbHostId != null:
     ├─ If dbHost hostsis = hostDao.findByClusterId(clusterId, Type.Routing)
   └─ Else if zone-scoped:
        hosts = hostDao.findByDataCenterId(zoneId)

2. Filter to UP KVM routing hosts

3. For each host in hosts:
   ├─ Send QUERY_LOCK_STATE command
   ├─ If successful:
   │  ├─ Parse ClvmLockTransferAnswerUp and KVM:
│     │  ├─ Send QUERY_LOCK_STATE to dbHostId
│     │  ├─ If active == TRUE:
│     │  │    return dbHostId                        // confirmed, early exit
│     │  └─ Else: log "fast path miss, falling back to fan-out"
│     └─ Else: log "fast path skip (host down/missing), falling back to fan-out"
│
├─ [Fan-out] Resolve hosts for pool:
│  ├─ If pool.getClusterId() != null:
│  │    hosts = hostDao.findByClusterId(clusterId, Type.Routing)
│  └─ Else if zone-scoped:
│       hosts = hostDao.findByDataCenterId(zoneId)
│
├─ Filter to UP KVM routing hosts, skip dbHostId (already checked above)
│
├─ For each host in hosts:
│  ├─ Send QUERY_LOCK_STATE command
│  └─ If active == TRUE: add to activeHostIds
│
└─ Evaluate results:
   ├─ If activeHostIds is empty:
   │  ├─ If updateDatabase and dbHostId != null:
   │  │    remove CLVM_LOCK_HOST_ID from volume_details
   │  └─ return null
   ├─ If activeHostIds.size > 1:
   │  ├─ Extract hostname from lv_hostlog warning "shared-mode LV (template?), skipping"├─└─ Resolve hostname → host IDreturn null
   └─ Else ├─ if updateDatabase(exactly one):
      ├─ If updateDatabase setClvmLockHostId(volumeId, hostId)
   │  └─ return hostId
   └─ If failed, try next host

4. If all hosts fail:
   ├─ Log warning
   └─ return nulland lockHostId != dbHostId:
      │    setClvmLockHostId(volumeId, lockHostId)   ← correct stale DB record
      └─ return lockHostId


Performance Considerations:

...

Purpose: Transfers exclusive lock from source to destination host

Code Block
1. actualLockHostId = queryCurrentLockHolder(..., queryActual=false)
   // Get real lock holder, not database hint

2. hostToDeactivate = actualLockHostId ?? sourceHostId
   // Use actual holder if known, fallback to provided source

32. if hostToDeactivate != null AND hostToDeactivate != destHostId:
   ├─ if host is UP:
   │    send DEACTIVATE command to hostToDeactivate
   └─ if host is DOWN:
        log warning "Host down, will force claim on destination"

43. send ACTIVATE_EXCLUSIVE command to destHostId
   // LVM force-claims if previous holder left cleanly

54. if activation successful:
   ├─ setClvmLockHostId(volumeId, destHostId)
   └─ return true

65. return false


setClvmLockHostId(volumeId, hostId)

...