1#![allow(dead_code)]
3#![allow(non_camel_case_types)]
4#![allow(clippy::missing_safety_doc)] use crate::iouring;
7use crate::{__IncompleteArrayField, cmd, d};
8use libc::{__u64, c_char, c_int, c_long, c_uint, c_ulong, c_ulonglong, c_ushort, c_void};
9
10pub const MAX_NR_HW_QUEUES: u32 = 32;
11pub const MAX_QD: u32 = 1024;
12pub const MAX_BUF_SIZE: u32 = 1024 << 10;
13
14pub const DEF_NR_HW_QUEUES: u32 = 1;
15pub const DEF_QD: u32 = 256;
16pub const DEF_BUF_SIZE: u32 = 512 << 10;
17
18pub const UBLKSRV_SHM_DIR: &[u8; 8] = b"ublksrv\0";
19pub const UBLKSRV_SHM_SIZE: u32 = 1024;
20
21pub const UBLKSRV_F_HAS_IO_DAEMON: u32 = 1;
27
28pub const UBLKSRV_F_NEED_EVENTFD: u32 = 2;
31
32#[repr(C)]
39#[derive(Debug, Copy, Clone)]
40pub struct ublksrv_aio_ctx {
41 _private: [u8; 0],
42}
43
44#[repr(C)]
48#[derive(Debug, Copy, Clone)]
49pub struct ublksrv_dev_data {
50 pub dev_id: c_int,
51 pub max_io_buf_bytes: c_uint,
52 pub nr_hw_queues: c_ushort,
53 pub queue_depth: c_ushort,
54 pub tgt_type: *const c_char,
55 pub tgt_ops: *const ublksrv_tgt_type,
56 pub tgt_argc: c_int,
57 pub tgt_argv: *mut *mut c_char,
58 pub run_dir: *const c_char,
59 pub flags: c_ulong,
60 pub ublksrv_flags: c_ulong,
61 pub reserved: [c_ulong; 7],
62}
63d!(ublksrv_dev_data);
64
65#[repr(C)]
66#[derive(Debug, Copy, Clone)]
67pub struct ublksrv_ctrl_dev {
68 pub ring: iouring::io_uring,
69 pub ctrl_fd: c_int,
70 pub bs_shift: c_uint,
71 pub dev_info: cmd::ublksrv_ctrl_dev_info,
72 pub tgt_type: *const c_char,
73 pub tgt_ops: *const ublksrv_tgt_type,
74 pub run_dir: *const c_char,
77 pub tgt_argc: c_int,
78 pub tgt_argv: *mut *mut c_char,
79 pub queues_cpuset: *mut libc::cpu_set_t,
80}
81d!(ublksrv_ctrl_dev);
82
83pub const UBLKSRV_NEED_FETCH_RQ: u32 = 1 << 0;
84pub const UBLKSRV_NEED_COMMIT_RQ_COMP: u32 = 1 << 1;
85pub const UBLKSRV_IO_FREE: u32 = 1 << 2;
86pub const UBLKSRV_NEED_GET_DATA: u32 = 1 << 3;
87
88#[repr(C)]
89#[derive(Copy, Clone)]
90pub struct ublk_io {
91 pub buf_addr: *mut c_char,
92 pub flags: c_uint,
93 pub union: ublk_io_anon_union_ty,
94 pub tgt_io_cqe: *mut iouring::io_uring_cqe,
95 pub io_data: c_ulong,
96}
97d!(ublk_io);
98
99#[repr(C)]
100#[derive(Copy, Clone)]
101pub union ublk_io_anon_union_ty {
102 pub result: c_uint,
104 pub queued_tgt_io: c_int,
106}
107d!(ublk_io_anon_union_ty);
108
109pub const UBLKSRV_QUEUE_STOPPING: u32 = 1;
110pub const UBLKSRV_QUEUE_IDLE: u32 = 2;
111pub const UBLKSRV_NR_CTX_BATCH: u32 = 4;
112
113#[repr(C)]
114pub struct ublksrv_queue {
115 pub q_id: c_int,
116 pub q_depth: c_int,
117 pub private_data: *mut c_void,
118 pub io_cmd_buf: *mut c_char,
126 pub io_buf: *mut c_char,
127 pub cmd_inflight: c_uint,
128 pub tgt_io_inflight: c_uint,
129 pub state: c_uint,
130 pub efd: c_int,
132 pub tgt_ops: *const ublksrv_tgt_type,
134 pub ring: iouring::io_uring,
137 pub dev: *mut ublksrv_dev,
138 pub tid: c_uint,
139 pub nr_ctxs: c_int,
140 pub ctxs: [*mut ublksrv_aio_ctx; UBLKSRV_NR_CTX_BATCH as usize],
141 pub ios: __IncompleteArrayField<ublk_io>,
142}
143d!(ublksrv_queue);
144
145pub const UBLKSRV_TGT_MAX_FDS: u32 = 32;
146
147pub const UBLKSRV_TGT_TYPE_NULL: c_uint = 0;
150pub const UBLKSRV_TGT_TYPE_LOOP: c_uint = 1;
152pub const UBLKSRV_TGT_TYPE_MAX: c_uint = 256;
153
154#[repr(C)]
155#[derive(Debug, Copy, Clone)]
156pub struct ublksrv_tgt_info {
157 pub dev_size: c_ulonglong,
158 pub tgt_ring_depth: c_uint,
160 pub nr_fds: c_uint,
161 pub fds: [c_int; UBLKSRV_TGT_MAX_FDS as usize],
162 pub tgt_data: *mut c_void,
163 pub ops: *const ublksrv_tgt_type,
164}
165d!(ublksrv_tgt_info);
166
167#[repr(C)]
168#[derive(Debug, Copy, Clone)]
169pub struct ublksrv_tgt_type {
170 pub handle_io_async:
176 Option<unsafe extern "C" fn(arg1: *mut ublksrv_queue, tag: c_int) -> c_int>,
177
178 pub tgt_io_done:
181 Option<unsafe extern "C" fn(arg1: *mut ublksrv_queue, arg2: *mut iouring::io_uring_cqe)>,
182
183 pub handle_event: Option<unsafe extern "C" fn(arg1: *mut ublksrv_queue)>,
202
203 pub handle_io_background:
211 Option<unsafe extern "C" fn(arg1: *mut ublksrv_queue, nr_queued_io: c_int)>,
212
213 pub usage_for_add: Option<unsafe extern "C" fn()>,
218
219 pub init_tgt: Option<
222 unsafe extern "C" fn(
223 arg1: *mut ublksrv_dev,
224 type_: c_int,
225 argc: c_int,
226 argv: *mut *mut c_char,
227 ) -> c_int,
228 >,
229
230 pub deinit_tgt: Option<unsafe extern "C" fn(arg1: *mut ublksrv_dev)>,
232
233 pub alloc_io_buf:
234 Option<unsafe extern "C" fn(q: *mut ublksrv_queue, tag: c_int, size: c_int) -> *mut c_void>,
235 pub free_io_buf:
236 Option<unsafe extern "C" fn(q: *mut ublksrv_queue, buf: *mut c_void, tag: c_int)>,
237
238 pub type_: c_int,
239
240 pub ublk_flags: c_uint,
242 pub ublksrv_flags: c_uint,
244 pub extra_ios: c_int,
246 pub name: *const c_char,
248}
249d!(ublksrv_tgt_type);
250
251#[repr(C)]
252#[derive(Debug, Copy, Clone)]
253pub struct ublksrv_dev {
254 pub tgt: ublksrv_tgt_info,
255 pub __queues: [*mut ublksrv_queue; MAX_NR_HW_QUEUES as usize],
256 pub io_buf_start: *mut c_char,
257 pub thread: *mut libc::pthread_t,
258 pub cdev_fd: c_int,
259 pub pid_file_fd: c_int,
260 pub ctrl_dev: *const ublksrv_ctrl_dev,
261 pub target_data: *mut c_void,
262}
263d!(ublksrv_dev);
264
265pub unsafe fn ublksrv_get_iod(q: *const ublksrv_queue, tag: c_int) -> *mut cmd::ublksrv_io_desc {
266 let idx = tag as usize * std::mem::size_of::<cmd::ublksrv_io_desc>();
267 (*q).io_cmd_buf.add(idx) as *mut cmd::ublksrv_io_desc
268}
269
270pub unsafe fn build_user_data(
271 tag: c_uint,
272 op: c_uint,
273 tgt_data: c_uint,
274 is_target_io: c_uint,
275) -> __u64 {
276 assert!((tag >> 16 == 0) && (op >> 8 == 0) && (tgt_data >> 16 == 0));
277 tag as __u64 | (op << 16) as __u64 | (tgt_data << 24) as __u64 | (is_target_io as __u64) << 63
278}
279
280pub unsafe fn user_data_to_tag(user_data: __u64) -> c_int {
281 (user_data & 0xffff) as c_int
282}
283
284pub unsafe fn user_data_to_op(user_data: __u64) -> c_int {
285 ((user_data >> 16) & 0xff) as c_int
286}
287
288pub unsafe fn user_data_to_tgt_data(user_data: __u64) -> c_int {
289 ((user_data >> 24) & 0xffff) as c_int
290}
291
292extern "C" {
293 pub fn ublksrv_ctrl_deinit(dev: *mut ublksrv_ctrl_dev);
294 pub fn ublksrv_ctrl_init(data: *mut ublksrv_dev_data) -> *mut ublksrv_ctrl_dev;
295 pub fn ublksrv_ctrl_get_affinity(ctrl_dev: *mut ublksrv_ctrl_dev) -> c_int;
296 pub fn ublksrv_ctrl_add_dev(dev: *mut ublksrv_ctrl_dev) -> c_int;
297 pub fn ublksrv_ctrl_del_dev(dev: *mut ublksrv_ctrl_dev) -> c_int;
298 pub fn ublksrv_ctrl_get_info(dev: *mut ublksrv_ctrl_dev) -> c_int;
299 pub fn ublksrv_ctrl_stop_dev(dev: *mut ublksrv_ctrl_dev) -> c_int;
300 pub fn ublksrv_ctrl_dump(dev: *mut ublksrv_ctrl_dev, buf: *const c_char);
301 pub fn ublksrv_ctrl_start_dev(ctrl_dev: *mut ublksrv_ctrl_dev, daemon_pid: c_int) -> c_int;
302 pub fn ublksrv_ctrl_set_params(
303 dev: *mut ublksrv_ctrl_dev,
304 params: *mut cmd::ublk_params,
305 ) -> c_int;
306 pub fn ublksrv_ctrl_get_params(
307 dev: *mut ublksrv_ctrl_dev,
308 params: *mut cmd::ublk_params,
309 ) -> c_int;
310 pub fn ublksrv_dev_init(ctrl_dev: *const ublksrv_ctrl_dev) -> *mut ublksrv_dev;
311 pub fn ublksrv_dev_deinit(dev: *mut ublksrv_dev);
312}
313
314pub const UBLKSRV_TGT_NAME_MAX_LEN: u32 = 32;
316#[repr(C)]
317#[derive(Debug, Default, Copy, Clone)]
318pub struct ublksrv_tgt_base_json {
319 pub name: [c_char; UBLKSRV_TGT_NAME_MAX_LEN as usize],
320 pub type_: c_int,
321 pub dev_size: c_ulonglong,
322}
323
324extern "C" {
325 pub fn ublksrv_json_write_dev_info(
326 dev: *const ublksrv_ctrl_dev,
327 buf: *mut c_char,
328 len: c_int,
329 ) -> c_int;
330 pub fn ublksrv_json_read_dev_info(
331 json_buf: *const c_char,
332 info: *mut cmd::ublksrv_ctrl_dev_info,
333 ) -> c_int;
334 pub fn ublksrv_json_write_queue_info(
335 dev: *const ublksrv_ctrl_dev,
336 jbuf: *mut c_char,
337 len: c_int,
338 qid: c_int,
339 ubq_daemon_tid: c_int,
340 ) -> c_int;
341 pub fn ublksrv_json_read_queue_info(
342 jbuf: *const c_char,
343 qid: c_int,
344 tid: *mut c_uint,
345 affinity_buf: *mut c_char,
346 len: c_int,
347 ) -> c_int;
348 pub fn ublksrv_json_read_target_info(
349 jbuf: *const c_char,
350 tgt_buf: *mut c_char,
351 len: c_int,
352 ) -> c_int;
353 pub fn ublksrv_json_write_target_str_info(
354 jbuf: *mut c_char,
355 len: c_int,
356 name: *const c_char,
357 val: *const c_char,
358 ) -> c_int;
359 pub fn ublksrv_json_write_target_long_info(
360 jbuf: *mut c_char,
361 len: c_int,
362 name: *const c_char,
363 val: c_long,
364 ) -> c_int;
365 pub fn ublksrv_json_write_target_ulong_info(
366 jbuf: *mut c_char,
367 len: c_int,
368 name: *const c_char,
369 val: c_ulong,
370 ) -> c_int;
371 pub fn ublksrv_json_dump(jbuf: *const c_char);
372 pub fn ublksrv_json_read_target_base_info(
373 jbuf: *const c_char,
374 tgt: *mut ublksrv_tgt_base_json,
375 ) -> c_int;
376 pub fn ublksrv_json_write_target_base_info(
377 jbuf: *mut c_char,
378 len: c_int,
379 tgt: *const ublksrv_tgt_base_json,
380 ) -> c_int;
381 pub fn ublksrv_json_read_params(p: *mut cmd::ublk_params, jbuf: *const c_char) -> c_int;
382 pub fn ublksrv_json_write_params(
383 p: *const cmd::ublk_params,
384 jbuf: *mut c_char,
385 len: c_int,
386 ) -> c_int;
387 pub fn ublksrv_json_dump_params(jbuf: *const c_char) -> c_int;
388 pub fn ublksrv_json_get_length(jbuf: *const c_char) -> c_int;
389}
390
391pub unsafe fn ublksrv_queue_get_data(q: *const ublksrv_queue) -> *mut c_void {
392 (*q).private_data
393}
394
395extern "C" {
396 pub fn ublksrv_queue_init(
397 dev: *mut ublksrv_dev,
398 q_id: c_ushort,
399 nr_extra_ios: c_int,
400 queue_data: *mut c_void,
401 ) -> *mut ublksrv_queue;
402 pub fn ublksrv_queue_deinit(q: *mut ublksrv_queue);
403 pub fn ublksrv_queue_handled_event(q: *mut ublksrv_queue) -> c_int;
404 pub fn ublksrv_queue_send_event(q: *mut ublksrv_queue) -> c_int;
405 pub fn ublksrv_get_queue(dev: *const ublksrv_dev, q_id: c_int) -> *mut ublksrv_queue;
406 pub fn ublksrv_process_io(q: *mut ublksrv_queue) -> c_int;
407 pub fn ublksrv_complete_io(q: *mut ublksrv_queue, tag: c_uint, res: c_int) -> c_int;
408 pub fn ublksrv_register_tgt_type(type_: *mut ublksrv_tgt_type) -> c_int;
409 pub fn ublksrv_unregister_tgt_type(type_: *mut ublksrv_tgt_type);
410 pub fn ublksrv_for_each_tgt_type(
411 handle_tgt_type: Option<
412 unsafe extern "C" fn(idx: c_uint, type_: *const ublksrv_tgt_type, data: *mut c_void),
413 >,
414 data: *mut c_void,
415 );
416 pub fn ublksrv_find_tgt_type(name: *const c_char) -> *const ublksrv_tgt_type;
417 pub fn ublksrv_apply_oom_protection();
418}
419
420