Skip to content

Commit

Permalink
kvm: ref-count storage pool usage
Browse files Browse the repository at this point in the history
If a storage pool is used by e.g. 2 concurrent snapshot->template
actions, if the first action finished it removed the netfs mount
point for the other action.
Now the storage pools are usage ref-counted and will only
deleted if there are no more users.
  • Loading branch information
rp- committed Aug 7, 2024
1 parent 21f3fde commit 669f29d
Showing 1 changed file with 42 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
private StorageLayer _storageLayer;
private String _mountPoint = "/mnt";
private String _manageSnapshotPath;
private final HashMap<String, Integer> storagePoolRefCounts = new HashMap<>();

private String rbdTemplateSnapName = "cloudstack-base-snap";
private static final int RBD_FEATURE_LAYERING = 1;
Expand Down Expand Up @@ -637,6 +638,38 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
}
}

/**
* Thread-safe increment storage pool usage refcount
* @param uuid UUID of the storage pool to increment the count
*/
private void incStoragePoolRefCount(String uuid) {
synchronized (storagePoolRefCounts) {
int refCount = storagePoolRefCounts.computeIfAbsent(uuid, k -> 0);
refCount += 1;
storagePoolRefCounts.put(uuid, refCount);
}
}

/**
* Thread-safe decrement storage pool usage refcount for the given uuid and return if storage pool still in use.
* @param uuid UUID of the storage pool to decrement the count
* @return true if the storage pool is still used, else false.
*/
private boolean decStoragePoolRefCount(String uuid) {
synchronized (storagePoolRefCounts) {
Integer refCount = storagePoolRefCounts.get(uuid);

Check warning on line 660 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java#L658-L660

Added lines #L658 - L660 were not covered by tests
if (refCount != null && refCount > 1) {
s_logger.debug(String.format("Storage pool %s still in use, refCount %d", uuid, refCount));
refCount -= 1;
storagePoolRefCounts.put(uuid, refCount);
return true;

Check warning on line 665 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java#L662-L665

Added lines #L662 - L665 were not covered by tests
} else {
storagePoolRefCounts.remove(uuid);
return false;

Check warning on line 668 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java#L667-L668

Added lines #L667 - L668 were not covered by tests
}
}
}

Check warning on line 671 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java#L671

Added line #L671 was not covered by tests

@Override
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details) {
s_logger.info("Attempting to create storage pool " + name + " (" + type.toString() + ") in libvirt");
Expand Down Expand Up @@ -744,6 +777,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
}

try {
incStoragePoolRefCount(name);
if (sp.isActive() == 0) {
s_logger.debug("Attempting to activate pool " + name);
sp.create(0);
Expand All @@ -755,6 +789,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri

return getStoragePool(name);
} catch (LibvirtException e) {
decStoragePoolRefCount(name);

Check warning on line 792 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java#L792

Added line #L792 was not covered by tests
String error = e.toString();
if (error.contains("Storage source conflict")) {
throw new CloudRuntimeException("A pool matching this location already exists in libvirt, " +
Expand Down Expand Up @@ -805,6 +840,13 @@ private boolean destroyStoragePoolHandleException(Connect conn, String uuid)
@Override
public boolean deleteStoragePool(String uuid) {
s_logger.info("Attempting to remove storage pool " + uuid + " from libvirt");

// decrement and check if storage pool still in use
if (decStoragePoolRefCount(uuid)) {
s_logger.info(String.format("deleteStoragePool: Storage pool %s still in use", uuid));
return true;

Check warning on line 847 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java#L846-L847

Added lines #L846 - L847 were not covered by tests
}

Connect conn;
try {
conn = LibvirtConnection.getConnection();
Expand Down

0 comments on commit 669f29d

Please sign in to comment.