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 : : // Removed definition of MAX_SEGMENTS_PER_REQ from here. Use BLKIF_MAX_SEGMENTS_PER_REQUEST
77 : : // which must match the value in xen/io/blkif.h, trying to make it clear that these are
78 : : // the same thing.
79 : : #ifndef BLKIF_MAX_SEGMENTS_PER_REQUEST
80 : : #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
81 : : #endif
82 : : #define MAX_REQUESTS 32U
83 : : #define SECTOR_SHIFT 9
84 : : #define DEFAULT_SECTOR_SIZE 512
85 : :
86 : : #define TAPDISK_DATA_REQUESTS (MAX_REQUESTS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
87 : :
88 : : //#define BLK_NOT_ALLOCATED (-99)
89 : : #define TD_NO_PARENT 1
90 : :
91 : : #define MAX_RAMDISK_SIZE 1024000 /*500MB disk limit*/
92 : :
93 : : enum TD_OPS{
94 : : TD_OP_READ = 0,
95 : : TD_OP_WRITE,
96 : : TD_OP_BLOCK_STATUS,
97 : : TD_OPS_END
98 : : };
99 : :
100 : : #define TD_OPEN_QUIET 0x00001
101 : : #define TD_OPEN_QUERY 0x00002
102 : : #define TD_OPEN_RDONLY 0x00004
103 : : #define TD_OPEN_STRICT 0x00008
104 : : #define TD_OPEN_SHAREABLE 0x00010
105 : : #define TD_OPEN_ADD_CACHE 0x00020
106 : : #define TD_OPEN_VHD_INDEX 0x00040
107 : : #define TD_OPEN_ADD_LOG 0x00080
108 : : #define TD_OPEN_LOCAL_CACHE 0x00100
109 : : #define TD_OPEN_REUSE_PARENT 0x00200
110 : : #define TD_OPEN_SECONDARY 0x00400
111 : : #define TD_OPEN_STANDBY 0x00800
112 : : #define TD_IGNORE_ENOSPC 0x01000
113 : : #define TD_OPEN_NO_O_DIRECT 0x02000
114 : :
115 : : #define TD_CREATE_SPARSE 0x00001
116 : : #define TD_CREATE_MULTITYPE 0x00002
117 : :
118 : : #define td_flag_set(word, flag) ((word) |= (flag))
119 : : #define td_flag_clear(word, flag) ((word) &= ~(flag))
120 : : #define td_flag_test(word, flag) ((word) & (flag))
121 : :
122 : : #define TD_BLOCK_STATE_NONE 0
123 : : #define TD_BLOCK_STATE_HOLE (1 <<0)
124 : : #define TD_BLOCK_STATE_ZERO (1 <<1)
125 : :
126 : : typedef uint16_t td_uuid_t;
127 : : typedef uint32_t td_flag_t;
128 : : typedef uint64_t td_sector_t;
129 : : typedef struct td_disk_id td_disk_id_t;
130 : : typedef struct td_disk_info td_disk_info_t;
131 : : typedef struct td_request td_request_t;
132 : : typedef struct td_driver_handle td_driver_t;
133 : : typedef struct td_image_handle td_image_t;
134 : : typedef struct td_sector_count td_sector_count_t;
135 : : typedef struct td_vbd_request td_vbd_request_t;
136 : : typedef struct td_vbd_handle td_vbd_t;
137 : :
138 : : /*
139 : : * Prototype of the callback to activate as requests complete.
140 : : */
141 : : typedef void (*td_callback_t)(td_request_t, int);
142 : : typedef void (*td_vreq_callback_t)(td_vbd_request_t*, int, void*, int);
143 : :
144 : : struct td_disk_id {
145 : : char *name;
146 : : int type;
147 : : int flags;
148 : : };
149 : :
150 : : struct td_disk_info {
151 : : td_sector_t size;
152 : : long sector_size;
153 : : uint32_t info;
154 : : };
155 : :
156 : : struct td_iovec {
157 : : void *base;
158 : : unsigned int secs;
159 : : };
160 : :
161 : : struct td_vbd_request {
162 : : int op;
163 : : td_sector_t sec;
164 : : struct td_iovec *iov;
165 : : int iovcnt;
166 : :
167 : : td_vreq_callback_t cb;
168 : : void *token;
169 : : void *data;
170 : : const char *name;
171 : :
172 : : int error;
173 : : int prev_error;
174 : :
175 : : int submitting;
176 : : int secs_pending;
177 : : int num_retries;
178 : : struct timeval ts;
179 : : struct timeval last_try;
180 : : /* When "reading-through" the local cache, don't write back to the source */
181 : : bool skip_mirror;
182 : :
183 : : td_vbd_t *vbd;
184 : : struct list_head next;
185 : : struct list_head *list_head;
186 : : };
187 : :
188 : : struct td_request {
189 : : int op;
190 : : void *buf;
191 : :
192 : : int status;
193 : : td_sector_t sec;
194 : : int secs;
195 : :
196 : : td_image_t *image;
197 : :
198 : : td_callback_t cb;
199 : : void *cb_data;
200 : :
201 : : int sidx;
202 : : td_vbd_request_t *vreq;
203 : : };
204 : :
205 : : struct td_vbd_encryption
206 : : {
207 : : /* key size in octets */
208 : : uint8_t key_size;
209 : : uint8_t *encryption_key;
210 : : };
211 : :
212 : : /*
213 : : * Structure describing the interface to a virtual disk implementation.
214 : : * See note at the top of this file describing this interface.
215 : : */
216 : : struct tap_disk {
217 : : const char *disk_type;
218 : : td_flag_t flags;
219 : : int private_data_size;
220 : : int (*td_open) (td_driver_t *, const char *, struct td_vbd_encryption *encryption, td_flag_t);
221 : : int (*td_close) (td_driver_t *);
222 : : int (*td_get_parent_id) (td_driver_t *, td_disk_id_t *);
223 : : int (*td_validate_parent) (td_driver_t *, td_driver_t *, td_flag_t);
224 : : void (*td_queue_read) (td_driver_t *, td_request_t);
225 : : void (*td_queue_block_status)(td_driver_t *, td_request_t);
226 : : void (*td_queue_write) (td_driver_t *, td_request_t);
227 : : void (*td_debug) (td_driver_t *);
228 : : void (*td_stats) (td_driver_t *, td_stats_t *);
229 : :
230 : : /**
231 : : * Callback to produce RRD output.
232 : : *
233 : : * Return a positive integer on success, 0 if the RRD has not been updated,
234 : : * and -errno on failure.
235 : : */
236 : : int (*td_rrd) (td_driver_t *, char *buf,
237 : : int * const off, int * const size);
238 : : };
239 : :
240 : : struct td_sector_count {
241 : : td_sector_t rd;
242 : : td_sector_t wr;
243 : : };
244 : :
245 : : static inline void
246 : : td_sector_count_add(td_sector_count_t *s, td_sector_t v, int write)
247 : : {
248 [ - + ][ # # ]: 1 : if (write)
[ # # ]
249 : 0 : s->wr += v;
250 : : else
251 : 1 : s->rd += v;
252 : : }
253 : :
254 : : void td_panic(void);
255 : :
256 : : typedef struct tapdisk_extent
257 : : {
258 : : td_sector_t start;
259 : : td_sector_t length;
260 : : int flag;
261 : : struct tapdisk_extent *next;
262 : : } tapdisk_extent_t;
263 : :
264 : : typedef struct tapdisk_extents
265 : : {
266 : : tapdisk_extent_t *head;
267 : : tapdisk_extent_t *tail;
268 : : size_t count;
269 : : } tapdisk_extents_t;
270 : :
271 : : #endif
|