ublk-cpp v0.1
A ublk library for std::execution.
Loading...
Searching...
No Matches
control.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
10#include "ublk/detail/retry.hpp"
11#include "ublk/detail/task.hpp"
12#include "ublk/raw.hpp"
13#include <cerrno>
14#include <condy.hpp>
15#include <system_error>
16
17namespace ublk {
18namespace detail {
19
20struct control_get_dev_info_t {
21 template <typename Sched, typename Alloc>
22 ex::task<void, TaskEnv<Sched, Alloc>> invoke(int fd, uint32_t dev_id,
23 ublksrv_ctrl_dev_info *info) {
24 DevPathBuf<ublksrv_ctrl_dev_info> buf(dev_id);
25 bool ok = co_await retry<Sched, Alloc>(
26 [&]() -> ex::task<bool, TaskEnv<Sched, Alloc>> {
27 int32_t r =
28 co_await (raw::get_dev_info2(fd, dev_id, &buf, sizeof(buf),
29 DEV_PATH_LEN) |
30 ex::upon_error([](std::error_code ec) noexcept {
31 return -ec.value();
32 }));
33 if (r >= 0) {
34 *info = buf.payload;
35 co_return true;
36 }
37 if (r == -EACCES) {
38 co_return false;
39 }
40 if (r == -EOPNOTSUPP) {
41 co_await raw::get_dev_info(fd, dev_id, info);
42 co_return true;
43 }
44 throw std::system_error(-r, std::generic_category(),
45 "get_dev_info2");
46 },
47 20, 100);
48 if (!ok) {
49 throw std::system_error(EACCES, std::generic_category(),
50 "get_dev_info2");
51 }
52 }
53};
54
55template <typename Sched, typename Alloc>
56inline ex::task<void, TaskEnv<Sched, Alloc>>
57cached_get_dev_info(int fd, uint32_t dev_id, ublksrv_ctrl_dev_info *info) {
58 const auto *dev_info = co_await ex::read_env(fetch_dev_info);
59 if (dev_info && dev_info->dev_id == dev_id) {
60 *info = *dev_info;
61 co_return;
62 }
63 co_await control_get_dev_info_t{}.invoke<Sched, Alloc>(fd, dev_id, info);
64}
65
66struct control_get_queue_affinity_t {
67 template <typename Sched, typename Alloc>
68 ex::task<void, TaskEnv<Sched, Alloc>>
69 invoke(int control_fd, uint32_t dev_id, uint16_t q_id, cpu_set_t *cpuset) {
70 ublksrv_ctrl_dev_info info;
71 co_await cached_get_dev_info<Sched, Alloc>(control_fd, dev_id, &info);
72 if (info.flags & UBLK_F_UNPRIVILEGED_DEV) {
73 DevPathBuf<cpu_set_t> buf(dev_id);
74 co_await raw::get_queue_affinity(control_fd, dev_id, q_id, &buf,
75 sizeof(buf), DEV_PATH_LEN);
76 *cpuset = buf.payload;
77 } else {
78 co_await raw::get_queue_affinity(control_fd, dev_id, q_id, cpuset);
79 }
80 }
81};
82
83template <typename Sched, typename Alloc, typename Fn>
84inline ex::task<void, TaskEnv<Sched, Alloc>>
85with_dev_path(int control_fd, uint32_t dev_id, Fn fn) {
86 ublksrv_ctrl_dev_info info;
87 char path[DEV_PATH_LEN];
88 fill_dev_path(path, sizeof(path), dev_id);
89 auto s = cached_get_dev_info<Sched, Alloc>(control_fd, dev_id, &info) |
90 ex::let_value([&, fn = std::move(fn)]() noexcept(
91 noexcept(std::move(fn)(path, DEV_PATH_LEN))) {
92 if (info.flags & UBLK_F_UNPRIVILEGED_DEV) {
93 return std::move(fn)(path, DEV_PATH_LEN);
94 } else {
95 return std::move(fn)(nullptr, 0);
96 }
97 });
98 co_await std::move(s);
99}
100
101struct control_del_dev_t {
102 template <typename Sched, typename Alloc>
103 auto invoke(int control_fd, uint32_t dev_id) {
104 return with_dev_path<Sched, Alloc>(
105 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
106 return raw::del_dev(control_fd, dev_id, path, len);
107 });
108 }
109};
110
111struct control_start_dev_t {
112 template <typename Sched, typename Alloc>
113 auto invoke(int control_fd, uint32_t dev_id, int32_t daemon_pid) {
114 return with_dev_path<Sched, Alloc>(
115 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
116 return raw::start_dev(control_fd, dev_id, daemon_pid, path,
117 len);
118 });
119 }
120};
121
122struct control_stop_dev_t {
123 template <typename Sched, typename Alloc>
124 auto invoke(int control_fd, uint32_t dev_id) {
125 return with_dev_path<Sched, Alloc>(
126 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
127 return raw::stop_dev(control_fd, dev_id, path, len);
128 });
129 }
130};
131
132struct control_set_params_t {
133 template <typename Sched, typename Alloc>
134 ex::task<void, TaskEnv<Sched, Alloc>>
135 invoke(int control_fd, uint32_t dev_id, const ublk_params *params) {
136 ublksrv_ctrl_dev_info info;
137 co_await cached_get_dev_info<Sched, Alloc>(control_fd, dev_id, &info);
138 ublk_params full = *params;
139 full.len = sizeof(full);
140 if (info.flags & UBLK_F_UNPRIVILEGED_DEV) {
141 DevPathBuf<ublk_params> buf(dev_id);
142 buf.payload = full;
143 co_await raw::set_params(control_fd, dev_id, &buf, sizeof(buf),
144 DEV_PATH_LEN);
145 } else {
146 co_await raw::set_params(control_fd, dev_id, &full);
147 }
148 }
149};
150
151struct control_get_params_t {
152 template <typename Sched, typename Alloc>
153 ex::task<void, TaskEnv<Sched, Alloc>>
154 invoke(int control_fd, uint32_t dev_id, ublk_params *params) {
155 ublksrv_ctrl_dev_info info;
156 co_await cached_get_dev_info<Sched, Alloc>(control_fd, dev_id, &info);
157 params->len = sizeof(*params);
158 if (info.flags & UBLK_F_UNPRIVILEGED_DEV) {
159 DevPathBuf<ublk_params> buf(dev_id);
160 buf.payload.len = sizeof(buf.payload);
161 co_await raw::get_params(control_fd, dev_id, &buf, sizeof(buf),
162 DEV_PATH_LEN);
163 *params = buf.payload;
164 } else {
165 co_await raw::get_params(control_fd, dev_id, params);
166 }
167 }
168};
169
170struct control_start_user_recovery_t {
171 template <typename Sched, typename Alloc>
172 auto invoke(int control_fd, uint32_t dev_id) {
173 return with_dev_path<Sched, Alloc>(
174 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
175 return raw::start_user_recovery(control_fd, dev_id, path, len);
176 });
177 }
178};
179
180struct control_end_user_recovery_t {
181 template <typename Sched, typename Alloc>
182 auto invoke(int control_fd, uint32_t dev_id, int32_t daemon_pid) {
183 return with_dev_path<Sched, Alloc>(
184 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
185 return raw::end_user_recovery(control_fd, dev_id, daemon_pid,
186 path, len);
187 });
188 }
189};
190
191struct control_del_dev_async_t {
192 template <typename Sched, typename Alloc>
193 auto invoke(int control_fd, uint32_t dev_id) {
194 return with_dev_path<Sched, Alloc>(
195 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
196 return raw::del_dev_async(control_fd, dev_id, path, len);
197 });
198 }
199};
200
201struct control_update_size_t {
202 template <typename Sched, typename Alloc>
203 auto invoke(int control_fd, uint32_t dev_id, uint64_t sectors) {
204 return with_dev_path<Sched, Alloc>(
205 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
206 return raw::update_size(control_fd, dev_id, sectors, path, len);
207 });
208 }
209};
210
211struct control_quiesce_dev_t {
212 template <typename Sched, typename Alloc>
213 auto invoke(int control_fd, uint32_t dev_id, uint64_t timeout_ms) {
214 return with_dev_path<Sched, Alloc>(
215 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
216 return raw::quiesce_dev(control_fd, dev_id, timeout_ms, path,
217 len);
218 });
219 }
220};
221
222struct control_try_stop_dev_t {
223 template <typename Sched, typename Alloc>
224 auto invoke(int control_fd, uint32_t dev_id) {
225 return with_dev_path<Sched, Alloc>(
226 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
227 return raw::try_stop_dev(control_fd, dev_id, path, len);
228 });
229 }
230};
231
232struct control_register_shm_buf_t {
233 template <typename Sched, typename Alloc>
234 ex::task<int32_t, TaskEnv<Sched, Alloc>>
235 invoke(int control_fd, uint32_t dev_id, const ublk_shmem_buf_reg *reg) {
236 ublksrv_ctrl_dev_info info;
237 co_await cached_get_dev_info<Sched, Alloc>(control_fd, dev_id, &info);
238 if (info.flags & UBLK_F_UNPRIVILEGED_DEV) {
239 DevPathBuf<ublk_shmem_buf_reg> buf(dev_id);
240 buf.payload = *reg;
241 co_return co_await raw::register_shm_buf(control_fd, dev_id, &buf,
242 sizeof(buf), DEV_PATH_LEN);
243 } else {
244 co_return co_await raw::register_shm_buf(control_fd, dev_id, reg);
245 }
246 }
247};
248
249struct control_unregister_shm_buf_t {
250 template <typename Sched, typename Alloc>
251 auto invoke(int control_fd, uint32_t dev_id, uint64_t buf_index) {
252 return with_dev_path<Sched, Alloc>(
253 control_fd, dev_id, [=](char *path, uint16_t len) noexcept {
254 return raw::unregister_shm_buf(control_fd, dev_id, buf_index,
255 path, len);
256 });
257 }
258};
259
260} // namespace detail
261} // namespace ublk
The std::execution backend namespace used by ublk-cpp.
auto start_user_recovery(Fd fd, uint32_t dev_id, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of start_user_recovery().
Definition raw.hpp:203
auto update_size(Fd fd, uint32_t dev_id, uint64_t sectors, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of update_size().
Definition raw.hpp:299
auto end_user_recovery(Fd fd, uint32_t dev_id, int32_t daemon_pid, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of end_user_recovery().
Definition raw.hpp:225
auto set_params(Fd fd, uint32_t dev_id, const void *data, uint16_t size, uint16_t dev_path_len) noexcept
Unprivileged version of set_params().
Definition raw.hpp:156
auto quiesce_dev(Fd fd, uint32_t dev_id, uint64_t timeout_ms, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of quiesce_dev().
Definition raw.hpp:322
auto start_dev(Fd fd, uint32_t dev_id, int32_t daemon_pid, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of start_dev().
Definition raw.hpp:111
auto register_shm_buf(Fd fd, uint32_t dev_id, const void *data, uint16_t size, uint16_t dev_path_len) noexcept
Unprivileged version of register_shm_buf().
Definition raw.hpp:368
auto try_stop_dev(Fd fd, uint32_t dev_id, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of try_stop_dev().
Definition raw.hpp:346
auto del_dev_async(Fd fd, uint32_t dev_id, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of del_dev_async().
Definition raw.hpp:277
auto unregister_shm_buf(Fd fd, uint32_t dev_id, uint64_t buf_index, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of unregister_shm_buf().
Definition raw.hpp:395
auto get_dev_info(Fd fd, uint32_t dev_id, void *data, uint16_t size, uint16_t dev_path_len) noexcept
Unprivileged version of get_dev_info().
Definition raw.hpp:52
auto stop_dev(Fd fd, uint32_t dev_id, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of stop_dev().
Definition raw.hpp:135
auto get_dev_info2(Fd fd, uint32_t dev_id, void *data, uint16_t size, uint16_t dev_path_len) noexcept
Get the device information of a ublk device, works both for privileged and unprivileged modes.
Definition raw.hpp:253
auto del_dev(Fd fd, uint32_t dev_id, const char *dev_path, uint16_t dev_path_len) noexcept
Unprivileged version of del_dev().
Definition raw.hpp:90
auto get_params(Fd fd, uint32_t dev_id, void *data, uint16_t size, uint16_t dev_path_len) noexcept
Unprivileged version of get_params().
Definition raw.hpp:180
auto get_queue_affinity(Fd fd, uint32_t dev_id, uint16_t q_id, void *data, uint16_t size, uint16_t dev_path_len) noexcept
Unprivileged version of get_queue_affinity().
Definition raw.hpp:26
The main namespace of the ublk-cpp library.
Definition ublk.hpp:21
constexpr fetch_dev_info_t fetch_dev_info
Query object instance of fetch_dev_info_t.
Definition query.hpp:45
Path related helpers.
Low-level io_uring command senders for ublk control and I/O commands.
Task environment utils.