File:  [Qemu by Fabrice Bellard] / qemu / block.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:37:52 2018 UTC (2 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0072, HEAD
qemu 0.7.2

    1: /*
    2:  * QEMU System Emulator block driver
    3:  * 
    4:  * Copyright (c) 2003 Fabrice Bellard
    5:  * 
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: #include "vl.h"
   25: #include "block_int.h"
   26: 
   27: #ifdef _BSD
   28: #include <sys/types.h>
   29: #include <sys/stat.h>
   30: #include <sys/ioctl.h>
   31: #include <sys/queue.h>
   32: #include <sys/disk.h>
   33: #endif
   34: 
   35: static BlockDriverState *bdrv_first;
   36: static BlockDriver *first_drv;
   37: 
   38: void bdrv_register(BlockDriver *bdrv)
   39: {
   40:     bdrv->next = first_drv;
   41:     first_drv = bdrv;
   42: }
   43: 
   44: /* create a new block device (by default it is empty) */
   45: BlockDriverState *bdrv_new(const char *device_name)
   46: {
   47:     BlockDriverState **pbs, *bs;
   48: 
   49:     bs = qemu_mallocz(sizeof(BlockDriverState));
   50:     if(!bs)
   51:         return NULL;
   52:     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
   53:     if (device_name[0] != '\0') {
   54:         /* insert at the end */
   55:         pbs = &bdrv_first;
   56:         while (*pbs != NULL)
   57:             pbs = &(*pbs)->next;
   58:         *pbs = bs;
   59:     }
   60:     return bs;
   61: }
   62: 
   63: BlockDriver *bdrv_find_format(const char *format_name)
   64: {
   65:     BlockDriver *drv1;
   66:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
   67:         if (!strcmp(drv1->format_name, format_name))
   68:             return drv1;
   69:     }
   70:     return NULL;
   71: }
   72: 
   73: int bdrv_create(BlockDriver *drv, 
   74:                 const char *filename, int64_t size_in_sectors,
   75:                 const char *backing_file, int flags)
   76: {
   77:     if (!drv->bdrv_create)
   78:         return -ENOTSUP;
   79:     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
   80: }
   81: 
   82: #ifdef _WIN32
   83: static void get_tmp_filename(char *filename, int size)
   84: {
   85:     /* XXX: find a better function */
   86:     tmpnam(filename);
   87: }
   88: #else
   89: static void get_tmp_filename(char *filename, int size)
   90: {
   91:     int fd;
   92:     /* XXX: race condition possible */
   93:     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
   94:     fd = mkstemp(filename);
   95:     close(fd);
   96: }
   97: #endif
   98: 
   99: /* XXX: force raw format if block or character device ? It would
  100:    simplify the BSD case */
  101: static BlockDriver *find_image_format(const char *filename)
  102: {
  103:     int fd, ret, score, score_max;
  104:     BlockDriver *drv1, *drv;
  105:     uint8_t *buf;
  106:     size_t bufsize = 1024;
  107: 
  108:     fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  109:     if (fd < 0) {
  110:         buf = NULL;
  111:         ret = 0;
  112:     } else {
  113: #ifdef DIOCGSECTORSIZE
  114:         {
  115:             unsigned int sectorsize = 512;
  116:             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  117:                 sectorsize > bufsize)
  118:                 bufsize = sectorsize;
  119:         }
  120: #endif
  121:         buf = qemu_malloc(bufsize);
  122:         if (!buf)
  123:             return NULL;
  124:         ret = read(fd, buf, bufsize);
  125:         if (ret < 0) {
  126:             close(fd);
  127:             qemu_free(buf);
  128:             return NULL;
  129:         }
  130:         close(fd);
  131:     }
  132:     
  133:     drv = NULL;
  134:     score_max = 0;
  135:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  136:         score = drv1->bdrv_probe(buf, ret, filename);
  137:         if (score > score_max) {
  138:             score_max = score;
  139:             drv = drv1;
  140:         }
  141:     }
  142:     qemu_free(buf);
  143:     return drv;
  144: }
  145: 
  146: int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
  147: {
  148:     return bdrv_open2(bs, filename, snapshot, NULL);
  149: }
  150: 
  151: int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
  152:                BlockDriver *drv)
  153: {
  154:     int ret;
  155:     char tmp_filename[1024];
  156:     
  157:     bs->read_only = 0;
  158:     bs->is_temporary = 0;
  159:     bs->encrypted = 0;
  160: 
  161:     if (snapshot) {
  162:         BlockDriverState *bs1;
  163:         int64_t total_size;
  164:         
  165:         /* if snapshot, we create a temporary backing file and open it
  166:            instead of opening 'filename' directly */
  167: 
  168:         /* if there is a backing file, use it */
  169:         bs1 = bdrv_new("");
  170:         if (!bs1) {
  171:             return -1;
  172:         }
  173:         if (bdrv_open(bs1, filename, 0) < 0) {
  174:             bdrv_delete(bs1);
  175:             return -1;
  176:         }
  177:         total_size = bs1->total_sectors;
  178:         bdrv_delete(bs1);
  179:         
  180:         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
  181:         /* XXX: use cow for linux as it is more efficient ? */
  182:         if (bdrv_create(&bdrv_qcow, tmp_filename, 
  183:                         total_size, filename, 0) < 0) {
  184:             return -1;
  185:         }
  186:         filename = tmp_filename;
  187:         bs->is_temporary = 1;
  188:     }
  189: 
  190:     pstrcpy(bs->filename, sizeof(bs->filename), filename);
  191:     if (!drv) {
  192:         drv = find_image_format(filename);
  193:         if (!drv)
  194:             return -1;
  195:     }
  196:     bs->drv = drv;
  197:     bs->opaque = qemu_mallocz(drv->instance_size);
  198:     if (bs->opaque == NULL && drv->instance_size > 0)
  199:         return -1;
  200:     
  201:     ret = drv->bdrv_open(bs, filename);
  202:     if (ret < 0) {
  203:         qemu_free(bs->opaque);
  204:         return -1;
  205:     }
  206: #ifndef _WIN32
  207:     if (bs->is_temporary) {
  208:         unlink(filename);
  209:     }
  210: #endif
  211:     if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
  212:         /* if there is a backing file, use it */
  213:         bs->backing_hd = bdrv_new("");
  214:         if (!bs->backing_hd) {
  215:         fail:
  216:             bdrv_close(bs);
  217:             return -1;
  218:         }
  219:         if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
  220:             goto fail;
  221:     }
  222: 
  223:     bs->inserted = 1;
  224: 
  225:     /* call the change callback */
  226:     if (bs->change_cb)
  227:         bs->change_cb(bs->change_opaque);
  228: 
  229:     return 0;
  230: }
  231: 
  232: void bdrv_close(BlockDriverState *bs)
  233: {
  234:     if (bs->inserted) {
  235:         if (bs->backing_hd)
  236:             bdrv_delete(bs->backing_hd);
  237:         bs->drv->bdrv_close(bs);
  238:         qemu_free(bs->opaque);
  239: #ifdef _WIN32
  240:         if (bs->is_temporary) {
  241:             unlink(bs->filename);
  242:         }
  243: #endif
  244:         bs->opaque = NULL;
  245:         bs->drv = NULL;
  246:         bs->inserted = 0;
  247: 
  248:         /* call the change callback */
  249:         if (bs->change_cb)
  250:             bs->change_cb(bs->change_opaque);
  251:     }
  252: }
  253: 
  254: void bdrv_delete(BlockDriverState *bs)
  255: {
  256:     /* XXX: remove the driver list */
  257:     bdrv_close(bs);
  258:     qemu_free(bs);
  259: }
  260: 
  261: /* commit COW file into the raw image */
  262: int bdrv_commit(BlockDriverState *bs)
  263: {
  264:     int64_t i;
  265:     int n, j;
  266:     unsigned char sector[512];
  267: 
  268:     if (!bs->inserted)
  269:         return -ENOENT;
  270: 
  271:     if (bs->read_only) {
  272: 	return -EACCES;
  273:     }
  274: 
  275:     if (!bs->backing_hd) {
  276: 	return -ENOTSUP;
  277:     }
  278: 
  279:     for (i = 0; i < bs->total_sectors;) {
  280:         if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  281:             for(j = 0; j < n; j++) {
  282:                 if (bdrv_read(bs, i, sector, 1) != 0) {
  283:                     return -EIO;
  284:                 }
  285: 
  286:                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
  287:                     return -EIO;
  288:                 }
  289:                 i++;
  290: 	    }
  291: 	} else {
  292:             i += n;
  293:         }
  294:     }
  295:     return 0;
  296: }
  297: 
  298: /* return -1 if error */
  299: int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
  300:               uint8_t *buf, int nb_sectors)
  301: {
  302:     int ret, n;
  303:     BlockDriver *drv = bs->drv;
  304: 
  305:     if (!bs->inserted)
  306:         return -1;
  307: 
  308:     while (nb_sectors > 0) {
  309:         if (sector_num == 0 && bs->boot_sector_enabled) {
  310:             memcpy(buf, bs->boot_sector_data, 512);
  311:             n = 1;
  312:         } else if (bs->backing_hd) {
  313:             if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
  314:                 ret = drv->bdrv_read(bs, sector_num, buf, n);
  315:                 if (ret < 0)
  316:                     return -1;
  317:             } else {
  318:                 /* read from the base image */
  319:                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  320:                 if (ret < 0)
  321:                     return -1;
  322:             }
  323:         } else {
  324:             ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  325:             if (ret < 0)
  326:                 return -1;
  327:             /* no need to loop */
  328:             break;
  329:         }
  330:         nb_sectors -= n;
  331:         sector_num += n;
  332:         buf += n * 512;
  333:     }
  334:     return 0;
  335: }
  336: 
  337: /* return -1 if error */
  338: int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
  339:                const uint8_t *buf, int nb_sectors)
  340: {
  341:     if (!bs->inserted)
  342:         return -1;
  343:     if (bs->read_only)
  344:         return -1;
  345:     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  346: }
  347: 
  348: void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
  349: {
  350:     *nb_sectors_ptr = bs->total_sectors;
  351: }
  352: 
  353: /* force a given boot sector. */
  354: void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
  355: {
  356:     bs->boot_sector_enabled = 1;
  357:     if (size > 512)
  358:         size = 512;
  359:     memcpy(bs->boot_sector_data, data, size);
  360:     memset(bs->boot_sector_data + size, 0, 512 - size);
  361: }
  362: 
  363: void bdrv_set_geometry_hint(BlockDriverState *bs, 
  364:                             int cyls, int heads, int secs)
  365: {
  366:     bs->cyls = cyls;
  367:     bs->heads = heads;
  368:     bs->secs = secs;
  369: }
  370: 
  371: void bdrv_set_type_hint(BlockDriverState *bs, int type)
  372: {
  373:     bs->type = type;
  374:     bs->removable = ((type == BDRV_TYPE_CDROM ||
  375:                       type == BDRV_TYPE_FLOPPY));
  376: }
  377: 
  378: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
  379: {
  380:     bs->translation = translation;
  381: }
  382: 
  383: void bdrv_get_geometry_hint(BlockDriverState *bs, 
  384:                             int *pcyls, int *pheads, int *psecs)
  385: {
  386:     *pcyls = bs->cyls;
  387:     *pheads = bs->heads;
  388:     *psecs = bs->secs;
  389: }
  390: 
  391: int bdrv_get_type_hint(BlockDriverState *bs)
  392: {
  393:     return bs->type;
  394: }
  395: 
  396: int bdrv_get_translation_hint(BlockDriverState *bs)
  397: {
  398:     return bs->translation;
  399: }
  400: 
  401: int bdrv_is_removable(BlockDriverState *bs)
  402: {
  403:     return bs->removable;
  404: }
  405: 
  406: int bdrv_is_read_only(BlockDriverState *bs)
  407: {
  408:     return bs->read_only;
  409: }
  410: 
  411: int bdrv_is_inserted(BlockDriverState *bs)
  412: {
  413:     return bs->inserted;
  414: }
  415: 
  416: int bdrv_is_locked(BlockDriverState *bs)
  417: {
  418:     return bs->locked;
  419: }
  420: 
  421: void bdrv_set_locked(BlockDriverState *bs, int locked)
  422: {
  423:     bs->locked = locked;
  424: }
  425: 
  426: void bdrv_set_change_cb(BlockDriverState *bs, 
  427:                         void (*change_cb)(void *opaque), void *opaque)
  428: {
  429:     bs->change_cb = change_cb;
  430:     bs->change_opaque = opaque;
  431: }
  432: 
  433: int bdrv_is_encrypted(BlockDriverState *bs)
  434: {
  435:     if (bs->backing_hd && bs->backing_hd->encrypted)
  436:         return 1;
  437:     return bs->encrypted;
  438: }
  439: 
  440: int bdrv_set_key(BlockDriverState *bs, const char *key)
  441: {
  442:     int ret;
  443:     if (bs->backing_hd && bs->backing_hd->encrypted) {
  444:         ret = bdrv_set_key(bs->backing_hd, key);
  445:         if (ret < 0)
  446:             return ret;
  447:         if (!bs->encrypted)
  448:             return 0;
  449:     }
  450:     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
  451:         return -1;
  452:     return bs->drv->bdrv_set_key(bs, key);
  453: }
  454: 
  455: void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
  456: {
  457:     if (!bs->inserted || !bs->drv) {
  458:         buf[0] = '\0';
  459:     } else {
  460:         pstrcpy(buf, buf_size, bs->drv->format_name);
  461:     }
  462: }
  463: 
  464: void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
  465:                          void *opaque)
  466: {
  467:     BlockDriver *drv;
  468: 
  469:     for (drv = first_drv; drv != NULL; drv = drv->next) {
  470:         it(opaque, drv->format_name);
  471:     }
  472: }
  473: 
  474: BlockDriverState *bdrv_find(const char *name)
  475: {
  476:     BlockDriverState *bs;
  477: 
  478:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  479:         if (!strcmp(name, bs->device_name))
  480:             return bs;
  481:     }
  482:     return NULL;
  483: }
  484: 
  485: void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
  486: {
  487:     BlockDriverState *bs;
  488: 
  489:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  490:         it(opaque, bs->device_name);
  491:     }
  492: }
  493: 
  494: const char *bdrv_get_device_name(BlockDriverState *bs)
  495: {
  496:     return bs->device_name;
  497: }
  498: 
  499: void bdrv_info(void)
  500: {
  501:     BlockDriverState *bs;
  502: 
  503:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  504:         term_printf("%s:", bs->device_name);
  505:         term_printf(" type=");
  506:         switch(bs->type) {
  507:         case BDRV_TYPE_HD:
  508:             term_printf("hd");
  509:             break;
  510:         case BDRV_TYPE_CDROM:
  511:             term_printf("cdrom");
  512:             break;
  513:         case BDRV_TYPE_FLOPPY:
  514:             term_printf("floppy");
  515:             break;
  516:         }
  517:         term_printf(" removable=%d", bs->removable);
  518:         if (bs->removable) {
  519:             term_printf(" locked=%d", bs->locked);
  520:         }
  521:         if (bs->inserted) {
  522:             term_printf(" file=%s", bs->filename);
  523:             if (bs->backing_file[0] != '\0')
  524:                 term_printf(" backing_file=%s", bs->backing_file);
  525:             term_printf(" ro=%d", bs->read_only);
  526:             term_printf(" drv=%s", bs->drv->format_name);
  527:             if (bs->encrypted)
  528:                 term_printf(" encrypted");
  529:         } else {
  530:             term_printf(" [not inserted]");
  531:         }
  532:         term_printf("\n");
  533:     }
  534: }
  535: 
  536: 
  537: /**************************************************************/
  538: /* RAW block driver */
  539: 
  540: typedef struct BDRVRawState {
  541:     int fd;
  542: } BDRVRawState;
  543: 
  544: static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
  545: {
  546:     return 1; /* maybe */
  547: }
  548: 
  549: static int raw_open(BlockDriverState *bs, const char *filename)
  550: {
  551:     BDRVRawState *s = bs->opaque;
  552:     int fd;
  553:     int64_t size;
  554: #ifdef _BSD
  555:     struct stat sb;
  556: #endif
  557: 
  558:     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  559:     if (fd < 0) {
  560:         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  561:         if (fd < 0)
  562:             return -1;
  563:         bs->read_only = 1;
  564:     }
  565: #ifdef _BSD
  566:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  567: #ifdef DIOCGMEDIASIZE
  568: 	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  569: #endif
  570: 	    size = lseek(fd, 0LL, SEEK_END);
  571:     } else
  572: #endif
  573:     {
  574:         size = lseek(fd, 0, SEEK_END);
  575:     }
  576: #ifdef _WIN32
  577:     /* On Windows hosts it can happen that we're unable to get file size
  578:        for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
  579:     if (size == -1)
  580:         size = LONG_LONG_MAX;
  581: #endif
  582:     bs->total_sectors = size / 512;
  583:     s->fd = fd;
  584:     return 0;
  585: }
  586: 
  587: static int raw_read(BlockDriverState *bs, int64_t sector_num, 
  588:                     uint8_t *buf, int nb_sectors)
  589: {
  590:     BDRVRawState *s = bs->opaque;
  591:     int ret;
  592:     
  593:     lseek(s->fd, sector_num * 512, SEEK_SET);
  594:     ret = read(s->fd, buf, nb_sectors * 512);
  595:     if (ret != nb_sectors * 512) 
  596:         return -1;
  597:     return 0;
  598: }
  599: 
  600: static int raw_write(BlockDriverState *bs, int64_t sector_num, 
  601:                      const uint8_t *buf, int nb_sectors)
  602: {
  603:     BDRVRawState *s = bs->opaque;
  604:     int ret;
  605:     
  606:     lseek(s->fd, sector_num * 512, SEEK_SET);
  607:     ret = write(s->fd, buf, nb_sectors * 512);
  608:     if (ret != nb_sectors * 512) 
  609:         return -1;
  610:     return 0;
  611: }
  612: 
  613: static void raw_close(BlockDriverState *bs)
  614: {
  615:     BDRVRawState *s = bs->opaque;
  616:     close(s->fd);
  617: }
  618: 
  619: static int raw_create(const char *filename, int64_t total_size,
  620:                       const char *backing_file, int flags)
  621: {
  622:     int fd;
  623: 
  624:     if (flags || backing_file)
  625:         return -ENOTSUP;
  626: 
  627:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
  628:               0644);
  629:     if (fd < 0)
  630:         return -EIO;
  631:     ftruncate(fd, total_size * 512);
  632:     close(fd);
  633:     return 0;
  634: }
  635: 
  636: BlockDriver bdrv_raw = {
  637:     "raw",
  638:     sizeof(BDRVRawState),
  639:     raw_probe,
  640:     raw_open,
  641:     raw_read,
  642:     raw_write,
  643:     raw_close,
  644:     raw_create,
  645: };
  646: 
  647: void bdrv_init(void)
  648: {
  649:     bdrv_register(&bdrv_raw);
  650: #ifndef _WIN32
  651:     bdrv_register(&bdrv_cow);
  652: #endif
  653:     bdrv_register(&bdrv_qcow);
  654:     bdrv_register(&bdrv_vmdk);
  655:     bdrv_register(&bdrv_cloop);
  656:     bdrv_register(&bdrv_dmg);
  657:     bdrv_register(&bdrv_bochs);
  658:     bdrv_register(&bdrv_vpc);
  659:     bdrv_register(&bdrv_vvfat);
  660: }

unix.superglobalmegacorp.com