ublk_sys/
cmd.rs

1// SPDX-License-Identifier: MIT
2#![allow(dead_code)]
3#![allow(non_camel_case_types)]
4#![allow(clippy::missing_safety_doc)] // FIXME
5use libc::{__s32, __u16, __u32, __u64, __u8};
6
7/// Admin commands, issued by ublk server, and handled by ublk driver.
8pub const UBLK_CMD_GET_QUEUE_AFFINITY: u32 = 1;
9pub const UBLK_CMD_GET_DEV_INFO: u32 = 2;
10pub const UBLK_CMD_ADD_DEV: u32 = 4;
11pub const UBLK_CMD_DEL_DEV: u32 = 5;
12pub const UBLK_CMD_START_DEV: u32 = 6;
13pub const UBLK_CMD_STOP_DEV: u32 = 7;
14pub const UBLK_CMD_SET_PARAMS: u32 = 8;
15pub const UBLK_CMD_GET_PARAMS: u32 = 9;
16
17/// IO commands, issued by ublk server, and handled by ublk driver.
18///
19/// FETCH_REQ: issued via sqe(URING_CMD) beforehand for fetching IO request
20///      from ublk driver, should be issued only when starting device. After
21///      the associated cqe is returned, request's tag can be retrieved via
22///      cqe->userdata.
23///
24/// COMMIT_AND_FETCH_REQ: issued via sqe(URING_CMD) after ublkserver handled
25///      this IO request, request's handling result is committed to ublk
26///      driver, meantime FETCH_REQ is piggyback, and FETCH_REQ has to be
27///      handled before completing io request.
28///
29/// NEED_GET_DATA: only used for write requests to set io addr and copy data
30///      When NEED_GET_DATA is set, ublksrv has to issue UBLK_IO_NEED_GET_DATA
31///      command after ublk driver returns UBLK_IO_RES_NEED_GET_DATA.
32///
33///      It is only used if ublksrv set UBLK_F_NEED_GET_DATA flag while starting a ublk device.
34pub const UBLK_IO_FETCH_REQ: u32 = 32;
35pub const UBLK_IO_COMMIT_AND_FETCH_REQ: u32 = 33;
36pub const UBLK_IO_NEED_GET_DATA: u32 = 34;
37
38/// only ABORT means that no re-fetch
39pub const UBLK_IO_RES_OK: u32 = 0;
40pub const UBLK_IO_RES_NEED_GET_DATA: u32 = 1;
41pub const UBLK_IO_RES_ABORT: i32 = -libc::ENODEV;
42
43pub const UBLKSRV_CMD_BUF_OFFSET: u32 = 0;
44pub const UBLKSRV_IO_BUF_OFFSET: u32 = 0x80000000;
45
46/// tag bit is 12bit, so at most 4096 IOs for each queue
47pub const UBLK_MAX_QUEUE_DEPTH: u32 = 4096;
48
49/// zero copy requires 4k block size, and can remap ublk driver's io
50/// request into ublksrv's vm space
51pub const UBLK_F_SUPPORT_ZERO_COPY: u32 = 1 << 0;
52
53/// Force to complete io cmd via io_uring_cmd_complete_in_task so that
54/// performance comparison is done easily with using task_work_add
55pub const UBLK_F_URING_CMD_COMP_IN_TASK: u32 = 1 << 1;
56
57/// User should issue io cmd again for write requests to
58/// set io buffer address and copy data from bio vectors
59/// to the userspace io buffer.
60///
61/// In this mode, task_work is not used.
62pub const UBLK_F_NEED_GET_DATA: u32 = 1 << 2;
63
64/// device state
65pub const UBLK_S_DEV_DEAD: u32 = 0;
66pub const UBLK_S_DEV_LIVE: u32 = 1;
67
68/// shipped via sqe->cmd of io_uring command
69#[repr(C)]
70#[derive(Debug, Default, Copy, Clone)]
71pub struct ublksrv_ctrl_cmd {
72    /// sent to which device, must be valid
73    pub dev_id: __u32,
74    /// sent to which queue, must be -1 if the cmd isn't for queue
75    pub queue_id: __u16,
76    /// cmd specific buffer, can be IN or OUT
77    pub len: __u16,
78    pub addr: __u64,
79    /// inline data
80    pub data: [__u64; 2],
81}
82
83#[repr(C)]
84#[derive(Debug, Default, Copy, Clone)]
85pub struct ublksrv_ctrl_dev_info {
86    pub nr_hw_queues: __u16,
87    pub queue_depth: __u16,
88    pub state: __u16,
89    pub pad0: __u16,
90    pub max_io_buf_bytes: __u32,
91    pub dev_id: __u32,
92    pub ublksrv_pid: __s32,
93    pub pad1: __u32,
94    pub flags: __u64,
95    /// For ublksrv internal use, invisible to ublk driver
96    pub ublksrv_flags: __u64,
97    pub reserved0: __u64,
98    pub reserved1: __u64,
99    pub reserved2: __u64,
100}
101
102pub const UBLK_IO_OP_READ: u32 = 0;
103pub const UBLK_IO_OP_WRITE: u32 = 1;
104pub const UBLK_IO_OP_FLUSH: u32 = 2;
105pub const UBLK_IO_OP_DISCARD: u32 = 3;
106pub const UBLK_IO_OP_WRITE_SAME: u32 = 4;
107pub const UBLK_IO_OP_WRITE_ZEROES: u32 = 5;
108
109pub const UBLK_IO_F_FAILFAST_DEV: u32 = 1 << 8;
110pub const UBLK_IO_F_FAILFAST_TRANSPORT: u32 = 1 << 9;
111pub const UBLK_IO_F_FAILFAST_DRIVER: u32 = 1 << 10;
112pub const UBLK_IO_F_META: u32 = 1 << 11;
113pub const UBLK_IO_F_FUA: u32 = 1 << 13;
114pub const UBLK_IO_F_NOUNMAP: u32 = 1 << 15;
115pub const UBLK_IO_F_SWAP: u32 = 1 << 16;
116
117/// io cmd is described by this structure, and stored in share memory, indexed by request tag.
118///
119/// The data is stored by ublk driver, and read by ublksrv after one fetch command returns.
120#[repr(C)]
121#[derive(Debug, Default, Copy, Clone)]
122pub struct ublksrv_io_desc {
123    /// op: bit 0-7, flags: bit 8-31
124    pub op_flags: __u32,
125    pub nr_sectors: __u32,
126    /// start sector for this io
127    pub start_sector: __u64,
128    /// buffer address in ublksrv daemon vm space, from ublk driver
129    pub addr: __u64,
130}
131
132pub unsafe fn ublksrv_get_op(iod: *const ublksrv_io_desc) -> __u8 {
133    ((*iod).op_flags & 0xff) as __u8
134}
135
136pub unsafe fn ublksrv_get_flags(iod: *const ublksrv_io_desc) -> __u32 {
137    (*iod).op_flags >> 8
138}
139
140/// issued to ublk driver via /dev/ublkcN
141#[repr(C)]
142#[derive(Debug, Default, Copy, Clone)]
143pub struct ublksrv_io_cmd {
144    pub q_id: __u16,
145    /// for fetch/commit which result
146    pub tag: __u16,
147    /// io result, it is valid for COMMIT* command only
148    pub result: __s32,
149    /// userspace buffer address in ublksrv daemon process, valid for * FETCH* command only
150    pub addr: __u64,
151}
152
153pub const UBLK_ATTR_READ_ONLY: u32 = 1 << 0;
154pub const UBLK_ATTR_ROTATIONAL: u32 = 1 << 1;
155pub const UBLK_ATTR_VOLATILE_CACHE: u32 = 1 << 2;
156pub const UBLK_ATTR_FUA: u32 = 1 << 3;
157
158#[repr(C)]
159#[derive(Debug, Default, Copy, Clone)]
160pub struct ublk_param_basic {
161    pub attrs: __u32,
162    pub logical_bs_shift: __u8,
163    pub physical_bs_shift: __u8,
164    pub io_opt_shift: __u8,
165    pub io_min_shift: __u8,
166    pub max_sectors: __u32,
167    pub chunk_sectors: __u32,
168    pub dev_sectors: __u64,
169    pub virt_boundary_mask: __u64,
170}
171
172#[repr(C)]
173#[derive(Debug, Default, Copy, Clone)]
174pub struct ublk_param_discard {
175    pub discard_alignment: __u32,
176    pub discard_granularity: __u32,
177    pub max_discard_sectors: __u32,
178    pub max_write_zeroes_sectors: __u32,
179    pub max_discard_segments: __u16,
180    pub reserved0: __u16,
181}
182
183pub const UBLK_PARAM_TYPE_BASIC: u32 = 1 << 0;
184pub const UBLK_PARAM_TYPE_DISCARD: u32 = 1 << 1;
185
186#[repr(C)]
187#[derive(Debug, Default, Copy, Clone)]
188pub struct ublk_params {
189    /// Total length of parameters, userspace has to set 'len' for both
190    /// SET_PARAMS and GET_PARAMS command, and driver may update len
191    /// if two sides use different version of 'ublk_params', same with
192    /// 'types' fields.
193    pub len: __u32,
194    pub types: __u32,
195    pub basic: ublk_param_basic,
196    pub discard: ublk_param_discard,
197}