forked from open-iscsi/tcmu-runner
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibtcmu_common.h
164 lines (140 loc) · 6.31 KB
/
libtcmu_common.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* Copyright 2014, Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/*
* APIs for both libtcmu users and tcmu-runner plugins to use.
*/
#ifndef __LIBTCMU_COMMON_H
#define __LIBTCMU_COMMON_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
struct tcmu_device;
struct tgt_port;
struct tcmulib_cmd;
#define TCMU_NOT_HANDLED -1
#define TCMU_ASYNC_HANDLED -2
#define SENSE_BUFFERSIZE 96
#define CFGFS_ROOT "/sys/kernel/config/target"
#define CFGFS_CORE CFGFS_ROOT"/core"
/* Temporarily limit this to 32M */
#define VPD_MAX_UNMAP_LBA_COUNT (32 * 1024 * 1024)
#define VPD_MAX_UNMAP_BLOCK_DESC_COUNT 0x04
#define max(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
(void) (&_a == &_b); \
_a < _b ? _b : _a; })
#define min(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
(void) (&_a == &_b); \
_a < _b ? _a : _b; })
#define round_up(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
((_a + (_b - 1)) / _b) * _b; })
#define round_down(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
(_a - (_a % _b)); })
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define VPD_MAX_WRITE_SAME_LENGTH 0xFFFFFFFF
typedef void (*cmd_done_t)(struct tcmu_device *, struct tcmulib_cmd *, int);
struct tcmulib_cmd {
uint16_t cmd_id;
uint8_t *cdb;
struct iovec *iovec;
size_t iov_cnt;
uint8_t sense_buf[SENSE_BUFFERSIZE];
/*
* this is mostly used by compound operations as such operations
* need to carry some state around for multiple commands.
*/
void *cmdstate;
/* callback to finish/continue command processing */
cmd_done_t done;
};
/* Set/Get methods for the opaque tcmu_device */
void *tcmu_get_dev_private(struct tcmu_device *dev);
void tcmu_set_dev_private(struct tcmu_device *dev, void *priv);
void *tcmu_get_daemon_dev_private(struct tcmu_device *dev);
void tcmu_set_daemon_dev_private(struct tcmu_device *dev, void *priv);
int tcmu_get_dev_fd(struct tcmu_device *dev);
char *tcmu_get_dev_cfgstring(struct tcmu_device *dev);
void tcmu_set_dev_num_lbas(struct tcmu_device *dev, uint64_t num_lbas);
uint64_t tcmu_get_dev_num_lbas(struct tcmu_device *dev);
int tcmu_update_num_lbas(struct tcmu_device *dev, uint64_t new_size);
void tcmu_set_dev_block_size(struct tcmu_device *dev, uint32_t block_size);
uint32_t tcmu_get_dev_block_size(struct tcmu_device *dev);
void tcmu_set_dev_max_xfer_len(struct tcmu_device *dev, uint32_t len);
uint32_t tcmu_get_dev_max_xfer_len(struct tcmu_device *dev);
void tcmu_set_dev_opt_unmap_gran(struct tcmu_device *dev, uint32_t len);
uint32_t tcmu_get_dev_opt_unmap_gran(struct tcmu_device *dev);
void tcmu_set_dev_unmap_gran_align(struct tcmu_device *dev, uint32_t len);
uint32_t tcmu_get_dev_unmap_gran_align(struct tcmu_device *dev);
void tcmu_set_dev_write_cache_enabled(struct tcmu_device *dev, bool enabled);
bool tcmu_get_dev_write_cache_enabled(struct tcmu_device *dev);
void tcmu_set_dev_solid_state_media(struct tcmu_device *dev, bool solid_state);
bool tcmu_get_dev_solid_state_media(struct tcmu_device *dev);
struct tcmulib_handler *tcmu_get_dev_handler(struct tcmu_device *dev);
struct tcmur_handler *tcmu_get_runner_handler(struct tcmu_device *dev);
void tcmu_block_device(struct tcmu_device *dev);
void tcmu_unblock_device(struct tcmu_device *dev);
void tcmu_flush_device(struct tcmu_device *dev);
/* Helper routines for processing commands */
char *tcmu_get_cfgfs_str(const char *path);
int tcmu_set_cfgfs_str(const char *path, const char *val, int val_len);
int tcmu_get_cfgfs_int(const char *path);
int tcmu_set_cfgfs_ul(const char *path, unsigned long val);
int tcmu_get_attribute(struct tcmu_device *dev, const char *name);
bool tcmu_cfgfs_file_is_supported(struct tcmu_device *dev, const char *name);
int tcmu_exec_cfgfs_dev_action(struct tcmu_device *dev, const char *name,
unsigned long val);
long long tcmu_get_device_size(struct tcmu_device *dev);
char *tcmu_get_wwn(struct tcmu_device *dev);
int tcmu_get_cdb_length(uint8_t *cdb);
uint64_t tcmu_get_lba(uint8_t *cdb);
uint32_t tcmu_get_xfer_length(uint8_t *cdb);
off_t tcmu_compare_with_iovec(void *mem, struct iovec *iovec, size_t size);
size_t tcmu_seek_in_iovec(struct iovec *iovec, size_t count);
void tcmu_seek_in_cmd_iovec(struct tcmulib_cmd *cmd, size_t count);
void tcmu_zero_iovec(struct iovec *iovec, size_t iov_cnt);
size_t tcmu_memcpy_into_iovec(struct iovec *iovec, size_t iov_cnt, void *src, size_t len);
size_t tcmu_memcpy_from_iovec(void *dest, size_t len, struct iovec *iovec, size_t iov_cnt);
size_t tcmu_iovec_length(struct iovec *iovec, size_t iov_cnt);
bool char_to_hex(unsigned char *val, char c);
void tcmu_copy_cmd_sense_data(struct tcmulib_cmd *tocmd, struct tcmulib_cmd *fromcmd);
/* Basic implementations of mandatory SCSI commands */
int tcmu_set_sense_data(uint8_t *sense_buf, uint8_t key, uint16_t asc_ascq, uint32_t *info);
int tcmu_emulate_inquiry(struct tcmu_device *dev, struct tgt_port *port, uint8_t *cdb, struct iovec *iovec, size_t iov_cnt, uint8_t *sense);
int tcmu_emulate_start_stop(struct tcmu_device *dev, uint8_t *cdb, uint8_t *sense);
int tcmu_emulate_test_unit_ready(uint8_t *cdb, struct iovec *iovec, size_t iov_cnt, uint8_t *sense);
int tcmu_emulate_read_capacity_10(uint64_t num_lbas, uint32_t block_size, uint8_t *cdb,
struct iovec *iovec, size_t iov_cnt, uint8_t *sense);
int tcmu_emulate_read_capacity_16(uint64_t num_lbas, uint32_t block_size, uint8_t *cdb,
struct iovec *iovec, size_t iov_cnt, uint8_t *sense);
int tcmu_emulate_mode_sense(struct tcmu_device *dev, uint8_t *cdb,
struct iovec *iovec, size_t iov_cnt, uint8_t *sense);
int tcmu_emulate_mode_select(struct tcmu_device *dev, uint8_t *cdb,
struct iovec *iovec, size_t iov_cnt,
uint8_t *sense);
/* SCSI helpers */
void tcmu_cdb_debug_info(struct tcmu_device *dev, const struct tcmulib_cmd *cmd);
#ifdef __cplusplus
}
#endif
#endif