fix(fuse): do not take a new file Drive lists before its commit as empty (B163)

This commit is contained in:
nvrl committed 2026-10-04 18:51:39 +02:00
1 parent 18587124ac
commit b37d5e7928
6 files changed
+166 -4

No files matched your search

+33
View File
@@ -12,6 +12,39 @@ Conventions:
---
## B163 — A file read right after its create landed is empty
**Status:** Fixed.
**Found:** 2026-10-04, by the account run on 2.10.0 ("unusual but legal names", on-demand
pairing). The case wrote some twenty files into a new folder, listed it and read each back.
`-starts-with-dash` read 0 bytes for 17. Its create had landed with the bytes a moment before.
No revision was queued for it and nothing was logged.
**Where:** `Core::read_back` in `crates/pdfs-fuse/src/lib.rs`.
**Cause.** After a create, the drain reads the new node back and adopts that answer into the
tree. Drive can answer a read before it lists a node it has just made, so an empty answer is
asked again (B143). It can also list the node before the create's revision is committed, as a
file with no active revision: no claimed size and nothing on storage, so its size reads as 0.
The adoption took that answer, and the tree showed the new file as empty. The folder was made
here, so its listing came from the tree. The size fetch the listing starts met the same answer
and left the 0. The kernel capped the read at it.
The run logged nothing for the file, so the stale answer is inferred, not observed. It is the
one path found that leaves a landed file empty with no op queued.
**Fix.** `read_back` treats a file without an active revision like a node Drive does not list
yet: it asks again after 250 ms and 1 s. If both answers are still without a revision, it
reports the node as not found, and the drain adopts it later, as it does for a node Drive
never lists in that time.
**Test:** simulation test `a_file_read_back_before_drive_committed_it_keeps_its_bytes` (failed
before the fix: the listing showed the file with 0 bytes). The fake Drive can now answer a
file's next reads as Drive lists a file that is not committed yet
(`FakeClient::answer_reads_unrevised`).
---
## B162 — A folder removed and made again at once loses what goes into it
**Status:** Fixed.
+2
View File
@@ -53,6 +53,8 @@ by its local id, in the queue, the stored tree and pins alike.
link (B161).
- **A folder removed and made again at once keeps what goes into it.** It used to be created
inside the removed folder and was trashed along with it (B162).
- **A new file no longer reads as empty just after it is uploaded.** Drive can list it a moment
before its contents are committed, and the mount took that answer (B163).
- **A file renamed just as its upload finished keeps its new name.** The mount no longer showed
the old name, and a second rename no longer failed with "No such file or directory" (B152).
- **A change that waits for a name to be freed no longer waits seconds after it is.** A rename or
+5 -2
View File
@@ -9,7 +9,7 @@ Tracks `docs/MILESTONE-3.0.0.md`. Update it with every commit that moves a phase
- **Phase 2**: local ids, inode = local id, one tree for every mount (2.10.0).
- **Phase 3, first part**: mkdir, create, rename, unlink and rmdir on the mount are recorded
locally and sent from the queue; `"local_first": false` brings back the old path (5e0f30c).
- Fixes from the simulation and account runs since then: B127 and B141 to B162.
- Fixes from the simulation and account runs since then: B127 and B141 to B163.
- **Sync issues, first cut** (§6.2): refusals sorted into issues, shown at once in the app,
tray and CLI; Export button and `pdfs sync export`; `pdfs sync issues`.
@@ -97,7 +97,10 @@ Tracks `docs/MILESTONE-3.0.0.md`. Update it with every commit that moves a phase
to reach Drive at once and now accepts queued ones. The move cases were the harness:
it retried every source after one was busy, and expected a refusal where a mirror to
mirror move carries the local copy along. The journal showed a conflict copy retrying
into a deleted folder (B150, fixed). Not confirmed yet.
into a deleted folder (B150, fixed). Not confirmed yet. The run on 2.10.0
(2026-10-04: 260 passed, 3 failed) failed a new file that read back empty (B163,
fixed), a 128-entry folder that listed 129, and its cleanup, which ran while the
daemon was restarting.
5. **Release**: 2.10.0 is tagged; the 2.9.0 tag still waits for the user's go-ahead.
## After 3.0.0