mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 16:56:59 +01:00
fix(fuse): keep inode stable across rename
relocate() called forget(), dropping the node's by_uid mapping, so the re-enumeration assigned a fresh inode. The kernel had already carried the renamed dentry onto the old one and holds it for the entry TTL, so lookup/getattr/opendir resolved to an inode entries no longer held and returned ENOENT — while readdir walked children and reported the new inode. A renamed directory listed in its parent but could not be entered until the TTL expired. Rewrite the node in place and invalidate both parents' listings instead. Also stops the moved node's DB row being deleted and recreated on every move, which the B1 data-loss fix worked around
This commit is contained in:
1 parent
f9250211b8
commit
532628456e
14 files changed
+1302
-244
No files matched your search
@@ -90,7 +90,11 @@ impl Db {
|
||||
/// pass over a large cache does not read every row to drop a few, and so the
|
||||
/// `(kind, last_accessed)` index can answer it as a range scan with an early
|
||||
/// stop.
|
||||
pub fn cache_eviction_candidates(&self, kind: &str, limit: usize) -> Result<Vec<(String, u64)>> {
|
||||
pub fn cache_eviction_candidates(
|
||||
&self,
|
||||
kind: &str,
|
||||
limit: usize,
|
||||
) -> Result<Vec<(String, u64)>> {
|
||||
let conn = self.conn.lock();
|
||||
let mut stmt = conn.prepare_cached(
|
||||
"SELECT cache_key, size_bytes FROM cache_entries
|
||||
|
||||
@@ -373,7 +373,8 @@ fn children_if_listed_gated_on_flag() {
|
||||
fn a_deleted_child_leaves_a_listed_parent_serving_a_stale_listing() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
db.upsert_node(&folder("root", None, "My Files")).unwrap();
|
||||
db.upsert_node(&folder("dst", Some("root"), "dest")).unwrap();
|
||||
db.upsert_node(&folder("dst", Some("root"), "dest"))
|
||||
.unwrap();
|
||||
db.upsert_node(&file("f1", "root", "a.txt", 1)).unwrap();
|
||||
db.set_listed(&uid("dst"), true).unwrap();
|
||||
|
||||
@@ -1302,7 +1303,10 @@ fn next_due_op_respects_backoff() {
|
||||
let id = db.enqueue_op(&bulk_op(1, &root)).unwrap().0;
|
||||
db.record_op_failure(id, "boom", 5_000).unwrap();
|
||||
|
||||
assert!(db.next_due_op(4_999).unwrap().is_none(), "still backing off");
|
||||
assert!(
|
||||
db.next_due_op(4_999).unwrap().is_none(),
|
||||
"still backing off"
|
||||
);
|
||||
assert!(db.next_due_op(5_000).unwrap().is_some(), "due now");
|
||||
}
|
||||
|
||||
@@ -1362,7 +1366,9 @@ fn cache_total_bytes_agrees_with_summing_the_rows() {
|
||||
// query. The claim that matters — that the *common* path does not touch the
|
||||
// database at all — is pinned by `budget_check_is_free_when_under_budget`,
|
||||
// which compares against itself and so is load-independent.
|
||||
println!("B4: {rounds} budget checks over {N} entries — scan {scan:?}, aggregate {aggregate:?}");
|
||||
println!(
|
||||
"B4: {rounds} budget checks over {N} entries — scan {scan:?}, aggregate {aggregate:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// Victims still come out least-recently-accessed first, now in bounded batches
|
||||
|
||||
Reference in new issue
Block a user