diff options
author | Devendra Tewari <devendra.tewari@gmail.com> | 2021-04-19 11:23:58 -0300 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-05-06 11:04:59 +0100 |
commit | 581233a798434f178898f12fa35bbcccb92e7768 (patch) | |
tree | 85b7608515935ce107304532ea64cda8a0e80dd9 /bitbake | |
parent | 7fbd7744ea68c17f396e87e15f9c7c9f6a371f23 (diff) | |
download | poky-581233a798434f178898f12fa35bbcccb92e7768.tar.gz |
bitbake: lib/bb: Add bb.utils.rename() helper function and use for renaming
os.rename can fail for example an incremental build in Docker fails with:
OSError: [Errno 18] Invalid cross-device link
when source and destination are on different overlay filesystems.
Rather than trying to fix every call site, add a wrapper in bb.utils
for renames. We can then handle cross device failures and
fall back to shutil.move. The reason os.rename is still used is
because shutil.move is too slow for speed sensitive sections of code.
[YOCTO #14301]
(Bitbake rev: c5c4e49574ab2a65e06298a0a77bb98b041cf56b)
Signed-off-by: Devendra Tewari <devendra.tewari@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r-- | bitbake/lib/bb/siggen.py | 2 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/fetch.py | 4 | ||||
-rw-r--r-- | bitbake/lib/bb/utils.py | 18 |
3 files changed, 18 insertions, 6 deletions
diff --git a/bitbake/lib/bb/siggen.py b/bitbake/lib/bb/siggen.py index f3fa3000fa..07692e673c 100644 --- a/bitbake/lib/bb/siggen.py +++ b/bitbake/lib/bb/siggen.py | |||
@@ -402,7 +402,7 @@ class SignatureGeneratorBasic(SignatureGenerator): | |||
402 | p = pickle.dump(data, stream, -1) | 402 | p = pickle.dump(data, stream, -1) |
403 | stream.flush() | 403 | stream.flush() |
404 | os.chmod(tmpfile, 0o664) | 404 | os.chmod(tmpfile, 0o664) |
405 | os.rename(tmpfile, sigfile) | 405 | bb.utils.rename(tmpfile, sigfile) |
406 | except (OSError, IOError) as err: | 406 | except (OSError, IOError) as err: |
407 | try: | 407 | try: |
408 | os.unlink(tmpfile) | 408 | os.unlink(tmpfile) |
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py index 0f7585e119..9291ce4a06 100644 --- a/bitbake/lib/bb/tests/fetch.py +++ b/bitbake/lib/bb/tests/fetch.py | |||
@@ -1798,7 +1798,7 @@ class GitShallowTest(FetcherTest): | |||
1798 | 1798 | ||
1799 | # Set up the mirror | 1799 | # Set up the mirror |
1800 | mirrordir = os.path.join(self.tempdir, 'mirror') | 1800 | mirrordir = os.path.join(self.tempdir, 'mirror') |
1801 | os.rename(self.dldir, mirrordir) | 1801 | bb.utils.rename(self.dldir, mirrordir) |
1802 | self.d.setVar('PREMIRRORS', 'gitsm://.*/.* file://%s/\n' % mirrordir) | 1802 | self.d.setVar('PREMIRRORS', 'gitsm://.*/.* file://%s/\n' % mirrordir) |
1803 | 1803 | ||
1804 | # Fetch from the mirror | 1804 | # Fetch from the mirror |
@@ -1916,7 +1916,7 @@ class GitShallowTest(FetcherTest): | |||
1916 | bb.utils.mkdirhier(mirrordir) | 1916 | bb.utils.mkdirhier(mirrordir) |
1917 | self.d.setVar('PREMIRRORS', 'git://.*/.* file://%s/\n' % mirrordir) | 1917 | self.d.setVar('PREMIRRORS', 'git://.*/.* file://%s/\n' % mirrordir) |
1918 | 1918 | ||
1919 | os.rename(os.path.join(self.dldir, mirrortarball), | 1919 | bb.utils.rename(os.path.join(self.dldir, mirrortarball), |
1920 | os.path.join(mirrordir, mirrortarball)) | 1920 | os.path.join(mirrordir, mirrortarball)) |
1921 | 1921 | ||
1922 | # Fetch from the mirror | 1922 | # Fetch from the mirror |
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index b282d09abf..6ba1d2a376 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py | |||
@@ -782,7 +782,7 @@ def movefile(src, dest, newmtime = None, sstat = None): | |||
782 | 782 | ||
783 | if sstat[stat.ST_DEV] == dstat[stat.ST_DEV]: | 783 | if sstat[stat.ST_DEV] == dstat[stat.ST_DEV]: |
784 | try: | 784 | try: |
785 | os.rename(src, destpath) | 785 | bb.utils.rename(src, destpath) |
786 | renamefailed = 0 | 786 | renamefailed = 0 |
787 | except Exception as e: | 787 | except Exception as e: |
788 | if e.errno != errno.EXDEV: | 788 | if e.errno != errno.EXDEV: |
@@ -796,7 +796,7 @@ def movefile(src, dest, newmtime = None, sstat = None): | |||
796 | if stat.S_ISREG(sstat[stat.ST_MODE]): | 796 | if stat.S_ISREG(sstat[stat.ST_MODE]): |
797 | try: # For safety copy then move it over. | 797 | try: # For safety copy then move it over. |
798 | shutil.copyfile(src, destpath + "#new") | 798 | shutil.copyfile(src, destpath + "#new") |
799 | os.rename(destpath + "#new", destpath) | 799 | bb.utils.rename(destpath + "#new", destpath) |
800 | didcopy = 1 | 800 | didcopy = 1 |
801 | except Exception as e: | 801 | except Exception as e: |
802 | print('movefile: copy', src, '->', dest, 'failed.', e) | 802 | print('movefile: copy', src, '->', dest, 'failed.', e) |
@@ -874,7 +874,7 @@ def copyfile(src, dest, newmtime = None, sstat = None): | |||
874 | 874 | ||
875 | # For safety copy then move it over. | 875 | # For safety copy then move it over. |
876 | shutil.copyfile(src, dest + "#new") | 876 | shutil.copyfile(src, dest + "#new") |
877 | os.rename(dest + "#new", dest) | 877 | bb.utils.rename(dest + "#new", dest) |
878 | except Exception as e: | 878 | except Exception as e: |
879 | logger.warning("copyfile: copy %s to %s failed (%s)" % (src, dest, e)) | 879 | logger.warning("copyfile: copy %s to %s failed (%s)" % (src, dest, e)) |
880 | return False | 880 | return False |
@@ -1669,3 +1669,15 @@ def is_semver(version): | |||
1669 | return False | 1669 | return False |
1670 | 1670 | ||
1671 | return True | 1671 | return True |
1672 | |||
1673 | # Wrapper around os.rename which can handle cross device problems | ||
1674 | # e.g. from container filesystems | ||
1675 | def rename(src, dst): | ||
1676 | try: | ||
1677 | os.rename(src, dst) | ||
1678 | except OSError as err: | ||
1679 | if err.errno == 18: | ||
1680 | # Invalid cross-device link error | ||
1681 | shutil.move(src, dst) | ||
1682 | else: | ||
1683 | raise err | ||