1use super::{MemoryDescription, Result, StorageError, StorageKind, actions, nixl::NixlDescriptor};
7use std::any::Any;
8use std::ptr::NonNull;
9
10#[derive(Debug)]
12pub struct SystemStorage {
13 ptr: NonNull<u8>,
14 len: usize,
15}
16
17unsafe impl Send for SystemStorage {}
18unsafe impl Sync for SystemStorage {}
19
20impl SystemStorage {
21 pub fn new(len: usize) -> Result<Self> {
23 if len == 0 {
24 return Err(StorageError::AllocationFailed(
25 "zero-sized allocations are not supported".into(),
26 ));
27 }
28
29 let mut ptr: *mut libc::c_void = std::ptr::null_mut();
30
31 let result = unsafe { libc::posix_memalign(&mut ptr, 4096, len) };
40 if result != 0 {
41 return Err(StorageError::AllocationFailed(format!(
42 "posix_memalign failed for size {}",
43 len
44 )));
45 }
46 let ptr = NonNull::new(ptr as *mut u8).ok_or_else(|| {
47 StorageError::AllocationFailed(format!("malloc failed for size {}", len))
48 })?;
49
50 unsafe {
52 std::ptr::write_bytes(ptr.as_ptr(), 0, len);
53 }
54
55 Ok(Self { ptr, len })
56 }
57
58 pub unsafe fn as_ptr(&self) -> *const u8 {
63 self.ptr.as_ptr()
64 }
65
66 pub unsafe fn as_mut_ptr(&mut self) -> *mut u8 {
72 self.ptr.as_ptr()
73 }
74}
75
76impl Drop for SystemStorage {
77 fn drop(&mut self) {
78 unsafe {
80 libc::free(self.ptr.as_ptr() as *mut libc::c_void);
81 }
82 }
83}
84
85impl MemoryDescription for SystemStorage {
86 fn addr(&self) -> usize {
87 self.ptr.as_ptr() as usize
88 }
89
90 fn size(&self) -> usize {
91 self.len
92 }
93
94 fn storage_kind(&self) -> StorageKind {
95 StorageKind::System
96 }
97
98 fn as_any(&self) -> &dyn Any {
99 self
100 }
101
102 fn nixl_descriptor(&self) -> Option<NixlDescriptor> {
103 None
104 }
105}
106
107impl super::nixl::NixlCompatible for SystemStorage {
109 fn nixl_params(&self) -> (*const u8, usize, nixl_sys::MemType, u64) {
110 (self.ptr.as_ptr(), self.len, nixl_sys::MemType::Dram, 0)
111 }
112}
113
114impl actions::Memset for SystemStorage {
115 fn memset(&mut self, value: u8, offset: usize, size: usize) -> Result<()> {
116 let end = offset
117 .checked_add(size)
118 .ok_or_else(|| StorageError::OperationFailed("memset: offset overflow".into()))?;
119 if end > self.len {
120 return Err(StorageError::OperationFailed(
121 "memset: offset + size > storage size".into(),
122 ));
123 }
124 unsafe {
125 let ptr = self.ptr.as_ptr().add(offset);
126 std::ptr::write_bytes(ptr, value, size);
127 }
128 Ok(())
129 }
130}
131
132impl actions::Slice for SystemStorage {
133 unsafe fn as_slice(&self) -> Result<&[u8]> {
134 Ok(unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len) })
140 }
141}