Introduce fallocate support
fallocate() allows for reserving disk space for a particular inode and fd. Hence, a client can be sure that he won't see a ENOSPC (eventually a 507 HTTP response) later during writes. Swift's object server has had fallocate() support from a long time. P.S: Older versions of glusterfs (<3.6) did not support fallocate because FUSE did not support it earlier. http://review.gluster.org/4969 http://fuse.996288.n3.nabble.com/fallocate-support-in-FUSE-td10668.html Change-Id: Ida4b16357901707d624f92bf1b2dc8f07da4f1ad Signed-off-by: Prashanth Pai <ppai@redhat.com>
This commit is contained in:
parent
60eaebbb01
commit
9e65dd9ceb
@ -20,8 +20,13 @@ max_clients = 1024
|
|||||||
# If not doing the above, setting this value initially to match the number of
|
# If not doing the above, setting this value initially to match the number of
|
||||||
# CPUs is a good starting point for determining the right value.
|
# CPUs is a good starting point for determining the right value.
|
||||||
workers = 1
|
workers = 1
|
||||||
# Override swift's default behaviour for fallocate.
|
# You can set disable_fallocate to true to turn off usage of fallocate()
|
||||||
disable_fallocate = true
|
# sys call to reserve space during a PUT operation.
|
||||||
|
# disable_fallocate = false
|
||||||
|
#
|
||||||
|
# You can set fallocate_reserve to the number of bytes you'd like fallocate to
|
||||||
|
# reserve, whether there is space for the given file size or not.
|
||||||
|
# fallocate_reserve = 0
|
||||||
|
|
||||||
[pipeline:main]
|
[pipeline:main]
|
||||||
pipeline = object-server
|
pipeline = object-server
|
||||||
|
@ -28,7 +28,8 @@ from eventlet import sleep
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from swiftonfile.swift.common.exceptions import AlreadyExistsAsFile, \
|
from swiftonfile.swift.common.exceptions import AlreadyExistsAsFile, \
|
||||||
AlreadyExistsAsDir
|
AlreadyExistsAsDir
|
||||||
from swift.common.utils import ThreadPool, hash_path, normalize_timestamp
|
from swift.common.utils import ThreadPool, hash_path, \
|
||||||
|
normalize_timestamp, fallocate
|
||||||
from swift.common.exceptions import DiskFileNotExist, DiskFileError, \
|
from swift.common.exceptions import DiskFileNotExist, DiskFileError, \
|
||||||
DiskFileNoSpace, DiskFileDeviceUnavailable, DiskFileNotOpen, \
|
DiskFileNoSpace, DiskFileDeviceUnavailable, DiskFileNotOpen, \
|
||||||
DiskFileExpired
|
DiskFileExpired
|
||||||
@ -931,14 +932,19 @@ class DiskFile(object):
|
|||||||
break
|
break
|
||||||
dw = None
|
dw = None
|
||||||
try:
|
try:
|
||||||
|
if size is not None and size > 0:
|
||||||
|
try:
|
||||||
|
fallocate(fd, size)
|
||||||
|
except OSError as err:
|
||||||
|
if err.errno in (errno.ENOSPC, errno.EDQUOT):
|
||||||
|
raise DiskFileNoSpace()
|
||||||
|
raise
|
||||||
# Ensure it is properly owned before we make it available.
|
# Ensure it is properly owned before we make it available.
|
||||||
do_fchown(fd, self._uid, self._gid)
|
do_fchown(fd, self._uid, self._gid)
|
||||||
# NOTE: we do not perform the fallocate() call at all. We ignore
|
|
||||||
# it completely since at the time of this writing FUSE does not
|
|
||||||
# support it.
|
|
||||||
dw = DiskFileWriter(fd, tmppath, self)
|
dw = DiskFileWriter(fd, tmppath, self)
|
||||||
yield dw
|
yield dw
|
||||||
finally:
|
finally:
|
||||||
|
if dw:
|
||||||
dw.close()
|
dw.close()
|
||||||
if dw._tmppath:
|
if dw._tmppath:
|
||||||
do_unlink(dw._tmppath)
|
do_unlink(dw._tmppath)
|
||||||
|
@ -89,6 +89,10 @@ def _mock_do_fsync(fd):
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _mock_fallocate(fd, size):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class MockRenamerCalled(Exception):
|
class MockRenamerCalled(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -134,6 +138,8 @@ class TestDiskFile(unittest.TestCase):
|
|||||||
swiftonfile.swift.common.utils.read_metadata = _mock_read_metadata
|
swiftonfile.swift.common.utils.read_metadata = _mock_read_metadata
|
||||||
self._saved_do_fsync = swiftonfile.swift.obj.diskfile.do_fsync
|
self._saved_do_fsync = swiftonfile.swift.obj.diskfile.do_fsync
|
||||||
swiftonfile.swift.obj.diskfile.do_fsync = _mock_do_fsync
|
swiftonfile.swift.obj.diskfile.do_fsync = _mock_do_fsync
|
||||||
|
self._saved_fallocate = swiftonfile.swift.obj.diskfile.fallocate
|
||||||
|
swiftonfile.swift.obj.diskfile.fallocate = _mock_fallocate
|
||||||
self.td = tempfile.mkdtemp()
|
self.td = tempfile.mkdtemp()
|
||||||
self.conf = dict(devices=self.td, mb_per_sync=2,
|
self.conf = dict(devices=self.td, mb_per_sync=2,
|
||||||
keep_cache_size=(1024 * 1024), mount_check=False)
|
keep_cache_size=(1024 * 1024), mount_check=False)
|
||||||
@ -148,6 +154,7 @@ class TestDiskFile(unittest.TestCase):
|
|||||||
swiftonfile.swift.common.utils.write_metadata = self._saved_ut_wm
|
swiftonfile.swift.common.utils.write_metadata = self._saved_ut_wm
|
||||||
swiftonfile.swift.common.utils.read_metadata = self._saved_ut_rm
|
swiftonfile.swift.common.utils.read_metadata = self._saved_ut_rm
|
||||||
swiftonfile.swift.obj.diskfile.do_fsync = self._saved_do_fsync
|
swiftonfile.swift.obj.diskfile.do_fsync = self._saved_do_fsync
|
||||||
|
swiftonfile.swift.obj.diskfile.fallocate = self._saved_fallocate
|
||||||
shutil.rmtree(self.td)
|
shutil.rmtree(self.td)
|
||||||
|
|
||||||
def _get_diskfile(self, d, p, a, c, o, **kwargs):
|
def _get_diskfile(self, d, p, a, c, o, **kwargs):
|
||||||
|
Loading…
Reference in New Issue
Block a user