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 Sep 17, 2024
1 parent a0932b0 commit c599a58
Showing 1 changed file with 44 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


Expand All @@ -80,6 +81,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
private StorageLayer _storageLayer;
private String _mountPoint = "/mnt";
private String _manageSnapshotPath;
private static final ConcurrentHashMap<String, Integer> storagePoolRefCounts = new ConcurrentHashMap<>();

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

/**
* adjust refcount
*/
private int adjustStoragePoolRefCount(String uuid, int adjustment) {
synchronized (uuid) {
// some access on the storagePoolRefCounts.key(uuid) element
int refCount = storagePoolRefCounts.computeIfAbsent(uuid, k -> 0);
refCount += adjustment;
storagePoolRefCounts.put(uuid, refCount);
if (refCount < 1) {
storagePoolRefCounts.remove(uuid);

Check warning on line 652 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#L652

Added line #L652 was not covered by tests
} else {
storagePoolRefCounts.put(uuid, refCount);
}
return refCount;
}
}
/**
* Thread-safe increment storage pool usage refcount
* @param uuid UUID of the storage pool to increment the count
*/
private void incStoragePoolRefCount(String uuid) {
adjustStoragePoolRefCount(uuid, 1);
}
/**
* 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) {

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
return adjustStoragePoolRefCount(uuid, -1) > 0;
}

Check warning on line 673 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#L673

Added line #L673 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 +779,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 +791,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri

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

Check warning on line 794 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#L794

Added line #L794 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 +842,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 849 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#L848-L849

Added lines #L848 - L849 were not covered by tests
}

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

0 comments on commit c599a58

Please sign in to comment.