]> 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:48:24 +0000 (17:48 -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 a247d33a298de51bc5e1c45caf5925d185f220a8..b67f2a14743662bde34ec5b81df876fc656462bf 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 f14a4902702f3faae7c03f78ef42ba52f2496009..06300166a6ccd5ab4cb27d305dc0098b21230bbd 100644 (file)
@@ -273,6 +273,7 @@ class Module(MgrModule):
     run = True
     plans = {}
     mode = ''
+    optimizing = False
 
     def __init__(self, *args, **kwargs):
         super(Module, self).__init__(*args, **kwargs)
@@ -333,6 +334,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']
@@ -346,10 +352,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'])
@@ -370,6 +375,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'])
@@ -428,10 +438,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()
@@ -442,7 +453,6 @@ class Module(MgrModule):
                                  self.get("pg_dump"),
                                  'plan %s initial' % name),
                     pools)
-        self.plans[name] = plan
         return plan
 
     def plan_rm(self, name):