diff --git a/doc/source/development_saio.rst b/doc/source/development_saio.rst index bca218cad5..1d497a526f 100644 --- a/doc/source/development_saio.rst +++ b/doc/source/development_saio.rst @@ -591,3 +591,17 @@ doesn't work, here are some good starting places to look for issues: you check that you can ``GET`` account, use ``sudo service memcached status`` and check if memcache is running. If memcache is not running, start it using ``sudo service memcached start``. Once memcache is running, rerun ``GET`` account. + +------------ +Known Issues +------------ + +Listed here are some "gotcha's" that you may run into when using or testing your SAIO: + +#. fallocate_reserve - in most cases a SAIO doesn't have a very large XFS partition + so having fallocate enabled and fallocate_reserve set can cause issues, specifically + when trying to run the functional tests. For this reason fallocate has been turned + off on the object-servers in the SAIO. If you want to play with the fallocate_reserve + settings then know that functional tests will fail unless you change the max_file_size + constraint to something more reasonable then the default (5G). Ideally you'd make + it 1/4 of your XFS file system size so the tests can pass. diff --git a/swift/common/utils.py b/swift/common/utils.py index a33df51ed8..4694f5951e 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -596,7 +596,8 @@ class FileLikeIter(object): class FallocateWrapper(object): def __init__(self, noop=False): - if noop: + self.noop = noop + if self.noop: self.func_name = 'posix_fallocate' self.fallocate = noop_libc_function return @@ -614,16 +615,18 @@ class FallocateWrapper(object): def __call__(self, fd, mode, offset, length): """The length parameter must be a ctypes.c_uint64.""" - if FALLOCATE_RESERVE > 0: - st = os.fstatvfs(fd) - free = st.f_frsize * st.f_bavail - length.value - if FALLOCATE_IS_PERCENT: - free = (float(free) / float(st.f_frsize * st.f_blocks)) * 100 - if float(free) <= float(FALLOCATE_RESERVE): - raise OSError( - errno.ENOSPC, - 'FALLOCATE_RESERVE fail %s <= %s' % (free, - FALLOCATE_RESERVE)) + if not self.noop: + if FALLOCATE_RESERVE > 0: + st = os.fstatvfs(fd) + free = st.f_frsize * st.f_bavail - length.value + if FALLOCATE_IS_PERCENT: + free = \ + (float(free) / float(st.f_frsize * st.f_blocks)) * 100 + if float(free) <= float(FALLOCATE_RESERVE): + raise OSError( + errno.ENOSPC, + 'FALLOCATE_RESERVE fail %s <= %s' % + (free, FALLOCATE_RESERVE)) args = { 'fallocate': (fd, mode, offset, length), 'posix_fallocate': (fd, offset, length) diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index 9b9ffe9b14..14e826c908 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -2601,6 +2601,19 @@ cluster_dfw1 = http://dfw1.host/v1/ try: fallocate = utils.FallocateWrapper(noop=True) utils.os.fstatvfs = fstatvfs + + # Make sure setting noop, which disables fallocate, also stops the + # fallocate_reserve check. + # Set the fallocate_reserve to 99% and request an object that is + # about 50% the size. With fallocate_reserve off this will succeed. + utils.FALLOCATE_RESERVE, utils.FALLOCATE_IS_PERCENT = \ + utils.config_fallocate_value('99%') + self.assertEqual(fallocate(0, 1, 0, ctypes.c_uint64(500)), 0) + + # Setting noop to False after the constructor allows us to use + # a noop fallocate syscall and still test fallocate_reserve. + fallocate.noop = False + # Want 1023 reserved, have 1024 * 1 free, so succeeds utils.FALLOCATE_RESERVE, utils.FALLOCATE_IS_PERCENT = \ utils.config_fallocate_value('1023')