From f92be1bdd011388b2cf763c9ff62b330119362c3 Mon Sep 17 00:00:00 2001 From: Matthew Oliver Date: Tue, 29 Mar 2022 20:47:33 +1100 Subject: [PATCH] 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 --- swift/obj/diskfile.py | 10 ++++++++-- test/unit/obj/test_diskfile.py | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/swift/obj/diskfile.py b/swift/obj/diskfile.py index b7a97a31f7..68ea00b755 100644 --- a/swift/obj/diskfile.py +++ b/swift/obj/diskfile.py @@ -2540,8 +2540,14 @@ class BaseDiskFile(object): self._data_file = file_info.get('data_file') if not self._data_file: raise self._construct_exception_from_ts_file(**file_info) - self._fp = self._construct_from_data_file( - current_time=current_time, modernize=modernize, **file_info) + try: + 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. self._metadata = self._metadata or {} return self diff --git a/test/unit/obj/test_diskfile.py b/test/unit/obj/test_diskfile.py index 8fdb9b1a7d..288864e5e3 100644 --- a/test/unit/obj/test_diskfile.py +++ b/test/unit/obj/test_diskfile.py @@ -4649,6 +4649,21 @@ class DiskFileMixin(BaseDiskFileTestMixin): DiskFileQuarantined, 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): df, df_data = self._create_test_file(b'1234567890', account="abc", container='123', obj='xyz')