llvm.org GIT mirror llvm / 645f3d0
[ThinLTO] Update ThinLTO cache file atimes when on Windows ThinLTO cache file access times are used for expiration based pruning and since Vista, file access times are not updated by Windows by default: https://blogs.technet.microsoft.com/filecab/2006/11/07/disabling-last-access-time-in-windows-vista-to-improve-ntfs-performance This means on Windows, cache files are currently being pruned from creation time. This change manually updates cache files that are accessed by ThinLTO, when on Windows. Patch by Owen Reynolds. Differential Revision: https://reviews.llvm.org/D47266 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336276 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Ng 1 year, 3 months ago
6 changed file(s) with 113 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
727727 /// When a child process is launched, this file should remain open in the
728728 /// child process.
729729 OF_ChildInherit = 8,
730
731 /// Force files Atime to be updated on access. Only makes a difference on windows.
732 OF_UpdateAtime = 16,
730733 };
731734
732735 /// Create a uniquely named file.
1818 #include "llvm/Support/Process.h"
1919 #include "llvm/Support/raw_ostream.h"
2020
21 #if !defined(_MSC_VER) && !defined(__MINGW32__)
22 #include
23 #else
24 #include
25 #endif
26
2127 using namespace llvm;
2228 using namespace llvm::lto;
2329
3238 SmallString<64> EntryPath;
3339 sys::path::append(EntryPath, CacheDirectoryPath, "llvmcache-" + Key);
3440 // First, see if we have a cache hit.
35 ErrorOr> MBOrErr =
36 MemoryBuffer::getFile(EntryPath);
37 if (MBOrErr) {
38 AddBuffer(Task, std::move(*MBOrErr));
39 return AddStreamFn();
41 int FD;
42 SmallString<64> ResultPath;
43 std::error_code EC = sys::fs::openFileForRead(
44 Twine(EntryPath), FD, sys::fs::OF_UpdateAtime, &ResultPath);
45 if (!EC) {
46 ErrorOr> MBOrErr =
47 MemoryBuffer::getOpenFile(FD, EntryPath,
48 /*FileSize*/ -1,
49 /*RequiresNullTerminator*/ false);
50 close(FD);
51 if (MBOrErr) {
52 AddBuffer(Task, std::move(*MBOrErr));
53 return AddStreamFn();
54 }
55 EC = MBOrErr.getError();
4056 }
4157
4258 // On Windows we can fail to open a cache file with a permission denied
4561 // process has opened the file without the sharing permissions we need.
4662 // Since the file is probably being deleted we handle it in the same way as
4763 // if the file did not exist at all.
48 if (MBOrErr.getError() != errc::no_such_file_or_directory &&
49 MBOrErr.getError() != errc::permission_denied)
64 if (EC != errc::no_such_file_or_directory && EC != errc::permission_denied)
5065 report_fatal_error(Twine("Failed to open cache file ") + EntryPath +
51 ": " + MBOrErr.getError().message() + "\n");
66 ": " + EC.message() + "\n");
5267
5368 // This native object stream is responsible for commiting the resulting
5469 // file to the cache and calling AddBuffer to add it to the link.
5454
5555 #include
5656
57 #if !defined(_MSC_VER) && !defined(__MINGW32__)
58 #include
59 #else
60 #include
61 #endif
62
5763 using namespace llvm;
5864
5965 #define DEBUG_TYPE "thinlto"
390396 ErrorOr> tryLoadingBuffer() {
391397 if (EntryPath.empty())
392398 return std::error_code();
393 return MemoryBuffer::getFile(EntryPath);
399 int FD;
400 SmallString<64> ResultPath;
401 std::error_code EC = sys::fs::openFileForRead(
402 Twine(EntryPath), FD, sys::fs::OF_UpdateAtime, &ResultPath);
403 if (EC)
404 return EC;
405 ErrorOr> MBOrErr =
406 MemoryBuffer::getOpenFile(FD, EntryPath,
407 /*FileSize*/ -1,
408 /*RequiresNullTerminator*/ false);
409 close(FD);
410 return MBOrErr;
394411 }
395412
396413 // Cache the Produced object file
10481048 Result |= GENERIC_WRITE;
10491049 if (Flags & OF_Delete)
10501050 Result |= DELETE;
1051 if (Flags & OF_UpdateAtime)
1052 Result |= FILE_WRITE_ATTRIBUTES;
10511053 return Result;
10521054 }
10531055
11031105 Name, Result, NativeDisp, NativeAccess, FILE_ATTRIBUTE_NORMAL, Inherit);
11041106 if (EC)
11051107 return errorCodeToError(EC);
1108
1109 if (Flags & OF_UpdateAtime) {
1110 FILETIME FileTime;
1111 SYSTEMTIME SystemTime;
1112 GetSystemTime(&SystemTime);
1113 if (SystemTimeToFileTime(&SystemTime, &FileTime) == 0 ||
1114 SetFileTime(Result, NULL, &FileTime, NULL) == 0) {
1115 DWORD LastError = ::GetLastError();
1116 ::CloseHandle(Result);
1117 return errorCodeToError(mapWindowsError(LastError));
1118 }
1119 }
1120
11061121 if (Flags & OF_Delete) {
11071122 if ((EC = setDeleteDisposition(Result, true))) {
11081123 ::CloseHandle(Result);
7979 ; RUN: llvm-lto -thinlto-action=run -exported-symbol=globalfunc %t2.bc %t.bc -thinlto-cache-dir %t.cache --thinlto-cache-pruning-interval 0
8080 ; RUN: not ls %t.cache/llvmcache-foo
8181
82 ; Populate the cache with files with "old" access times, then check llvm-lto updates these file times
83 ; A negative pruning interval is used to avoid removing cache entries
84 ; RUN: rm -Rf %t.cache && mkdir %t.cache
85 ; RUN: llvm-lto -thinlto-action=run -exported-symbol=globalfunc %t2.bc %t.bc -thinlto-cache-dir %t.cache
86 ; RUN: touch -a -t 197001011200 %t.cache/llvmcache-*
87 ; RUN: llvm-lto -thinlto-action=run -exported-symbol=globalfunc %t2.bc %t.bc -thinlto-cache-dir %t.cache --thinlto-cache-pruning-interval -1
88 ; RUN: ls -ltu %t.cache/* | not grep 1970-01-01
89
90 ; Populate the cache with files with "old" access times, then check llvm-lto2 updates these file times
91 ; RUN: rm -Rf %t.cache
92 ; RUN: llvm-lto2 run -o %t.o %t2.bc %t.bc -cache-dir %t.cache \
93 ; RUN: -r=%t2.bc,_main,plx \
94 ; RUN: -r=%t2.bc,_globalfunc,lx \
95 ; RUN: -r=%t.bc,_globalfunc,plx
96 ; RUN: touch -a -t 197001011200 %t.cache/llvmcache-*
97 ; RUN: llvm-lto2 run -o %t.o %t2.bc %t.bc -cache-dir %t.cache \
98 ; RUN: -r=%t2.bc,_main,plx \
99 ; RUN: -r=%t2.bc,_globalfunc,lx \
100 ; RUN: -r=%t.bc,_globalfunc,plx
101 ; RUN: ls -ltu %t.cache/* | not grep 1970-01-01
102
82103 ; Verify that specifying max size for the cache directory prunes it to this
83104 ; size, removing the largest files first.
84105 ; RUN: rm -Rf %t.cache && mkdir %t.cache
2525
2626 #ifdef _WIN32
2727 #include "llvm/ADT/ArrayRef.h"
28 #include "llvm/Support/Chrono.h"
2829 #include
2930 #include
3031 #endif
12501251 ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2));
12511252 ASSERT_EQ(D1, D2);
12521253 }
1253
12541254 ::close(FileDescriptor);
1255 ::close(FileDescriptor2);
1256
1257 #ifdef _WIN32
1258 // Since Windows Vista, file access time is not updated by default.
1259 // This is instead updated manually by openFileForRead.
1260 // https://blogs.technet.microsoft.com/filecab/2006/11/07/disabling-last-access-time-in-windows-vista-to-improve-ntfs-performance/
1261 // This part of the unit test is Windows specific as the updating of
1262 // access times can be disabled on Linux using /etc/fstab.
1263
1264 // Set access time to UNIX epoch.
1265 ASSERT_NO_ERROR(sys::fs::openFileForWrite(Twine(TempPath), FileDescriptor,
1266 fs::CD_OpenExisting));
1267 TimePoint<> Epoch(std::chrono::milliseconds(0));
1268 ASSERT_NO_ERROR(fs::setLastModificationAndAccessTime(FileDescriptor, Epoch));
1269 ::close(FileDescriptor);
1270
1271 // Open the file and ensure access time is updated, when forced.
1272 bool ForceATime = true;
1273 ASSERT_NO_ERROR(fs::openFileForRead(Twine(TempPath), FileDescriptor,
1274 fs::OF_UpdateAtime, &ResultPath));
1275
1276 sys::fs::file_status Status;
1277 ASSERT_NO_ERROR(sys::fs::status(FileDescriptor, Status));
1278 auto FileAccessTime = Status.getLastAccessedTime();
1279
1280 ASSERT_NE(Epoch, FileAccessTime);
1281 ::close(FileDescriptor);
1282
1283 // Ideally this test would include a case when ATime is not forced to update,
1284 // however the expected behaviour will differ depending on the configuration
1285 // of the Windows file system.
1286 #endif
12551287 }
12561288
12571289 static void createFileWithData(const Twine &Path, bool ShouldExistBefore,