blob: 1deee2b3b7d442498009688810b0b2eab5aee1ac [file] [log] [blame]
Pavo Banicevic56d31872022-08-04 11:47:23 +02001// SPDX-License-Identifier: MIT or GPL-2.0-only
2
Ming Leifc0fc082022-06-28 17:21:49 +08003#ifndef UBLKSRV_TGT_INC_H
4#define UBLKSRV_TGT_INC_H
5
Ming Leic50e47e2022-11-30 03:38:25 +00006#include <unistd.h>
7#include <stdlib.h>
8#include <pthread.h>
9#include <getopt.h>
10#include <string.h>
11#include <stdarg.h>
Bart Trojanowski67f81a12023-06-28 13:46:19 +000012#include <limits.h>
Ming Leic50e47e2022-11-30 03:38:25 +000013#include <sys/types.h>
14#include <sys/stat.h>
15#include <sys/ioctl.h>
16
Ming Lei28eb5fb2022-07-25 03:37:01 +000017#include <libgen.h>
Ming Lei616d6e52022-07-02 09:56:22 +000018#include <coroutine>
19#include <iostream>
20#include <type_traits>
Ming Leifc0fc082022-06-28 17:21:49 +080021
Ming Leieb30b922022-11-30 03:39:59 +000022#include "ublksrv_utils.h"
Ming Lei49087ae2022-11-29 13:47:26 +000023#include "ublksrv.h"
Ming Lei616d6e52022-07-02 09:56:22 +000024
Ming Lei62327db2022-11-29 13:29:08 +000025#define ublk_assert(x) do { \
26 if (!(x)) { \
Ming Lei21bc3702023-02-04 12:46:31 +000027 ublk_err("%s %d: assert!\n", __func__, __LINE__); \
Ming Lei62327db2022-11-29 13:29:08 +000028 assert(x); \
29 } \
30} while (0)
31
32static inline unsigned ilog2(unsigned x)
33{
34 return sizeof(unsigned) * 8 - 1 - __builtin_clz(x);
35}
36
Ming Lei7dd7e1f2022-07-02 10:09:41 +000037#define MAX_NR_UBLK_DEVS 128
Ming Leie6300482022-11-16 00:56:03 +000038#define UBLKSRV_PID_DIR "/tmp/ublksrvd"
Ming Lei7dd7e1f2022-07-02 10:09:41 +000039
Ming Leic9034e52022-07-25 11:16:03 +000040/* json device data is stored at this offset of pid file */
41#define JSON_OFFSET 32
42
43char *ublksrv_tgt_return_json_buf(struct ublksrv_dev *dev, int *size);
44char *ublksrv_tgt_realloc_json_buf(struct ublksrv_dev *dev, int *size);
45
Ming Lei616d6e52022-07-02 09:56:22 +000046static inline unsigned ublksrv_convert_cmd_op(const struct ublksrv_io_desc *iod)
47{
48 unsigned ublk_op = ublksrv_get_op(iod);
49
50 switch (ublk_op) {
51 case UBLK_IO_OP_READ:
52 return IORING_OP_READ;
53 case UBLK_IO_OP_WRITE:
54 return IORING_OP_WRITE;
55 case UBLK_IO_OP_FLUSH:
56 return IORING_OP_FSYNC;
57 case UBLK_IO_OP_DISCARD:
58 case UBLK_IO_OP_WRITE_SAME:
59 case UBLK_IO_OP_WRITE_ZEROES:
60 return IORING_OP_FALLOCATE;
61 default:
62 return -1;
63 }
64}
65
Ming Lei616d6e52022-07-02 09:56:22 +000066/*
Alexey467d62f2022-12-30 15:34:49 -080067 * Our convention is to use this macro instead of raw `co_await` to make it
68 * easy to log `tag` when debugging coroutine issues.
Ming Lei616d6e52022-07-02 09:56:22 +000069 */
Alexey467d62f2022-12-30 15:34:49 -080070#define co_await__suspend_always(tag) { \
71 static_assert(std::is_same<decltype(tag), int>::value, "tag not int");\
72 co_await std::suspend_always(); \
73}
Ming Lei616d6e52022-07-02 09:56:22 +000074
75using co_handle_type = std::coroutine_handle<>;
76struct co_io_job {
77 struct promise_type {
78 co_io_job get_return_object() {
79 return {std::coroutine_handle<promise_type>::from_promise(*this)};
80 }
Alexey467d62f2022-12-30 15:34:49 -080081 std::suspend_never initial_suspend() {
Ming Lei616d6e52022-07-02 09:56:22 +000082 return {};
83 }
Alexey467d62f2022-12-30 15:34:49 -080084 std::suspend_never final_suspend() noexcept {
Ming Lei616d6e52022-07-02 09:56:22 +000085 return {};
86 }
87 void return_void() {}
88 void unhandled_exception() {}
89 };
90
91 co_handle_type coro;
92
Alexey467d62f2022-12-30 15:34:49 -080093 co_io_job(co_handle_type h): coro(h) {}
Ming Lei616d6e52022-07-02 09:56:22 +000094
95 operator co_handle_type() const { return coro; }
96};
97
Ming Lei616d6e52022-07-02 09:56:22 +000098struct ublk_io_tgt {
Ming Lei616d6e52022-07-02 09:56:22 +000099 co_handle_type co;
Ming Lei87d94062022-11-29 03:38:06 +0000100 const struct io_uring_cqe *tgt_io_cqe;
Ming Leia58faf02022-11-28 09:03:57 +0000101 int queued_tgt_io; /* obsolete */
Ming Lei616d6e52022-07-02 09:56:22 +0000102};
103
Ming Leifed9fe32022-11-29 03:20:05 +0000104static inline struct ublk_io_tgt *__ublk_get_io_tgt_data(const struct ublk_io_data *io)
Ming Leia58faf02022-11-28 09:03:57 +0000105{
106 return (struct ublk_io_tgt *)io->private_data;
107}
108
Ming Lei0e9a4b82022-11-29 00:58:38 +0000109static inline struct ublk_io_tgt *ublk_get_io_tgt_data(
110 const struct ublksrv_queue *q, int tag)
111{
112 return (struct ublk_io_tgt *)ublksrv_io_private_data(q, tag);
113}
114
Ming Lei76e0f1d2022-11-30 02:14:23 +0000115static inline void ublksrv_tgt_set_io_data_size(struct ublksrv_tgt_info *tgt)
116{
117 tgt->io_data_size = sizeof(struct ublk_io_tgt);
118}
119
Ming Leia58faf02022-11-28 09:03:57 +0000120//static_assert(sizeof(struct ublk_io_tgt) == sizeof(struct ublk_io), "ublk_io is defined as wrong");
Ming Leifc0fc082022-06-28 17:21:49 +0800121
Ming Lei10817922022-11-29 14:25:03 +0000122enum {
123 /* evaluate communication cost, ublksrv_null vs /dev/nullb0 */
124 UBLKSRV_TGT_TYPE_NULL,
125
126 /* ublksrv_loop vs. /dev/loop */
127 UBLKSRV_TGT_TYPE_LOOP,
128
129 UBLKSRV_TGT_TYPE_QCOW2,
130
Ming Lei7b9e0592023-01-19 10:48:50 +0000131 UBLKSRV_TGT_TYPE_NBD,
132
Ming Lei10817922022-11-29 14:25:03 +0000133 UBLKSRV_TGT_TYPE_MAX = 256,
134};
135extern int ublksrv_register_tgt_type(struct ublksrv_tgt_type *type);
136extern void ublksrv_unregister_tgt_type(struct ublksrv_tgt_type *type);
137
Ming Lei58a6af22023-01-08 14:53:00 +0000138enum {
139 UBLK_UNIQUE_TAG_BITS = 16,
140 UBLK_UNIQUE_TAG_MASK = (1 << UBLK_UNIQUE_TAG_BITS) - 1,
141};
142
143static inline unsigned int ublk_unique_tag(unsigned short hwq,
144 unsigned short tag)
145{
146 return (hwq << UBLK_UNIQUE_TAG_BITS) | (tag & UBLK_UNIQUE_TAG_MASK);
147}
148
149static inline unsigned short ublk_unique_tag_to_hwq(unsigned int unique_tag)
150{
151 return unique_tag >> UBLK_UNIQUE_TAG_BITS;
152}
153
154static inline unsigned short ublk_unique_tag_to_tag(unsigned int unique_tag)
155{
156 return unique_tag & UBLK_UNIQUE_TAG_MASK;
157}
158
Ming Leibe375652023-04-06 12:52:20 +0000159static inline bool ublk_param_is_valid(const struct ublk_params *p)
160{
161 if (p->basic.logical_bs_shift < 9 || p->basic.physical_bs_shift > 12)
162 return false;
163 if (p->basic.logical_bs_shift > p->basic.physical_bs_shift)
164 return false;
165 return true;
166}
167
Ming Leib6b14bc2023-04-27 09:12:26 +0000168int ublk_json_write_tgt_str(struct ublksrv_dev *dev, char **jbuf,
169 int *len, const char *name, const char *val);
170int ublk_json_write_tgt_long(struct ublksrv_dev *dev, char **jbuf,
171 int *len, const char *name, long val);
Ming Lei80dc0b22023-04-27 09:41:20 +0000172int ublk_json_write_tgt_ulong(struct ublksrv_dev *dev, char **jbuf,
173 int *len, const char *name, unsigned long val);
174int ublk_json_write_dev_info(struct ublksrv_dev *dev, char **jbuf, int *len);
175int ublk_json_write_params(struct ublksrv_dev *dev, char **jbuf, int *len,
176 const struct ublk_params *p);
177int ublk_json_write_target_base(struct ublksrv_dev *dev, char **jbuf, int *len,
178 const struct ublksrv_tgt_base_json *tgt);
Ming Leib6b14bc2023-04-27 09:12:26 +0000179
Ming Leie32fee02023-03-29 12:46:20 +0000180static inline void ublk_get_sqe_pair(struct io_uring *r,
181 struct io_uring_sqe **sqe, struct io_uring_sqe **sqe2)
182{
183 unsigned left = io_uring_sq_space_left(r);
184
185 if (left < 2)
186 io_uring_submit(r);
187 *sqe = io_uring_get_sqe(r);
188 if (sqe2)
189 *sqe2 = io_uring_get_sqe(r);
190}
191
Ming Leifc0fc082022-06-28 17:21:49 +0800192#endif