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