File:  [Qemu by Fabrice Bellard] / qemu / block.c
Revision 1.1.1.9 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:01:52 2018 UTC (19 months, 2 weeks ago) by root
Branches: qemu, MAIN
CVS tags: qemu0102, HEAD
qemu 0.10.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 "config-host.h"
   25: #ifdef _BSD
   26: /* include native header before sys-queue.h */
   27: #include <sys/queue.h>
   28: #endif
   29: 
   30: #include "qemu-common.h"
   31: #include "console.h"
   32: #include "block_int.h"
   33: 
   34: #ifdef _BSD
   35: #include <sys/types.h>
   36: #include <sys/stat.h>
   37: #include <sys/ioctl.h>
   38: #include <sys/disk.h>
   39: #endif
   40: 
   41: #define SECTOR_BITS 9
   42: #define SECTOR_SIZE (1 << SECTOR_BITS)
   43: 
   44: typedef struct BlockDriverAIOCBSync {
   45:     BlockDriverAIOCB common;
   46:     QEMUBH *bh;
   47:     int ret;
   48: } BlockDriverAIOCBSync;
   49: 
   50: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
   51:         int64_t sector_num, uint8_t *buf, int nb_sectors,
   52:         BlockDriverCompletionFunc *cb, void *opaque);
   53: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
   54:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
   55:         BlockDriverCompletionFunc *cb, void *opaque);
   56: static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
   57: static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
   58:                         uint8_t *buf, int nb_sectors);
   59: static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
   60:                          const uint8_t *buf, int nb_sectors);
   61: 
   62: BlockDriverState *bdrv_first;
   63: 
   64: static BlockDriver *first_drv;
   65: 
   66: int path_is_absolute(const char *path)
   67: {
   68:     const char *p;
   69: #ifdef _WIN32
   70:     /* specific case for names like: "\\.\d:" */
   71:     if (*path == '/' || *path == '\\')
   72:         return 1;
   73: #endif
   74:     p = strchr(path, ':');
   75:     if (p)
   76:         p++;
   77:     else
   78:         p = path;
   79: #ifdef _WIN32
   80:     return (*p == '/' || *p == '\\');
   81: #else
   82:     return (*p == '/');
   83: #endif
   84: }
   85: 
   86: /* if filename is absolute, just copy it to dest. Otherwise, build a
   87:    path to it by considering it is relative to base_path. URL are
   88:    supported. */
   89: void path_combine(char *dest, int dest_size,
   90:                   const char *base_path,
   91:                   const char *filename)
   92: {
   93:     const char *p, *p1;
   94:     int len;
   95: 
   96:     if (dest_size <= 0)
   97:         return;
   98:     if (path_is_absolute(filename)) {
   99:         pstrcpy(dest, dest_size, filename);
  100:     } else {
  101:         p = strchr(base_path, ':');
  102:         if (p)
  103:             p++;
  104:         else
  105:             p = base_path;
  106:         p1 = strrchr(base_path, '/');
  107: #ifdef _WIN32
  108:         {
  109:             const char *p2;
  110:             p2 = strrchr(base_path, '\\');
  111:             if (!p1 || p2 > p1)
  112:                 p1 = p2;
  113:         }
  114: #endif
  115:         if (p1)
  116:             p1++;
  117:         else
  118:             p1 = base_path;
  119:         if (p1 > p)
  120:             p = p1;
  121:         len = p - base_path;
  122:         if (len > dest_size - 1)
  123:             len = dest_size - 1;
  124:         memcpy(dest, base_path, len);
  125:         dest[len] = '\0';
  126:         pstrcat(dest, dest_size, filename);
  127:     }
  128: }
  129: 
  130: 
  131: static void bdrv_register(BlockDriver *bdrv)
  132: {
  133:     if (!bdrv->bdrv_aio_read) {
  134:         /* add AIO emulation layer */
  135:         bdrv->bdrv_aio_read = bdrv_aio_read_em;
  136:         bdrv->bdrv_aio_write = bdrv_aio_write_em;
  137:         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
  138:         bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
  139:     } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
  140:         /* add synchronous IO emulation layer */
  141:         bdrv->bdrv_read = bdrv_read_em;
  142:         bdrv->bdrv_write = bdrv_write_em;
  143:     }
  144:     bdrv->next = first_drv;
  145:     first_drv = bdrv;
  146: }
  147: 
  148: /* create a new block device (by default it is empty) */
  149: BlockDriverState *bdrv_new(const char *device_name)
  150: {
  151:     BlockDriverState **pbs, *bs;
  152: 
  153:     bs = qemu_mallocz(sizeof(BlockDriverState));
  154:     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
  155:     if (device_name[0] != '\0') {
  156:         /* insert at the end */
  157:         pbs = &bdrv_first;
  158:         while (*pbs != NULL)
  159:             pbs = &(*pbs)->next;
  160:         *pbs = bs;
  161:     }
  162:     return bs;
  163: }
  164: 
  165: BlockDriver *bdrv_find_format(const char *format_name)
  166: {
  167:     BlockDriver *drv1;
  168:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  169:         if (!strcmp(drv1->format_name, format_name))
  170:             return drv1;
  171:     }
  172:     return NULL;
  173: }
  174: 
  175: int bdrv_create(BlockDriver *drv,
  176:                 const char *filename, int64_t size_in_sectors,
  177:                 const char *backing_file, int flags)
  178: {
  179:     if (!drv->bdrv_create)
  180:         return -ENOTSUP;
  181:     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
  182: }
  183: 
  184: #ifdef _WIN32
  185: void get_tmp_filename(char *filename, int size)
  186: {
  187:     char temp_dir[MAX_PATH];
  188: 
  189:     GetTempPath(MAX_PATH, temp_dir);
  190:     GetTempFileName(temp_dir, "qem", 0, filename);
  191: }
  192: #else
  193: void get_tmp_filename(char *filename, int size)
  194: {
  195:     int fd;
  196:     const char *tmpdir;
  197:     /* XXX: race condition possible */
  198:     tmpdir = getenv("TMPDIR");
  199:     if (!tmpdir)
  200:         tmpdir = "/tmp";
  201:     snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
  202:     fd = mkstemp(filename);
  203:     close(fd);
  204: }
  205: #endif
  206: 
  207: #ifdef _WIN32
  208: static int is_windows_drive_prefix(const char *filename)
  209: {
  210:     return (((filename[0] >= 'a' && filename[0] <= 'z') ||
  211:              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
  212:             filename[1] == ':');
  213: }
  214: 
  215: static int is_windows_drive(const char *filename)
  216: {
  217:     if (is_windows_drive_prefix(filename) &&
  218:         filename[2] == '\0')
  219:         return 1;
  220:     if (strstart(filename, "\\\\.\\", NULL) ||
  221:         strstart(filename, "//./", NULL))
  222:         return 1;
  223:     return 0;
  224: }
  225: #endif
  226: 
  227: static BlockDriver *find_protocol(const char *filename)
  228: {
  229:     BlockDriver *drv1;
  230:     char protocol[128];
  231:     int len;
  232:     const char *p;
  233: 
  234: #ifdef _WIN32
  235:     if (is_windows_drive(filename) ||
  236:         is_windows_drive_prefix(filename))
  237:         return &bdrv_raw;
  238: #endif
  239:     p = strchr(filename, ':');
  240:     if (!p)
  241:         return &bdrv_raw;
  242:     len = p - filename;
  243:     if (len > sizeof(protocol) - 1)
  244:         len = sizeof(protocol) - 1;
  245:     memcpy(protocol, filename, len);
  246:     protocol[len] = '\0';
  247:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  248:         if (drv1->protocol_name &&
  249:             !strcmp(drv1->protocol_name, protocol))
  250:             return drv1;
  251:     }
  252:     return NULL;
  253: }
  254: 
  255: /* XXX: force raw format if block or character device ? It would
  256:    simplify the BSD case */
  257: static BlockDriver *find_image_format(const char *filename)
  258: {
  259:     int ret, score, score_max;
  260:     BlockDriver *drv1, *drv;
  261:     uint8_t buf[2048];
  262:     BlockDriverState *bs;
  263: 
  264:     /* detect host devices. By convention, /dev/cdrom[N] is always
  265:        recognized as a host CDROM */
  266:     if (strstart(filename, "/dev/cdrom", NULL))
  267:         return &bdrv_host_device;
  268: #ifdef _WIN32
  269:     if (is_windows_drive(filename))
  270:         return &bdrv_host_device;
  271: #else
  272:     {
  273:         struct stat st;
  274:         if (stat(filename, &st) >= 0 &&
  275:             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
  276:             return &bdrv_host_device;
  277:         }
  278:     }
  279: #endif
  280: 
  281:     drv = find_protocol(filename);
  282:     /* no need to test disk image formats for vvfat */
  283:     if (drv == &bdrv_vvfat)
  284:         return drv;
  285: 
  286:     ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
  287:     if (ret < 0)
  288:         return NULL;
  289:     ret = bdrv_pread(bs, 0, buf, sizeof(buf));
  290:     bdrv_delete(bs);
  291:     if (ret < 0) {
  292:         return NULL;
  293:     }
  294: 
  295:     score_max = 0;
  296:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  297:         if (drv1->bdrv_probe) {
  298:             score = drv1->bdrv_probe(buf, ret, filename);
  299:             if (score > score_max) {
  300:                 score_max = score;
  301:                 drv = drv1;
  302:             }
  303:         }
  304:     }
  305:     return drv;
  306: }
  307: 
  308: int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
  309: {
  310:     BlockDriverState *bs;
  311:     int ret;
  312: 
  313:     bs = bdrv_new("");
  314:     ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
  315:     if (ret < 0) {
  316:         bdrv_delete(bs);
  317:         return ret;
  318:     }
  319:     bs->growable = 1;
  320:     *pbs = bs;
  321:     return 0;
  322: }
  323: 
  324: int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
  325: {
  326:     return bdrv_open2(bs, filename, flags, NULL);
  327: }
  328: 
  329: int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
  330:                BlockDriver *drv)
  331: {
  332:     int ret, open_flags;
  333:     char tmp_filename[PATH_MAX];
  334:     char backing_filename[PATH_MAX];
  335: 
  336:     bs->read_only = 0;
  337:     bs->is_temporary = 0;
  338:     bs->encrypted = 0;
  339:     bs->valid_key = 0;
  340: 
  341:     if (flags & BDRV_O_SNAPSHOT) {
  342:         BlockDriverState *bs1;
  343:         int64_t total_size;
  344:         int is_protocol = 0;
  345: 
  346:         /* if snapshot, we create a temporary backing file and open it
  347:            instead of opening 'filename' directly */
  348: 
  349:         /* if there is a backing file, use it */
  350:         bs1 = bdrv_new("");
  351:         ret = bdrv_open(bs1, filename, 0);
  352:         if (ret < 0) {
  353:             bdrv_delete(bs1);
  354:             return ret;
  355:         }
  356:         total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
  357: 
  358:         if (bs1->drv && bs1->drv->protocol_name)
  359:             is_protocol = 1;
  360: 
  361:         bdrv_delete(bs1);
  362: 
  363:         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
  364: 
  365:         /* Real path is meaningless for protocols */
  366:         if (is_protocol)
  367:             snprintf(backing_filename, sizeof(backing_filename),
  368:                      "%s", filename);
  369:         else
  370:             realpath(filename, backing_filename);
  371: 
  372:         ret = bdrv_create(&bdrv_qcow2, tmp_filename,
  373:                           total_size, backing_filename, 0);
  374:         if (ret < 0) {
  375:             return ret;
  376:         }
  377:         filename = tmp_filename;
  378:         bs->is_temporary = 1;
  379:     }
  380: 
  381:     pstrcpy(bs->filename, sizeof(bs->filename), filename);
  382:     if (flags & BDRV_O_FILE) {
  383:         drv = find_protocol(filename);
  384:     } else if (!drv) {
  385:         drv = find_image_format(filename);
  386:     }
  387:     if (!drv) {
  388:         ret = -ENOENT;
  389:         goto unlink_and_fail;
  390:     }
  391:     bs->drv = drv;
  392:     bs->opaque = qemu_mallocz(drv->instance_size);
  393:     /* Note: for compatibility, we open disk image files as RDWR, and
  394:        RDONLY as fallback */
  395:     if (!(flags & BDRV_O_FILE))
  396:         open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK);
  397:     else
  398:         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
  399:     ret = drv->bdrv_open(bs, filename, open_flags);
  400:     if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
  401:         ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
  402:         bs->read_only = 1;
  403:     }
  404:     if (ret < 0) {
  405:         qemu_free(bs->opaque);
  406:         bs->opaque = NULL;
  407:         bs->drv = NULL;
  408:     unlink_and_fail:
  409:         if (bs->is_temporary)
  410:             unlink(filename);
  411:         return ret;
  412:     }
  413:     if (drv->bdrv_getlength) {
  414:         bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  415:     }
  416: #ifndef _WIN32
  417:     if (bs->is_temporary) {
  418:         unlink(filename);
  419:     }
  420: #endif
  421:     if (bs->backing_file[0] != '\0') {
  422:         /* if there is a backing file, use it */
  423:         bs->backing_hd = bdrv_new("");
  424:         path_combine(backing_filename, sizeof(backing_filename),
  425:                      filename, bs->backing_file);
  426:         ret = bdrv_open(bs->backing_hd, backing_filename, open_flags);
  427:         if (ret < 0) {
  428:             bdrv_close(bs);
  429:             return ret;
  430:         }
  431:     }
  432: 
  433:     /* call the change callback */
  434:     bs->media_changed = 1;
  435:     if (bs->change_cb)
  436:         bs->change_cb(bs->change_opaque);
  437: 
  438:     return 0;
  439: }
  440: 
  441: void bdrv_close(BlockDriverState *bs)
  442: {
  443:     if (bs->drv) {
  444:         if (bs->backing_hd)
  445:             bdrv_delete(bs->backing_hd);
  446:         bs->drv->bdrv_close(bs);
  447:         qemu_free(bs->opaque);
  448: #ifdef _WIN32
  449:         if (bs->is_temporary) {
  450:             unlink(bs->filename);
  451:         }
  452: #endif
  453:         bs->opaque = NULL;
  454:         bs->drv = NULL;
  455: 
  456:         /* call the change callback */
  457:         bs->media_changed = 1;
  458:         if (bs->change_cb)
  459:             bs->change_cb(bs->change_opaque);
  460:     }
  461: }
  462: 
  463: void bdrv_delete(BlockDriverState *bs)
  464: {
  465:     BlockDriverState **pbs;
  466: 
  467:     pbs = &bdrv_first;
  468:     while (*pbs != bs && *pbs != NULL)
  469:         pbs = &(*pbs)->next;
  470:     if (*pbs == bs)
  471:         *pbs = bs->next;
  472: 
  473:     bdrv_close(bs);
  474:     qemu_free(bs);
  475: }
  476: 
  477: /* commit COW file into the raw image */
  478: int bdrv_commit(BlockDriverState *bs)
  479: {
  480:     BlockDriver *drv = bs->drv;
  481:     int64_t i, total_sectors;
  482:     int n, j;
  483:     unsigned char sector[512];
  484: 
  485:     if (!drv)
  486:         return -ENOMEDIUM;
  487: 
  488:     if (bs->read_only) {
  489: 	return -EACCES;
  490:     }
  491: 
  492:     if (!bs->backing_hd) {
  493: 	return -ENOTSUP;
  494:     }
  495: 
  496:     total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  497:     for (i = 0; i < total_sectors;) {
  498:         if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  499:             for(j = 0; j < n; j++) {
  500:                 if (bdrv_read(bs, i, sector, 1) != 0) {
  501:                     return -EIO;
  502:                 }
  503: 
  504:                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
  505:                     return -EIO;
  506:                 }
  507:                 i++;
  508: 	    }
  509: 	} else {
  510:             i += n;
  511:         }
  512:     }
  513: 
  514:     if (drv->bdrv_make_empty)
  515: 	return drv->bdrv_make_empty(bs);
  516: 
  517:     return 0;
  518: }
  519: 
  520: static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
  521:                                    size_t size)
  522: {
  523:     int64_t len;
  524: 
  525:     if (!bdrv_is_inserted(bs))
  526:         return -ENOMEDIUM;
  527: 
  528:     if (bs->growable)
  529:         return 0;
  530: 
  531:     len = bdrv_getlength(bs);
  532: 
  533:     if ((offset + size) > len)
  534:         return -EIO;
  535: 
  536:     return 0;
  537: }
  538: 
  539: static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
  540:                               int nb_sectors)
  541: {
  542:     int64_t offset;
  543: 
  544:     /* Deal with byte accesses */
  545:     if (sector_num < 0)
  546:         offset = -sector_num;
  547:     else
  548:         offset = sector_num * 512;
  549: 
  550:     return bdrv_check_byte_request(bs, offset, nb_sectors * 512);
  551: }
  552: 
  553: /* return < 0 if error. See bdrv_write() for the return codes */
  554: int bdrv_read(BlockDriverState *bs, int64_t sector_num,
  555:               uint8_t *buf, int nb_sectors)
  556: {
  557:     BlockDriver *drv = bs->drv;
  558: 
  559:     if (!drv)
  560:         return -ENOMEDIUM;
  561:     if (bdrv_check_request(bs, sector_num, nb_sectors))
  562:         return -EIO;
  563: 
  564:     if (drv->bdrv_pread) {
  565:         int ret, len;
  566:         len = nb_sectors * 512;
  567:         ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
  568:         if (ret < 0)
  569:             return ret;
  570:         else if (ret != len)
  571:             return -EINVAL;
  572:         else {
  573: 	    bs->rd_bytes += (unsigned) len;
  574: 	    bs->rd_ops ++;
  575:             return 0;
  576: 	}
  577:     } else {
  578:         return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  579:     }
  580: }
  581: 
  582: /* Return < 0 if error. Important errors are:
  583:   -EIO         generic I/O error (may happen for all errors)
  584:   -ENOMEDIUM   No media inserted.
  585:   -EINVAL      Invalid sector number or nb_sectors
  586:   -EACCES      Trying to write a read-only device
  587: */
  588: int bdrv_write(BlockDriverState *bs, int64_t sector_num,
  589:                const uint8_t *buf, int nb_sectors)
  590: {
  591:     BlockDriver *drv = bs->drv;
  592:     if (!bs->drv)
  593:         return -ENOMEDIUM;
  594:     if (bs->read_only)
  595:         return -EACCES;
  596:     if (bdrv_check_request(bs, sector_num, nb_sectors))
  597:         return -EIO;
  598: 
  599:     if (drv->bdrv_pwrite) {
  600:         int ret, len, count = 0;
  601:         len = nb_sectors * 512;
  602:         do {
  603:             ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len - count);
  604:             if (ret < 0) {
  605:                 printf("bdrv_write ret=%d\n", ret);
  606:                 return ret;
  607:             }
  608:             count += ret;
  609:             buf += ret;
  610:         } while (count != len);
  611:         bs->wr_bytes += (unsigned) len;
  612:         bs->wr_ops ++;
  613:         return 0;
  614:     }
  615:     return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  616: }
  617: 
  618: static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
  619:                          uint8_t *buf, int count1)
  620: {
  621:     uint8_t tmp_buf[SECTOR_SIZE];
  622:     int len, nb_sectors, count;
  623:     int64_t sector_num;
  624: 
  625:     count = count1;
  626:     /* first read to align to sector start */
  627:     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  628:     if (len > count)
  629:         len = count;
  630:     sector_num = offset >> SECTOR_BITS;
  631:     if (len > 0) {
  632:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  633:             return -EIO;
  634:         memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
  635:         count -= len;
  636:         if (count == 0)
  637:             return count1;
  638:         sector_num++;
  639:         buf += len;
  640:     }
  641: 
  642:     /* read the sectors "in place" */
  643:     nb_sectors = count >> SECTOR_BITS;
  644:     if (nb_sectors > 0) {
  645:         if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
  646:             return -EIO;
  647:         sector_num += nb_sectors;
  648:         len = nb_sectors << SECTOR_BITS;
  649:         buf += len;
  650:         count -= len;
  651:     }
  652: 
  653:     /* add data from the last sector */
  654:     if (count > 0) {
  655:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  656:             return -EIO;
  657:         memcpy(buf, tmp_buf, count);
  658:     }
  659:     return count1;
  660: }
  661: 
  662: static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
  663:                           const uint8_t *buf, int count1)
  664: {
  665:     uint8_t tmp_buf[SECTOR_SIZE];
  666:     int len, nb_sectors, count;
  667:     int64_t sector_num;
  668: 
  669:     count = count1;
  670:     /* first write to align to sector start */
  671:     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  672:     if (len > count)
  673:         len = count;
  674:     sector_num = offset >> SECTOR_BITS;
  675:     if (len > 0) {
  676:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  677:             return -EIO;
  678:         memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
  679:         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  680:             return -EIO;
  681:         count -= len;
  682:         if (count == 0)
  683:             return count1;
  684:         sector_num++;
  685:         buf += len;
  686:     }
  687: 
  688:     /* write the sectors "in place" */
  689:     nb_sectors = count >> SECTOR_BITS;
  690:     if (nb_sectors > 0) {
  691:         if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
  692:             return -EIO;
  693:         sector_num += nb_sectors;
  694:         len = nb_sectors << SECTOR_BITS;
  695:         buf += len;
  696:         count -= len;
  697:     }
  698: 
  699:     /* add data from the last sector */
  700:     if (count > 0) {
  701:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  702:             return -EIO;
  703:         memcpy(tmp_buf, buf, count);
  704:         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  705:             return -EIO;
  706:     }
  707:     return count1;
  708: }
  709: 
  710: /**
  711:  * Read with byte offsets (needed only for file protocols)
  712:  */
  713: int bdrv_pread(BlockDriverState *bs, int64_t offset,
  714:                void *buf1, int count1)
  715: {
  716:     BlockDriver *drv = bs->drv;
  717: 
  718:     if (!drv)
  719:         return -ENOMEDIUM;
  720:     if (bdrv_check_byte_request(bs, offset, count1))
  721:         return -EIO;
  722: 
  723:     if (!drv->bdrv_pread)
  724:         return bdrv_pread_em(bs, offset, buf1, count1);
  725:     return drv->bdrv_pread(bs, offset, buf1, count1);
  726: }
  727: 
  728: /**
  729:  * Write with byte offsets (needed only for file protocols)
  730:  */
  731: int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
  732:                 const void *buf1, int count1)
  733: {
  734:     BlockDriver *drv = bs->drv;
  735: 
  736:     if (!drv)
  737:         return -ENOMEDIUM;
  738:     if (bdrv_check_byte_request(bs, offset, count1))
  739:         return -EIO;
  740: 
  741:     if (!drv->bdrv_pwrite)
  742:         return bdrv_pwrite_em(bs, offset, buf1, count1);
  743:     return drv->bdrv_pwrite(bs, offset, buf1, count1);
  744: }
  745: 
  746: /**
  747:  * Truncate file to 'offset' bytes (needed only for file protocols)
  748:  */
  749: int bdrv_truncate(BlockDriverState *bs, int64_t offset)
  750: {
  751:     BlockDriver *drv = bs->drv;
  752:     if (!drv)
  753:         return -ENOMEDIUM;
  754:     if (!drv->bdrv_truncate)
  755:         return -ENOTSUP;
  756:     return drv->bdrv_truncate(bs, offset);
  757: }
  758: 
  759: /**
  760:  * Length of a file in bytes. Return < 0 if error or unknown.
  761:  */
  762: int64_t bdrv_getlength(BlockDriverState *bs)
  763: {
  764:     BlockDriver *drv = bs->drv;
  765:     if (!drv)
  766:         return -ENOMEDIUM;
  767:     if (!drv->bdrv_getlength) {
  768:         /* legacy mode */
  769:         return bs->total_sectors * SECTOR_SIZE;
  770:     }
  771:     return drv->bdrv_getlength(bs);
  772: }
  773: 
  774: /* return 0 as number of sectors if no device present or error */
  775: void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
  776: {
  777:     int64_t length;
  778:     length = bdrv_getlength(bs);
  779:     if (length < 0)
  780:         length = 0;
  781:     else
  782:         length = length >> SECTOR_BITS;
  783:     *nb_sectors_ptr = length;
  784: }
  785: 
  786: struct partition {
  787:         uint8_t boot_ind;           /* 0x80 - active */
  788:         uint8_t head;               /* starting head */
  789:         uint8_t sector;             /* starting sector */
  790:         uint8_t cyl;                /* starting cylinder */
  791:         uint8_t sys_ind;            /* What partition type */
  792:         uint8_t end_head;           /* end head */
  793:         uint8_t end_sector;         /* end sector */
  794:         uint8_t end_cyl;            /* end cylinder */
  795:         uint32_t start_sect;        /* starting sector counting from 0 */
  796:         uint32_t nr_sects;          /* nr of sectors in partition */
  797: } __attribute__((packed));
  798: 
  799: /* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
  800: static int guess_disk_lchs(BlockDriverState *bs,
  801:                            int *pcylinders, int *pheads, int *psectors)
  802: {
  803:     uint8_t buf[512];
  804:     int ret, i, heads, sectors, cylinders;
  805:     struct partition *p;
  806:     uint32_t nr_sects;
  807:     uint64_t nb_sectors;
  808: 
  809:     bdrv_get_geometry(bs, &nb_sectors);
  810: 
  811:     ret = bdrv_read(bs, 0, buf, 1);
  812:     if (ret < 0)
  813:         return -1;
  814:     /* test msdos magic */
  815:     if (buf[510] != 0x55 || buf[511] != 0xaa)
  816:         return -1;
  817:     for(i = 0; i < 4; i++) {
  818:         p = ((struct partition *)(buf + 0x1be)) + i;
  819:         nr_sects = le32_to_cpu(p->nr_sects);
  820:         if (nr_sects && p->end_head) {
  821:             /* We make the assumption that the partition terminates on
  822:                a cylinder boundary */
  823:             heads = p->end_head + 1;
  824:             sectors = p->end_sector & 63;
  825:             if (sectors == 0)
  826:                 continue;
  827:             cylinders = nb_sectors / (heads * sectors);
  828:             if (cylinders < 1 || cylinders > 16383)
  829:                 continue;
  830:             *pheads = heads;
  831:             *psectors = sectors;
  832:             *pcylinders = cylinders;
  833: #if 0
  834:             printf("guessed geometry: LCHS=%d %d %d\n",
  835:                    cylinders, heads, sectors);
  836: #endif
  837:             return 0;
  838:         }
  839:     }
  840:     return -1;
  841: }
  842: 
  843: void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
  844: {
  845:     int translation, lba_detected = 0;
  846:     int cylinders, heads, secs;
  847:     uint64_t nb_sectors;
  848: 
  849:     /* if a geometry hint is available, use it */
  850:     bdrv_get_geometry(bs, &nb_sectors);
  851:     bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
  852:     translation = bdrv_get_translation_hint(bs);
  853:     if (cylinders != 0) {
  854:         *pcyls = cylinders;
  855:         *pheads = heads;
  856:         *psecs = secs;
  857:     } else {
  858:         if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
  859:             if (heads > 16) {
  860:                 /* if heads > 16, it means that a BIOS LBA
  861:                    translation was active, so the default
  862:                    hardware geometry is OK */
  863:                 lba_detected = 1;
  864:                 goto default_geometry;
  865:             } else {
  866:                 *pcyls = cylinders;
  867:                 *pheads = heads;
  868:                 *psecs = secs;
  869:                 /* disable any translation to be in sync with
  870:                    the logical geometry */
  871:                 if (translation == BIOS_ATA_TRANSLATION_AUTO) {
  872:                     bdrv_set_translation_hint(bs,
  873:                                               BIOS_ATA_TRANSLATION_NONE);
  874:                 }
  875:             }
  876:         } else {
  877:         default_geometry:
  878:             /* if no geometry, use a standard physical disk geometry */
  879:             cylinders = nb_sectors / (16 * 63);
  880: 
  881:             if (cylinders > 16383)
  882:                 cylinders = 16383;
  883:             else if (cylinders < 2)
  884:                 cylinders = 2;
  885:             *pcyls = cylinders;
  886:             *pheads = 16;
  887:             *psecs = 63;
  888:             if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
  889:                 if ((*pcyls * *pheads) <= 131072) {
  890:                     bdrv_set_translation_hint(bs,
  891:                                               BIOS_ATA_TRANSLATION_LARGE);
  892:                 } else {
  893:                     bdrv_set_translation_hint(bs,
  894:                                               BIOS_ATA_TRANSLATION_LBA);
  895:                 }
  896:             }
  897:         }
  898:         bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
  899:     }
  900: }
  901: 
  902: void bdrv_set_geometry_hint(BlockDriverState *bs,
  903:                             int cyls, int heads, int secs)
  904: {
  905:     bs->cyls = cyls;
  906:     bs->heads = heads;
  907:     bs->secs = secs;
  908: }
  909: 
  910: void bdrv_set_type_hint(BlockDriverState *bs, int type)
  911: {
  912:     bs->type = type;
  913:     bs->removable = ((type == BDRV_TYPE_CDROM ||
  914:                       type == BDRV_TYPE_FLOPPY));
  915: }
  916: 
  917: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
  918: {
  919:     bs->translation = translation;
  920: }
  921: 
  922: void bdrv_get_geometry_hint(BlockDriverState *bs,
  923:                             int *pcyls, int *pheads, int *psecs)
  924: {
  925:     *pcyls = bs->cyls;
  926:     *pheads = bs->heads;
  927:     *psecs = bs->secs;
  928: }
  929: 
  930: int bdrv_get_type_hint(BlockDriverState *bs)
  931: {
  932:     return bs->type;
  933: }
  934: 
  935: int bdrv_get_translation_hint(BlockDriverState *bs)
  936: {
  937:     return bs->translation;
  938: }
  939: 
  940: int bdrv_is_removable(BlockDriverState *bs)
  941: {
  942:     return bs->removable;
  943: }
  944: 
  945: int bdrv_is_read_only(BlockDriverState *bs)
  946: {
  947:     return bs->read_only;
  948: }
  949: 
  950: int bdrv_is_sg(BlockDriverState *bs)
  951: {
  952:     return bs->sg;
  953: }
  954: 
  955: /* XXX: no longer used */
  956: void bdrv_set_change_cb(BlockDriverState *bs,
  957:                         void (*change_cb)(void *opaque), void *opaque)
  958: {
  959:     bs->change_cb = change_cb;
  960:     bs->change_opaque = opaque;
  961: }
  962: 
  963: int bdrv_is_encrypted(BlockDriverState *bs)
  964: {
  965:     if (bs->backing_hd && bs->backing_hd->encrypted)
  966:         return 1;
  967:     return bs->encrypted;
  968: }
  969: 
  970: int bdrv_key_required(BlockDriverState *bs)
  971: {
  972:     BlockDriverState *backing_hd = bs->backing_hd;
  973: 
  974:     if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
  975:         return 1;
  976:     return (bs->encrypted && !bs->valid_key);
  977: }
  978: 
  979: int bdrv_set_key(BlockDriverState *bs, const char *key)
  980: {
  981:     int ret;
  982:     if (bs->backing_hd && bs->backing_hd->encrypted) {
  983:         ret = bdrv_set_key(bs->backing_hd, key);
  984:         if (ret < 0)
  985:             return ret;
  986:         if (!bs->encrypted)
  987:             return 0;
  988:     }
  989:     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
  990:         return -1;
  991:     ret = bs->drv->bdrv_set_key(bs, key);
  992:     bs->valid_key = (ret == 0);
  993:     return ret;
  994: }
  995: 
  996: void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
  997: {
  998:     if (!bs->drv) {
  999:         buf[0] = '\0';
 1000:     } else {
 1001:         pstrcpy(buf, buf_size, bs->drv->format_name);
 1002:     }
 1003: }
 1004: 
 1005: void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
 1006:                          void *opaque)
 1007: {
 1008:     BlockDriver *drv;
 1009: 
 1010:     for (drv = first_drv; drv != NULL; drv = drv->next) {
 1011:         it(opaque, drv->format_name);
 1012:     }
 1013: }
 1014: 
 1015: BlockDriverState *bdrv_find(const char *name)
 1016: {
 1017:     BlockDriverState *bs;
 1018: 
 1019:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
 1020:         if (!strcmp(name, bs->device_name))
 1021:             return bs;
 1022:     }
 1023:     return NULL;
 1024: }
 1025: 
 1026: void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
 1027: {
 1028:     BlockDriverState *bs;
 1029: 
 1030:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
 1031:         it(opaque, bs);
 1032:     }
 1033: }
 1034: 
 1035: const char *bdrv_get_device_name(BlockDriverState *bs)
 1036: {
 1037:     return bs->device_name;
 1038: }
 1039: 
 1040: void bdrv_flush(BlockDriverState *bs)
 1041: {
 1042:     if (bs->drv->bdrv_flush)
 1043:         bs->drv->bdrv_flush(bs);
 1044:     if (bs->backing_hd)
 1045:         bdrv_flush(bs->backing_hd);
 1046: }
 1047: 
 1048: void bdrv_flush_all(void)
 1049: {
 1050:     BlockDriverState *bs;
 1051: 
 1052:     for (bs = bdrv_first; bs != NULL; bs = bs->next)
 1053:         if (bs->drv && !bdrv_is_read_only(bs) && 
 1054:             (!bdrv_is_removable(bs) || bdrv_is_inserted(bs)))
 1055:             bdrv_flush(bs);
 1056: }
 1057: 
 1058: /*
 1059:  * Returns true iff the specified sector is present in the disk image. Drivers
 1060:  * not implementing the functionality are assumed to not support backing files,
 1061:  * hence all their sectors are reported as allocated.
 1062:  *
 1063:  * 'pnum' is set to the number of sectors (including and immediately following
 1064:  * the specified sector) that are known to be in the same
 1065:  * allocated/unallocated state.
 1066:  *
 1067:  * 'nb_sectors' is the max value 'pnum' should be set to.
 1068:  */
 1069: int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 1070: 	int *pnum)
 1071: {
 1072:     int64_t n;
 1073:     if (!bs->drv->bdrv_is_allocated) {
 1074:         if (sector_num >= bs->total_sectors) {
 1075:             *pnum = 0;
 1076:             return 0;
 1077:         }
 1078:         n = bs->total_sectors - sector_num;
 1079:         *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
 1080:         return 1;
 1081:     }
 1082:     return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
 1083: }
 1084: 
 1085: void bdrv_info(void)
 1086: {
 1087:     BlockDriverState *bs;
 1088: 
 1089:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
 1090:         term_printf("%s:", bs->device_name);
 1091:         term_printf(" type=");
 1092:         switch(bs->type) {
 1093:         case BDRV_TYPE_HD:
 1094:             term_printf("hd");
 1095:             break;
 1096:         case BDRV_TYPE_CDROM:
 1097:             term_printf("cdrom");
 1098:             break;
 1099:         case BDRV_TYPE_FLOPPY:
 1100:             term_printf("floppy");
 1101:             break;
 1102:         }
 1103:         term_printf(" removable=%d", bs->removable);
 1104:         if (bs->removable) {
 1105:             term_printf(" locked=%d", bs->locked);
 1106:         }
 1107:         if (bs->drv) {
 1108:             term_printf(" file=");
 1109: 	    term_print_filename(bs->filename);
 1110:             if (bs->backing_file[0] != '\0') {
 1111:                 term_printf(" backing_file=");
 1112: 		term_print_filename(bs->backing_file);
 1113: 	    }
 1114:             term_printf(" ro=%d", bs->read_only);
 1115:             term_printf(" drv=%s", bs->drv->format_name);
 1116:             term_printf(" encrypted=%d", bdrv_is_encrypted(bs));
 1117:         } else {
 1118:             term_printf(" [not inserted]");
 1119:         }
 1120:         term_printf("\n");
 1121:     }
 1122: }
 1123: 
 1124: /* The "info blockstats" command. */
 1125: void bdrv_info_stats (void)
 1126: {
 1127:     BlockDriverState *bs;
 1128: 
 1129:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
 1130: 	term_printf ("%s:"
 1131: 		     " rd_bytes=%" PRIu64
 1132: 		     " wr_bytes=%" PRIu64
 1133: 		     " rd_operations=%" PRIu64
 1134: 		     " wr_operations=%" PRIu64
 1135:                      "\n",
 1136: 		     bs->device_name,
 1137: 		     bs->rd_bytes, bs->wr_bytes,
 1138: 		     bs->rd_ops, bs->wr_ops);
 1139:     }
 1140: }
 1141: 
 1142: const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
 1143: {
 1144:     if (bs->backing_hd && bs->backing_hd->encrypted)
 1145:         return bs->backing_file;
 1146:     else if (bs->encrypted)
 1147:         return bs->filename;
 1148:     else
 1149:         return NULL;
 1150: }
 1151: 
 1152: void bdrv_get_backing_filename(BlockDriverState *bs,
 1153:                                char *filename, int filename_size)
 1154: {
 1155:     if (!bs->backing_hd) {
 1156:         pstrcpy(filename, filename_size, "");
 1157:     } else {
 1158:         pstrcpy(filename, filename_size, bs->backing_file);
 1159:     }
 1160: }
 1161: 
 1162: int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
 1163:                           const uint8_t *buf, int nb_sectors)
 1164: {
 1165:     BlockDriver *drv = bs->drv;
 1166:     if (!drv)
 1167:         return -ENOMEDIUM;
 1168:     if (!drv->bdrv_write_compressed)
 1169:         return -ENOTSUP;
 1170:     return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
 1171: }
 1172: 
 1173: int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 1174: {
 1175:     BlockDriver *drv = bs->drv;
 1176:     if (!drv)
 1177:         return -ENOMEDIUM;
 1178:     if (!drv->bdrv_get_info)
 1179:         return -ENOTSUP;
 1180:     memset(bdi, 0, sizeof(*bdi));
 1181:     return drv->bdrv_get_info(bs, bdi);
 1182: }
 1183: 
 1184: int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
 1185: {
 1186:     BlockDriver *drv = bs->drv;
 1187:     if (!drv)
 1188:         return -ENOMEDIUM;
 1189:     if (!drv->bdrv_put_buffer)
 1190:         return -ENOTSUP;
 1191:     return drv->bdrv_put_buffer(bs, buf, pos, size);
 1192: }
 1193: 
 1194: int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
 1195: {
 1196:     BlockDriver *drv = bs->drv;
 1197:     if (!drv)
 1198:         return -ENOMEDIUM;
 1199:     if (!drv->bdrv_get_buffer)
 1200:         return -ENOTSUP;
 1201:     return drv->bdrv_get_buffer(bs, buf, pos, size);
 1202: }
 1203: 
 1204: /**************************************************************/
 1205: /* handling of snapshots */
 1206: 
 1207: int bdrv_snapshot_create(BlockDriverState *bs,
 1208:                          QEMUSnapshotInfo *sn_info)
 1209: {
 1210:     BlockDriver *drv = bs->drv;
 1211:     if (!drv)
 1212:         return -ENOMEDIUM;
 1213:     if (!drv->bdrv_snapshot_create)
 1214:         return -ENOTSUP;
 1215:     return drv->bdrv_snapshot_create(bs, sn_info);
 1216: }
 1217: 
 1218: int bdrv_snapshot_goto(BlockDriverState *bs,
 1219:                        const char *snapshot_id)
 1220: {
 1221:     BlockDriver *drv = bs->drv;
 1222:     if (!drv)
 1223:         return -ENOMEDIUM;
 1224:     if (!drv->bdrv_snapshot_goto)
 1225:         return -ENOTSUP;
 1226:     return drv->bdrv_snapshot_goto(bs, snapshot_id);
 1227: }
 1228: 
 1229: int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
 1230: {
 1231:     BlockDriver *drv = bs->drv;
 1232:     if (!drv)
 1233:         return -ENOMEDIUM;
 1234:     if (!drv->bdrv_snapshot_delete)
 1235:         return -ENOTSUP;
 1236:     return drv->bdrv_snapshot_delete(bs, snapshot_id);
 1237: }
 1238: 
 1239: int bdrv_snapshot_list(BlockDriverState *bs,
 1240:                        QEMUSnapshotInfo **psn_info)
 1241: {
 1242:     BlockDriver *drv = bs->drv;
 1243:     if (!drv)
 1244:         return -ENOMEDIUM;
 1245:     if (!drv->bdrv_snapshot_list)
 1246:         return -ENOTSUP;
 1247:     return drv->bdrv_snapshot_list(bs, psn_info);
 1248: }
 1249: 
 1250: #define NB_SUFFIXES 4
 1251: 
 1252: char *get_human_readable_size(char *buf, int buf_size, int64_t size)
 1253: {
 1254:     static const char suffixes[NB_SUFFIXES] = "KMGT";
 1255:     int64_t base;
 1256:     int i;
 1257: 
 1258:     if (size <= 999) {
 1259:         snprintf(buf, buf_size, "%" PRId64, size);
 1260:     } else {
 1261:         base = 1024;
 1262:         for(i = 0; i < NB_SUFFIXES; i++) {
 1263:             if (size < (10 * base)) {
 1264:                 snprintf(buf, buf_size, "%0.1f%c",
 1265:                          (double)size / base,
 1266:                          suffixes[i]);
 1267:                 break;
 1268:             } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
 1269:                 snprintf(buf, buf_size, "%" PRId64 "%c",
 1270:                          ((size + (base >> 1)) / base),
 1271:                          suffixes[i]);
 1272:                 break;
 1273:             }
 1274:             base = base * 1024;
 1275:         }
 1276:     }
 1277:     return buf;
 1278: }
 1279: 
 1280: char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
 1281: {
 1282:     char buf1[128], date_buf[128], clock_buf[128];
 1283: #ifdef _WIN32
 1284:     struct tm *ptm;
 1285: #else
 1286:     struct tm tm;
 1287: #endif
 1288:     time_t ti;
 1289:     int64_t secs;
 1290: 
 1291:     if (!sn) {
 1292:         snprintf(buf, buf_size,
 1293:                  "%-10s%-20s%7s%20s%15s",
 1294:                  "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
 1295:     } else {
 1296:         ti = sn->date_sec;
 1297: #ifdef _WIN32
 1298:         ptm = localtime(&ti);
 1299:         strftime(date_buf, sizeof(date_buf),
 1300:                  "%Y-%m-%d %H:%M:%S", ptm);
 1301: #else
 1302:         localtime_r(&ti, &tm);
 1303:         strftime(date_buf, sizeof(date_buf),
 1304:                  "%Y-%m-%d %H:%M:%S", &tm);
 1305: #endif
 1306:         secs = sn->vm_clock_nsec / 1000000000;
 1307:         snprintf(clock_buf, sizeof(clock_buf),
 1308:                  "%02d:%02d:%02d.%03d",
 1309:                  (int)(secs / 3600),
 1310:                  (int)((secs / 60) % 60),
 1311:                  (int)(secs % 60),
 1312:                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
 1313:         snprintf(buf, buf_size,
 1314:                  "%-10s%-20s%7s%20s%15s",
 1315:                  sn->id_str, sn->name,
 1316:                  get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
 1317:                  date_buf,
 1318:                  clock_buf);
 1319:     }
 1320:     return buf;
 1321: }
 1322: 
 1323: 
 1324: /**************************************************************/
 1325: /* async I/Os */
 1326: 
 1327: typedef struct VectorTranslationState {
 1328:     QEMUIOVector *iov;
 1329:     uint8_t *bounce;
 1330:     int is_write;
 1331:     BlockDriverAIOCB *aiocb;
 1332:     BlockDriverAIOCB *this_aiocb;
 1333: } VectorTranslationState;
 1334: 
 1335: static void bdrv_aio_rw_vector_cb(void *opaque, int ret)
 1336: {
 1337:     VectorTranslationState *s = opaque;
 1338: 
 1339:     if (!s->is_write) {
 1340:         qemu_iovec_from_buffer(s->iov, s->bounce, s->iov->size);
 1341:     }
 1342:     qemu_vfree(s->bounce);
 1343:     s->this_aiocb->cb(s->this_aiocb->opaque, ret);
 1344:     qemu_aio_release(s->this_aiocb);
 1345: }
 1346: 
 1347: static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
 1348:                                             int64_t sector_num,
 1349:                                             QEMUIOVector *iov,
 1350:                                             int nb_sectors,
 1351:                                             BlockDriverCompletionFunc *cb,
 1352:                                             void *opaque,
 1353:                                             int is_write)
 1354: 
 1355: {
 1356:     VectorTranslationState *s = qemu_mallocz(sizeof(*s));
 1357:     BlockDriverAIOCB *aiocb = qemu_aio_get(bs, cb, opaque);
 1358: 
 1359:     s->this_aiocb = aiocb;
 1360:     s->iov = iov;
 1361:     s->bounce = qemu_memalign(512, nb_sectors * 512);
 1362:     s->is_write = is_write;
 1363:     if (is_write) {
 1364:         qemu_iovec_to_buffer(s->iov, s->bounce);
 1365:         s->aiocb = bdrv_aio_write(bs, sector_num, s->bounce, nb_sectors,
 1366:                                   bdrv_aio_rw_vector_cb, s);
 1367:     } else {
 1368:         s->aiocb = bdrv_aio_read(bs, sector_num, s->bounce, nb_sectors,
 1369:                                  bdrv_aio_rw_vector_cb, s);
 1370:     }
 1371:     return aiocb;
 1372: }
 1373: 
 1374: BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
 1375:                                  QEMUIOVector *iov, int nb_sectors,
 1376:                                  BlockDriverCompletionFunc *cb, void *opaque)
 1377: {
 1378:     if (bdrv_check_request(bs, sector_num, nb_sectors))
 1379:         return NULL;
 1380: 
 1381:     return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
 1382:                               cb, opaque, 0);
 1383: }
 1384: 
 1385: BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
 1386:                                   QEMUIOVector *iov, int nb_sectors,
 1387:                                   BlockDriverCompletionFunc *cb, void *opaque)
 1388: {
 1389:     if (bdrv_check_request(bs, sector_num, nb_sectors))
 1390:         return NULL;
 1391: 
 1392:     return bdrv_aio_rw_vector(bs, sector_num, iov, nb_sectors,
 1393:                               cb, opaque, 1);
 1394: }
 1395: 
 1396: BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
 1397:                                 uint8_t *buf, int nb_sectors,
 1398:                                 BlockDriverCompletionFunc *cb, void *opaque)
 1399: {
 1400:     BlockDriver *drv = bs->drv;
 1401:     BlockDriverAIOCB *ret;
 1402: 
 1403:     if (!drv)
 1404:         return NULL;
 1405:     if (bdrv_check_request(bs, sector_num, nb_sectors))
 1406:         return NULL;
 1407: 
 1408:     ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
 1409: 
 1410:     if (ret) {
 1411: 	/* Update stats even though technically transfer has not happened. */
 1412: 	bs->rd_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
 1413: 	bs->rd_ops ++;
 1414:     }
 1415: 
 1416:     return ret;
 1417: }
 1418: 
 1419: BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
 1420:                                  const uint8_t *buf, int nb_sectors,
 1421:                                  BlockDriverCompletionFunc *cb, void *opaque)
 1422: {
 1423:     BlockDriver *drv = bs->drv;
 1424:     BlockDriverAIOCB *ret;
 1425: 
 1426:     if (!drv)
 1427:         return NULL;
 1428:     if (bs->read_only)
 1429:         return NULL;
 1430:     if (bdrv_check_request(bs, sector_num, nb_sectors))
 1431:         return NULL;
 1432: 
 1433:     ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
 1434: 
 1435:     if (ret) {
 1436: 	/* Update stats even though technically transfer has not happened. */
 1437: 	bs->wr_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
 1438: 	bs->wr_ops ++;
 1439:     }
 1440: 
 1441:     return ret;
 1442: }
 1443: 
 1444: void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 1445: {
 1446:     BlockDriver *drv = acb->bs->drv;
 1447: 
 1448:     if (acb->cb == bdrv_aio_rw_vector_cb) {
 1449:         VectorTranslationState *s = acb->opaque;
 1450:         acb = s->aiocb;
 1451:     }
 1452: 
 1453:     drv->bdrv_aio_cancel(acb);
 1454: }
 1455: 
 1456: 
 1457: /**************************************************************/
 1458: /* async block device emulation */
 1459: 
 1460: static void bdrv_aio_bh_cb(void *opaque)
 1461: {
 1462:     BlockDriverAIOCBSync *acb = opaque;
 1463:     acb->common.cb(acb->common.opaque, acb->ret);
 1464:     qemu_aio_release(acb);
 1465: }
 1466: 
 1467: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
 1468:         int64_t sector_num, uint8_t *buf, int nb_sectors,
 1469:         BlockDriverCompletionFunc *cb, void *opaque)
 1470: {
 1471:     BlockDriverAIOCBSync *acb;
 1472:     int ret;
 1473: 
 1474:     acb = qemu_aio_get(bs, cb, opaque);
 1475:     if (!acb->bh)
 1476:         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 1477:     ret = bdrv_read(bs, sector_num, buf, nb_sectors);
 1478:     acb->ret = ret;
 1479:     qemu_bh_schedule(acb->bh);
 1480:     return &acb->common;
 1481: }
 1482: 
 1483: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
 1484:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
 1485:         BlockDriverCompletionFunc *cb, void *opaque)
 1486: {
 1487:     BlockDriverAIOCBSync *acb;
 1488:     int ret;
 1489: 
 1490:     acb = qemu_aio_get(bs, cb, opaque);
 1491:     if (!acb->bh)
 1492:         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 1493:     ret = bdrv_write(bs, sector_num, buf, nb_sectors);
 1494:     acb->ret = ret;
 1495:     qemu_bh_schedule(acb->bh);
 1496:     return &acb->common;
 1497: }
 1498: 
 1499: static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 1500: {
 1501:     BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
 1502:     qemu_bh_cancel(acb->bh);
 1503:     qemu_aio_release(acb);
 1504: }
 1505: 
 1506: /**************************************************************/
 1507: /* sync block device emulation */
 1508: 
 1509: static void bdrv_rw_em_cb(void *opaque, int ret)
 1510: {
 1511:     *(int *)opaque = ret;
 1512: }
 1513: 
 1514: #define NOT_DONE 0x7fffffff
 1515: 
 1516: static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
 1517:                         uint8_t *buf, int nb_sectors)
 1518: {
 1519:     int async_ret;
 1520:     BlockDriverAIOCB *acb;
 1521: 
 1522:     async_ret = NOT_DONE;
 1523:     acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
 1524:                         bdrv_rw_em_cb, &async_ret);
 1525:     if (acb == NULL)
 1526:         return -1;
 1527: 
 1528:     while (async_ret == NOT_DONE) {
 1529:         qemu_aio_wait();
 1530:     }
 1531: 
 1532:     return async_ret;
 1533: }
 1534: 
 1535: static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
 1536:                          const uint8_t *buf, int nb_sectors)
 1537: {
 1538:     int async_ret;
 1539:     BlockDriverAIOCB *acb;
 1540: 
 1541:     async_ret = NOT_DONE;
 1542:     acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
 1543:                          bdrv_rw_em_cb, &async_ret);
 1544:     if (acb == NULL)
 1545:         return -1;
 1546:     while (async_ret == NOT_DONE) {
 1547:         qemu_aio_wait();
 1548:     }
 1549:     return async_ret;
 1550: }
 1551: 
 1552: void bdrv_init(void)
 1553: {
 1554:     bdrv_register(&bdrv_raw);
 1555:     bdrv_register(&bdrv_host_device);
 1556: #ifndef _WIN32
 1557:     bdrv_register(&bdrv_cow);
 1558: #endif
 1559:     bdrv_register(&bdrv_qcow);
 1560:     bdrv_register(&bdrv_vmdk);
 1561:     bdrv_register(&bdrv_cloop);
 1562:     bdrv_register(&bdrv_dmg);
 1563:     bdrv_register(&bdrv_bochs);
 1564:     bdrv_register(&bdrv_vpc);
 1565:     bdrv_register(&bdrv_vvfat);
 1566:     bdrv_register(&bdrv_qcow2);
 1567:     bdrv_register(&bdrv_parallels);
 1568:     bdrv_register(&bdrv_nbd);
 1569: }
 1570: 
 1571: void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
 1572:                    void *opaque)
 1573: {
 1574:     BlockDriver *drv;
 1575:     BlockDriverAIOCB *acb;
 1576: 
 1577:     drv = bs->drv;
 1578:     if (drv->free_aiocb) {
 1579:         acb = drv->free_aiocb;
 1580:         drv->free_aiocb = acb->next;
 1581:     } else {
 1582:         acb = qemu_mallocz(drv->aiocb_size);
 1583:     }
 1584:     acb->bs = bs;
 1585:     acb->cb = cb;
 1586:     acb->opaque = opaque;
 1587:     return acb;
 1588: }
 1589: 
 1590: void qemu_aio_release(void *p)
 1591: {
 1592:     BlockDriverAIOCB *acb = p;
 1593:     BlockDriver *drv = acb->bs->drv;
 1594:     acb->next = drv->free_aiocb;
 1595:     drv->free_aiocb = acb;
 1596: }
 1597: 
 1598: /**************************************************************/
 1599: /* removable device support */
 1600: 
 1601: /**
 1602:  * Return TRUE if the media is present
 1603:  */
 1604: int bdrv_is_inserted(BlockDriverState *bs)
 1605: {
 1606:     BlockDriver *drv = bs->drv;
 1607:     int ret;
 1608:     if (!drv)
 1609:         return 0;
 1610:     if (!drv->bdrv_is_inserted)
 1611:         return 1;
 1612:     ret = drv->bdrv_is_inserted(bs);
 1613:     return ret;
 1614: }
 1615: 
 1616: /**
 1617:  * Return TRUE if the media changed since the last call to this
 1618:  * function. It is currently only used for floppy disks
 1619:  */
 1620: int bdrv_media_changed(BlockDriverState *bs)
 1621: {
 1622:     BlockDriver *drv = bs->drv;
 1623:     int ret;
 1624: 
 1625:     if (!drv || !drv->bdrv_media_changed)
 1626:         ret = -ENOTSUP;
 1627:     else
 1628:         ret = drv->bdrv_media_changed(bs);
 1629:     if (ret == -ENOTSUP)
 1630:         ret = bs->media_changed;
 1631:     bs->media_changed = 0;
 1632:     return ret;
 1633: }
 1634: 
 1635: /**
 1636:  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
 1637:  */
 1638: void bdrv_eject(BlockDriverState *bs, int eject_flag)
 1639: {
 1640:     BlockDriver *drv = bs->drv;
 1641:     int ret;
 1642: 
 1643:     if (!drv || !drv->bdrv_eject) {
 1644:         ret = -ENOTSUP;
 1645:     } else {
 1646:         ret = drv->bdrv_eject(bs, eject_flag);
 1647:     }
 1648:     if (ret == -ENOTSUP) {
 1649:         if (eject_flag)
 1650:             bdrv_close(bs);
 1651:     }
 1652: }
 1653: 
 1654: int bdrv_is_locked(BlockDriverState *bs)
 1655: {
 1656:     return bs->locked;
 1657: }
 1658: 
 1659: /**
 1660:  * Lock or unlock the media (if it is locked, the user won't be able
 1661:  * to eject it manually).
 1662:  */
 1663: void bdrv_set_locked(BlockDriverState *bs, int locked)
 1664: {
 1665:     BlockDriver *drv = bs->drv;
 1666: 
 1667:     bs->locked = locked;
 1668:     if (drv && drv->bdrv_set_locked) {
 1669:         drv->bdrv_set_locked(bs, locked);
 1670:     }
 1671: }
 1672: 
 1673: /* needed for generic scsi interface */
 1674: 
 1675: int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
 1676: {
 1677:     BlockDriver *drv = bs->drv;
 1678: 
 1679:     if (drv && drv->bdrv_ioctl)
 1680:         return drv->bdrv_ioctl(bs, req, buf);
 1681:     return -ENOTSUP;
 1682: }

unix.superglobalmegacorp.com