]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
rust/bql: Ensure BQL locked early at BqlRefCell borrowing
authorZhao Liu <zhao1.liu@intel.com>
Thu, 13 Nov 2025 05:19:20 +0000 (13:19 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Sat, 27 Dec 2025 09:11:10 +0000 (10:11 +0100)
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 <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20251113051937.4017675-6-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
rust/bql/src/cell.rs

index f4bfa697d3227c3eff1e70ba635063b86b157e4a..b25906a6503e03ddf64bd717ac3f6b6471e33548 100644 (file)
 //! 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<T> {
     // for std::cell::BqlRefCell), so that we can use offset_of! on it.
     // UnsafeCell and repr(C) both prevent usage of niches.
     value: UnsafeCell<T>,
-    borrow: Cell<BorrowFlag>,
+    borrow: BqlCell<BorrowFlag>,
     // 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<T> BqlRefCell<T> {
     pub const fn new(value: T) -> BqlRefCell<T> {
         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<T> From<T> for BqlRefCell<T> {
 }
 
 struct BorrowRef<'b> {
-    borrow: &'b Cell<BorrowFlag>,
+    borrow: &'b BqlCell<BorrowFlag>,
 }
 
 impl<'b> BorrowRef<'b> {
     #[inline]
-    fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
+    fn new(borrow: &'b BqlCell<BorrowFlag>) -> Option<BorrowRef<'b>> {
         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<T: fmt::Display> fmt::Display for BqlRef<'_, T> {
 }
 
 struct BorrowRefMut<'b> {
-    borrow: &'b Cell<BorrowFlag>,
+    borrow: &'b BqlCell<BorrowFlag>,
 }
 
 impl<'b> BorrowRefMut<'b> {
     #[inline]
-    fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
+    fn new(borrow: &'b BqlCell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
         // 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() {