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>