Obj Auditor: Quarantine ENODATA

We've seen a disk corruption take place that throws -ENODATA when a diskfile
it opened. We currently don't quarantine on this IOError.

This patch catches and quarantines the datafile. The catch happens in
diskfile.open in order to group similar quarantines in the same place
for easier maintenance.

Change-Id: I729e3ba5f19160aa09dd8eb983d9594cb102e85b
This commit is contained in:
Matthew Oliver 2022-03-29 20:47:33 +11:00
parent ec964b23bb
commit f92be1bdd0
2 changed files with 23 additions and 2 deletions

View File

@ -2540,8 +2540,14 @@ class BaseDiskFile(object):
self._data_file = file_info.get('data_file') self._data_file = file_info.get('data_file')
if not self._data_file: if not self._data_file:
raise self._construct_exception_from_ts_file(**file_info) raise self._construct_exception_from_ts_file(**file_info)
self._fp = self._construct_from_data_file( try:
current_time=current_time, modernize=modernize, **file_info) self._fp = self._construct_from_data_file(
current_time=current_time, modernize=modernize, **file_info)
except IOError as e:
if e.errno == errno.ENODATA:
raise self._quarantine(
file_info['data_file'],
"Failed to open %s: %s" % (file_info['data_file'], e))
# This method must populate the internal _metadata attribute. # This method must populate the internal _metadata attribute.
self._metadata = self._metadata or {} self._metadata = self._metadata or {}
return self return self

View File

@ -4649,6 +4649,21 @@ class DiskFileMixin(BaseDiskFileTestMixin):
DiskFileQuarantined, DiskFileQuarantined,
self._get_open_disk_file) self._get_open_disk_file)
def test_quarantine_ioerror_enodata(self):
df = self._get_open_disk_file()
def my_open(filename, mode, *args, **kwargs):
if mode == 'rb':
raise IOError(errno.ENODATA, '-ENODATA fool!')
return open(filename, mode, *args, **kwargs)
with mock.patch('swift.obj.diskfile.open', my_open):
with self.assertRaises(DiskFileQuarantined) as err:
df.open()
self.assertEqual(
'Failed to open %s: [Errno 61] -ENODATA fool!' % df._data_file,
str(err.exception))
def test_quarantine_hashdir_not_a_directory(self): def test_quarantine_hashdir_not_a_directory(self):
df, df_data = self._create_test_file(b'1234567890', account="abc", df, df_data = self._create_test_file(b'1234567890', account="abc",
container='123', obj='xyz') container='123', obj='xyz')