mirror of
https://github.com/Start9Labs/patch-db.git
synced 2026-03-26 02:11:54 +00:00
fix implicit locktype escalation
This commit is contained in:
committed by
Aiden McClelland
parent
0860275869
commit
70dc690437
@@ -315,6 +315,16 @@ impl LockOrderEnforcer {
|
|||||||
}
|
}
|
||||||
// locks must be acquired in lexicographic order for the pointer, and reverse order for type
|
// locks must be acquired in lexicographic order for the pointer, and reverse order for type
|
||||||
fn validate(&self, req: &LockInfo) -> Result<(), LockError> {
|
fn validate(&self, req: &LockInfo) -> Result<(), LockError> {
|
||||||
|
// the following notation is used to denote an example sequence that can cause deadlocks
|
||||||
|
//
|
||||||
|
// Individual Lock Requests
|
||||||
|
// 1W/A/B
|
||||||
|
// |||> Node whose lock is being acquired: /A/B (strings prefixed by slashes, indicating descent path)
|
||||||
|
// ||> Type of Lock: W (E/R/W)
|
||||||
|
// |> Session Number: 1 (any natural number)
|
||||||
|
//
|
||||||
|
// Sequences
|
||||||
|
// LockRequest >> LockRequest
|
||||||
match self.locks_held.get(&req.handle_id) {
|
match self.locks_held.get(&req.handle_id) {
|
||||||
None => Ok(()),
|
None => Ok(()),
|
||||||
Some(m) => {
|
Some(m) => {
|
||||||
@@ -329,35 +339,52 @@ impl LockOrderEnforcer {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let err = m.keys().find_map(|(ptr, ty)| {
|
let err = m.keys().find_map(|(ptr, ty)| match ptr.cmp(&req.ptr) {
|
||||||
match ptr.cmp(&req.ptr) {
|
std::cmp::Ordering::Less => {
|
||||||
std::cmp::Ordering::Less => None, // this is OK
|
if req.ptr.starts_with(ptr)
|
||||||
std::cmp::Ordering::Equal => {
|
&& req.ty == LockType::Write
|
||||||
if req.ty > *ty {
|
&& *ty == LockType::Read
|
||||||
Some(LockError::LockTypeEscalation {
|
{
|
||||||
session: req.handle_id.clone(),
|
// 1R/A >> 2R/A >> 1W/A/A >> 2W/A/B
|
||||||
ptr: ptr.clone(),
|
Some(LockError::LockTypeEscalationImplicit {
|
||||||
first: *ty,
|
|
||||||
second: req.ty,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cmp::Ordering::Greater => Some(if ptr.starts_with(&req.ptr) {
|
|
||||||
LockError::LockTaxonomyEscalation {
|
|
||||||
session: req.handle_id.clone(),
|
session: req.handle_id.clone(),
|
||||||
first: ptr.clone(),
|
first_ptr: ptr.clone(),
|
||||||
second: req.ptr.clone(),
|
first_type: *ty,
|
||||||
}
|
second_ptr: req.ptr.clone(),
|
||||||
|
second_type: req.ty,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
LockError::NonCanonicalOrdering {
|
None
|
||||||
session: req.handle_id.clone(),
|
}
|
||||||
first: ptr.clone(),
|
|
||||||
second: req.ptr.clone(),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
if req.ty > *ty {
|
||||||
|
// 1R/A >> 2R/A >> 1W/A >> 1W/A
|
||||||
|
Some(LockError::LockTypeEscalation {
|
||||||
|
session: req.handle_id.clone(),
|
||||||
|
ptr: ptr.clone(),
|
||||||
|
first: *ty,
|
||||||
|
second: req.ty,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cmp::Ordering::Greater => Some(if ptr.starts_with(&req.ptr) {
|
||||||
|
// 1W/A/A >> 2W/A/B >> 1R/A >> 2R/A
|
||||||
|
LockError::LockTaxonomyEscalation {
|
||||||
|
session: req.handle_id.clone(),
|
||||||
|
first: ptr.clone(),
|
||||||
|
second: req.ptr.clone(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 1W/A >> 2W/B >> 1W/B >> 2W/A
|
||||||
|
LockError::NonCanonicalOrdering {
|
||||||
|
session: req.handle_id.clone(),
|
||||||
|
first: ptr.clone(),
|
||||||
|
second: req.ptr.clone(),
|
||||||
|
}
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
err.map_or(Ok(()), Err)
|
err.map_or(Ok(()), Err)
|
||||||
}
|
}
|
||||||
@@ -1064,6 +1091,14 @@ pub enum LockError {
|
|||||||
first: LockType,
|
first: LockType,
|
||||||
second: LockType,
|
second: LockType,
|
||||||
},
|
},
|
||||||
|
#[error("Lock Type Escalation Implicit: Session = {session:?}, First = {first_ptr}:{first_type}, Second = {second_ptr}:{second_type}")]
|
||||||
|
LockTypeEscalationImplicit {
|
||||||
|
session: HandleId,
|
||||||
|
first_ptr: JsonPointer,
|
||||||
|
first_type: LockType,
|
||||||
|
second_ptr: JsonPointer,
|
||||||
|
second_type: LockType,
|
||||||
|
},
|
||||||
#[error(
|
#[error(
|
||||||
"Non-Canonical Lock Ordering: Session = {session:?}, First = {first}, Second = {second}"
|
"Non-Canonical Lock Ordering: Session = {session:?}, First = {first}, Second = {second}"
|
||||||
)]
|
)]
|
||||||
|
|||||||
Reference in New Issue
Block a user