1pub mod local;
2pub mod opencl;
3#[path = "ublk/server.rs"]
4mod server;
5
6pub use server::start_ublk_server;
7
8use anyhow::Result;
9pub trait VBuffer: Send + Sync {
10 fn read(&self, offset: u64, data: &mut [u8]) -> Result<()>;
12 fn write(&self, offset: u64, data: &[u8]) -> Result<()>;
14 fn remaining(&self, offset: u64) -> Option<usize>;
16 fn offset(&mut self, offset: u64);
18 fn size(&self) -> usize;
20}
21pub struct VMemory<T> {
22 vrams: Vec<T>,
23 size: u64,
24}
25
26unsafe impl<T: VBuffer> Send for VMemory<T> {}
27unsafe impl<T: VBuffer> Sync for VMemory<T> {}
28
29impl<T: VBuffer> VMemory<T> {
30 pub fn new(mut vrams: Vec<T>) -> Self {
31 let mut size: u64 = 0;
32 for i in vrams.iter_mut() {
33 i.offset(size);
34 size += i.size() as u64;
35 }
36 Self { vrams, size }
37 }
38
39 pub unsafe fn read(&self, offset: u64, length: usize, data: *mut u8) -> i32 {
42 let mut local_offset = 0;
43 let mut global_offset = offset;
44 let mut global_remaining = length;
45 for (i, vram) in self.vrams.iter().enumerate() {
46 let local_remaining = vram.remaining(global_offset);
47 if local_remaining.is_none() {
48 continue;
49 }
50 let local_length = global_remaining.min(local_remaining.unwrap());
52
53 let array = unsafe {
54 std::slice::from_raw_parts_mut(data.add(local_offset), local_length)
55 };
56 if let Err(e) = vram.read(global_offset, array) {
57 log::error!(
58 "Read error, device vram-{} offset {} size {}, code {}",
59 i,
60 global_offset,
61 local_length,
62 e
63 );
64 return -libc::EIO;
65 }
66
67 global_remaining -= local_length;
69 if global_remaining == 0 {
70 break;
71 }
72 local_offset += local_length;
73 global_offset += local_length as u64;
74 }
75 if global_remaining > 0 {
76 log::error!(
77 "Read error, offset {} size {}",
78 global_offset,
79 global_remaining
80 );
81 return -libc::EIO;
82 }
83 length as i32
84 }
85
86 pub unsafe fn write(&self, offset: u64, length: usize, data: *const u8) -> i32 {
89 let mut local_offset = 0;
90 let mut global_offset = offset;
91 let mut global_remaining = length;
92 for (i, vram) in self.vrams.iter().enumerate() {
93 let local_remaining = vram.remaining(global_offset);
94 if local_remaining.is_none() {
95 continue;
96 }
97 let local_length = global_remaining.min(local_remaining.unwrap());
99
100 let array = unsafe { std::slice::from_raw_parts(data.add(local_offset), local_length) };
101 if let Err(e) = vram.write(global_offset, array) {
102 log::error!(
103 "Write error, device vram-{} offset {} size {}, code {}",
104 i,
105 global_offset,
106 local_length,
107 e
108 );
109 return -libc::EIO;
110 }
111
112 global_remaining -= local_length;
114 if global_remaining == 0 {
115 break;
116 }
117 local_offset += local_length;
118 global_offset += local_length as u64;
119 }
120 if global_remaining > 0 {
121 log::error!(
122 "Read error, offset {} size {}",
123 global_offset,
124 global_remaining
125 );
126 return -libc::EIO;
127 }
128 length as i32
129 }
130
131 pub fn size(&self) -> u64 {
132 self.size
133 }
134 pub fn blocks(&self) -> usize {
135 self.vrams.len()
136 }
137}
138
139impl<T: VBuffer> From<Vec<T>> for VMemory<T> {
140 fn from(vrams: Vec<T>) -> Self {
141 VMemory::new(vrams)
142 }
143}