mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
fix(fuse,core): what a create sent, and where, outlives a restart and a rename (B182, B183, B184)
The known-bug confirmation run failed one_client_on_a_flaky_link seeds 6 and 11 on three bugs around a create whose answer was lost: - B182: after a restart, a write over a file whose create landed but was never read back forked a conflict copy. A revision of a file that has no revision of Drive's now adopts the landed node first. - B183: the SHA-1s a create sent were kept in memory, so after a restart its trash or retry no longer knew the node Drive made. They are now on the op's row (pending_op.sent_sha1, schema 42). - B184: a rename rewrote the op's target, and the trash and the retry looked for the node under the last name only. Each attempt's parent and name are recorded (pending_op.sent_to); the trash looks under all of them, and a retry adopts the node an earlier attempt made and moves it to the current name.
This commit is contained in:
1 parent
a8ed6060af
commit
307305282e
10 files changed
+548
-49
No files matched your search
+66
-2
@@ -12,6 +12,71 @@ Conventions:
|
||||
|
||||
---
|
||||
|
||||
## B184 — A file renamed after its create lost its answer stays on Drive under its old name
|
||||
|
||||
**Status:** Fixed (unverified).
|
||||
**Found:** 2026-10-05, replaying `one_client_on_a_flaky_link` seed 11 with the B183 fix. `a.txt`'s
|
||||
create reached Drive and lost its answer. The file was then rewritten, renamed to `b.txt` and
|
||||
then `d`, and deleted. Drive kept `a.txt` with the bytes the create had sent.
|
||||
|
||||
**Where:** `Core::withdrawn_twin` and `Core::create_local_node` in
|
||||
`crates/pdfs-fuse/src/drain.rs`.
|
||||
|
||||
**Cause.** A rename while a create waits rewrites the op's parent and name, but the node a lost
|
||||
answer left stays where the create was sent. The trash a delete made of the create, and the
|
||||
create's retry, looked for that node under the op's last name only. The trash found nothing
|
||||
and left the file on Drive. The retry made a second file under the new name, so Drive had both.
|
||||
|
||||
**Fix.** Each attempt records the parent and name it is sent under on the op's row, in a new
|
||||
`pending_op.sent_to` column (schema 42). The trash looks for its node under each of them. A
|
||||
retry first adopts a node an earlier attempt made under another name, and the rename to the
|
||||
current name follows it. Sim tests `a_file_renamed_after_its_create_lost_its_answer_lands_once`
|
||||
and `a_file_renamed_and_deleted_after_its_create_lost_its_answer_leaves_nothing`, and
|
||||
`what_a_create_sent_outlives_a_newer_blob_its_trash_and_a_restart` in
|
||||
`crates/pdfs-core/src/db/tests.rs`.
|
||||
|
||||
## B183 — A file deleted after a restart stays on Drive when its create lost its answer
|
||||
|
||||
**Status:** Fixed (unverified).
|
||||
**Found:** 2026-10-05, by the known-bug confirmation run (`PDFS_SIM_KNOWN=fail`) on da013c2:
|
||||
`one_client_on_a_flaky_link` seed 11 failed every replay. `d` was made, written again while
|
||||
its create was on the wire, and deleted after several restarts. Drive kept a `d` with the bytes
|
||||
the create had sent, and the next file renamed to `d` landed as `d (sync-conflict …)`.
|
||||
|
||||
**Where:** `Core::withdrawn_twin` and `Core::adoptable_twin` in `crates/pdfs-fuse/src/drain.rs`.
|
||||
|
||||
**Cause.** The trash a delete makes of a create that was sent looks for a node Drive made with
|
||||
the bytes the create sent (B151). Those were kept in memory only (B156). After a restart the
|
||||
trash knew only the blob the op held last, which a later write had replaced. It found no node of
|
||||
its own and left the file on Drive. A create retried after a restart had the same gap and forked
|
||||
a conflict copy.
|
||||
|
||||
**Fix.** Each attempt records the SHA-1 of the blob it sends on the op's row, in a new
|
||||
`pending_op.sent_sha1` column (schema 42). The row keeps it through a newer blob, through the
|
||||
turn into a trash and across restarts. The in-memory map is gone. Tests
|
||||
`what_a_create_sent_outlives_a_newer_blob_its_trash_and_a_restart` in
|
||||
`crates/pdfs-core/src/db/tests.rs`, and sim test
|
||||
`a_file_deleted_after_a_restart_leaves_drive_with_what_its_create_sent`.
|
||||
|
||||
## B182 — A write after a restart over a create never read back lands as a conflict copy
|
||||
|
||||
**Status:** Fixed (unverified).
|
||||
**Found:** 2026-10-05, by the known-bug confirmation run on da013c2:
|
||||
`one_client_on_a_flaky_link` seed 6 failed two of three replays. `y/x/c.bin`'s create landed and
|
||||
the link went down before it was read back. The daemon restarted, and a write to the file landed
|
||||
as `c (sync-conflict …).bin`, with Drive keeping the old bytes.
|
||||
|
||||
**Where:** `Core::finish_adoption` in `crates/pdfs-fuse/src/drain.rs`.
|
||||
|
||||
**Cause.** A create that landed but was not read back is adopted before the next op for the
|
||||
node is sent (B143). The node is remembered for that in memory, and a restart forgot it. The
|
||||
tree then still had the file as it was made here, with no revision of Drive's, and a write was
|
||||
based on that. The drain found Drive's revision in its way and took it for someone else's.
|
||||
|
||||
**Fix.** A queued write over a file the tree holds without a revision id is adopted first, as
|
||||
B143 does, after a restart too. Sim test
|
||||
`a_write_after_a_restart_over_a_create_never_read_back_is_not_a_conflict`.
|
||||
|
||||
## B181 — The app shows a queued edit kept as a conflict copy in English
|
||||
|
||||
**Status:** Fixed.
|
||||
@@ -673,8 +738,7 @@ the op held at the retry was hashed. The twin held the bytes an earlier attempt
|
||||
|
||||
**Fix.** Each attempt records the SHA-1 of the blob it uploads, by op id, in memory. A twin holding
|
||||
any of them is ours. One holding older bytes than the op's is adopted, and the op's blob goes up
|
||||
as a revision of it. After a restart such a twin still forks a conflict copy, which loses
|
||||
nothing. Sim test `a_file_written_again_after_its_create_lost_its_answer_lands_once`; the fake
|
||||
as a revision of it. Kept on the op's row since B183, so a restart no longer forgets them. Sim test `a_file_written_again_after_its_create_lost_its_answer_lands_once`; the fake
|
||||
Drive's held and lost create answers now combine.
|
||||
|
||||
## B155 — A write whose upload lost its answer lands as a conflict copy of itself
|
||||
|
||||
+12
-3
@@ -11,9 +11,10 @@ scratch (user data in `staging/` and `recovery/` is never touched by this).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
Schema: **41**. The queue table is rebuilt so an id is never given out twice; queued changes
|
||||
are kept. Queued changes get a column for the reason Drive refused them, and name their file
|
||||
and folder by local id as well as by Drive's id. Stored files and folders name their parent
|
||||
Schema: **42**. The queue table is rebuilt so an id is never given out twice; queued changes
|
||||
are kept. Queued changes get a column for the reason Drive refused them, and two for the
|
||||
content a new file was sent with and where, and name their file and folder by local id as well
|
||||
as by Drive's id. Stored files and folders name their parent
|
||||
folder by local id too. A file or folder made on this machine that Drive does not have yet goes
|
||||
by its local id, in the queue, the stored tree and pins alike.
|
||||
|
||||
@@ -96,6 +97,14 @@ by its local id, in the queue, the stored tree and pins alike.
|
||||
- **The daemon no longer hangs when a file being read changes on Drive** (B130).
|
||||
- **The Activity page says in your language why an edit was kept as a conflicting copy**,
|
||||
instead of the daemon's English (B181).
|
||||
- **A file written after a restart no longer lands as a conflict copy of itself** when the
|
||||
connection dropped just as it first reached Drive (B182).
|
||||
- **A file deleted after a restart is removed from Drive too** when the connection lost Drive's
|
||||
answer to its upload and the file was written again meanwhile. It no longer stayed there and
|
||||
turned the next file under its name into a conflict copy (B183).
|
||||
- **A file renamed while the connection lost Drive's answer to its upload lands once.** It no
|
||||
longer stayed on Drive under its old name too, or, when deleted, under its old name alone
|
||||
(B184).
|
||||
- **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,
|
||||
B172).
|
||||
|
||||
@@ -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: B125, B127, B130 and B141 to B181.
|
||||
- Fixes from the simulation and account runs since then: B125, B127, B130 and B141 to B184.
|
||||
- **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`; Discard button and
|
||||
`pdfs sync discard`; a warning badge on the node in the file browser.
|
||||
@@ -102,7 +102,12 @@ Tracks `docs/MILESTONE-3.0.0.md`. Update it with every commit that moves a phase
|
||||
which a68dae9 (not yet pushed then) also takes off the runtime. CI now keeps a hung
|
||||
run's stacks.
|
||||
- [ ] Known-bug list in `sim/run.rs` is empty: none open; B125, B127, B129, B130 and B132
|
||||
fixed but not yet confirmed by the runs.
|
||||
fixed but not yet confirmed by the runs. The confirmation run (`PDFS_SIM_KNOWN=fail`)
|
||||
on da013c2 failed `one_client_on_a_flaky_link` seeds 6 and 11 on two new bugs, both
|
||||
after restarts: a write over a create never read back (B182) and a trash that forgot
|
||||
what its create sent (B183). Replays with those fixed found a third: a create renamed
|
||||
after it lost its answer (B184). All three fixed; no known-bug matcher fired. It was
|
||||
stopped before `three_clients`.
|
||||
- [ ] A clean account run. The one on a6f36d5 (2026-10-04, LAN: 427 passed, 12 failed)
|
||||
failed B113 and B121 on every on-demand mount, two mirror-to-mirror move cases, and
|
||||
the journal check. B121 was a bug (B149, fixed); B113's case still expected creates
|
||||
|
||||
Reference in new issue
Block a user