Annotation of embedaddon/istgt/src/istgt_lu_disk_vbox.c, revision 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>