metrale_gpu_sys/
cufile.rs1#![deny(warnings)]
13#![deny(clippy::all)]
14#![allow(non_camel_case_types, non_snake_case)]
15
16use libloading::{Library, Symbol};
17use std::ffi::{c_int, c_void};
18use std::os::raw::c_long;
19
20pub const CUFILEOP_BASE_ERR: i32 = 5000;
21pub const CU_FILE_SUCCESS: i32 = 0;
22pub const CU_FILE_DRIVER_NOT_INITIALIZED: i32 = CUFILEOP_BASE_ERR + 1;
23pub const CU_FILE_PLATFORM_NOT_SUPPORTED: i32 = CUFILEOP_BASE_ERR + 7;
24pub const CU_FILE_IO_NOT_SUPPORTED: i32 = CUFILEOP_BASE_ERR + 8;
25pub const CU_FILE_DEVICE_NOT_SUPPORTED: i32 = CUFILEOP_BASE_ERR + 9;
26
27pub const CU_FILE_HANDLE_TYPE_OPAQUE_FD: c_int = 1;
28
29pub type CUfileHandle_t = *mut c_void;
30pub type CUresult = c_int;
31pub type CUfileOpError = c_int;
32
33#[repr(C)]
34#[derive(Copy, Clone, Debug)]
35pub struct CUfileError_t {
36 pub err: CUfileOpError,
37 pub cu_err: CUresult,
38}
39
40#[repr(C)]
41pub struct CUfileDescrHandle {
42 pub fd: c_int,
43 _pad: [u8; 8 - core::mem::size_of::<c_int>()],
44}
45
46impl CUfileDescrHandle {
47 pub fn from_fd(fd: c_int) -> Self {
48 Self {
49 fd,
50 _pad: [0; 8 - core::mem::size_of::<c_int>()],
51 }
52 }
53}
54
55#[repr(C)]
56pub struct CUfileDescr_t {
57 pub type_: c_int,
58 pub handle: CUfileDescrHandle,
59 pub fs_ops: *const c_void,
60}
61
62pub type FnDriverOpen = unsafe extern "C" fn() -> CUfileError_t;
63pub type FnDriverClose = unsafe extern "C" fn() -> CUfileError_t;
64pub type FnHandleRegister =
65 unsafe extern "C" fn(*mut CUfileHandle_t, *mut CUfileDescr_t) -> CUfileError_t;
66pub type FnHandleDeregister = unsafe extern "C" fn(CUfileHandle_t);
67pub type FnBufRegister = unsafe extern "C" fn(*const c_void, libc::size_t, c_int) -> CUfileError_t;
68pub type FnBufDeregister = unsafe extern "C" fn(*const c_void) -> CUfileError_t;
69pub type FnRead = unsafe extern "C" fn(
70 CUfileHandle_t,
71 *mut c_void,
72 libc::size_t,
73 c_long,
74 c_long,
75) -> libc::ssize_t;
76pub type FnWrite = unsafe extern "C" fn(
77 CUfileHandle_t,
78 *const c_void,
79 libc::size_t,
80 c_long,
81 c_long,
82) -> libc::ssize_t;
83pub type FnGetVersion = unsafe extern "C" fn(*mut c_int) -> CUfileError_t;
84
85pub struct CuFile {
86 _lib: Library,
87 pub driver_open: FnDriverOpen,
88 pub driver_close: FnDriverClose,
89 pub handle_register: FnHandleRegister,
90 pub handle_deregister: FnHandleDeregister,
91 pub buf_register: FnBufRegister,
92 pub buf_deregister: FnBufDeregister,
93 pub read: FnRead,
94 pub write: FnWrite,
95 pub get_version: FnGetVersion,
96}
97
98const SEARCH_PATHS: &[&str] = &[
99 "libcufile.so.0",
100 "libcufile.so",
101 "/usr/local/cuda/targets/sbsa-linux/lib/libcufile.so.0",
102 "/usr/local/cuda/targets/x86_64-linux/lib/libcufile.so.0",
103 "/usr/local/cuda-13.0/targets/sbsa-linux/lib/libcufile.so.0",
104];
105
106impl CuFile {
107 pub fn load() -> Result<Self, String> {
108 let mut last_err = String::new();
109 for path in SEARCH_PATHS {
110 match unsafe { Library::new(path) } {
111 Ok(lib) => return Self::resolve(lib).map_err(|e| format!("{path}: {e}")),
112 Err(e) => last_err = format!("{path}: {e}"),
113 }
114 }
115 Err(format!("libcufile not found ({last_err})"))
116 }
117
118 fn resolve(lib: Library) -> Result<Self, String> {
119 unsafe fn sym<'a, T: Copy + 'a>(lib: &'a Library, name: &[u8]) -> Result<T, String> {
120 unsafe {
121 let s: Symbol<'a, T> = lib
122 .get(name)
123 .map_err(|e| format!("symbol {}: {e}", String::from_utf8_lossy(name)))?;
124 Ok(*s)
125 }
126 }
127 unsafe {
128 let driver_open = sym::<FnDriverOpen>(&lib, b"cuFileDriverOpen\0")?;
129 let driver_close = sym::<FnDriverClose>(&lib, b"cuFileDriverClose\0")?;
130 let handle_register = sym::<FnHandleRegister>(&lib, b"cuFileHandleRegister\0")?;
131 let handle_deregister = sym::<FnHandleDeregister>(&lib, b"cuFileHandleDeregister\0")?;
132 let buf_register = sym::<FnBufRegister>(&lib, b"cuFileBufRegister\0")?;
133 let buf_deregister = sym::<FnBufDeregister>(&lib, b"cuFileBufDeregister\0")?;
134 let read = sym::<FnRead>(&lib, b"cuFileRead\0")?;
135 let write = sym::<FnWrite>(&lib, b"cuFileWrite\0")?;
136 let get_version = sym::<FnGetVersion>(&lib, b"cuFileGetVersion\0")?;
137 Ok(Self {
138 _lib: lib,
139 driver_open,
140 driver_close,
141 handle_register,
142 handle_deregister,
143 buf_register,
144 buf_deregister,
145 read,
146 write,
147 get_version,
148 })
149 }
150 }
151}
152
153pub fn err_to_str(err: CUfileOpError) -> &'static str {
154 match err {
155 0 => "success",
156 x if x == CU_FILE_DRIVER_NOT_INITIALIZED => "CU_FILE_DRIVER_NOT_INITIALIZED",
157 x if x == CU_FILE_PLATFORM_NOT_SUPPORTED => "CU_FILE_PLATFORM_NOT_SUPPORTED",
158 x if x == CU_FILE_IO_NOT_SUPPORTED => "CU_FILE_IO_NOT_SUPPORTED",
159 x if x == CU_FILE_DEVICE_NOT_SUPPORTED => "CU_FILE_DEVICE_NOT_SUPPORTED",
160 _ => "CU_FILE_OTHER_ERROR",
161 }
162}
163
164pub fn nvidia_fs_loaded() -> bool {
165 let modules = match std::fs::read_to_string("/proc/modules") {
166 Ok(s) => s,
167 Err(_) => return false,
168 };
169 modules
170 .lines()
171 .any(|l| l.starts_with("nvidia_fs ") || l.starts_with("nvidia-fs "))
172}