mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
fix(fuse): a folder trashed while sync is paused drops the creates in it (B178)
This commit is contained in:
1 parent
0f3c06f982
commit
a6f019ebe6
5 files changed
+51
-14
No files matched your search
@@ -299,29 +299,30 @@ impl Core {
|
||||
return;
|
||||
}
|
||||
let now = now_millis();
|
||||
// Offline or paused, nothing is claimed. A claimed create may be on
|
||||
// the wire, so trashing its folder kept it as a trash; claimed
|
||||
// only to be handed back, it was kept although nothing had sent
|
||||
// it (`docs/BUGS.md` B178).
|
||||
let online = self.online.load(Ordering::Relaxed);
|
||||
let paused = self.sync_paused();
|
||||
// One row, chosen and *claimed* by the database. Reading the whole
|
||||
// queue to pick one op made a long queue quadratic to drain, and
|
||||
// held the shared connection — and so every FUSE metadata call —
|
||||
// for the duration.
|
||||
let due = match self.db.claim_next_due_op(now) {
|
||||
Ok(due) => due,
|
||||
let due = match (online && !paused)
|
||||
.then(|| self.db.claim_next_due_op(now))
|
||||
.transpose()
|
||||
{
|
||||
Ok(due) => due.flatten(),
|
||||
Err(error) => {
|
||||
error!(%error, "claiming the next pending operation failed");
|
||||
self.wait_for_drain_work();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let online = self.online.load(Ordering::Relaxed);
|
||||
let paused = self.sync_paused();
|
||||
let op = match due {
|
||||
Some(op) if online && !paused => op,
|
||||
idle => {
|
||||
// Claimed but offline: hand it straight back, or it stays
|
||||
// invisible to every worker until this one happens to be
|
||||
// the next to notice the reconnect.
|
||||
if let Some(op) = idle {
|
||||
self.release_claim(&op);
|
||||
}
|
||||
Some(op) => op,
|
||||
None => {
|
||||
if primary {
|
||||
// Nothing to upload is exactly when the connection is
|
||||
// free, so this is where the read path's buffered LRU
|
||||
|
||||
@@ -9034,6 +9034,17 @@ mod tests {
|
||||
assert!(!rename.contains(".lock().relocate("));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_paused_drain_claims_nothing() {
|
||||
// A claimed create counts as sent, so trashing its folder kept it as
|
||||
// a trash, although the paused worker only handed it back (B178).
|
||||
let worker: String =
|
||||
function_source(include_str!("drain.rs"), "pub(crate) fn run_pending_drain(")
|
||||
.split_whitespace()
|
||||
.collect();
|
||||
assert!(worker.contains("(online&&!paused).then(||self.db.claim_next_due_op(now))"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_landed_upload_stays_pending_until_its_bytes_are_cached() {
|
||||
let drain = function_source(include_str!("drain.rs"), "pub(crate) fn drain_revision(");
|
||||
|
||||
@@ -12,6 +12,27 @@ Conventions:
|
||||
|
||||
---
|
||||
|
||||
## B178 — Trashing a folder while sync is paused keeps a create in it as a trash
|
||||
|
||||
**Status:** Fixed (unverified).
|
||||
**Found:** 2026-10-04, by the account run on 378667f, on an on-demand sync folder: B116's
|
||||
`pdfs rm b116` with sync paused left the create of `b116/sub/deeper/b116 held.bin` queued as
|
||||
trash #16098.
|
||||
|
||||
**Where:** `Core::run_pending_drain` in `crates/pdfs-fuse/src/drain.rs`.
|
||||
|
||||
**Cause.** Trashing a folder drops the creates queued below it, but keeps a create that may
|
||||
already be on the wire as a trash, for a node Drive may have made (B151). A claimed create
|
||||
counts as such. A drain worker that woke while sync was paused or offline claimed the next due
|
||||
op and only then saw it could not send it, and handed it back. The rename that lets a parked
|
||||
create go wakes the workers, so a trash in that moment kept a create nothing had sent.
|
||||
|
||||
**Fix.** A worker checks that it is online and not paused before it claims anything.
|
||||
|
||||
**Test:** `a_paused_drain_claims_nothing` in `crates/pdfs-fuse/src/lib.rs`.
|
||||
|
||||
---
|
||||
|
||||
## B177 — A folder listed just as its create lands answers "Input/output error"
|
||||
|
||||
**Status:** Fixed (unverified).
|
||||
|
||||
@@ -81,6 +81,8 @@ by its local id, in the queue, the stored tree and pins alike.
|
||||
- **A write closed just as its file reached Drive is no longer lost** (B176).
|
||||
- **Opening a folder just as it reaches Drive no longer fails with "Input/output error"**
|
||||
(B177).
|
||||
- **Deleting a folder while sync is paused no longer leaves a queued change behind** for a
|
||||
file in it that was never uploaded (B178).
|
||||
- **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: B127 and B141 to B177.
|
||||
- Fixes from the simulation and account runs since then: B127 and B141 to B178.
|
||||
- **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`.
|
||||
|
||||
@@ -122,7 +122,9 @@ Tracks `docs/MILESTONE-3.0.0.md`. Update it with every commit that moves a phase
|
||||
seed 8: a file replaced by a rename in that gap stayed on Drive (B175, fixed), and
|
||||
seed 12: a write closed as its file's create landed was dropped (B176, fixed).
|
||||
The account run on 378667f: a folder listed as its create landed asked Drive by
|
||||
its stand-in and answered `EIO` (B177, fixed).
|
||||
its stand-in and answered `EIO` (B177, fixed). A folder trashed while sync was
|
||||
paused kept a create below it as a trash: a paused drain worker had claimed it
|
||||
(B178, fixed).
|
||||
5. **Release**: 2.10.0 is tagged; the 2.9.0 tag still waits for the user's go-ahead.
|
||||
|
||||
## After 3.0.0
|
||||
|
||||
Reference in new issue
Block a user