Annotation of embedaddon/istgt/src/istgt_lu_disk_vbox.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
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
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: */
27:
28: #ifdef HAVE_CONFIG_H
29: #include "config.h"
30: #endif
31:
32: #include <inttypes.h>
33: #include <stdint.h>
34:
35: #include <errno.h>
36: #include <stdarg.h>
37: #include <stdio.h>
38: #include <string.h>
39: #include <pthread.h>
40:
41: #include <fcntl.h>
42: #include <unistd.h>
43:
44: #include "istgt.h"
45: #include "istgt_log.h"
46: #include "istgt_misc.h"
47: #include "istgt_lu.h"
48: #include "istgt_proto.h"
49:
50: #if !defined(__GNUC__)
51: #undef __attribute__
52: #define __attribute__(x)
53: #endif
54:
55: #ifdef USE_VBOXVD
56: #define IN_RING3
57: #include "iprt/buildconfig.h"
58: #include "VBox/vd.h"
59:
60: typedef struct istgt_lu_disk_vbox_t {
61: PVBOXHDD pDisk;
62: PVDINTERFACE pVDIfs;
63: PVDINTERFACE pVDIfsImage;
64: VDINTERFACE VDIfsDisk;
65: VDINTERFACEERROR VDIfError;
66: VDTYPE enmType;
67: RTUUID uuid;
68: } ISTGT_LU_DISK_VBOX;
69:
70: #ifndef O_ACCMODE
71: #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
72: #endif
73:
74: static void istgt_lu_disk_vbox_error(void *pvUser, int rc, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list va) __attribute__((__format__(__printf__, 6, 0)));
75:
76: static void istgt_lu_disk_vbox_error(void *pvUser, int rc, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list va)
77: {
78: ISTGT_LU_DISK *spec = (ISTGT_LU_DISK*)pvUser;
79: char buf[MAX_TMPBUF*2];
80:
81: vsnprintf(buf, sizeof buf, pszFormat, va);
82: ISTGT_ERRLOG("LU%d: LUN%d: rc=%d, %s:%u:%s: %s", spec->num, spec->lun,
83: rc, pszFile, iLine, pszFunction, buf);
84: }
85:
86: static int
87: istgt_lu_disk_open_vbox(ISTGT_LU_DISK *spec, int flags, int mode __attribute__((__unused__)))
88: {
89: ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
90: PVDINTERFACE pIf;
91: uint32_t major, minor, build;
92: unsigned uOpenFlags;
93: int rc;
94:
95: major = RTBldCfgVersionMajor();
96: minor = RTBldCfgVersionMinor();
97: build = RTBldCfgVersionBuild();
98: if (major > 4 || (major == 4 && minor >= 2)) {
99: // VBoxDDU >= 4.2
100: if (ISTGT_VBOXINC_VERSION_MAJOR < 4 ||
101: (ISTGT_VBOXINC_VERSION_MAJOR == 4 && ISTGT_VBOXINC_VERSION_MINOR < 2)) {
102: ISTGT_ERRLOG("VBox library is newer than istgt\n");
103: return -1;
104: }
105: } else {
106: // VBoxDDU < 4.2
107: if (ISTGT_VBOXINC_VERSION_MAJOR > 4 ||
108: (ISTGT_VBOXINC_VERSION_MAJOR == 4 && ISTGT_VBOXINC_VERSION_MINOR >= 2)) {
109: ISTGT_ERRLOG("VBox library is older than istgt\n");
110: return -1;
111: }
112: if (strcasecmp(spec->disktype, "QCOW") == 0
113: || strcasecmp(spec->disktype, "QED") == 0
114: || strcasecmp(spec->disktype, "VHDX") == 0) {
115: ISTGT_ERRLOG("VD format(%s) is not supported in this version.\n",
116: spec->disktype);
117: return -1;
118: }
119: }
120:
121: if ((flags & O_ACCMODE) == O_RDONLY) {
122: uOpenFlags = VD_OPEN_FLAGS_READONLY;
123: } else if ((flags & O_ACCMODE) == O_RDWR) {
124: uOpenFlags = VD_OPEN_FLAGS_NORMAL;
125: } else {
126: ISTGT_ERRLOG("not supported mode %x\n", (flags & O_ACCMODE));
127: return -1;
128: }
129:
130: exspec->pDisk = NULL;
131: exspec->pVDIfs = NULL;
132: exspec->pVDIfsImage = NULL;
133: exspec->enmType = VDTYPE_HDD;
134:
135: #if ((ISTGT_VBOXINC_VERSION_MAJOR > 4) || (ISTGT_VBOXINC_VERSION_MAJOR == 4 && ISTGT_VBOXINC_VERSION_MINOR >= 2))
136: exspec->VDIfError.pfnError = istgt_lu_disk_vbox_error;
137: exspec->VDIfError.pfnMessage = NULL;
138: pIf = (PVDINTERFACE)&exspec->VDIfError;
139:
140: rc = VDInterfaceAdd(pIf, "VD interface error", VDINTERFACETYPE_ERROR,
141: spec, sizeof(VDINTERFACEERROR), &exspec->pVDIfs);
142: #else /* VBox < 4.2 */
143: exspec->VDIfError.cbSize = sizeof(VDINTERFACEERROR);
144: exspec->VDIfError.enmInterface = VDINTERFACETYPE_ERROR;
145: exspec->VDIfError.pfnError = istgt_lu_disk_vbox_error;
146: exspec->VDIfError.pfnMessage = NULL;
147: pIf = &exspec->VDIfsDisk;
148:
149: rc = VDInterfaceAdd(pIf, "VD interface error", VDINTERFACETYPE_ERROR,
150: &exspec->VDIfError, spec, &exspec->pVDIfs);
151: #endif /* VBox >= 4.2 */
152: if (RT_FAILURE(rc)) {
153: ISTGT_ERRLOG("VDInterfaceAdd error\n");
154: return -1;
155: }
156:
157: rc = VDCreate(exspec->pVDIfs, exspec->enmType, &exspec->pDisk);
158: if (RT_FAILURE(rc)) {
159: ISTGT_ERRLOG("VDCreate error\n");
160: VDInterfaceRemove(pIf, &exspec->pVDIfs);
161: exspec->pDisk = NULL;
162: exspec->pVDIfs = NULL;
163: exspec->pVDIfsImage = NULL;
164: return -1;
165: }
166: rc = VDOpen(exspec->pDisk, spec->disktype, spec->file, uOpenFlags,
167: exspec->pVDIfsImage);
168: if (RT_FAILURE(rc)) {
169: ISTGT_ERRLOG("VDOpen error\n");
170: VDDestroy(exspec->pDisk);
171: VDInterfaceRemove(pIf, &exspec->pVDIfs);
172: exspec->pDisk = NULL;
173: exspec->pVDIfs = NULL;
174: exspec->pVDIfsImage = NULL;
175: return -1;
176: }
177: return 0;
178: }
179:
180: static int
181: istgt_lu_disk_close_vbox(ISTGT_LU_DISK *spec)
182: {
183: ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
184: PVDINTERFACE pIf;
185: bool fDelete = false;
186: int rc;
187:
188: #if ((ISTGT_VBOXINC_VERSION_MAJOR > 4) || (ISTGT_VBOXINC_VERSION_MAJOR == 4 && ISTGT_VBOXINC_VERSION_MINOR >= 2))
189: pIf = (PVDINTERFACE)&exspec->VDIfError;
190: #else /* VBox < 4.2 */
191: pIf = &exspec->VDIfsDisk;
192: #endif /* VBox >= 4.2 */
193: rc = VDClose(exspec->pDisk, fDelete);
194: if (RT_FAILURE(rc)) {
195: ISTGT_ERRLOG("VDClose error\n");
196: VDDestroy(exspec->pDisk);
197: VDInterfaceRemove(pIf, &exspec->pVDIfs);
198: exspec->pDisk = NULL;
199: exspec->pVDIfs = NULL;
200: exspec->pVDIfsImage = NULL;
201: return -1;
202: }
203: VDDestroy(exspec->pDisk);
204: VDInterfaceRemove(pIf, &exspec->pVDIfs);
205: exspec->pDisk = NULL;
206: exspec->pVDIfs = NULL;
207: exspec->pVDIfsImage = NULL;
208: return 0;
209: }
210:
211: static int64_t
212: istgt_lu_disk_seek_vbox(ISTGT_LU_DISK *spec, uint64_t offset)
213: {
214: //ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
215:
216: spec->foffset = offset;
217: return 0;
218: }
219:
220: static int64_t
221: istgt_lu_disk_read_vbox(ISTGT_LU_DISK *spec, void *buf, uint64_t nbytes)
222: {
223: ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
224: uint64_t offset;
225: int rc;
226:
227: offset = spec->foffset;
228: rc = VDRead(exspec->pDisk, offset, buf, (size_t)nbytes);
229: if (RT_FAILURE(rc)) {
230: ISTGT_ERRLOG("VDRead error\n");
231: return -1;
232: }
233: spec->foffset += nbytes;
234: return (int64_t)nbytes;
235: }
236:
237: static int64_t
238: istgt_lu_disk_write_vbox(ISTGT_LU_DISK *spec, const void *buf, uint64_t nbytes)
239: {
240: ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
241: uint64_t offset;
242: int rc;
243:
244: offset = spec->foffset;
245: rc = VDWrite(exspec->pDisk, offset, buf, (size_t)nbytes);
246: if (RT_FAILURE(rc)) {
247: ISTGT_ERRLOG("VDWrite error\n");
248: return -1;
249: }
250: spec->foffset += nbytes;
251: return (int64_t)nbytes;
252: }
253:
254: static int64_t
255: istgt_lu_disk_sync_vbox(ISTGT_LU_DISK *spec, uint64_t offset __attribute__((__unused__)), uint64_t nbytes __attribute__((__unused__)))
256: {
257: ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
258: int rc;
259:
260: rc = VDFlush(exspec->pDisk);
261: if (RT_FAILURE(rc)) {
262: ISTGT_ERRLOG("VDFlush error\n");
263: return -1;
264: }
265: return 0;
266: }
267:
268: static int
269: istgt_lu_disk_allocate_vbox(ISTGT_LU_DISK *spec __attribute__((__unused__)))
270: {
271: //ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
272:
273: return 0;
274: }
275:
276: static int
277: istgt_lu_disk_setcache_vbox(ISTGT_LU_DISK *spec)
278: {
279: //ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
280:
281: if (spec->read_cache) {
282: }
283: if (spec->write_cache) {
284: }
285: return 0;
286: }
287:
288: int
289: istgt_lu_disk_vbox_lun_init(ISTGT_LU_DISK *spec, ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu)
290: {
291: ISTGT_LU_DISK_VBOX *exspec;
292: uint64_t capacity;
293: uint64_t fsize;
294: int flags;
295: int rc;
296:
297: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_disk_vbox_lun_init\n");
298:
299: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d for disktype=%s\n",
300: spec->num, spec->lun, spec->disktype);
301:
302: spec->open = istgt_lu_disk_open_vbox;
303: spec->close = istgt_lu_disk_close_vbox;
304: spec->seek = istgt_lu_disk_seek_vbox;
305: spec->read = istgt_lu_disk_read_vbox;
306: spec->write = istgt_lu_disk_write_vbox;
307: spec->sync = istgt_lu_disk_sync_vbox;
308: spec->allocate = istgt_lu_disk_allocate_vbox;
309: spec->setcache = istgt_lu_disk_setcache_vbox;
310:
311: exspec = xmalloc(sizeof *exspec);
312: memset(exspec, 0, sizeof *exspec);
313: spec->exspec = exspec;
314:
315: flags = lu->readonly ? O_RDONLY : O_RDWR;
316: rc = spec->open(spec, flags, 0666);
317: if (rc < 0) {
318: ISTGT_ERRLOG("LU%d: LUN%d: open error(rc=%d)\n",
319: spec->num, spec->lun, rc);
320: return -1;
321: }
322:
323: capacity = VDGetSize(exspec->pDisk, 0);
324: fsize = VDGetFileSize(exspec->pDisk, 0);
325:
326: spec->size = capacity;
327: spec->blocklen = 512;
328: spec->blockcnt = spec->size / spec->blocklen;
329: if (spec->blockcnt == 0) {
330: ISTGT_ERRLOG("LU%d: LUN%d: size zero\n", spec->num, spec->lun);
331: spec->close(spec);
332: return -1;
333: }
334:
335: #if 0
336: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
337: "LU%d: LUN%d file=%s, size=%"PRIu64"\n",
338: spec->num, spec->lun, spec->file, spec->size);
339: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
340: "LU%d: LUN%d %"PRIu64" blocks, %"
341: PRIu64" bytes/block\n",
342: spec->num, spec->lun, spec->blockcnt, spec->blocklen);
343: #endif
344:
345: printf("LU%d: LUN%d file=%s, size=%"PRIu64"\n",
346: spec->num, spec->lun, spec->file, spec->size);
347: printf("LU%d: LUN%d %"PRIu64" blocks, %"PRIu64" bytes/block\n",
348: spec->num, spec->lun, spec->blockcnt, spec->blocklen);
349:
350: if (strcasecmp(spec->disktype, "VDI") == 0
351: || strcasecmp(spec->disktype, "VHD") == 0
352: || strcasecmp(spec->disktype, "VMDK") == 0) {
353: rc = VDGetUuid(exspec->pDisk, 0, &exspec->uuid);
354: if (RT_FAILURE(rc)) {
355: ISTGT_ERRLOG("LU%d: LUN%d: uuid error\n", spec->num, spec->lun);
356: spec->close(spec);
357: return -1;
358: }
359: printf("LU%d: LUN%d UUID="
360: "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
361: spec->num, spec->lun,
362: exspec->uuid.Gen.u32TimeLow,
363: exspec->uuid.Gen.u16TimeMid,
364: exspec->uuid.Gen.u16TimeHiAndVersion,
365: exspec->uuid.Gen.u8ClockSeqHiAndReserved,
366: exspec->uuid.Gen.u8ClockSeqLow,
367: exspec->uuid.Gen.au8Node[0],
368: exspec->uuid.Gen.au8Node[1],
369: exspec->uuid.Gen.au8Node[2],
370: exspec->uuid.Gen.au8Node[3],
371: exspec->uuid.Gen.au8Node[4],
372: exspec->uuid.Gen.au8Node[5]);
373: }
374: return 0;
375: }
376:
377: int
378: istgt_lu_disk_vbox_lun_shutdown(ISTGT_LU_DISK *spec, ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu __attribute__((__unused__)))
379: {
380: ISTGT_LU_DISK_VBOX *exspec = (ISTGT_LU_DISK_VBOX *)spec->exspec;
381: int rc;
382:
383: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_disk_vbox_lun_shutdown\n");
384:
385: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d for disktype=%s\n",
386: spec->num, spec->lun, spec->disktype);
387:
388: if (!spec->lu->readonly) {
389: rc = spec->sync(spec, 0, spec->size);
390: if (rc < 0) {
391: //ISTGT_ERRLOG("LU%d: lu_disk_sync() failed\n", lu->num);
392: /* ignore error */
393: }
394: }
395: rc = spec->close(spec);
396: if (rc < 0) {
397: //ISTGT_ERRLOG("LU%d: lu_disk_close() failed\n", lu->num);
398: /* ignore error */
399: }
400:
401: xfree(exspec);
402: spec->exspec = NULL;
403: return 0;
404: }
405: #else /* USE_VBOXVD */
406: int
407: istgt_lu_disk_vbox_lun_init(ISTGT_LU_DISK *spec, ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu __attribute__((__unused__)))
408: {
409: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d unsupported virtual disk\n",
410: spec->num, spec->lun);
411: return -1;
412: }
413:
414: int
415: istgt_lu_disk_vbox_lun_shutdown(ISTGT_LU_DISK *spec, ISTGT_Ptr istgt __attribute__((__unused__)), ISTGT_LU_Ptr lu __attribute__((__unused__)))
416: {
417: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: LUN%d unsupported virtual disk\n",
418: spec->num, spec->lun);
419: return -1;
420: }
421: #endif /* USE_VBOXVD */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>