mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
2bfdf6f481
Summary: A while back, we saw that concurrent directory creation would lead to EdenFS being confused and failing to record some of the created directories. This then caused EdenFS to no longer being in sync with what was on disk. To handle this case, we've had to manually creating these directories recursively. What I didn't realize at the time was that these concurrent notifications could also happen on removal this time, and if a directory removal notification wins the race against the removal of its last children, that directory wouldn't be removed and EdenFS would once again be confused about the state of the repository. Fixing this is a bit trickier than directory creation as it's more racier. Consider a directory that is being removed, and then immediately recreated with a file in it in a different process. The naive approach of simply force removing all of the children of a directory when handling the removal notification would clash with the file creation. We could argue that nobody should be doing this, but there would be an unhandled race, and thus a bug where data would potentially be lost[0]. We can however fix this bug slightly differently. For file/directory removal, we can actually hook onto the pre-callback, ie: one that happens before the file/directory is no longer visible on disk. This inherently eliminate the race altogether as the callback will be guaranteed to run when none of its children are present, and if a race happens with a file creation in it, we can simply fail the removal properly. The only tricky bit is for the renaming logic, as renaming a file is logically a removal followed by a creation. For that reason, I've moved part of the renaming bits to the pre-callback too. In theory, this change may negatively affect workloads that do concurrent directory removal as the duration during which a file/directory is visible ondisk now includes the EdenFS callback while it didn't before. Such workflows should be fairly rare and/or redirected to avoid EdenFS altogether if performance matters. [0]: This left-over file that EdenFS wouldn't be aware of would also later cause the checkout code to fail due to invalidation failures triggered when trying to invalidate that directory. This would be fairly hard to debug. Reviewed By: fanzeyi Differential Revision: D25112381 fbshipit-source-id: 9300499ce872ad93d0a687f0e61b7e2a9caf9556 |
||
---|---|---|
.. | ||
test | ||
BucketedLog.h | ||
BufVec.h | ||
Bug.cpp | ||
Bug.h | ||
ChronoParse.cpp | ||
ChronoParse.h | ||
ChronoUnit.cpp | ||
ChronoUnit.gperf | ||
ChronoUnit.h | ||
Clock.cpp | ||
Clock.h | ||
CMakeLists.txt | ||
CoverageSet.cpp | ||
CoverageSet.h | ||
DirType.cpp | ||
DirType.h | ||
EnumValue.h | ||
FaultInjector.cpp | ||
FaultInjector.h | ||
FileDescriptor.cpp | ||
FileDescriptor.h | ||
FileUtils.cpp | ||
FileUtils.h | ||
Future.h | ||
FutureUnixSocket.cpp | ||
FutureUnixSocket.h | ||
Guid.h | ||
Handle.h | ||
IDGen.cpp | ||
IDGen.h | ||
IoFuture.cpp | ||
IoFuture.h | ||
LazyInitialize.h | ||
LeaseCache.h | ||
MappedDiskVector.h | ||
Memory.cpp | ||
Memory.h | ||
NotImplemented.h | ||
PathFuncs.cpp | ||
PathFuncs.h | ||
PathMap.h | ||
Pipe.cpp | ||
Pipe.h | ||
ProcessAccessLog.cpp | ||
ProcessAccessLog.h | ||
ProcessNameCache.cpp | ||
ProcessNameCache.h | ||
ProcUtil.cpp | ||
ProcUtil.h | ||
SortedInsert.h | ||
SpawnedProcess.cpp | ||
SpawnedProcess.h | ||
SSLContext.cpp | ||
SSLContext.h | ||
StatTimes.h | ||
StringConv.cpp | ||
StringConv.h | ||
Synchronized.h | ||
SystemError.h | ||
Thread.cpp | ||
Thread.h | ||
TimeUtil.cpp | ||
TimeUtil.h | ||
UnboundedQueueExecutor.cpp | ||
UnboundedQueueExecutor.h | ||
UnixSocket.cpp | ||
UnixSocket.h | ||
UserInfo.cpp | ||
UserInfo.h | ||
Utf8.cpp | ||
Utf8.h | ||
WinError.cpp | ||
WinError.h | ||
XAttr.cpp | ||
XAttr.h |