diff --git a/Makefile.am b/Makefile.am index 6815392fd52d4aa7f888851c37b2a5d7b33f049c..9ba8d0baea6f84e613c431b1ac9673114c89e3c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -214,6 +214,7 @@ server_PYTHON = \ utils_PYTHON = \ lib/utils/__init__.py \ lib/utils/algo.py \ + lib/utils/mlock.py \ lib/utils/retry.py \ lib/utils/text.py @@ -482,9 +483,9 @@ python_tests = \ test/ganeti.ssh_unittest.py \ test/ganeti.uidpool_unittest.py \ test/ganeti.utils.algo_unittest.py \ + test/ganeti.utils.mlock_unittest.py \ test/ganeti.utils.retry_unittest.py \ test/ganeti.utils.text_unittest.py \ - test/ganeti.utils_mlockall_unittest.py \ test/ganeti.utils_unittest.py \ test/ganeti.workerpool_unittest.py \ test/cfgupgrade_unittest.py \ diff --git a/lib/utils/__init__.py b/lib/utils/__init__.py index 417df597d8267707647ef9e66195fc39867b8ddc..2090f02cb804aefff5a9f85c88daa9b423aec084 100644 --- a/lib/utils/__init__.py +++ b/lib/utils/__init__.py @@ -51,12 +51,6 @@ import hmac from cStringIO import StringIO -try: - # pylint: disable-msg=F0401 - import ctypes -except ImportError: - ctypes = None - from ganeti import errors from ganeti import constants from ganeti import compat @@ -64,6 +58,7 @@ from ganeti import compat from ganeti.utils.algo import * # pylint: disable-msg=W0401 from ganeti.utils.retry import * # pylint: disable-msg=W0401 from ganeti.utils.text import * # pylint: disable-msg=W0401 +from ganeti.utils.mlock import * # pylint: disable-msg=W0401 _locksheld = [] @@ -90,10 +85,6 @@ UUID_RE = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-' (CERT_WARNING, CERT_ERROR) = range(1, 3) -# Flags for mlockall() (from bits/mman.h) -_MCL_CURRENT = 1 -_MCL_FUTURE = 2 - (_TIMEOUT_NONE, _TIMEOUT_TERM, _TIMEOUT_KILL) = range(3) @@ -1995,40 +1986,6 @@ def CloseFDs(noclose_fds=None): _CloseFDNoErr(fd) -def Mlockall(_ctypes=ctypes): - """Lock current process' virtual address space into RAM. - - This is equivalent to the C call mlockall(MCL_CURRENT|MCL_FUTURE), - see mlock(2) for more details. This function requires ctypes module. - - @raises errors.NoCtypesError: if ctypes module is not found - - """ - if _ctypes is None: - raise errors.NoCtypesError() - - libc = _ctypes.cdll.LoadLibrary("libc.so.6") - if libc is None: - logging.error("Cannot set memory lock, ctypes cannot load libc") - return - - # Some older version of the ctypes module don't have built-in functionality - # to access the errno global variable, where function error codes are stored. - # By declaring this variable as a pointer to an integer we can then access - # its value correctly, should the mlockall call fail, in order to see what - # the actual error code was. - # pylint: disable-msg=W0212 - libc.__errno_location.restype = _ctypes.POINTER(_ctypes.c_int) - - if libc.mlockall(_MCL_CURRENT | _MCL_FUTURE): - # pylint: disable-msg=W0212 - logging.error("Cannot set memory lock: %s", - os.strerror(libc.__errno_location().contents.value)) - return - - logging.debug("Memory lock set") - - def Daemonize(logfile): """Daemonize the current process. diff --git a/lib/utils/mlock.py b/lib/utils/mlock.py new file mode 100644 index 0000000000000000000000000000000000000000..0f7f31ee1c685a104d68c1b3d640f90eaf76d5e0 --- /dev/null +++ b/lib/utils/mlock.py @@ -0,0 +1,73 @@ +# +# + +# Copyright (C) 2009, 2010, 2011 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +"""Wrapper around mlockall(2). + +""" + +import os +import logging + +from ganeti import errors + +try: + # pylint: disable-msg=F0401 + import ctypes +except ImportError: + ctypes = None + + +# Flags for mlockall() (from bits/mman.h) +_MCL_CURRENT = 1 +_MCL_FUTURE = 2 + + +def Mlockall(_ctypes=ctypes): + """Lock current process' virtual address space into RAM. + + This is equivalent to the C call mlockall(MCL_CURRENT|MCL_FUTURE), + see mlock(2) for more details. This function requires ctypes module. + + @raises errors.NoCtypesError: if ctypes module is not found + + """ + if _ctypes is None: + raise errors.NoCtypesError() + + libc = _ctypes.cdll.LoadLibrary("libc.so.6") + if libc is None: + logging.error("Cannot set memory lock, ctypes cannot load libc") + return + + # Some older version of the ctypes module don't have built-in functionality + # to access the errno global variable, where function error codes are stored. + # By declaring this variable as a pointer to an integer we can then access + # its value correctly, should the mlockall call fail, in order to see what + # the actual error code was. + # pylint: disable-msg=W0212 + libc.__errno_location.restype = _ctypes.POINTER(_ctypes.c_int) + + if libc.mlockall(_MCL_CURRENT | _MCL_FUTURE): + # pylint: disable-msg=W0212 + logging.error("Cannot set memory lock: %s", + os.strerror(libc.__errno_location().contents.value)) + return + + logging.debug("Memory lock set") diff --git a/test/ganeti.utils_mlockall_unittest.py b/test/ganeti.utils.mlock_unittest.py similarity index 90% rename from test/ganeti.utils_mlockall_unittest.py rename to test/ganeti.utils.mlock_unittest.py index 17726b7cbc8a4bf01451c7ff52ed7a3e4e9e54f3..8c5c7469bbd6e6279d88e8343e4cb6175a9ebb9c 100755 --- a/test/ganeti.utils_mlockall_unittest.py +++ b/test/ganeti.utils.mlock_unittest.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -# Copyright (C) 2010 Google Inc. +# Copyright (C) 2010, 2011 Google Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -33,6 +33,10 @@ from ganeti import errors import testutils +# WARNING: The following tests modify the memory behaviour at runtime. Don't +# add unrelated tests here. + + class TestMlockallWithCtypes(unittest.TestCase): """Whether Mlockall() works if ctypes is present.