Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : /*
32 : : * Some notes on the tap_disk interface:
33 : : *
34 : : * tap_disk aims to provide a generic interface to easily implement new
35 : : * types of image accessors. The structure-of-function-calls is similar
36 : : * to disk interfaces used in qemu/denali/etc, with the significant
37 : : * difference being the expectation of asynchronous rather than synchronous
38 : : * I/O. The asynchronous interface is intended to allow lots of requests to
39 : : * be pipelined through a disk, without the disk requiring any of its own
40 : : * threads of control. As such, a batch of requests is delivered to the disk
41 : : * using:
42 : : *
43 : : * td_queue_[read,write]()
44 : : *
45 : : * and passing in a completion callback, which the disk is responsible for
46 : : * tracking. Disks should transform these requests as necessary and return
47 : : * the resulting iocbs to tapdisk using td_prep_[read,write]() and
48 : : * td_queue_tiocb().
49 : : *
50 : : * NOTE: tapdisk uses the number of sectors submitted per request as a
51 : : * ref count. Plugins must use the callback function to communicate the
52 : : * completion -- or error -- of every sector submitted to them.
53 : : *
54 : : * td_get_parent_id returns:
55 : : * 0 if parent id successfully retrieved
56 : : * TD_NO_PARENT if no parent exists
57 : : * -errno on error
58 : : */
59 : :
60 : : #ifndef _TAPDISK_H_
61 : : #define _TAPDISK_H_
62 : :
63 : : #include <time.h>
64 : : #include <stdint.h>
65 : :
66 : : #include "list.h"
67 : : #include "compiler.h"
68 : : #include "tapdisk-log.h"
69 : : #include "tapdisk-utils.h"
70 : : #include "tapdisk-stats.h"
71 : :
72 : : extern unsigned int PAGE_SIZE;
73 : : extern unsigned int PAGE_MASK;
74 : : extern unsigned int PAGE_SHIFT;
75 : :
76 : : #define MAX_SEGMENTS_PER_REQ 11
77 : : #define MAX_REQUESTS 32U
78 : : #define SECTOR_SHIFT 9
79 : : #define DEFAULT_SECTOR_SIZE 512
80 : :
81 : : #define TAPDISK_DATA_REQUESTS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ)
82 : :
83 : : //#define BLK_NOT_ALLOCATED (-99)
84 : : #define TD_NO_PARENT 1
85 : :
86 : : #define MAX_RAMDISK_SIZE 1024000 /*500MB disk limit*/
87 : :
88 : : enum TD_OPS{
89 : : TD_OP_READ = 0,
90 : : TD_OP_WRITE,
91 : : TD_OP_BLOCK_STATUS,
92 : : TD_OPS_END
93 : : };
94 : :
95 : : #define TD_OPEN_QUIET 0x00001
96 : : #define TD_OPEN_QUERY 0x00002
97 : : #define TD_OPEN_RDONLY 0x00004
98 : : #define TD_OPEN_STRICT 0x00008
99 : : #define TD_OPEN_SHAREABLE 0x00010
100 : : #define TD_OPEN_ADD_CACHE 0x00020
101 : : #define TD_OPEN_VHD_INDEX 0x00040
102 : : #define TD_OPEN_ADD_LOG 0x00080
103 : : #define TD_OPEN_LOCAL_CACHE 0x00100
104 : : #define TD_OPEN_REUSE_PARENT 0x00200
105 : : #define TD_OPEN_SECONDARY 0x00400
106 : : #define TD_OPEN_STANDBY 0x00800
107 : : #define TD_IGNORE_ENOSPC 0x01000
108 : : #define TD_OPEN_NO_O_DIRECT 0x02000
109 : : #define TD_USE_NEW_NBD 0x04000
110 : :
111 : : #define TD_CREATE_SPARSE 0x00001
112 : : #define TD_CREATE_MULTITYPE 0x00002
113 : :
114 : : #define td_flag_set(word, flag) ((word) |= (flag))
115 : : #define td_flag_clear(word, flag) ((word) &= ~(flag))
116 : : #define td_flag_test(word, flag) ((word) & (flag))
117 : :
118 : : #define TD_BLOCK_STATE_NONE 0
119 : : #define TD_BLOCK_STATE_HOLE (1 <<0)
120 : : #define TD_BLOCK_STATE_ZERO (1 <<1)
121 : :
122 : : typedef uint16_t td_uuid_t;
123 : : typedef uint32_t td_flag_t;
124 : : typedef uint64_t td_sector_t;
125 : : typedef struct td_disk_id td_disk_id_t;
126 : : typedef struct td_disk_info td_disk_info_t;
127 : : typedef struct td_request td_request_t;
128 : : typedef struct td_driver_handle td_driver_t;
129 : : typedef struct td_image_handle td_image_t;
130 : : typedef struct td_sector_count td_sector_count_t;
131 : : typedef struct td_vbd_request td_vbd_request_t;
132 : : typedef struct td_vbd_handle td_vbd_t;
133 : :
134 : : /*
135 : : * Prototype of the callback to activate as requests complete.
136 : : */
137 : : typedef void (*td_callback_t)(td_request_t, int);
138 : : typedef void (*td_vreq_callback_t)(td_vbd_request_t*, int, void*, int);
139 : :
140 : : struct td_disk_id {
141 : : char *name;
142 : : int type;
143 : : int flags;
144 : : };
145 : :
146 : : struct td_disk_info {
147 : : td_sector_t size;
148 : : long sector_size;
149 : : uint32_t info;
150 : : };
151 : :
152 : : struct td_iovec {
153 : : void *base;
154 : : unsigned int secs;
155 : : };
156 : :
157 : : struct td_vbd_request {
158 : : int op;
159 : : td_sector_t sec;
160 : : struct td_iovec *iov;
161 : : int iovcnt;
162 : :
163 : : td_vreq_callback_t cb;
164 : : void *token;
165 : : void *data;
166 : : const char *name;
167 : :
168 : : int error;
169 : : int prev_error;
170 : :
171 : : int submitting;
172 : : int secs_pending;
173 : : int num_retries;
174 : : struct timeval ts;
175 : : struct timeval last_try;
176 : :
177 : : td_vbd_t *vbd;
178 : : struct list_head next;
179 : : struct list_head *list_head;
180 : : };
181 : :
182 : : struct td_request {
183 : : int op;
184 : : void *buf;
185 : :
186 : : int status;
187 : : td_sector_t sec;
188 : : int secs;
189 : :
190 : : td_image_t *image;
191 : :
192 : : td_callback_t cb;
193 : : void *cb_data;
194 : :
195 : : int sidx;
196 : : td_vbd_request_t *vreq;
197 : : };
198 : :
199 : : struct td_vbd_encryption
200 : : {
201 : : /* key size in octets */
202 : : uint8_t key_size;
203 : : uint8_t *encryption_key;
204 : : };
205 : :
206 : : /*
207 : : * Structure describing the interface to a virtual disk implementation.
208 : : * See note at the top of this file describing this interface.
209 : : */
210 : : struct tap_disk {
211 : : const char *disk_type;
212 : : td_flag_t flags;
213 : : int private_data_size;
214 : : int (*td_open) (td_driver_t *, const char *, struct td_vbd_encryption *encryption, td_flag_t);
215 : : int (*td_close) (td_driver_t *);
216 : : int (*td_get_parent_id) (td_driver_t *, td_disk_id_t *);
217 : : int (*td_validate_parent) (td_driver_t *, td_driver_t *, td_flag_t);
218 : : void (*td_queue_read) (td_driver_t *, td_request_t);
219 : : void (*td_queue_block_status)(td_driver_t *, td_request_t);
220 : : void (*td_queue_write) (td_driver_t *, td_request_t);
221 : : void (*td_debug) (td_driver_t *);
222 : : void (*td_stats) (td_driver_t *, td_stats_t *);
223 : :
224 : : /**
225 : : * Callback to produce RRD output.
226 : : *
227 : : * Return a positive integer on success, 0 if the RRD has not been updated,
228 : : * and -errno on failure.
229 : : */
230 : : int (*td_rrd) (td_driver_t *, char *buf,
231 : : int * const off, int * const size);
232 : : };
233 : :
234 : : struct td_sector_count {
235 : : td_sector_t rd;
236 : : td_sector_t wr;
237 : : };
238 : :
239 : : static inline void
240 : : td_sector_count_add(td_sector_count_t *s, td_sector_t v, int write)
241 : : {
242 [ - + ][ # # ]: 1 : if (write)
[ # # ]
243 : 0 : s->wr += v;
244 : : else
245 : 1 : s->rd += v;
246 : : }
247 : :
248 : : void td_panic(void);
249 : :
250 : : typedef struct tapdisk_extent
251 : : {
252 : : td_sector_t start;
253 : : td_sector_t length;
254 : : int flag;
255 : : struct tapdisk_extent *next;
256 : : } tapdisk_extent_t;
257 : :
258 : : typedef struct tapdisk_extents
259 : : {
260 : : tapdisk_extent_t *head;
261 : : tapdisk_extent_t *tail;
262 : : size_t count;
263 : : } tapdisk_extents_t;
264 : :
265 : : #endif
|