Skip to content

Commit 23a1238

Browse files
bonziniBennoLossin
authored andcommitted
lib: revert InPlaceWrite implementation for Arc<MaybeUninit<T>>
The kernel version of pinned_init implemented InPlaceWrite on UniqueArc, not Arc. This ensures that InPlaceWrite is not writing to a shared Arc. Userspace does not have this facility and therefore cannot lift the kernel implementation of InPlaceWrite directly into Arc<>. One possibility would be to use Arc::get_mut(), though this would introduce a panic in the case where the Arc is shared. So just revert part of commit 6841b61 ("rust: init: add `write_[pin_]init` functions", 2024-11-22). Suggested-by: Benno Lossin <benno.lossin@proton.me> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 1769d7f commit 23a1238

File tree

1 file changed

+16
-27
lines changed

1 file changed

+16
-27
lines changed

src/lib.rs

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,15 +1225,29 @@ impl<T> InPlaceInit<T> for Arc<T> {
12251225
where
12261226
E: From<AllocError>,
12271227
{
1228-
Arc::try_new_uninit()?.write_pin_init(init)
1228+
let mut this = Arc::try_new_uninit()?;
1229+
let slot = unsafe { Arc::get_mut_unchecked(&mut this) };
1230+
let slot = slot.as_mut_ptr();
1231+
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1232+
// slot is valid and will not be moved, because we pin it later.
1233+
unsafe { init.__pinned_init(slot)? };
1234+
// SAFETY: All fields have been initialized and this is the only `Arc` to that data.
1235+
Ok(unsafe { Pin::new_unchecked(this.assume_init()) })
12291236
}
12301237

12311238
#[inline]
12321239
fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E>
12331240
where
12341241
E: From<AllocError>,
12351242
{
1236-
Arc::try_new_uninit()?.write_init(init)
1243+
let mut this = Arc::try_new_uninit()?;
1244+
let slot = unsafe { Arc::get_mut_unchecked(&mut this) };
1245+
let slot = slot.as_mut_ptr();
1246+
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1247+
// slot is valid.
1248+
unsafe { init.__init(slot)? };
1249+
// SAFETY: All fields have been initialized.
1250+
Ok(unsafe { this.assume_init() })
12371251
}
12381252
}
12391253

@@ -1276,31 +1290,6 @@ impl<T> InPlaceWrite<T> for Box<MaybeUninit<T>> {
12761290
}
12771291
}
12781292

1279-
#[cfg(feature = "alloc")]
1280-
impl<T> InPlaceWrite<T> for Arc<MaybeUninit<T>> {
1281-
type Initialized = Arc<T>;
1282-
1283-
fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
1284-
let slot = unsafe { Arc::get_mut_unchecked(&mut self) };
1285-
let slot = slot.as_mut_ptr();
1286-
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1287-
// slot is valid.
1288-
unsafe { init.__init(slot)? };
1289-
// SAFETY: All fields have been initialized.
1290-
Ok(unsafe { self.assume_init() })
1291-
}
1292-
1293-
fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
1294-
let slot = unsafe { Arc::get_mut_unchecked(&mut self) };
1295-
let slot = slot.as_mut_ptr();
1296-
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1297-
// slot is valid and will not be moved, because we pin it later.
1298-
unsafe { init.__pinned_init(slot)? };
1299-
// SAFETY: All fields have been initialized and this is the only `Arc` to that data.
1300-
Ok(unsafe { Pin::new_unchecked(self.assume_init()) })
1301-
}
1302-
}
1303-
13041293
/// Trait facilitating pinned destruction.
13051294
///
13061295
/// Use [`pinned_drop`] to implement this trait safely:

0 commit comments

Comments
 (0)