forked from ublk-org/ublksrv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathublksrv_tgt.h
135 lines (109 loc) · 3.31 KB
/
ublksrv_tgt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// SPDX-License-Identifier: MIT or GPL-2.0-only
#ifndef UBLKSRV_TGT_INC_H
#define UBLKSRV_TGT_INC_H
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <libgen.h>
#include <coroutine>
#include <iostream>
#include <type_traits>
#include "ublksrv_utils.h"
#include "ublksrv.h"
#define ublk_assert(x) do { \
if (!(x)) { \
syslog(LOG_ERR, "%s %d: assert!\n", __func__, __LINE__); \
assert(x); \
} \
} while (0)
static inline unsigned ilog2(unsigned x)
{
return sizeof(unsigned) * 8 - 1 - __builtin_clz(x);
}
#define MAX_NR_UBLK_DEVS 128
#define UBLKSRV_PID_DIR "/var/run/ublksrvd"
/* json device data is stored at this offset of pid file */
#define JSON_OFFSET 32
char *ublksrv_tgt_return_json_buf(struct ublksrv_dev *dev, int *size);
char *ublksrv_tgt_realloc_json_buf(struct ublksrv_dev *dev, int *size);
static inline unsigned ublksrv_convert_cmd_op(const struct ublksrv_io_desc *iod)
{
unsigned ublk_op = ublksrv_get_op(iod);
switch (ublk_op) {
case UBLK_IO_OP_READ:
return IORING_OP_READ;
case UBLK_IO_OP_WRITE:
return IORING_OP_WRITE;
case UBLK_IO_OP_FLUSH:
return IORING_OP_FSYNC;
case UBLK_IO_OP_DISCARD:
case UBLK_IO_OP_WRITE_SAME:
case UBLK_IO_OP_WRITE_ZEROES:
return IORING_OP_FALLOCATE;
default:
return -1;
}
}
/*
* Our convention is to use this macro instead of raw `co_await` to make it
* easy to log `tag` when debugging coroutine issues.
*/
#define co_await__suspend_always(tag) { \
static_assert(std::is_same<decltype(tag), int>::value, "tag not int");\
co_await std::suspend_always(); \
}
using co_handle_type = std::coroutine_handle<>;
struct co_io_job {
struct promise_type {
co_io_job get_return_object() {
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() {
return {};
}
std::suspend_never final_suspend() noexcept {
return {};
}
void return_void() {}
void unhandled_exception() {}
};
co_handle_type coro;
co_io_job(co_handle_type h): coro(h) {}
operator co_handle_type() const { return coro; }
};
struct ublk_io_tgt {
co_handle_type co;
const struct io_uring_cqe *tgt_io_cqe;
int queued_tgt_io; /* obsolete */
};
static inline struct ublk_io_tgt *__ublk_get_io_tgt_data(const struct ublk_io_data *io)
{
return (struct ublk_io_tgt *)io->private_data;
}
static inline struct ublk_io_tgt *ublk_get_io_tgt_data(
const struct ublksrv_queue *q, int tag)
{
return (struct ublk_io_tgt *)ublksrv_io_private_data(q, tag);
}
static inline void ublksrv_tgt_set_io_data_size(struct ublksrv_tgt_info *tgt)
{
tgt->io_data_size = sizeof(struct ublk_io_tgt);
}
//static_assert(sizeof(struct ublk_io_tgt) == sizeof(struct ublk_io), "ublk_io is defined as wrong");
enum {
/* evaluate communication cost, ublksrv_null vs /dev/nullb0 */
UBLKSRV_TGT_TYPE_NULL,
/* ublksrv_loop vs. /dev/loop */
UBLKSRV_TGT_TYPE_LOOP,
UBLKSRV_TGT_TYPE_QCOW2,
UBLKSRV_TGT_TYPE_MAX = 256,
};
extern int ublksrv_register_tgt_type(struct ublksrv_tgt_type *type);
extern void ublksrv_unregister_tgt_type(struct ublksrv_tgt_type *type);
#endif