From: David Zafman Date: Tue, 22 Oct 2019 22:24:05 +0000 (-0700) Subject: mgr: Release GIL before calling OSDMap::calc_pg_upmaps() X-Git-Tag: v12.2.13~18^2~17 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=36bc2c09453ce6fd59e964cb169988c1c51119f9;p=ceph.git mgr: Release GIL before calling OSDMap::calc_pg_upmaps() Prevent optimize and execute commands from running with active balancer Fixes: https://tracker.ceph.com/issues/42432 Signed-off-by: David Zafman (cherry picked from commit e2a35e8c8e9f381a635ad0ca01326a2c512590a9) Conflicts: src/pybind/mgr/balancer/module.py (trivial) src/test/cli-integration/balancer/misplaced.t (doesn't exist) --- diff --git a/src/mgr/PyOSDMap.cc b/src/mgr/PyOSDMap.cc index a247d33a298..b67f2a14743 100644 --- a/src/mgr/PyOSDMap.cc +++ b/src/mgr/PyOSDMap.cc @@ -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); } diff --git a/src/pybind/mgr/balancer/module.py b/src/pybind/mgr/balancer/module.py index f14a4902702..06300166a6c 100644 --- a/src/pybind/mgr/balancer/module.py +++ b/src/pybind/mgr/balancer/module.py @@ -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):