Don't danger_cast all pagecache Free calls, as they may fail their CAS due to pagecache relocation
@@ -1108,9 +1108,19 @@ impl Tree {
"root hoist from {} to {} failed: {:?}",
from, new_root_pid, cas
);
- self.pages
- .free(new_root_pid, new_root_ptr, guard)
- .map_err(|e| e.danger_cast())
+ let mut ptr = new_root_ptr.clone();
+ loop {
+ match self.pages.free(new_root_pid, ptr, guard) {
+ Ok(_) => break,
+ Err(Error::CasFailed(Some(actual_ptr))) => {
+ ptr = actual_ptr.clone()
+ }
+ Err(Error::CasFailed(None)) => panic!("somehow allocated child was already freed"),
+ Err(other) => return Err(other.danger_cast()),
+ }
+ }
+
+ Ok(())
}
}
