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 : : #ifdef HAVE_CONFIG_H
32 : : #include "config.h"
33 : : #endif
34 : :
35 : : #include <signal.h>
36 : : #include <unistd.h>
37 : : #include <errno.h>
38 : :
39 : : #include "tapdisk.h"
40 : : #include "tapdisk-vbd.h"
41 : : #include "tapdisk-image.h"
42 : : #include "tapdisk-driver.h"
43 : : #include "tapdisk-server.h"
44 : : #include "tapdisk-interface.h"
45 : : #include "tapdisk-log.h"
46 : :
47 : : int
48 : 0 : td_load(td_image_t *image)
49 : : {
50 : : td_image_t *shared;
51 : : td_driver_t *driver;
52 : :
53 : 0 : shared = tapdisk_server_get_shared_image(image);
54 [ # # ]: 0 : if (!shared)
55 : : return -ENODEV;
56 : :
57 : 0 : driver = shared->driver;
58 [ # # ]: 0 : if (!driver)
59 : : return -EBADF;
60 : :
61 : 0 : driver->refcnt++;
62 : 0 : image->driver = driver;
63 : 0 : image->info = driver->info;
64 : :
65 : 0 : DPRINTF("loaded shared image %s (%d users, state: 0x%08x, type: %d)\n",
66 : : driver->name, driver->refcnt, driver->state, driver->type);
67 : 0 : return 0;
68 : : }
69 : :
70 : : int
71 : 0 : __td_open(td_image_t *image, struct td_vbd_encryption *encryption, td_disk_info_t *info)
72 : : {
73 : : int err;
74 : : td_driver_t *driver;
75 : :
76 : 0 : driver = image->driver;
77 [ # # ]: 0 : if (!driver) {
78 : 0 : driver = tapdisk_driver_allocate(image->type,
79 : 0 : image->name,
80 : : image->flags);
81 [ # # ]: 0 : if (!driver)
82 : : return -ENOMEM;
83 : :
84 [ # # ]: 0 : if (info) /* pre-seed driver->info for virtual drivers */
85 : 0 : driver->info = *info;
86 : : }
87 : :
88 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
89 : 0 : err = driver->ops->td_open(driver, image->name, encryption, image->flags);
90 [ # # ]: 0 : if (err) {
91 [ # # ]: 0 : if (!image->driver)
92 : 0 : tapdisk_driver_free(driver);
93 : 0 : return err;
94 : : }
95 : :
96 : 0 : td_flag_set(driver->state, TD_DRIVER_OPEN);
97 [ # # ]: 0 : DPRINTF("opened image %s (%d users, state: 0x%08x, type: %d, %s)\n",
98 : : driver->name, driver->refcnt + 1,
99 : : driver->state, driver->type,
100 : : td_flag_test(image->flags, TD_OPEN_RDONLY) ? "ro" : "rw");
101 : : }
102 : :
103 : 0 : image->driver = driver;
104 : 0 : image->info = driver->info;
105 : 0 : driver->refcnt++;
106 : 0 : return 0;
107 : : }
108 : :
109 : : int
110 : 0 : td_open(td_image_t *image, struct td_vbd_encryption *encryption)
111 : : {
112 : 0 : return __td_open(image, encryption, NULL);
113 : : }
114 : :
115 : : int
116 : 1 : td_close(td_image_t *image)
117 : : {
118 : : td_driver_t *driver;
119 : :
120 : 1 : driver = image->driver;
121 [ - + ]: 1 : if (!driver)
122 : : return -ENODEV;
123 : :
124 : 0 : driver->refcnt--;
125 [ # # ][ # # ]: 0 : if (!driver->refcnt && td_flag_test(driver->state, TD_DRIVER_OPEN)) {
126 : 0 : driver->ops->td_close(driver);
127 : 0 : td_flag_clear(driver->state, TD_DRIVER_OPEN);
128 : : }
129 : :
130 : 0 : DPRINTF("closed image %s (%d users, state: 0x%08x, type: %d)\n",
131 : : driver->name, driver->refcnt, driver->state, driver->type);
132 : :
133 : 0 : return 0;
134 : : }
135 : :
136 : : int
137 : 0 : td_get_parent_id(td_image_t *image, td_disk_id_t *id)
138 : : {
139 : : td_driver_t *driver;
140 : :
141 : 0 : driver = image->driver;
142 [ # # ]: 0 : if (!driver)
143 : : return -ENODEV;
144 : :
145 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN))
146 : : return -EBADF;
147 : :
148 : 0 : return driver->ops->td_get_parent_id(driver, id);
149 : : }
150 : :
151 : : int
152 : 0 : td_validate_parent(td_image_t *image, td_image_t *parent)
153 : : {
154 : : td_driver_t *driver, *pdriver;
155 : :
156 : 0 : driver = image->driver;
157 : 0 : pdriver = parent->driver;
158 [ # # ]: 0 : if (!driver || !pdriver)
159 : : return -ENODEV;
160 : :
161 [ # # ][ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN) ||
162 : 0 : !td_flag_test(pdriver->state, TD_DRIVER_OPEN))
163 : : return -EBADF;
164 : :
165 : 0 : return driver->ops->td_validate_parent(driver, pdriver, 0);
166 : : }
167 : :
168 : : void
169 : 0 : td_queue_write(td_image_t *image, td_request_t treq)
170 : : {
171 : : int err;
172 : : td_driver_t *driver;
173 : :
174 : 0 : driver = image->driver;
175 [ # # ]: 0 : if (!driver) {
176 : : err = -ENODEV;
177 : : goto fail;
178 : : }
179 : :
180 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
181 : : err = -EBADF;
182 : : goto fail;
183 : : }
184 : :
185 [ # # ]: 0 : if (!driver->ops->td_queue_write) {
186 : 0 : EPRINTF("Driver %s does not support write", driver->name);
187 : 0 : err = -EOPNOTSUPP;
188 : 0 : goto fail;
189 : : }
190 : :
191 : 0 : err = tapdisk_image_check_td_request(image, treq);
192 [ # # ]: 0 : if (err)
193 : : goto fail;
194 : :
195 : 0 : driver->ops->td_queue_write(driver, treq);
196 : :
197 : 0 : return;
198 : :
199 : : fail:
200 : 0 : td_complete_request(treq, err);
201 : : }
202 : :
203 : : void
204 : 0 : td_queue_read(td_image_t *image, td_request_t treq)
205 : : {
206 : : int err;
207 : : td_driver_t *driver;
208 : :
209 : 0 : driver = image->driver;
210 [ # # ]: 0 : if (!driver) {
211 : : err = -ENODEV;
212 : : goto fail;
213 : : }
214 : :
215 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
216 : : err = -EBADF;
217 : : goto fail;
218 : : }
219 : :
220 [ # # ]: 0 : if (!driver->ops->td_queue_read) {
221 : 0 : EPRINTF("Driver %s does not support read", driver->name);
222 : 0 : err = -EOPNOTSUPP;
223 : 0 : goto fail;
224 : : }
225 : :
226 : 0 : err = tapdisk_image_check_td_request(image, treq);
227 [ # # ]: 0 : if (err)
228 : : goto fail;
229 : :
230 : 0 : driver->ops->td_queue_read(driver, treq);
231 : :
232 : 0 : return;
233 : :
234 : : fail:
235 : 0 : td_complete_request(treq, err);
236 : : }
237 : :
238 : : void
239 : 0 : td_queue_block_status(td_image_t *image, td_request_t *treq)
240 : : {
241 : : int err;
242 : : td_driver_t *driver;
243 : :
244 : 0 : driver = image->driver;
245 [ # # ]: 0 : if (!driver) {
246 : : err = -ENODEV;
247 : : goto fail;
248 : : }
249 : :
250 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
251 : : err = -EBADF;
252 : : goto fail;
253 : : }
254 : :
255 [ # # ]: 0 : if (!driver->ops->td_queue_block_status) {
256 : 0 : EPRINTF("Driver %s does not support block status", driver->name);
257 : 0 : err = -EOPNOTSUPP;
258 : 0 : goto fail;
259 : : }
260 : :
261 : 0 : err = tapdisk_image_check_td_request(image, *treq);
262 [ # # ]: 0 : if (err)
263 : : goto fail;
264 : :
265 : 0 : driver->ops->td_queue_block_status(driver, *treq);
266 : :
267 : 0 : return;
268 : :
269 : : fail:
270 : 0 : td_complete_request(*treq, err);
271 : : }
272 : :
273 : : void
274 : 0 : td_forward_request(td_request_t treq)
275 : : {
276 : 0 : tapdisk_vbd_forward_request(treq);
277 : 0 : }
278 : :
279 : : void
280 : 0 : td_complete_request(td_request_t treq, int res)
281 : : {
282 : 0 : treq.cb(treq, res);
283 : 0 : }
284 : :
285 : : void
286 : 0 : td_queue_tiocb(td_driver_t *driver, struct tiocb *tiocb)
287 : : {
288 : 0 : tapdisk_driver_queue_tiocb(driver, tiocb);
289 : 0 : }
290 : :
291 : : void
292 : 0 : td_prep_read(td_driver_t *driver, struct tiocb *tiocb, int fd, char *buf, size_t bytes,
293 : : long long offset, td_queue_callback_t cb, void *arg)
294 : : {
295 : 0 : tapdisk_driver_prep_tiocb(driver, tiocb, fd, 0, buf, bytes, offset, cb, arg);
296 : 0 : }
297 : :
298 : : void
299 : 0 : td_prep_write(td_driver_t *driver, struct tiocb *tiocb, int fd, char *buf, size_t bytes,
300 : : long long offset, td_queue_callback_t cb, void *arg)
301 : : {
302 : 0 : tapdisk_driver_prep_tiocb(driver, tiocb, fd, 1, buf, bytes, offset, cb, arg);
303 : 0 : }
304 : :
305 : : void
306 : 0 : td_debug(td_image_t *image)
307 : : {
308 : : td_driver_t *driver;
309 : :
310 : 0 : driver = image->driver;
311 [ # # ][ # # ]: 0 : if (!driver || !td_flag_test(driver->state, TD_DRIVER_OPEN))
312 : :
313 : 0 : return;
314 : :
315 : 0 : tapdisk_driver_debug(driver);
316 : : }
317 : :
318 : : __noreturn void
319 : 0 : td_panic(void)
320 : : {
321 : 0 : tlog_precious(1);
322 : 0 : raise(SIGABRT);
323 : 0 : _exit(-1); /* not reached */
324 : : }
|