]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: Release GIL before calling OSDMap::calc_pg_upmaps()
authorDavid Zafman <dzafman@redhat.com>
Tue, 22 Oct 2019 22:24:05 +0000 (15:24 -0700)
committerDavid Zafman <dzafman@redhat.com>
Tue, 3 Dec 2019 01:34:22 +0000 (17:34 -0800)
Prevent optimize and execute commands from running with active balancer

Fixes: https://tracker.ceph.com/issues/42432
Signed-off-by: David Zafman <dzafman@redhat.com>
(cherry picked from commit e2a35e8c8e9f381a635ad0ca01326a2c512590a9)

Conflicts:
src/pybind/mgr/balancer/module.py (trivial)
src/test/cli-integration/balancer/misplaced.t (doesn't exist)

src/mgr/PyOSDMap.cc
src/pybind/mgr/balancer/module.py

index e4fdd8f5a15262739b63fea014c029838a48f022..72fbad02498288bbe9f897e3dc6b05be1d05e0a3 100644 (file)
@@ -147,11 +147,13 @@ static PyObject *osdmap_calc_pg_upmaps(BasePyOSDMap* self, PyObject *args)
           << " max_iterations " << max_iterations
           << " pools " << pools
           << dendl;
+  PyThreadState *tstate = PyEval_SaveThread();
   int r = self->osdmap->calc_pg_upmaps(g_ceph_context,
                                 max_deviation,
                                 max_iterations,
                                 pools,
                                 incobj->inc);
+  PyEval_RestoreThread(tstate);
   dout(10) << __func__ << " r = " << r << dendl;
   return PyInt_FromLong(r);
 }
index 0eddb0011d810875241751fe6a8141dc4519b440..b53831c61000bcdb47f2257535519515b3bc8f59 100644 (file)
@@ -290,6 +290,7 @@ class Module(MgrModule):
     run = True
     plans = {}
     mode = ''
+    optimizing = False
 
     def __init__(self, *args, **kwargs):
         super(Module, self).__init__(*args, **kwargs)
@@ -350,6 +351,11 @@ class Module(MgrModule):
                                   'current cluster')
             return (0, self.evaluate(ms, pools, verbose=verbose), '')
         elif command['prefix'] == 'balancer optimize':
+            # The GIL can be release by the active balancer, so disallow when active
+            if self.active:
+                return (-errno.EINVAL, '', 'Balancer enabled, disable to optimize manually')
+            if self.optimizing:
+                return (-errno.EINVAL, '', 'Balancer finishing up....try again')
             pools = []
             if 'pools' in command:
                 pools = command['pools']
@@ -363,10 +369,9 @@ class Module(MgrModule):
                 return (-errno.EINVAL, '', 'pools %s not found' % invalid_pool_names)
             plan = self.plan_create(command['plan'], osdmap, pools)
             r, detail = self.optimize(plan)
-            # remove plan if we are currently unable to find an optimization
-            # or distribution is already perfect
-            if r:
-                self.plan_rm(command['plan'])
+            # Add plan if an optimization was created
+            if not r:
+                self.plans[command['plan']] = plan
             return (r, '', detail)
         elif command['prefix'] == 'balancer rm':
             self.plan_rm(command['plan'])
@@ -387,6 +392,11 @@ class Module(MgrModule):
                 return (-errno.ENOENT, '', 'plan %s not found' % command['plan'])
             return (0, plan.show(), '')
         elif command['prefix'] == 'balancer execute':
+            # The GIL can be release by the active balancer, so disallow when active
+            if self.active:
+                return (-errno.EINVAL, '', 'Balancer enabled, disable to execute a plan')
+            if self.optimizing:
+                return (-errno.EINVAL, '', 'Balancer finishing up....try again')
             plan = self.plans.get(command['plan'])
             if not plan:
                 return (-errno.ENOENT, '', 'plan %s not found' % command['plan'])
@@ -445,10 +455,11 @@ class Module(MgrModule):
                 self.log.debug('Running')
                 name = 'auto_%s' % time.strftime(TIME_FORMAT, time.gmtime())
                 plan = self.plan_create(name, self.get_osdmap(), [])
+                self.optimizing = True
                 r, detail = self.optimize(plan)
                 if r == 0:
                     self.execute(plan)
-                self.plan_rm(name)
+                self.optimizing = False
             self.log.debug('Sleeping for %d', sleep_interval)
             self.event.wait(sleep_interval)
             self.event.clear()
@@ -459,7 +470,6 @@ class Module(MgrModule):
                                  self.get("pg_dump"),
                                  'plan %s initial' % name),
                     pools)
-        self.plans[name] = plan
         return plan
 
     def plan_rm(self, name):