linkat: Raise error if we run out of retries

Change-Id: Iae07ec8d38cd747f8bfffa3c08b423bee4b6623c
This commit is contained in:
Clay Gerrard 2025-03-03 10:16:46 -08:00 committed by Tim Burke
parent 7140633925
commit 34bb743b04
2 changed files with 14 additions and 1 deletions

View File

@ -877,12 +877,16 @@ def link_fd_to_path(fd, target_path, dirs_created=0, retries=2, fsync=True):
the newly created directories. the newly created directories.
""" """
dirpath = os.path.dirname(target_path) dirpath = os.path.dirname(target_path)
for _junk in range(0, retries): attempts = 0
while True:
attempts += 1
try: try:
linkat(linkat.AT_FDCWD, "/proc/self/fd/%d" % (fd), linkat(linkat.AT_FDCWD, "/proc/self/fd/%d" % (fd),
linkat.AT_FDCWD, target_path, linkat.AT_SYMLINK_FOLLOW) linkat.AT_FDCWD, target_path, linkat.AT_SYMLINK_FOLLOW)
break break
except IOError as err: except IOError as err:
if attempts > retries:
raise
if err.errno == errno.ENOENT: if err.errno == errno.ENOENT:
dirs_created = makedirs_count(dirpath) dirs_created = makedirs_count(dirpath)
elif err.errno == errno.EEXIST: elif err.errno == errno.EEXIST:

View File

@ -2275,6 +2275,15 @@ cluster_dfw1 = http://dfw1.host/v1/
self.fail("Expecting IOError exception") self.fail("Expecting IOError exception")
self.assertTrue(_m_linkat.called) self.assertTrue(_m_linkat.called)
def test_link_fd_to_path_runs_out_of_retries(self):
_m_linkat = mock.Mock(
side_effect=IOError(errno.ENOENT, os.strerror(errno.ENOENT)))
with mock.patch('swift.common.utils.linkat', _m_linkat), \
self.assertRaises(IOError) as caught:
utils.link_fd_to_path(0, '/path', 1)
self.assertEqual(caught.exception.errno, errno.ENOENT)
self.assertEqual(3, len(_m_linkat.mock_calls))
@requires_o_tmpfile_support_in_tmp @requires_o_tmpfile_support_in_tmp
@with_tempdir @with_tempdir
def test_linkat_race_dir_not_exists(self, tempdir): def test_linkat_race_dir_not_exists(self, tempdir):