Skip to content

Commit 427ed5a

Browse files
committed
kvm: ref-count secondary storage pool usage
If a secondary 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 03bdf11 commit 427ed5a

File tree

10 files changed

+59
-10
lines changed

10 files changed

+59
-10
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class IscsiAdmStorageAdaptor implements StorageAdaptor {
4343
private static final Map<String, KVMStoragePool> MapStorageUuidToStoragePool = new HashMap<>();
4444

4545
@Override
46-
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map<String, String> details) {
46+
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map<String, String> details, boolean isPrimaryStorage) {
4747
IscsiAdmStoragePool storagePool = new IscsiAdmStoragePool(uuid, host, port, storagePoolType, this);
4848

4949
MapStorageUuidToStoragePool.put(uuid, storagePool);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
361361
//Note: due to bug CLOUDSTACK-4459, createStoragepool can be called in parallel, so need to be synced.
362362
private synchronized KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details, boolean primaryStorage) {
363363
StorageAdaptor adaptor = getStorageAdaptor(type);
364-
KVMStoragePool pool = adaptor.createStoragePool(name, host, port, path, userInfo, type, details);
364+
KVMStoragePool pool = adaptor.createStoragePool(name, host, port, path, userInfo, type, details, primaryStorage);
365365

366366
// LibvirtStorageAdaptor-specific statement
367367
if (pool.isPoolSupportHA() && primaryStorage) {

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

Lines changed: 50 additions & 1 deletion
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,8 +639,41 @@ 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
641-
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details) {
676+
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details, boolean isPrimaryStorage) {
642677
s_logger.info("Attempting to create storage pool " + name + " (" + type.toString() + ") in libvirt");
643678

644679
StoragePool sp = null;
@@ -744,6 +779,12 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
744779
}
745780

746781
try {
782+
if (!isPrimaryStorage) {
783+
// only ref count storage pools for secondary storage, as primary storage is assumed
784+
// to be always mounted, as long the primary storage isn't fully deleted.
785+
incStoragePoolRefCount(name);
786+
}
787+
747788
if (sp.isActive() == 0) {
748789
s_logger.debug("Attempting to activate pool " + name);
749790
sp.create(0);
@@ -755,6 +796,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
755796

756797
return getStoragePool(name);
757798
} catch (LibvirtException e) {
799+
decStoragePoolRefCount(name);
758800
String error = e.toString();
759801
if (error.contains("Storage source conflict")) {
760802
throw new CloudRuntimeException("A pool matching this location already exists in libvirt, " +
@@ -805,6 +847,13 @@ private boolean destroyStoragePoolHandleException(Connect conn, String uuid)
805847
@Override
806848
public boolean deleteStoragePool(String uuid) {
807849
s_logger.info("Attempting to remove storage pool " + uuid + " from libvirt");
850+
851+
// decrement and check if storage pool still in use
852+
if (decStoragePoolRefCount(uuid)) {
853+
s_logger.info(String.format("deleteStoragePool: Storage pool %s still in use", uuid));
854+
return true;
855+
}
856+
808857
Connect conn;
809858
try {
810859
conn = LibvirtConnection.getConnection();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public ManagedNfsStorageAdaptor(StorageLayer storagelayer) {
5555
}
5656

5757
@Override
58-
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map<String, String> details) {
58+
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map<String, String> details, boolean isPrimaryStorage) {
5959

6060
LibvirtStoragePool storagePool = new LibvirtStoragePool(uuid, path, StoragePoolType.ManagedNFS, this, null);
6161
storagePool.setSourceHost(host);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ private KVMPhysicalDisk getPhysicalDisk(AddressInfo address, KVMStoragePool pool
168168
}
169169

170170
@Override
171-
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, Storage.StoragePoolType type, Map<String, String> details) {
171+
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, Storage.StoragePoolType type, Map<String, String> details, boolean isPrimaryStorage) {
172172
LOGGER.info(String.format("createStoragePool(uuid,host,port,path,type) called with args (%s, %s, %s, %s, %s)", uuid, host, ""+port, path, type));
173173
MultipathSCSIPool storagePool = new MultipathSCSIPool(uuid, host, port, path, type, details, this);
174174
MapStorageUuidToStoragePool.put(uuid, storagePool);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public KVMPhysicalDisk getPhysicalDisk(String volumePath, KVMStoragePool pool) {
143143
}
144144

145145
@Override
146-
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, Storage.StoragePoolType type, Map<String, String> details) {
146+
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, Storage.StoragePoolType type, Map<String, String> details, boolean isPrimaryStorage) {
147147
ScaleIOStoragePool storagePool = new ScaleIOStoragePool(uuid, host, port, path, type, details, this);
148148
MapStorageUuidToStoragePool.put(uuid, storagePool);
149149
return storagePool;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public interface StorageAdaptor {
3838
// it with info from local disk, and return it
3939
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool);
4040

41-
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details);
41+
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo, StoragePoolType type, Map<String, String> details, boolean isPrimaryStorage);
4242

4343
public boolean deleteStoragePool(String uuid);
4444

plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,6 @@ public void testCreateStoragePoolWithNFSMountOpts() throws Exception {
8686

8787
Map<String, String> details = new HashMap<>();
8888
details.put("nfsmountopts", "vers=4.1, nconnect=4");
89-
KVMStoragePool pool = libvirtStorageAdaptor.createStoragePool(uuid, null, 0, dir, null, Storage.StoragePoolType.NetworkFilesystem, details);
89+
KVMStoragePool pool = libvirtStorageAdaptor.createStoragePool(uuid, null, 0, dir, null, Storage.StoragePoolType.NetworkFilesystem, details, true);
9090
}
9191
}

plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public KVMPhysicalDisk getPhysicalDisk(String name, KVMStoragePool pool)
149149

150150
@Override
151151
public KVMStoragePool createStoragePool(String name, String host, int port, String path, String userInfo,
152-
Storage.StoragePoolType type, Map<String, String> details)
152+
Storage.StoragePoolType type, Map<String, String> details, boolean isPrimaryStorage)
153153
{
154154
s_logger.debug(String.format(
155155
"Linstor createStoragePool: name: '%s', host: '%s', path: %s, userinfo: %s", name, host, path, userInfo));

plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public static void SP_LOG(String fmt, Object... args) {
5757
private static final Map<String, KVMStoragePool> storageUuidToStoragePool = new HashMap<String, KVMStoragePool>();
5858

5959
@Override
60-
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map<String, String> details) {
60+
public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map<String, String> details, boolean isPrimaryStorage) {
6161
SP_LOG("StorPoolStorageAdaptor.createStoragePool: uuid=%s, host=%s:%d, path=%s, userInfo=%s, type=%s", uuid, host, port, path, userInfo, storagePoolType);
6262

6363
StorPoolStoragePool storagePool = new StorPoolStoragePool(uuid, host, port, storagePoolType, this);

0 commit comments

Comments
 (0)