From 048645300ebf9a4c39fa3c3903784b4698b26dca Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Tue, 1 Jul 2008 10:43:42 +0000 Subject: [PATCH] Processor: acquire the BGL for LUs requiring it If a LU required the BGL (all LUs do, right now, by default) we'll acquire it in the Processor before starting them. For LUs that don't we'll still acquire it, but in a shared fashion, so that they cannot run together with LUs that do. We'll also note down whether we own the BGL exclusively, and if we don't and we try to chain a LU that does, we'll fail. More work will need to be done, of course, to convert LUs not to require the BGL, but this basic infrastructure should guarantee the coexistance of the old and new world for the time being. Reviewed-by: iustinp --- lib/mcpu.py | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/mcpu.py b/lib/mcpu.py index 4e9659d0b..7c87c5942 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -37,6 +37,7 @@ from ganeti import cmdlib from ganeti import config from ganeti import ssconf from ganeti import logger +from ganeti import locking class Processor(object): @@ -98,6 +99,7 @@ class Processor(object): """ self.context = context self._feedback_fn = feedback + self.exclusive_BGL = False def ExecOpCode(self, op): """Execute an opcode. @@ -120,24 +122,31 @@ class Processor(object): sstore = ssconf.SimpleStore() write_count = self.context.cfg.write_count - lu = lu_class(self, op, self.context.cfg, sstore) - lu.CheckPrereq() - hm = HooksMaster(rpc.call_hooks_runner, self, lu) - h_results = hm.RunPhase(constants.HOOKS_PHASE_PRE) - lu.HooksCallBack(constants.HOOKS_PHASE_PRE, - h_results, self._feedback_fn, None) + + # Acquire the Big Ganeti Lock exclusively if this LU requires it, and in a + # shared fashion otherwise (to prevent concurrent run with an exclusive LU. + self.context.GLM.acquire(locking.LEVEL_CLUSTER, [locking.BGL], + shared=not lu_class.REQ_BGL) try: - result = lu.Exec(self._feedback_fn) - h_results = hm.RunPhase(constants.HOOKS_PHASE_POST) - result = lu.HooksCallBack(constants.HOOKS_PHASE_POST, - h_results, self._feedback_fn, result) - finally: - if lu.cfg is not None: - # we use lu.cfg and not self.cfg as for init cluster, self.cfg - # is None but lu.cfg has been recently initialized in the - # lu.Exec method - if write_count != lu.cfg.write_count: + self.exclusive_BGL = lu_class.REQ_BGL + lu = lu_class(self, op, self.context.cfg, sstore) + lu.CheckPrereq() + hm = HooksMaster(rpc.call_hooks_runner, self, lu) + h_results = hm.RunPhase(constants.HOOKS_PHASE_PRE) + lu.HooksCallBack(constants.HOOKS_PHASE_PRE, h_results, + self._feedback_fn, None) + try: + result = lu.Exec(self._feedback_fn) + h_results = hm.RunPhase(constants.HOOKS_PHASE_POST) + result = lu.HooksCallBack(constants.HOOKS_PHASE_POST, h_results, + self._feedback_fn, result) + finally: + # FIXME: This needs locks if not lu_class.REQ_BGL + if write_count != self.context.cfg.write_count: hm.RunConfigUpdate() + finally: + self.context.GLM.release(locking.LEVEL_CLUSTER) + self.exclusive_BGL = False return result @@ -158,6 +167,10 @@ class Processor(object): if lu_class is None: raise errors.OpCodeUnknown("Unknown opcode") + if lu_class.REQ_BGL and not self.exclusive_BGL: + raise errors.ProgrammerError("LUs which require the BGL cannot" + " be chained to granular ones.") + if lu_class.REQ_WSSTORE: sstore = ssconf.WritableSimpleStore() else: -- GitLab