mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
8f3f873874
Summary: TL;DR: File invalidation after checkout is broken on NFS macOS. This proposes a fix. Previously, to invalidate things on NFS we opened and closed all the parent directories of any files/directories that changed during a checkout operation. This worked on Linux because all open calls result in some request into the EdenFS daemon (usually a getattr I think). The returned response from this would show that the directory had update timestamps. So the open would see the parent directories in their updated state. This would trigger the NFS client to clear it's caches for that directory and their recursive children to preserve CTO. CTO or close-to-open consistency guarantees that if on process observed a file in state A and closed the file, then another process opened that same file , it will see the file in state A or a later state. macOS does not seem to do CTO. It seems that most of the "read" filesystem calls can basically be served from cache on NFS. Only writes seem to be guaranteed to make it into eden. So instead of using a "read" filesystem call to trigger invalidation, we need to use a write one. I tried opening things in write mode, but the problem is that we need to invalidate directories (to ensure the entry information is updated) and directories can not be opened in write mode. I tried writing 0 bytes to the files themselves that have changed, but this empty write is short circuited somewhere in the kernel. The only filesystem call that can be a noop, and seems to trigger a call into eden is chmod. We are not really working off any guarantees any more, but it seems to work on both Linux and macOS in my testing so far and is better than our current broken state of invalidation. So now to invalidate we chmod parent directories that have changed with their current mode. Note that this could get extra tricky if we were mixing updating directory permissions with invalidating them. We would need to ensure we chmod with the most up to date mode bits. However, because we do not update permissions anywhere that we also invalidate (checkout does not know how to update directory permissions) things are a little simpler. It's important that the chmod can not complete until it seems an updated view of the parent directory. So we have to be careful about locking here. (Although that hasn't really changed since we switched from open to chmod.) One thing that does change is that since chmod is technically a write, it could cause extra materialization that would be bad for checkout and status performance. To prevent these problems I have updated setattr to not materialize a directory when the attribute change is a noop which it should be in our invalidation technique unless another client modified the directory in the meantime in which case the directory should be modified anyways. This would mean that we could end up wiping out clients changes to permissions in the working copy during checkout. but this matches non eden checkout behavior. So I think this is ok. Reviewed By: xavierd Differential Revision: D35435764 fbshipit-source-id: 196c4995b130b595f9582204237e726e5212993f |
||
---|---|---|
.. | ||
portmap | ||
rpc | ||
test | ||
testharness | ||
xdr | ||
CMakeLists.txt | ||
DirList.cpp | ||
DirList.h | ||
Mountd.cpp | ||
Mountd.h | ||
MountdRpc.cpp | ||
MountdRpc.h | ||
Nfsd3.cpp | ||
Nfsd3.h | ||
NfsDispatcher.cpp | ||
NfsDispatcher.h | ||
NfsdRpc.cpp | ||
NfsdRpc.h | ||
NfsRequestContext.cpp | ||
NfsRequestContext.h | ||
NfsServer.cpp | ||
NfsServer.h | ||
NfsUtils.cpp | ||
NfsUtils.h |