1 /*
2 * Copyright (c) 2008, XenSource Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of XenSource Inc. nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include <errno.h>
29
30 #include "tapdisk.h"
31 #include "tapdisk-vbd.h"
32 #include "tapdisk-image.h"
33 #include "tapdisk-driver.h"
34 #include "tapdisk-server.h"
35 #include "tapdisk-interface.h"
36
37 int
td_load(td_image_t * image)38 td_load(td_image_t *image)
39 {
40 int err;
41 td_image_t *shared;
42 td_driver_t *driver;
43
44 shared = tapdisk_server_get_shared_image(image);
45 if (!shared)
46 return -ENODEV;
47
48 driver = shared->driver;
49 if (!driver)
50 return -EBADF;
51
52 driver->refcnt++;
53 image->driver = driver;
54 image->info = driver->info;
55
56 DPRINTF("loaded shared image %s (%d users, state: 0x%08x, type: %d)\n",
57 driver->name, driver->refcnt, driver->state, driver->type);
58 return 0;
59 }
60
61 int
__td_open(td_image_t * image,td_disk_info_t * info)62 __td_open(td_image_t *image, td_disk_info_t *info)
63 {
64 int err;
65 td_driver_t *driver;
66
67 driver = image->driver;
68 if (!driver) {
69 driver = tapdisk_driver_allocate(image->type,
70 image->name,
71 image->flags,
72 image->storage);
73 if (!driver)
74 return -ENOMEM;
75
76 if (info) /* pre-seed driver->info for virtual drivers */
77 driver->info = *info;
78 }
79
80 if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
81 err = driver->ops->td_open(driver, image->name, image->flags);
82 if (err) {
83 if (!image->driver)
84 tapdisk_driver_free(driver);
85 return err;
86 }
87
88 td_flag_set(driver->state, TD_DRIVER_OPEN);
89 DPRINTF("opened image %s (%d users, state: 0x%08x, type: %d)\n",
90 driver->name, driver->refcnt + 1,
91 driver->state, driver->type);
92 }
93
94 image->driver = driver;
95 image->info = driver->info;
96 driver->refcnt++;
97 return 0;
98 }
99
100 int
td_open(td_image_t * image)101 td_open(td_image_t *image)
102 {
103 return __td_open(image, NULL);
104 }
105
106 int
td_close(td_image_t * image)107 td_close(td_image_t *image)
108 {
109 td_driver_t *driver;
110
111 driver = image->driver;
112 if (!driver)
113 return -ENODEV;
114
115 driver->refcnt--;
116 if (!driver->refcnt && td_flag_test(driver->state, TD_DRIVER_OPEN)) {
117 driver->ops->td_close(driver);
118 td_flag_clear(driver->state, TD_DRIVER_OPEN);
119 }
120
121 DPRINTF("closed image %s (%d users, state: 0x%08x, type: %d)\n",
122 driver->name, driver->refcnt, driver->state, driver->type);
123
124 return 0;
125 }
126
127 int
td_get_parent_id(td_image_t * image,td_disk_id_t * id)128 td_get_parent_id(td_image_t *image, td_disk_id_t *id)
129 {
130 td_driver_t *driver;
131
132 driver = image->driver;
133 if (!driver)
134 return -ENODEV;
135
136 if (!td_flag_test(driver->state, TD_DRIVER_OPEN))
137 return -EBADF;
138
139 return driver->ops->td_get_parent_id(driver, id);
140 }
141
142 int
td_validate_parent(td_image_t * image,td_image_t * parent)143 td_validate_parent(td_image_t *image, td_image_t *parent)
144 {
145 td_driver_t *driver, *pdriver;
146
147 driver = image->driver;
148 pdriver = parent->driver;
149 if (!driver || !pdriver)
150 return -ENODEV;
151
152 if (!td_flag_test(driver->state, TD_DRIVER_OPEN) ||
153 !td_flag_test(pdriver->state, TD_DRIVER_OPEN))
154 return -EBADF;
155
156 return 0;
157 return driver->ops->td_validate_parent(driver, pdriver, 0);
158 }
159
160 void
td_queue_write(td_image_t * image,td_request_t treq)161 td_queue_write(td_image_t *image, td_request_t treq)
162 {
163 int err;
164 td_driver_t *driver;
165
166 driver = image->driver;
167 if (!driver) {
168 err = -ENODEV;
169 goto fail;
170 }
171
172 if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
173 err = -EBADF;
174 goto fail;
175 }
176
177 err = tapdisk_image_check_td_request(image, treq);
178 if (err)
179 goto fail;
180
181 driver->ops->td_queue_write(driver, treq);
182 return;
183
184 fail:
185 td_complete_request(treq, err);
186 }
187
188 void
td_queue_read(td_image_t * image,td_request_t treq)189 td_queue_read(td_image_t *image, td_request_t treq)
190 {
191 int err;
192 td_driver_t *driver;
193
194 driver = image->driver;
195 if (!driver) {
196 err = -ENODEV;
197 goto fail;
198 }
199
200 if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
201 err = -EBADF;
202 goto fail;
203 }
204
205 err = tapdisk_image_check_td_request(image, treq);
206 if (err)
207 goto fail;
208
209 driver->ops->td_queue_read(driver, treq);
210 return;
211
212 fail:
213 td_complete_request(treq, err);
214 }
215
216 void
td_forward_request(td_request_t treq)217 td_forward_request(td_request_t treq)
218 {
219 tapdisk_vbd_forward_request(treq);
220 }
221
222 void
td_complete_request(td_request_t treq,int res)223 td_complete_request(td_request_t treq, int res)
224 {
225 ((td_callback_t)treq.cb)(treq, res);
226 }
227
228 void
td_queue_tiocb(td_driver_t * driver,struct tiocb * tiocb)229 td_queue_tiocb(td_driver_t *driver, struct tiocb *tiocb)
230 {
231 tapdisk_driver_queue_tiocb(driver, tiocb);
232 }
233
234 void
td_prep_read(struct tiocb * tiocb,int fd,char * buf,size_t bytes,long long offset,td_queue_callback_t cb,void * arg)235 td_prep_read(struct tiocb *tiocb, int fd, char *buf, size_t bytes,
236 long long offset, td_queue_callback_t cb, void *arg)
237 {
238 tapdisk_prep_tiocb(tiocb, fd, 0, buf, bytes, offset, cb, arg);
239 }
240
241 void
td_prep_write(struct tiocb * tiocb,int fd,char * buf,size_t bytes,long long offset,td_queue_callback_t cb,void * arg)242 td_prep_write(struct tiocb *tiocb, int fd, char *buf, size_t bytes,
243 long long offset, td_queue_callback_t cb, void *arg)
244 {
245 tapdisk_prep_tiocb(tiocb, fd, 1, buf, bytes, offset, cb, arg);
246 }
247
248 void
td_debug(td_image_t * image)249 td_debug(td_image_t *image)
250 {
251 td_driver_t *driver;
252
253 driver = image->driver;
254 if (!driver || !td_flag_test(driver->state, TD_DRIVER_OPEN))
255
256 return;
257
258 tapdisk_driver_debug(driver);
259 }
260