Handle ENOSPC in mkstemp()
mkstemp() can fail with ENOSPC when filesystem runs out of inodes. And fallocate() used to raise DiskFileNoSpace for all OSErrors. Change-Id: I8c95cb710107d8e481d068b00eda53dd805c00a5 Signed-off-by: Prashanth Pai <ppai@redhat.com>
This commit is contained in:
parent
23f55b2ebc
commit
0eb27b96f2
@ -1603,14 +1603,22 @@ class DiskFile(object):
|
||||
"""
|
||||
if not exists(self._tmpdir):
|
||||
mkdirs(self._tmpdir)
|
||||
fd, tmppath = mkstemp(dir=self._tmpdir)
|
||||
try:
|
||||
fd, tmppath = mkstemp(dir=self._tmpdir)
|
||||
except OSError as err:
|
||||
if err.errno in (errno.ENOSPC, errno.EDQUOT):
|
||||
# No more inodes in filesystem
|
||||
raise DiskFileNoSpace()
|
||||
raise
|
||||
dfw = None
|
||||
try:
|
||||
if size is not None and size > 0:
|
||||
try:
|
||||
fallocate(fd, size)
|
||||
except OSError:
|
||||
raise DiskFileNoSpace()
|
||||
except OSError as err:
|
||||
if err.errno in (errno.ENOSPC, errno.EDQUOT):
|
||||
raise DiskFileNoSpace()
|
||||
raise
|
||||
dfw = DiskFileWriter(self._name, self._datadir, fd, tmppath,
|
||||
self._bytes_per_sync, self._threadpool)
|
||||
yield dfw
|
||||
|
@ -1595,16 +1595,56 @@ class TestDiskFile(unittest.TestCase):
|
||||
def test_create_prealloc_oserror(self):
|
||||
df = self.df_mgr.get_diskfile(self.existing_device, '0', 'abc', '123',
|
||||
'xyz')
|
||||
for e in (errno.ENOSPC, errno.EDQUOT):
|
||||
with mock.patch("swift.obj.diskfile.fallocate",
|
||||
mock.MagicMock(side_effect=OSError(
|
||||
e, os.strerror(e)))):
|
||||
try:
|
||||
with df.create(size=200):
|
||||
pass
|
||||
except DiskFileNoSpace:
|
||||
pass
|
||||
else:
|
||||
self.fail("Expected exception DiskFileNoSpace")
|
||||
|
||||
# Other OSErrors must not be raised as DiskFileNoSpace
|
||||
with mock.patch("swift.obj.diskfile.fallocate",
|
||||
mock.MagicMock(side_effect=OSError(
|
||||
errno.EACCES, os.strerror(errno.EACCES)))):
|
||||
try:
|
||||
with df.create(size=200):
|
||||
pass
|
||||
except DiskFileNoSpace:
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
self.fail("Expected exception DiskFileNoSpace")
|
||||
self.fail("Expected exception OSError")
|
||||
|
||||
def test_create_mkstemp_no_space(self):
|
||||
df = self.df_mgr.get_diskfile(self.existing_device, '0', 'abc', '123',
|
||||
'xyz')
|
||||
for e in (errno.ENOSPC, errno.EDQUOT):
|
||||
with mock.patch("swift.obj.diskfile.mkstemp",
|
||||
mock.MagicMock(side_effect=OSError(
|
||||
e, os.strerror(e)))):
|
||||
try:
|
||||
with df.create(size=200):
|
||||
pass
|
||||
except DiskFileNoSpace:
|
||||
pass
|
||||
else:
|
||||
self.fail("Expected exception DiskFileNoSpace")
|
||||
|
||||
# Other OSErrors must not be raised as DiskFileNoSpace
|
||||
with mock.patch("swift.obj.diskfile.mkstemp",
|
||||
mock.MagicMock(side_effect=OSError(
|
||||
errno.EACCES, os.strerror(errno.EACCES)))):
|
||||
try:
|
||||
with df.create(size=200):
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
self.fail("Expected exception OSError")
|
||||
|
||||
def test_create_close_oserror(self):
|
||||
df = self.df_mgr.get_diskfile(self.existing_device, '0', 'abc', '123',
|
||||
|
@ -4041,7 +4041,7 @@ class TestObjectController(unittest.TestCase):
|
||||
return ''
|
||||
|
||||
def fake_fallocate(fd, size):
|
||||
raise OSError(42, 'Unable to fallocate(%d)' % size)
|
||||
raise OSError(errno.ENOSPC, os.strerror(errno.ENOSPC))
|
||||
|
||||
orig_fallocate = diskfile.fallocate
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user