From: Zhao Liu Date: Thu, 13 Nov 2025 05:19:20 +0000 (+0800) Subject: rust/bql: Ensure BQL locked early at BqlRefCell borrowing X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0118c2d7e85536c6878aeca12765bd03f09f21ef;p=thirdparty%2Fqemu.git rust/bql: Ensure BQL locked early at BqlRefCell borrowing At present, BqlRefCell checks whether BQL is locked when it blocks BQL unlock (in bql_block_unlock). But the such check should be done earlier - at the beginning of BqlRefCell borrowing. So convert BqlRefCell::borrow field from Cell<> to BqlCell<>, to guarantee BQL is locked from the beginning when someone is trying to borrow BqlRefCell. Signed-off-by: Zhao Liu Link: https://lore.kernel.org/r/20251113051937.4017675-6-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini --- diff --git a/rust/bql/src/cell.rs b/rust/bql/src/cell.rs index f4bfa697d3..b25906a650 100644 --- a/rust/bql/src/cell.rs +++ b/rust/bql/src/cell.rs @@ -142,8 +142,10 @@ //! Multiple immutable borrows are allowed via [`borrow`](BqlRefCell::borrow), //! or a single mutable borrow via [`borrow_mut`](BqlRefCell::borrow_mut). The //! thread will panic if these rules are violated or if the BQL is not held. +#[cfg(feature = "debug_cell")] +use std::cell::Cell; use std::{ - cell::{Cell, UnsafeCell}, + cell::UnsafeCell, cmp::Ordering, fmt, marker::PhantomData, @@ -378,7 +380,7 @@ pub struct BqlRefCell { // for std::cell::BqlRefCell), so that we can use offset_of! on it. // UnsafeCell and repr(C) both prevent usage of niches. value: UnsafeCell, - borrow: Cell, + borrow: BqlCell, // Stores the location of the earliest currently active borrow. // This gets updated whenever we go from having zero borrows // to having a single borrow. When a borrow occurs, this gets included @@ -427,7 +429,7 @@ impl BqlRefCell { pub const fn new(value: T) -> BqlRefCell { BqlRefCell { value: UnsafeCell::new(value), - borrow: Cell::new(UNUSED), + borrow: BqlCell::new(UNUSED), #[cfg(feature = "debug_cell")] borrowed_at: Cell::new(None), } @@ -689,12 +691,12 @@ impl From for BqlRefCell { } struct BorrowRef<'b> { - borrow: &'b Cell, + borrow: &'b BqlCell, } impl<'b> BorrowRef<'b> { #[inline] - fn new(borrow: &'b Cell) -> Option> { + fn new(borrow: &'b BqlCell) -> Option> { let b = borrow.get().wrapping_add(1); if !is_reading(b) { // Incrementing borrow can result in a non-reading value (<= 0) in these cases: @@ -790,12 +792,12 @@ impl fmt::Display for BqlRef<'_, T> { } struct BorrowRefMut<'b> { - borrow: &'b Cell, + borrow: &'b BqlCell, } impl<'b> BorrowRefMut<'b> { #[inline] - fn new(borrow: &'b Cell) -> Option> { + fn new(borrow: &'b BqlCell) -> Option> { // There must currently be no existing references when borrow_mut() is // called, so we explicitly only allow going from UNUSED to UNUSED - 1. match borrow.get() {