Version
6.10
Operating System
Linux/Unix
Bug description
On an NFS-backed repository shared by multiple hosts, a reading host can fail to observe updates to packed-refs made by a writing host, even when core.trustPackedRefsStat=after_open is configured.
RefDirectory's AFTER_OPEN refresh opens the packed-refs file itself to force the NFS client to refresh cached attributes before FileSnapshot.isModified() decides whether to re-read it. This is insufficient in the following scenario:
On NFS, updating packed-refs replaces the file by atomically swapping in a new inode under the same name. If the previous packed-refs is still held open on a host when the swap occurs, NFS preserves the old inode as a hidden .nfsXXXX entry instead of deleting it (silly-rename). In this state, a reading host can keep resolving/observing the stale inode, and opening+closing the packed-refs file does not reliably trigger an attribute refresh. As a result, isModified() compares against stale attributes, concludes nothing changed, and the reader skips re-reading, so refs written on the writing host go unnoticed.
Actual behavior
With AFTER_OPEN configured, after a writing host updates packed-refs, a reading host may not detect that packed-refs was updated and read stale refs.
Expected behavior
After a writing host updates packed-refs, a reading host with AFTER_OPEN configured should always detect that packed-refs has changed and re-read it.
Relevant log output
Other information
This can possibly be reproduced by:
Reader
- Open a repo (with trustPackedRefsStat=after_open configured) via JGit RepositoryCache
- Start a reader thread which calls getRefDatabase().getRefs() in a loop
- Print any added/changed refs whenever a change in refs is detected
Writer
- Open the same repo's packed-refs file once in a thread and keep it open for the whole test run
- Repeat below for a few iterations:
- Open the repo via RepositoryCache
- Create a new commit
- Generate couple of randomly named refs
- Write both refs atomically using PackedBatchRefUpdate
- Sleep 1-2s before the next iteration
- After all iterations, stop the packed-refs holder thread
Version
6.10
Operating System
Linux/Unix
Bug description
On an NFS-backed repository shared by multiple hosts, a reading host can fail to observe updates to packed-refs made by a writing host, even when core.trustPackedRefsStat=after_open is configured.
RefDirectory's AFTER_OPEN refresh opens the packed-refs file itself to force the NFS client to refresh cached attributes before FileSnapshot.isModified() decides whether to re-read it. This is insufficient in the following scenario:
On NFS, updating packed-refs replaces the file by atomically swapping in a new inode under the same name. If the previous packed-refs is still held open on a host when the swap occurs, NFS preserves the old inode as a hidden .nfsXXXX entry instead of deleting it (silly-rename). In this state, a reading host can keep resolving/observing the stale inode, and opening+closing the packed-refs file does not reliably trigger an attribute refresh. As a result, isModified() compares against stale attributes, concludes nothing changed, and the reader skips re-reading, so refs written on the writing host go unnoticed.
Actual behavior
With AFTER_OPEN configured, after a writing host updates packed-refs, a reading host may not detect that packed-refs was updated and read stale refs.
Expected behavior
After a writing host updates packed-refs, a reading host with AFTER_OPEN configured should always detect that packed-refs has changed and re-read it.
Relevant log output
Other information
This can possibly be reproduced by:
Reader
Writer