Skip to main content

libublk_rs_sys/
lib.rs

1//! # libublk-rs-sys
2//!
3//! Low-level FFI bindings for the Linux ublk (userspace block device) kernel interface.
4//!
5//! This crate provides raw, unsafe bindings to the ublk kernel API. These bindings are
6//! automatically generated from the kernel headers using bindgen.
7//!
8//! ## Usage
9//!
10//! This is a `-sys` crate, which means it provides low-level FFI bindings without safe
11//! wrappers. If you're looking for a safe, high-level API, consider using the `libublk`
12//! crate instead.
13//!
14//! These bindings allow you to:
15//! - Issue ublk control commands to create/delete/manage ublk devices
16//! - Handle I/O operations on ublk queues
17//! - Configure device parameters
18//! - Use your own io_uring instance for handling ublk operations
19//!
20//! ## Example
21//!
22//! ```rust,no_run
23//! use libublk_rs_sys::*;
24//! use std::os::fd::AsRawFd;
25//!
26//! // Open the ublk control device
27//! let ctrl_fd = unsafe {
28//!     libc::open(
29//!         b"/dev/ublk-control\0".as_ptr() as *const i8,
30//!         libc::O_RDWR,
31//!     )
32//! };
33//!
34//! // Use the raw bindings with your own io_uring instance...
35//! ```
36//!
37//! ## Safety
38//!
39//! All functions and types in this crate are unsafe to use and require careful attention
40//! to the ublk kernel API documentation. Improper use can lead to undefined behavior,
41//! kernel panics, or data corruption.
42//!
43//! See the [Linux kernel documentation](https://docs.kernel.org/block/ublk.html) and
44//! the ublk header file for more information.
45
46#![allow(non_upper_case_globals)]
47#![allow(non_camel_case_types)]
48#![allow(non_snake_case)]
49#![allow(dead_code)]
50
51include!(concat!(env!("OUT_DIR"), "/ublk_cmd.rs"));
52
53/// Convert a packed u64 sqe address to an `ublk_auto_buf_reg` structure.
54///
55/// This function unpacks the automatic buffer registration data from the format
56/// used in io_uring sqe->addr field.
57///
58/// # Format
59/// - bits 0-15: buffer index
60/// - bits 16-23: flags
61/// - bits 24-31: reserved0
62/// - bits 32-63: reserved1
63#[inline(always)]
64pub fn ublk_sqe_addr_to_auto_buf_reg(sqe_addr: u64) -> ublk_auto_buf_reg {
65    ublk_auto_buf_reg {
66        index: sqe_addr as u16,
67        flags: (sqe_addr >> 16) as u8,
68        ..Default::default()
69    }
70}
71
72/// Convert an `ublk_auto_buf_reg` structure to a packed u64 sqe address.
73///
74/// This function packs automatic buffer registration data into the format
75/// used in io_uring sqe->addr field for `UBLK_F_AUTO_BUF_REG`.
76///
77/// # Format
78/// - bits 0-15: buffer index
79/// - bits 16-23: flags
80/// - bits 24-31: reserved0
81/// - bits 32-63: reserved1
82#[inline(always)]
83pub fn ublk_auto_buf_reg_to_sqe_addr(buf: &ublk_auto_buf_reg) -> u64 {
84    buf.index as u64
85        | (buf.flags as u64) << 16
86        | (buf.reserved0 as u64) << 24
87        | (buf.reserved1 as u64) << 32
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_auto_buf_reg_conversion() {
96        // Test round-trip conversion
97        let orig = ublk_auto_buf_reg {
98            index: 0x1234,
99            flags: 0xAB,
100            reserved0: 0xCD,
101            reserved1: 0xDEADBEEF,
102        };
103
104        let packed = ublk_auto_buf_reg_to_sqe_addr(&orig);
105        let unpacked = ublk_sqe_addr_to_auto_buf_reg(packed);
106
107        assert_eq!(unpacked.index, orig.index);
108        assert_eq!(unpacked.flags, orig.flags);
109        // Note: reserved fields are not preserved in the unpacking from sqe_addr
110        // as the current implementation uses Default::default() for them
111    }
112
113    #[test]
114    fn test_sqe_addr_packing() {
115        let buf = ublk_auto_buf_reg {
116            index: 0x00FF,
117            flags: 0x12,
118            reserved0: 0x34,
119            reserved1: 0x56789ABC,
120        };
121
122        let packed = ublk_auto_buf_reg_to_sqe_addr(&buf);
123
124        // Verify bit layout:
125        // bits 0-15: index (0x00FF)
126        // bits 16-23: flags (0x12)
127        // bits 24-31: reserved0 (0x34)
128        // bits 32-63: reserved1 (0x56789ABC)
129        assert_eq!(packed & 0xFFFF, 0x00FF);
130        assert_eq!((packed >> 16) & 0xFF, 0x12);
131        assert_eq!((packed >> 24) & 0xFF, 0x34);
132        assert_eq!((packed >> 32) & 0xFFFFFFFF, 0x56789ABC);
133    }
134}