Skip to main content

rdma_io/
mw.rs

1//! Memory Window — RAII wrapper for `ibv_mw`.
2//!
3//! Memory Windows provide fine-grained remote access control. A Type 2 MW
4//! can be bound to a sub-region of a Memory Region, giving remote peers
5//! scoped write access to only the bound range.
6
7use std::sync::Arc;
8
9use rdma_io_sys::ibverbs::*;
10use rdma_io_sys::wrapper::*;
11
12use crate::error::from_ptr;
13use crate::pd::ProtectionDomain;
14
15/// Memory Window type.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum MwType {
18    Type1 = 1,
19    Type2 = 2,
20}
21
22impl MwType {
23    /// Convert to the raw `ibv_mw_type` constant.
24    pub fn as_raw(self) -> u32 {
25        match self {
26            Self::Type1 => IBV_MW_TYPE_1,
27            Self::Type2 => IBV_MW_TYPE_2,
28        }
29    }
30}
31
32/// RAII wrapper for an RDMA Memory Window (`ibv_mw`).
33///
34/// Allocated via [`MemoryWindow::alloc`] and deallocated on [`Drop`].
35/// The PD is kept alive via `Arc` reference.
36pub struct MemoryWindow {
37    inner: *mut ibv_mw,
38    _pd: Arc<ProtectionDomain>,
39}
40
41// Safety: ibv_mw is a kernel-managed handle; safe to send/share across threads.
42unsafe impl Send for MemoryWindow {}
43unsafe impl Sync for MemoryWindow {}
44
45impl MemoryWindow {
46    /// Allocate a new Memory Window of the given type.
47    pub fn alloc(pd: &Arc<ProtectionDomain>, mw_type: MwType) -> crate::Result<Self> {
48        let mw = from_ptr(unsafe { rdma_wrap_ibv_alloc_mw(pd.as_raw(), mw_type.as_raw()) })?;
49        Ok(Self {
50            inner: mw,
51            _pd: Arc::clone(pd),
52        })
53    }
54
55    /// Remote key for this MW (valid after bind).
56    pub fn rkey(&self) -> u32 {
57        unsafe { (*self.inner).rkey }
58    }
59
60    /// Access the raw `ibv_mw` pointer.
61    pub fn as_raw(&self) -> *mut ibv_mw {
62        self.inner
63    }
64}
65
66impl Drop for MemoryWindow {
67    fn drop(&mut self) {
68        let ret = unsafe { rdma_wrap_ibv_dealloc_mw(self.inner) };
69        if ret != 0 {
70            tracing::error!("ibv_dealloc_mw failed: {}", std::io::Error::last_os_error());
71        }
72    }
73}
74
75impl std::fmt::Debug for MemoryWindow {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        f.debug_struct("MemoryWindow")
78            .field("rkey", &self.rkey())
79            .field("ptr", &self.inner)
80            .finish()
81    }
82}