Skip to content

Commit b896bbc

Browse files
committed
kvm: ref-count storage pool usage
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.
1 parent a6cef7a commit b896bbc

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import java.util.Arrays;
7373
import java.util.HashSet;
7474
import java.util.Set;
75+
import java.util.concurrent.ConcurrentHashMap;
7576
import java.util.stream.Collectors;
7677

7778

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

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

642+
/**
643+
* adjust refcount
644+
*/
645+
private int adjustStoragePoolRefCount(String uuid, int adjustment) {
646+
synchronized (uuid) {
647+
// some access on the storagePoolRefCounts.key(uuid) element
648+
int refCount = storagePoolRefCounts.computeIfAbsent(uuid, k -> 0);
649+
refCount += adjustment;
650+
storagePoolRefCounts.put(uuid, refCount);
651+
if (refCount < 1) {
652+
storagePoolRefCounts.remove(uuid);
653+
} else {
654+
storagePoolRefCounts.put(uuid, refCount);
655+
}
656+
return refCount;
657+
}
658+
}
659+
/**
660+
* Thread-safe increment storage pool usage refcount
661+
* @param uuid UUID of the storage pool to increment the count
662+
*/
663+
private void incStoragePoolRefCount(String uuid) {
664+
adjustStoragePoolRefCount(uuid, 1);
665+
}
666+
/**
667+
* Thread-safe decrement storage pool usage refcount for the given uuid and return if storage pool still in use.
668+
* @param uuid UUID of the storage pool to decrement the count
669+
* @return true if the storage pool is still used, else false.
670+
*/
671+
private boolean decStoragePoolRefCount(String uuid) {
672+
return adjustStoragePoolRefCount(uuid, -1) > 0;
673+
}
674+
640675
@Override
641676
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details) {
642677
s_logger.info("Attempting to create storage pool " + name + " (" + type.toString() + ") in libvirt");
@@ -744,6 +779,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
744779
}
745780

746781
try {
782+
incStoragePoolRefCount(name);
747783
if (sp.isActive() == 0) {
748784
s_logger.debug("Attempting to activate pool " + name);
749785
sp.create(0);
@@ -755,6 +791,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
755791

756792
return getStoragePool(name);
757793
} catch (LibvirtException e) {
794+
decStoragePoolRefCount(name);
758795
String error = e.toString();
759796
if (error.contains("Storage source conflict")) {
760797
throw new CloudRuntimeException("A pool matching this location already exists in libvirt, " +
@@ -805,6 +842,13 @@ private boolean destroyStoragePoolHandleException(Connect conn, String uuid)
805842
@Override
806843
public boolean deleteStoragePool(String uuid) {
807844
s_logger.info("Attempting to remove storage pool " + uuid + " from libvirt");
845+
846+
// decrement and check if storage pool still in use
847+
if (decStoragePoolRefCount(uuid)) {
848+
s_logger.info(String.format("deleteStoragePool: Storage pool %s still in use", uuid));
849+
return true;
850+
}
851+
808852
Connect conn;
809853
try {
810854
conn = LibvirtConnection.getConnection();

0 commit comments

Comments
 (0)