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 : 0 : td_close(td_image_t *image)
117 : : {
118 : : td_driver_t *driver;
119 : :
120 : 0 : driver = image->driver;
121 [ # # ]: 0 : 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 : : err = -EOPNOTSUPP;
187 : : goto fail;
188 : : }
189 : :
190 : 0 : err = tapdisk_image_check_td_request(image, treq);
191 [ # # ]: 0 : if (err)
192 : : goto fail;
193 : :
194 : 0 : driver->ops->td_queue_write(driver, treq);
195 : :
196 : 0 : return;
197 : :
198 : : fail:
199 : 0 : td_complete_request(treq, err);
200 : : }
201 : :
202 : : void
203 : 0 : td_queue_read(td_image_t *image, td_request_t treq)
204 : : {
205 : : int err;
206 : : td_driver_t *driver;
207 : :
208 : 0 : driver = image->driver;
209 [ # # ]: 0 : if (!driver) {
210 : : err = -ENODEV;
211 : : goto fail;
212 : : }
213 : :
214 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
215 : : err = -EBADF;
216 : : goto fail;
217 : : }
218 : :
219 [ # # ]: 0 : if (!driver->ops->td_queue_read) {
220 : : err = -EOPNOTSUPP;
221 : : goto fail;
222 : : }
223 : :
224 : 0 : err = tapdisk_image_check_td_request(image, treq);
225 [ # # ]: 0 : if (err)
226 : : goto fail;
227 : :
228 : 0 : driver->ops->td_queue_read(driver, treq);
229 : :
230 : 0 : return;
231 : :
232 : : fail:
233 : 0 : td_complete_request(treq, err);
234 : : }
235 : :
236 : : void
237 : 0 : td_queue_block_status(td_image_t *image, td_request_t *treq)
238 : : {
239 : : int err;
240 : : td_driver_t *driver;
241 : :
242 : 0 : driver = image->driver;
243 [ # # ]: 0 : if (!driver) {
244 : : err = -ENODEV;
245 : : goto fail;
246 : : }
247 : :
248 [ # # ]: 0 : if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
249 : : err = -EBADF;
250 : : goto fail;
251 : : }
252 : :
253 [ # # ]: 0 : if (!driver->ops->td_queue_block_status) {
254 : : err = -EOPNOTSUPP;
255 : : goto fail;
256 : : }
257 : :
258 : 0 : err = tapdisk_image_check_td_request(image, *treq);
259 [ # # ]: 0 : if (err)
260 : : goto fail;
261 : :
262 : 0 : driver->ops->td_queue_block_status(driver, *treq);
263 : :
264 : 0 : return;
265 : :
266 : : fail:
267 : 0 : td_complete_request(*treq, err);
268 : : }
269 : :
270 : : void
271 : 0 : td_forward_request(td_request_t treq)
272 : : {
273 : 0 : tapdisk_vbd_forward_request(treq);
274 : 0 : }
275 : :
276 : : void
277 : 0 : td_complete_request(td_request_t treq, int res)
278 : : {
279 : 0 : treq.cb(treq, res);
280 : 0 : }
281 : :
282 : : void
283 : 0 : td_queue_tiocb(td_driver_t *driver, struct tiocb *tiocb)
284 : : {
285 : 0 : tapdisk_driver_queue_tiocb(driver, tiocb);
286 : 0 : }
287 : :
288 : : void
289 : 0 : td_prep_read(td_driver_t *driver, struct tiocb *tiocb, int fd, char *buf, size_t bytes,
290 : : long long offset, td_queue_callback_t cb, void *arg)
291 : : {
292 : 0 : tapdisk_driver_prep_tiocb(driver, tiocb, fd, 0, buf, bytes, offset, cb, arg);
293 : 0 : }
294 : :
295 : : void
296 : 0 : td_prep_write(td_driver_t *driver, struct tiocb *tiocb, int fd, char *buf, size_t bytes,
297 : : long long offset, td_queue_callback_t cb, void *arg)
298 : : {
299 : 0 : tapdisk_driver_prep_tiocb(driver, tiocb, fd, 1, buf, bytes, offset, cb, arg);
300 : 0 : }
301 : :
302 : : void
303 : 0 : td_debug(td_image_t *image)
304 : : {
305 : : td_driver_t *driver;
306 : :
307 : 0 : driver = image->driver;
308 [ # # ][ # # ]: 0 : if (!driver || !td_flag_test(driver->state, TD_DRIVER_OPEN))
309 : :
310 : 0 : return;
311 : :
312 : 0 : tapdisk_driver_debug(driver);
313 : : }
314 : :
315 : : __noreturn void
316 : 0 : td_panic(void)
317 : : {
318 : 0 : tlog_precious(1);
319 : 0 : raise(SIGABRT);
320 : 0 : _exit(-1); /* not reached */
321 : : }
|