Arik Hadas has uploaded a new change for review.

Change subject: core: fix NPE in decreasePendingVms
......................................................................

core: fix NPE in decreasePendingVms

There was a race between the VdsUpdateRunTimeInfo thread that invokes
RunVmCommandBase#decreasePendingVms method through OnPowerringUp
callback and the thread that invokes MigrateVmCommand#rerun (the thread
is created in VdsEventListener#rerun). The 'rerun thread' was doing
'setVm(null)' in order to refresh the VM on the next getVm invocation
and the VdsUpdateRunTimeInfo thread was trying to the get the VM using
the 'getVm' method VM in the same time - as a result of this race, the
VdsUpdateRunTimeInfo thread might end up with null VM which results in
NPE.

The solution is to change the VdsUpdateRunTimeInfo thread to fetch the
VM directly from the DB instead of using the 'getVm' method, And since
we don't need the dynamic info of the VM we can query only the static
part of the VM.

Change-Id: Icaca2a3849a9fefbc33b055c6f4d2dd32959ad28
Bug-Url: https://bugzilla.redhat.com/1000824
Signed-off-by: Arik Hadas <aha...@redhat.com>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java
1 file changed, 24 insertions(+), 8 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/85/19885/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java
index 115b2e6..ea74927 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java
@@ -27,7 +27,9 @@
 import org.ovirt.engine.core.common.businessentities.LunDisk;
 import org.ovirt.engine.core.common.businessentities.StorageServerConnections;
 import org.ovirt.engine.core.common.businessentities.VDS;
+import org.ovirt.engine.core.common.businessentities.VM;
 import org.ovirt.engine.core.common.businessentities.VMStatus;
+import org.ovirt.engine.core.common.businessentities.VmStatic;
 import org.ovirt.engine.core.common.config.Config;
 import org.ovirt.engine.core.common.config.ConfigValues;
 import org.ovirt.engine.core.common.errors.VdcBllMessages;
@@ -40,6 +42,7 @@
 import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
 import org.ovirt.engine.core.compat.Guid;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dao.VdsDynamicDAO;
 import org.ovirt.engine.core.utils.log.Log;
 import org.ovirt.engine.core.utils.log.LogFactory;
 import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
@@ -277,17 +280,22 @@
     }
 
     protected void decreasePendingVms(Guid vdsId) {
-        DbFacade.getInstance()
-                .getVdsDynamicDao()
-                .updatePartialVdsDynamicCalc(vdsId, 0, 
-getVm().getNumOfCpus(), -getVm().getMinAllocatedMem(), 0, 0);
+        VM vm = getVm();
+        decreasePendingVms(vdsId, vm.getNumOfCpus(), vm.getMinAllocatedMem(), 
vm.getName());
+    }
+
+    protected void decreasePendingVms(Guid vdsId, int numOfCpus, int 
minAllocatedMem, String vmName) {
+        getVdsDynamicDao().updatePartialVdsDynamicCalc(vdsId, 0, -numOfCpus, 
-minAllocatedMem, 0, 0);
         getBlockingQueue(vdsId).offer(Boolean.TRUE);
 
         if (log.isDebugEnabled()) {
-            log.debugFormat("DecreasePendingVms::Decreasing vds {0} pending 
vcpu count, in {1}. Vm: {2}",
-                    vdsId, getVm().getNumOfCpus(), getVm().getName());
-            log.debugFormat("DecreasePendingVms::Decreasing vds {0} pending 
vmem size, in {1}. Vm: {2}",
-                    vdsId, getVm().getMinAllocatedMem(), getVm().getName());
+            log.debugFormat("Decreasing vds {0} pending vcpu count by {1} and 
vmem size by {2} (Vm: {3})",
+                    vdsId, numOfCpus, minAllocatedMem, vmName);
         }
+    }
+
+    protected VdsDynamicDAO getVdsDynamicDao() {
+        return DbFacade.getInstance().getVdsDynamicDao();
     }
 
     /**
@@ -329,9 +337,17 @@
         return 
ResourceManager.getInstance().GetVdsManager(vdsId).getVdsMonitor();
     }
 
+    /**
+     * Since this callback is called by the VdsUpdateRunTimeInfo thread, we 
don't want it
+     * to fetch the VM using {@link #getVm()}, as the thread that invokes 
{@link #rerun()},
+     * which runs in parallel, is doing setVm(null) to refresh the VM, and 
because of this
+     * race we might end up with null VM. so we fetch the static part of the 
VM from the DB.
+     */
     @Override
     public void onPowerringUp() {
-        decreasePendingVms(getCurrentVdsId());
+        VmStatic vmStatic = getVmStaticDAO().get(getVmId());
+        decreasePendingVms(getCurrentVdsId(), vmStatic.getNumOfCpus(),
+                vmStatic.getMinAllocatedMem(), vmStatic.getName());
     }
 
     @Override


-- 
To view, visit http://gerrit.ovirt.org/19885
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Icaca2a3849a9fefbc33b055c6f4d2dd32959ad28
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: ovirt-engine-3.3
Gerrit-Owner: Arik Hadas <aha...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to