mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
fix(fuse): a folder whose mkdir is queued is listed from the database (B125)
This commit is contained in:
1 parent
f9b1638603
commit
e743cd60cf
5 files changed
+72
-6
No files matched your search
@@ -2521,6 +2521,17 @@ impl Core {
|
|||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
Err(e) => warn!(%folder_uid, error = %e, "db children_if_listed failed"),
|
Err(e) => warn!(%folder_uid, error = %e, "db children_if_listed failed"),
|
||||||
}
|
}
|
||||||
|
// Drive knows nothing by a stand-in. Until its mkdir lands the folder
|
||||||
|
// is only here, and once it has, the DB holds what Drive does. A
|
||||||
|
// listing dropped meanwhile was asked of Drive, and every lookup in
|
||||||
|
// the folder failed with EIO (`docs/BUGS.md` B125).
|
||||||
|
if is_local_uid(&folder_uid) {
|
||||||
|
let nodes = self.db.known_children(&folder_uid).map_err(|e| {
|
||||||
|
warn!(%folder_uid, error = %e, "db known_children failed");
|
||||||
|
Errno::EIO
|
||||||
|
})?;
|
||||||
|
return self.adopt_db_listing(ino, &folder_uid, nodes, primary_root);
|
||||||
|
}
|
||||||
if !self.is_online() {
|
if !self.is_online() {
|
||||||
return self.adopt_stale_listing(ino, &folder_uid, cached, primary_root);
|
return self.adopt_stale_listing(ino, &folder_uid, cached, primary_root);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,6 +278,7 @@ pub(crate) fn wait_until(limit: Duration, mut done: impl FnMut() -> bool) -> boo
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::sim::fake_drive::{Entry, FakeDrive, Faults};
|
use crate::sim::fake_drive::{Entry, FakeDrive, Faults};
|
||||||
|
use pdfs_core::control::RefreshScope;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -644,6 +645,49 @@ mod tests {
|
|||||||
let _ = std::fs::remove_dir_all(&dir);
|
let _ = std::fs::remove_dir_all(&dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse sim:: -- --ignored`"]
|
||||||
|
fn a_folder_whose_mkdir_is_queued_lists_after_a_refresh() {
|
||||||
|
// Once its listing was dropped, the folder was asked of Drive by its
|
||||||
|
// stand-in, and every listing and lookup in it failed with EIO until
|
||||||
|
// its mkdir landed (B125).
|
||||||
|
let drive = FakeDrive::new();
|
||||||
|
let dir = scratch("queued-folder-refresh");
|
||||||
|
let daemon = Daemon::start(&dir, drive.client(1, Faults::lan())).unwrap();
|
||||||
|
let mnt = daemon.mountpoint.clone();
|
||||||
|
let paused = |paused| Request::SetSyncPaused {
|
||||||
|
paused,
|
||||||
|
until: None,
|
||||||
|
};
|
||||||
|
daemon.request(&paused(true)).unwrap();
|
||||||
|
std::fs::create_dir(mnt.join("d")).unwrap();
|
||||||
|
std::fs::write(mnt.join("d/f.txt"), b"queued").unwrap();
|
||||||
|
let path = mnt.join("d").to_string_lossy().into_owned();
|
||||||
|
let refresh = Request::Refresh {
|
||||||
|
scope: RefreshScope::Dir { path: path.clone() },
|
||||||
|
};
|
||||||
|
assert!(matches!(daemon.request(&refresh), Ok(Response::Ok { .. })));
|
||||||
|
let Ok(Response::Entries { entries }) = daemon.request(&Request::ListDir { path }) else {
|
||||||
|
panic!("the daemon did not list d");
|
||||||
|
};
|
||||||
|
let names: Vec<_> = entries.iter().map(|entry| entry.name.as_str()).collect();
|
||||||
|
assert_eq!(names, ["f.txt"]);
|
||||||
|
assert_eq!(std::fs::read(mnt.join("d/f.txt")).unwrap(), b"queued");
|
||||||
|
daemon.request(&paused(false)).unwrap();
|
||||||
|
assert!(
|
||||||
|
wait_until(Duration::from_secs(30), || {
|
||||||
|
daemon.pending().is_ok_and(|items| items.is_empty())
|
||||||
|
&& drive.tree().get("d/f.txt")
|
||||||
|
== Some(&Entry::File(Arc::new(b"queued".to_vec())))
|
||||||
|
}),
|
||||||
|
"{:?} {:?}",
|
||||||
|
daemon.pending(),
|
||||||
|
drive.tree()
|
||||||
|
);
|
||||||
|
assert!(matches!(daemon.stop(), Ok(MountOutcome::Shutdown)));
|
||||||
|
let _ = std::fs::remove_dir_all(&dir);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse sim:: -- --ignored`"]
|
#[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse sim:: -- --ignored`"]
|
||||||
fn a_file_moved_while_its_create_was_on_the_wire_keeps_its_new_name() {
|
fn a_file_moved_while_its_create_was_on_the_wire_keeps_its_new_name() {
|
||||||
|
|||||||
+12
-3
@@ -1344,7 +1344,7 @@ profile fails on it when it comes up, which depends on timing.
|
|||||||
|
|
||||||
## B125 — A folder made offline fails with `EIO` once its listing is invalidated
|
## B125 — A folder made offline fails with `EIO` once its listing is invalidated
|
||||||
|
|
||||||
**Status:** Open.
|
**Status:** Fixed.
|
||||||
**Found:** 2026-10-03, by the simulation runs (`sim::run`, profile one-client-flaky, seeds 3
|
**Found:** 2026-10-03, by the simulation runs (`sim::run`, profile one-client-flaky, seeds 3
|
||||||
and 4). Right after a restart, `rmdir y` (seed 3), and a write to a file in the client's folder
|
and 4). Right after a restart, `rmdir y` (seed 3), and a write to a file in the client's folder
|
||||||
(seed 4), failed with `EIO`. The daemon logged "enumerate folder children failed" with Drive's
|
(seed 4), failed with `EIO`. The daemon logged "enumerate folder children failed" with Drive's
|
||||||
@@ -1362,8 +1362,17 @@ uid. Drive answers 404, and every lookup in the folder fails with `EIO` until it
|
|||||||
Right after it lands, Drive may not list the new folder yet (the lag of B118). Then the listing
|
Right after it lands, Drive may not list the new folder yet (the lag of B118). Then the listing
|
||||||
fails with a 404 for the real uid too.
|
fails with a 404 for the real uid too.
|
||||||
|
|
||||||
**Test:** the simulation runs count it and go on. With `PDFS_SIM_KNOWN=fail` the flaky profile
|
**Fix.** A folder still known by its stand-in is listed from the database and never asked of
|
||||||
fails on it.
|
Drive. Until its mkdir lands the folder is only here; once it has, the database holds what Drive
|
||||||
|
does. The second case, a listing by the real uid that Drive does not show yet, needs a create
|
||||||
|
that landed without being read back: the read-back waits up to 1.25 s for Drive to list the
|
||||||
|
folder, longer than the lag of any simulation profile. The runs keep counting both until they
|
||||||
|
show neither again.
|
||||||
|
|
||||||
|
**Test:** `a_folder_whose_mkdir_is_queued_lists_after_a_refresh` in
|
||||||
|
`crates/pdfs-fuse/src/sim/daemon.rs`: with sync paused, a folder is made with a file in it, a
|
||||||
|
refresh drops its listing, and it is listed again. With `PDFS_SIM_KNOWN=fail` the flaky profile
|
||||||
|
fails on it in the simulation runs; seeds 3 and 4 no longer reach it since phase 3.
|
||||||
|
|
||||||
## B124 — After a replacing rename fails, the file it was replacing is gone from the mount
|
## B124 — After a replacing rename fails, the file it was replacing is gone from the mount
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ by its local id, in the queue, the stored tree and pins alike.
|
|||||||
- **A file read just as it reaches Drive no longer reads empty** (B179).
|
- **A file read just as it reaches Drive no longer reads empty** (B179).
|
||||||
- **Stopping the daemon no longer takes 10 seconds more than it needs** when an idle upload
|
- **Stopping the daemon no longer takes 10 seconds more than it needs** when an idle upload
|
||||||
worker missed the stop (B180).
|
worker missed the stop (B180).
|
||||||
|
- **A folder made while offline or with sync paused no longer fails with "Input/output
|
||||||
|
error"** once it is refreshed or the connection comes back (B125).
|
||||||
- **A file renamed just as its upload finished keeps its new name.** The mount no longer showed
|
- **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,
|
the old name, and a second rename no longer failed with "No such file or directory" (B152,
|
||||||
B172).
|
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 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
|
- **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).
|
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 B180.
|
- Fixes from the simulation and account runs since then: B125, B127 and B141 to B180.
|
||||||
- **Sync issues, first cut** (§6.2): refusals sorted into issues, shown at once in the app,
|
- **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`.
|
tray and CLI; Export button and `pdfs sync export`; `pdfs sync issues`.
|
||||||
|
|
||||||
@@ -89,8 +89,8 @@ Tracks `docs/MILESTONE-3.0.0.md`. Update it with every commit that moves a phase
|
|||||||
create was on the wire, which the mount showed under its old name (B161, fixed).
|
create was on the wire, which the mount showed under its old name (B161, fixed).
|
||||||
Seed 4 failed on a folder removed and made again, whose create adopted the removed
|
Seed 4 failed on a folder removed and made again, whose create adopted the removed
|
||||||
folder (B162, fixed). CI on 903452a passed every profile.
|
folder (B162, fixed). CI on 903452a passed every profile.
|
||||||
- [ ] Known-bug list in `sim/run.rs` is empty: B125 and B130 open; B127, B129 and B132 fixed
|
- [ ] Known-bug list in `sim/run.rs` is empty: B130 open; B125, B127, B129 and B132 fixed but
|
||||||
but unconfirmed.
|
unconfirmed.
|
||||||
- [ ] A clean account run. The one on a6f36d5 (2026-10-04, LAN: 427 passed, 12 failed)
|
- [ ] 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
|
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
|
the journal check. B121 was a bug (B149, fixed); B113's case still expected creates
|
||||||
|
|||||||
Reference in new issue
Block a user