nixl_sys/descriptors/
xfer.rs1use super::*;
17use super::sync_manager::{BackendSyncable, SyncManager};
18use std::ops::{Index, IndexMut};
19use serde::{Serialize, Deserialize};
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
23pub struct XferDescriptor {
24 pub addr: usize,
25 pub len: usize,
26 pub dev_id: u64,
27}
28
29#[derive(Debug, Serialize, Deserialize)]
31struct XferDescData {
32 mem_type: MemType,
33 descriptors: Vec<XferDescriptor>,
34}
35
36impl BackendSyncable for XferDescData {
37 type Backend = NonNull<bindings::nixl_capi_xfer_dlist_s>;
38 type Error = NixlError;
39
40 fn sync_to_backend(&self, backend: &Self::Backend) -> Result<(), Self::Error> {
41 let status = unsafe { nixl_capi_xfer_dlist_clear(backend.as_ptr()) };
43 match status {
44 NIXL_CAPI_SUCCESS => {}
45 NIXL_CAPI_ERROR_INVALID_PARAM => return Err(NixlError::InvalidParam),
46 _ => return Err(NixlError::BackendError),
47 }
48
49 for desc in &self.descriptors {
51 let status = unsafe {
52 nixl_capi_xfer_dlist_add_desc(backend.as_ptr(), desc.addr as uintptr_t, desc.len, desc.dev_id)
53 };
54 match status {
55 NIXL_CAPI_SUCCESS => {}
56 NIXL_CAPI_ERROR_INVALID_PARAM => return Err(NixlError::InvalidParam),
57 _ => return Err(NixlError::BackendError),
58 }
59 }
60
61 Ok(())
62 }
63}
64
65pub struct XferDescList<'a> {
67 sync_mgr: SyncManager<XferDescData>,
68 _phantom: PhantomData<&'a dyn NixlDescriptor>,
69 mem_type: MemType,
70}
71
72impl<'a> XferDescList<'a> {
73 pub fn new(mem_type: MemType) -> Result<Self, NixlError> {
75 let mut dlist = ptr::null_mut();
76 let status = unsafe {
77 nixl_capi_create_xfer_dlist(mem_type as nixl_capi_mem_type_t, &mut dlist)
78 };
79
80 match status {
81 NIXL_CAPI_SUCCESS => {
82 let backend = unsafe { NonNull::new_unchecked(dlist) };
84 let data = XferDescData {
85 mem_type,
86 descriptors: Vec::new(),
87 };
88 let sync_mgr = SyncManager::new(data, backend);
89
90 Ok(Self {
91 sync_mgr,
92 _phantom: PhantomData,
93 mem_type,
94 })
95 }
96 NIXL_CAPI_ERROR_INVALID_PARAM => Err(NixlError::InvalidParam),
97 _ => Err(NixlError::FailedToCreateXferDlistHandle),
98 }
99 }
100
101 pub fn as_ptr(&self) -> *mut bindings::nixl_capi_xfer_dlist_s {
102 self.sync_mgr.backend().map(|b| b.as_ptr()).unwrap_or(ptr::null_mut())
103 }
104
105 pub fn get_type(&self) -> Result<MemType, NixlError> { Ok(self.mem_type) }
107
108 pub fn add_desc(&mut self, addr: usize, len: usize, dev_id: u64) {
110 self.sync_mgr.data_mut().descriptors.push(XferDescriptor { addr, len, dev_id });
111 }
112
113 pub fn is_empty(&self) -> Result<bool, NixlError> {
115 Ok(self.len()? == 0)
116 }
117
118 pub fn desc_count(&self) -> Result<usize, NixlError> { Ok(self.sync_mgr.data().descriptors.len()) }
120
121 pub fn len(&self) -> Result<usize, NixlError> { Ok(self.sync_mgr.data().descriptors.len()) }
123
124 pub fn trim(&mut self) {
126 self.sync_mgr.data_mut().descriptors.shrink_to_fit();
127 }
128
129 pub fn rem_desc(&mut self, index: i32) -> Result<(), NixlError> {
131 if index < 0 { return Err(NixlError::InvalidParam); }
132 let idx = index as usize;
133
134 let data = self.sync_mgr.data_mut();
135 if idx >= data.descriptors.len() {
136 return Err(NixlError::InvalidParam);
137 }
138 data.descriptors.remove(idx);
139 Ok(())
140 }
141
142 pub fn clear(&mut self) {
144 self.sync_mgr.data_mut().descriptors.clear();
145 }
146
147 pub fn print(&self) -> Result<(), NixlError> {
149 let backend = self.sync_mgr.backend()?;
150 let status = unsafe { nixl_capi_xfer_dlist_print(backend.as_ptr()) };
151 match status {
152 NIXL_CAPI_SUCCESS => Ok(()),
153 NIXL_CAPI_ERROR_INVALID_PARAM => Err(NixlError::InvalidParam),
154 _ => Err(NixlError::BackendError),
155 }
156 }
157
158 pub fn resize(&mut self, new_size: usize) {
160 self.sync_mgr.data_mut().descriptors.resize(new_size, XferDescriptor {
161 addr: 0,
162 len: 0,
163 dev_id: 0,
164 });
165 }
166
167 pub fn get(&self, index: usize) -> Result<&XferDescriptor, NixlError> {
169 self.sync_mgr.data().descriptors
170 .get(index)
171 .ok_or(NixlError::InvalidParam)
172 }
173
174 pub fn get_mut(&mut self, index: usize) -> Result<&mut XferDescriptor, NixlError> {
176 self.sync_mgr.data_mut().descriptors
177 .get_mut(index)
178 .ok_or(NixlError::InvalidParam)
179 }
180
181 pub fn add_storage_desc<D: NixlDescriptor + 'a>(
188 &mut self,
189 desc: &'a D,
190 ) -> Result<(), NixlError> {
191 let desc_mem_type = desc.mem_type();
193 let list_mem_type = if self.len().unwrap_or(0) > 0 { self.get_type().unwrap() } else { desc_mem_type };
194
195 if desc_mem_type != list_mem_type && list_mem_type != MemType::Unknown {
196 return Err(NixlError::InvalidParam);
197 }
198
199 let addr = unsafe { desc.as_ptr() } as usize;
201 let len = desc.size();
202 let dev_id = desc.device_id();
203
204 self.add_desc(addr, len, dev_id);
206 Ok(())
207 }
208
209 pub(crate) fn handle(&self) -> *mut bindings::nixl_capi_xfer_dlist_s {
210 self.sync_mgr.backend().map(|b| b.as_ptr()).unwrap_or(ptr::null_mut())
211 }
212
213 pub fn serialize(&self) -> Result<Vec<u8>, NixlError> {
215 bincode::serialize(self.sync_mgr.data()).map_err(|_| NixlError::BackendError)
217 }
218
219 pub fn deserialize(bytes: &[u8]) -> Result<Self, NixlError> {
221 let data: XferDescData = bincode::deserialize(bytes)
222 .map_err(|_| NixlError::FailedToCreateXferDlistHandle)?;
223
224 let mut list = XferDescList::new(data.mem_type)?;
225 for desc in data.descriptors {
226 list.add_desc(desc.addr, desc.len, desc.dev_id);
227 }
228
229 list.sync_mgr.backend()?;
231
232 Ok(list)
233 }
234}
235
236impl std::fmt::Debug for XferDescList<'_> {
237 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 let mem_type = self.get_type().unwrap_or(MemType::Unknown);
239 let len = self.len().unwrap_or(0);
240 let desc_count = self.desc_count().unwrap_or(0);
241
242 f.debug_struct("XferDescList")
243 .field("mem_type", &mem_type)
244 .field("len", &len)
245 .field("desc_count", &desc_count)
246 .finish()
247 }
248}
249
250impl PartialEq for XferDescList<'_> {
251 fn eq(&self, other: &Self) -> bool {
252 if self.mem_type != other.mem_type {
254 return false;
255 }
256
257 self.sync_mgr.data().descriptors == other.sync_mgr.data().descriptors
259 }
260}
261
262impl Index<usize> for XferDescList<'_> {
264 type Output = XferDescriptor;
265
266 fn index(&self, index: usize) -> &Self::Output {
267 &self.sync_mgr.data().descriptors[index]
268 }
269}
270
271impl IndexMut<usize> for XferDescList<'_> {
273 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
274 &mut self.sync_mgr.data_mut().descriptors[index]
276 }
277}
278
279impl Drop for XferDescList<'_> {
280 fn drop(&mut self) {
281 if let Ok(backend) = self.sync_mgr.backend() {
282 unsafe {
283 nixl_capi_destroy_xfer_dlist(backend.as_ptr());
284 }
285 }
286 }
287}