Annotation of qemu/block.c, revision 1.1.1.5

1.1       root        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: 
1.1.1.5 ! root       35: #define SECTOR_BITS 9
        !            36: #define SECTOR_SIZE (1 << SECTOR_BITS)
1.1.1.2   root       37: 
1.1.1.5 ! root       38: typedef struct BlockDriverAIOCBSync {
        !            39:     BlockDriverAIOCB common;
        !            40:     QEMUBH *bh;
        !            41:     int ret;
        !            42: } BlockDriverAIOCBSync;
        !            43: 
        !            44: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
        !            45:         int64_t sector_num, uint8_t *buf, int nb_sectors,
        !            46:         BlockDriverCompletionFunc *cb, void *opaque);
        !            47: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
        !            48:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
        !            49:         BlockDriverCompletionFunc *cb, void *opaque);
        !            50: static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
        !            51: static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
        !            52:                         uint8_t *buf, int nb_sectors);
        !            53: static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
        !            54:                          const uint8_t *buf, int nb_sectors);
1.1.1.3   root       55: 
1.1       root       56: static BlockDriverState *bdrv_first;
                     57: static BlockDriver *first_drv;
                     58: 
1.1.1.5 ! root       59: int path_is_absolute(const char *path)
        !            60: {
        !            61:     const char *p;
        !            62: #ifdef _WIN32
        !            63:     /* specific case for names like: "\\.\d:" */
        !            64:     if (*path == '/' || *path == '\\')
        !            65:         return 1;
        !            66: #endif
        !            67:     p = strchr(path, ':');
        !            68:     if (p)
        !            69:         p++;
        !            70:     else
        !            71:         p = path;
        !            72: #ifdef _WIN32
        !            73:     return (*p == '/' || *p == '\\');
        !            74: #else
        !            75:     return (*p == '/');
        !            76: #endif
1.1.1.2   root       77: }
                     78: 
1.1.1.5 ! root       79: /* if filename is absolute, just copy it to dest. Otherwise, build a
        !            80:    path to it by considering it is relative to base_path. URL are
        !            81:    supported. */
        !            82: void path_combine(char *dest, int dest_size,
        !            83:                   const char *base_path,
        !            84:                   const char *filename)
        !            85: {
        !            86:     const char *p, *p1;
        !            87:     int len;
        !            88: 
        !            89:     if (dest_size <= 0)
        !            90:         return;
        !            91:     if (path_is_absolute(filename)) {
        !            92:         pstrcpy(dest, dest_size, filename);
        !            93:     } else {
        !            94:         p = strchr(base_path, ':');
        !            95:         if (p)
        !            96:             p++;
        !            97:         else
        !            98:             p = base_path;
        !            99:         p1 = strrchr(base_path, '/');
        !           100: #ifdef _WIN32
        !           101:         {
        !           102:             const char *p2;
        !           103:             p2 = strrchr(base_path, '\\');
        !           104:             if (!p1 || p2 > p1)
        !           105:                 p1 = p2;
1.1.1.2   root      106:         }
1.1.1.5 ! root      107: #endif
        !           108:         if (p1)
        !           109:             p1++;
        !           110:         else
        !           111:             p1 = base_path;
        !           112:         if (p1 > p)
        !           113:             p = p1;
        !           114:         len = p - base_path;
        !           115:         if (len > dest_size - 1)
        !           116:             len = dest_size - 1;
        !           117:         memcpy(dest, base_path, len);
        !           118:         dest[len] = '\0';
        !           119:         pstrcat(dest, dest_size, filename);
1.1.1.2   root      120:     }
                    121: }
                    122: 
                    123: 
1.1       root      124: void bdrv_register(BlockDriver *bdrv)
                    125: {
1.1.1.5 ! root      126:     if (!bdrv->bdrv_aio_read) {
        !           127:         /* add AIO emulation layer */
        !           128:         bdrv->bdrv_aio_read = bdrv_aio_read_em;
        !           129:         bdrv->bdrv_aio_write = bdrv_aio_write_em;
        !           130:         bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
        !           131:         bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
        !           132:     } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
        !           133:         /* add synchronous IO emulation layer */
        !           134:         bdrv->bdrv_read = bdrv_read_em;
        !           135:         bdrv->bdrv_write = bdrv_write_em;
        !           136:     }
1.1       root      137:     bdrv->next = first_drv;
                    138:     first_drv = bdrv;
                    139: }
                    140: 
                    141: /* create a new block device (by default it is empty) */
                    142: BlockDriverState *bdrv_new(const char *device_name)
                    143: {
                    144:     BlockDriverState **pbs, *bs;
                    145: 
                    146:     bs = qemu_mallocz(sizeof(BlockDriverState));
                    147:     if(!bs)
                    148:         return NULL;
                    149:     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
                    150:     if (device_name[0] != '\0') {
                    151:         /* insert at the end */
                    152:         pbs = &bdrv_first;
                    153:         while (*pbs != NULL)
                    154:             pbs = &(*pbs)->next;
                    155:         *pbs = bs;
                    156:     }
                    157:     return bs;
                    158: }
                    159: 
                    160: BlockDriver *bdrv_find_format(const char *format_name)
                    161: {
                    162:     BlockDriver *drv1;
                    163:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
                    164:         if (!strcmp(drv1->format_name, format_name))
                    165:             return drv1;
                    166:     }
                    167:     return NULL;
                    168: }
                    169: 
                    170: int bdrv_create(BlockDriver *drv, 
                    171:                 const char *filename, int64_t size_in_sectors,
                    172:                 const char *backing_file, int flags)
                    173: {
                    174:     if (!drv->bdrv_create)
                    175:         return -ENOTSUP;
                    176:     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
                    177: }
                    178: 
                    179: #ifdef _WIN32
1.1.1.2   root      180: void get_tmp_filename(char *filename, int size)
1.1       root      181: {
1.1.1.5 ! root      182:     char temp_dir[MAX_PATH];
        !           183:     
        !           184:     GetTempPath(MAX_PATH, temp_dir);
        !           185:     GetTempFileName(temp_dir, "qem", 0, filename);
1.1       root      186: }
                    187: #else
1.1.1.2   root      188: void get_tmp_filename(char *filename, int size)
1.1       root      189: {
                    190:     int fd;
                    191:     /* XXX: race condition possible */
                    192:     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
                    193:     fd = mkstemp(filename);
                    194:     close(fd);
                    195: }
                    196: #endif
                    197: 
1.1.1.5 ! root      198: #ifdef _WIN32
        !           199: static int is_windows_drive_prefix(const char *filename)
        !           200: {
        !           201:     return (((filename[0] >= 'a' && filename[0] <= 'z') ||
        !           202:              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
        !           203:             filename[1] == ':');
        !           204: }
        !           205:     
        !           206: static int is_windows_drive(const char *filename)
        !           207: {
        !           208:     if (is_windows_drive_prefix(filename) && 
        !           209:         filename[2] == '\0')
        !           210:         return 1;
        !           211:     if (strstart(filename, "\\\\.\\", NULL) ||
        !           212:         strstart(filename, "//./", NULL))
        !           213:         return 1;
        !           214:     return 0;
        !           215: }
        !           216: #endif
        !           217: 
        !           218: static BlockDriver *find_protocol(const char *filename)
        !           219: {
        !           220:     BlockDriver *drv1;
        !           221:     char protocol[128];
        !           222:     int len;
        !           223:     const char *p;
        !           224: 
        !           225: #ifdef _WIN32
        !           226:     if (is_windows_drive(filename) ||
        !           227:         is_windows_drive_prefix(filename))
        !           228:         return &bdrv_raw;
        !           229: #endif
        !           230:     p = strchr(filename, ':');
        !           231:     if (!p)
        !           232:         return &bdrv_raw;
        !           233:     len = p - filename;
        !           234:     if (len > sizeof(protocol) - 1)
        !           235:         len = sizeof(protocol) - 1;
        !           236:     memcpy(protocol, filename, len);
        !           237:     protocol[len] = '\0';
        !           238:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
        !           239:         if (drv1->protocol_name && 
        !           240:             !strcmp(drv1->protocol_name, protocol))
        !           241:             return drv1;
        !           242:     }
        !           243:     return NULL;
        !           244: }
        !           245: 
1.1       root      246: /* XXX: force raw format if block or character device ? It would
                    247:    simplify the BSD case */
                    248: static BlockDriver *find_image_format(const char *filename)
                    249: {
1.1.1.5 ! root      250:     int ret, score, score_max;
1.1       root      251:     BlockDriver *drv1, *drv;
1.1.1.5 ! root      252:     uint8_t buf[2048];
        !           253:     BlockDriverState *bs;
        !           254:     
        !           255:     /* detect host devices. By convention, /dev/cdrom[N] is always
        !           256:        recognized as a host CDROM */
        !           257:     if (strstart(filename, "/dev/cdrom", NULL))
        !           258:         return &bdrv_host_device;
        !           259: #ifdef _WIN32
        !           260:     if (is_windows_drive(filename))
        !           261:         return &bdrv_host_device;
        !           262: #else
        !           263:     {
        !           264:         struct stat st;
        !           265:         if (stat(filename, &st) >= 0 && 
        !           266:             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
        !           267:             return &bdrv_host_device;
1.1       root      268:         }
                    269:     }
1.1.1.5 ! root      270: #endif
1.1       root      271:     
1.1.1.5 ! root      272:     drv = find_protocol(filename);
        !           273:     /* no need to test disk image formats for vvfat */
        !           274:     if (drv == &bdrv_vvfat)
        !           275:         return drv;
        !           276: 
        !           277:     ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
        !           278:     if (ret < 0)
        !           279:         return NULL;
        !           280:     ret = bdrv_pread(bs, 0, buf, sizeof(buf));
        !           281:     bdrv_delete(bs);
        !           282:     if (ret < 0) {
        !           283:         return NULL;
        !           284:     }
        !           285: 
1.1       root      286:     score_max = 0;
                    287:     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
1.1.1.5 ! root      288:         if (drv1->bdrv_probe) {
        !           289:             score = drv1->bdrv_probe(buf, ret, filename);
        !           290:             if (score > score_max) {
        !           291:                 score_max = score;
        !           292:                 drv = drv1;
        !           293:             }
1.1       root      294:         }
                    295:     }
                    296:     return drv;
                    297: }
                    298: 
1.1.1.5 ! root      299: int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
1.1       root      300: {
1.1.1.5 ! root      301:     BlockDriverState *bs;
        !           302:     int ret;
        !           303: 
        !           304:     bs = bdrv_new("");
        !           305:     if (!bs)
        !           306:         return -ENOMEM;
        !           307:     ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
        !           308:     if (ret < 0) {
        !           309:         bdrv_delete(bs);
        !           310:         return ret;
1.1.1.2   root      311:     }
1.1.1.5 ! root      312:     *pbs = bs;
        !           313:     return 0;
        !           314: }
        !           315: 
        !           316: int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
        !           317: {
        !           318:     return bdrv_open2(bs, filename, flags, NULL);
1.1       root      319: }
                    320: 
1.1.1.5 ! root      321: int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
1.1       root      322:                BlockDriver *drv)
                    323: {
1.1.1.5 ! root      324:     int ret, open_flags;
1.1       root      325:     char tmp_filename[1024];
1.1.1.5 ! root      326:     char backing_filename[1024];
1.1       root      327:     
                    328:     bs->read_only = 0;
                    329:     bs->is_temporary = 0;
                    330:     bs->encrypted = 0;
                    331: 
1.1.1.5 ! root      332:     if (flags & BDRV_O_SNAPSHOT) {
1.1       root      333:         BlockDriverState *bs1;
                    334:         int64_t total_size;
                    335:         
                    336:         /* if snapshot, we create a temporary backing file and open it
                    337:            instead of opening 'filename' directly */
                    338: 
                    339:         /* if there is a backing file, use it */
                    340:         bs1 = bdrv_new("");
                    341:         if (!bs1) {
1.1.1.5 ! root      342:             return -ENOMEM;
1.1       root      343:         }
                    344:         if (bdrv_open(bs1, filename, 0) < 0) {
                    345:             bdrv_delete(bs1);
                    346:             return -1;
                    347:         }
1.1.1.5 ! root      348:         total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
1.1       root      349:         bdrv_delete(bs1);
                    350:         
                    351:         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
1.1.1.5 ! root      352:         realpath(filename, backing_filename);
        !           353:         if (bdrv_create(&bdrv_qcow2, tmp_filename, 
        !           354:                         total_size, backing_filename, 0) < 0) {
1.1       root      355:             return -1;
                    356:         }
                    357:         filename = tmp_filename;
                    358:         bs->is_temporary = 1;
                    359:     }
                    360: 
                    361:     pstrcpy(bs->filename, sizeof(bs->filename), filename);
1.1.1.5 ! root      362:     if (flags & BDRV_O_FILE) {
        !           363:         drv = find_protocol(filename);
1.1       root      364:         if (!drv)
1.1.1.5 ! root      365:             return -ENOENT;
        !           366:     } else {
        !           367:         if (!drv) {
        !           368:             drv = find_image_format(filename);
        !           369:             if (!drv)
        !           370:                 return -1;
        !           371:         }
1.1       root      372:     }
                    373:     bs->drv = drv;
                    374:     bs->opaque = qemu_mallocz(drv->instance_size);
                    375:     if (bs->opaque == NULL && drv->instance_size > 0)
                    376:         return -1;
1.1.1.5 ! root      377:     /* Note: for compatibility, we open disk image files as RDWR, and
        !           378:        RDONLY as fallback */
        !           379:     if (!(flags & BDRV_O_FILE))
        !           380:         open_flags = BDRV_O_RDWR;
        !           381:     else
        !           382:         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
        !           383:     ret = drv->bdrv_open(bs, filename, open_flags);
        !           384:     if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
        !           385:         ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
        !           386:         bs->read_only = 1;
        !           387:     }
1.1       root      388:     if (ret < 0) {
                    389:         qemu_free(bs->opaque);
1.1.1.5 ! root      390:         bs->opaque = NULL;
        !           391:         bs->drv = NULL;
        !           392:         return ret;
        !           393:     }
        !           394:     if (drv->bdrv_getlength) {
        !           395:         bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
1.1       root      396:     }
                    397: #ifndef _WIN32
                    398:     if (bs->is_temporary) {
                    399:         unlink(filename);
                    400:     }
                    401: #endif
1.1.1.5 ! root      402:     if (bs->backing_file[0] != '\0') {
1.1       root      403:         /* if there is a backing file, use it */
                    404:         bs->backing_hd = bdrv_new("");
                    405:         if (!bs->backing_hd) {
                    406:         fail:
                    407:             bdrv_close(bs);
1.1.1.5 ! root      408:             return -ENOMEM;
1.1       root      409:         }
1.1.1.5 ! root      410:         path_combine(backing_filename, sizeof(backing_filename),
        !           411:                      filename, bs->backing_file);
        !           412:         if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
1.1       root      413:             goto fail;
                    414:     }
                    415: 
                    416:     /* call the change callback */
1.1.1.5 ! root      417:     bs->media_changed = 1;
1.1       root      418:     if (bs->change_cb)
                    419:         bs->change_cb(bs->change_opaque);
                    420: 
                    421:     return 0;
                    422: }
                    423: 
                    424: void bdrv_close(BlockDriverState *bs)
                    425: {
1.1.1.5 ! root      426:     if (bs->drv) {
1.1       root      427:         if (bs->backing_hd)
                    428:             bdrv_delete(bs->backing_hd);
                    429:         bs->drv->bdrv_close(bs);
                    430:         qemu_free(bs->opaque);
                    431: #ifdef _WIN32
                    432:         if (bs->is_temporary) {
                    433:             unlink(bs->filename);
                    434:         }
                    435: #endif
                    436:         bs->opaque = NULL;
                    437:         bs->drv = NULL;
                    438: 
                    439:         /* call the change callback */
1.1.1.5 ! root      440:         bs->media_changed = 1;
1.1       root      441:         if (bs->change_cb)
                    442:             bs->change_cb(bs->change_opaque);
                    443:     }
                    444: }
                    445: 
                    446: void bdrv_delete(BlockDriverState *bs)
                    447: {
                    448:     /* XXX: remove the driver list */
                    449:     bdrv_close(bs);
                    450:     qemu_free(bs);
                    451: }
                    452: 
                    453: /* commit COW file into the raw image */
                    454: int bdrv_commit(BlockDriverState *bs)
                    455: {
1.1.1.5 ! root      456:     BlockDriver *drv = bs->drv;
        !           457:     int64_t i, total_sectors;
1.1       root      458:     int n, j;
                    459:     unsigned char sector[512];
                    460: 
1.1.1.5 ! root      461:     if (!drv)
        !           462:         return -ENOMEDIUM;
1.1       root      463: 
                    464:     if (bs->read_only) {
                    465:        return -EACCES;
                    466:     }
                    467: 
                    468:     if (!bs->backing_hd) {
                    469:        return -ENOTSUP;
                    470:     }
                    471: 
1.1.1.5 ! root      472:     total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
        !           473:     for (i = 0; i < total_sectors;) {
        !           474:         if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
1.1       root      475:             for(j = 0; j < n; j++) {
                    476:                 if (bdrv_read(bs, i, sector, 1) != 0) {
                    477:                     return -EIO;
                    478:                 }
                    479: 
                    480:                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
                    481:                     return -EIO;
                    482:                 }
                    483:                 i++;
                    484:            }
                    485:        } else {
                    486:             i += n;
                    487:         }
                    488:     }
1.1.1.2   root      489: 
1.1.1.5 ! root      490:     if (drv->bdrv_make_empty)
        !           491:        return drv->bdrv_make_empty(bs);
1.1.1.2   root      492: 
1.1       root      493:     return 0;
                    494: }
                    495: 
1.1.1.5 ! root      496: /* return < 0 if error. See bdrv_write() for the return codes */
1.1       root      497: int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
                    498:               uint8_t *buf, int nb_sectors)
                    499: {
                    500:     BlockDriver *drv = bs->drv;
                    501: 
1.1.1.5 ! root      502:     if (!drv)
        !           503:         return -ENOMEDIUM;
1.1       root      504: 
1.1.1.5 ! root      505:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
1.1       root      506:             memcpy(buf, bs->boot_sector_data, 512);
1.1.1.5 ! root      507:         sector_num++;
        !           508:         nb_sectors--;
        !           509:         buf += 512;
        !           510:         if (nb_sectors == 0)
        !           511:             return 0;
        !           512:     }
        !           513:     if (drv->bdrv_pread) {
        !           514:         int ret, len;
        !           515:         len = nb_sectors * 512;
        !           516:         ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
        !           517:         if (ret < 0)
        !           518:             return ret;
        !           519:         else if (ret != len)
        !           520:             return -EINVAL;
        !           521:         else
        !           522:             return 0;
        !           523:     } else {
        !           524:         return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
1.1       root      525:     }
                    526: }
                    527: 
1.1.1.5 ! root      528: /* Return < 0 if error. Important errors are: 
        !           529:   -EIO         generic I/O error (may happen for all errors)
        !           530:   -ENOMEDIUM   No media inserted.
        !           531:   -EINVAL      Invalid sector number or nb_sectors
        !           532:   -EACCES      Trying to write a read-only device
        !           533: */
1.1       root      534: int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
                    535:                const uint8_t *buf, int nb_sectors)
                    536: {
1.1.1.5 ! root      537:     BlockDriver *drv = bs->drv;
        !           538:     if (!bs->drv)
        !           539:         return -ENOMEDIUM;
1.1       root      540:     if (bs->read_only)
1.1.1.5 ! root      541:         return -EACCES;
1.1.1.2   root      542:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
                    543:         memcpy(bs->boot_sector_data, buf, 512);   
                    544:     }
1.1.1.5 ! root      545:     if (drv->bdrv_pwrite) {
        !           546:         int ret, len;
        !           547:         len = nb_sectors * 512;
        !           548:         ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
        !           549:         if (ret < 0)
        !           550:             return ret;
        !           551:         else if (ret != len)
        !           552:             return -EIO;
        !           553:         else
        !           554:             return 0;
        !           555:     } else {
        !           556:         return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
        !           557:     }
1.1       root      558: }
                    559: 
1.1.1.5 ! root      560: static int bdrv_pread_em(BlockDriverState *bs, int64_t offset, 
        !           561:                          uint8_t *buf, int count1)
        !           562: {
        !           563:     uint8_t tmp_buf[SECTOR_SIZE];
        !           564:     int len, nb_sectors, count;
        !           565:     int64_t sector_num;
        !           566: 
        !           567:     count = count1;
        !           568:     /* first read to align to sector start */
        !           569:     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
        !           570:     if (len > count)
        !           571:         len = count;
        !           572:     sector_num = offset >> SECTOR_BITS;
        !           573:     if (len > 0) {
        !           574:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
        !           575:             return -EIO;
        !           576:         memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
        !           577:         count -= len;
        !           578:         if (count == 0)
        !           579:             return count1;
        !           580:         sector_num++;
        !           581:         buf += len;
        !           582:     }
        !           583: 
        !           584:     /* read the sectors "in place" */
        !           585:     nb_sectors = count >> SECTOR_BITS;
        !           586:     if (nb_sectors > 0) {
        !           587:         if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
        !           588:             return -EIO;
        !           589:         sector_num += nb_sectors;
        !           590:         len = nb_sectors << SECTOR_BITS;
        !           591:         buf += len;
        !           592:         count -= len;
        !           593:     }
        !           594: 
        !           595:     /* add data from the last sector */
        !           596:     if (count > 0) {
        !           597:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
        !           598:             return -EIO;
        !           599:         memcpy(buf, tmp_buf, count);
        !           600:     }
        !           601:     return count1;
        !           602: }
        !           603: 
        !           604: static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset, 
        !           605:                           const uint8_t *buf, int count1)
        !           606: {
        !           607:     uint8_t tmp_buf[SECTOR_SIZE];
        !           608:     int len, nb_sectors, count;
        !           609:     int64_t sector_num;
        !           610: 
        !           611:     count = count1;
        !           612:     /* first write to align to sector start */
        !           613:     len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
        !           614:     if (len > count)
        !           615:         len = count;
        !           616:     sector_num = offset >> SECTOR_BITS;
        !           617:     if (len > 0) {
        !           618:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
        !           619:             return -EIO;
        !           620:         memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
        !           621:         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
        !           622:             return -EIO;
        !           623:         count -= len;
        !           624:         if (count == 0)
        !           625:             return count1;
        !           626:         sector_num++;
        !           627:         buf += len;
        !           628:     }
        !           629: 
        !           630:     /* write the sectors "in place" */
        !           631:     nb_sectors = count >> SECTOR_BITS;
        !           632:     if (nb_sectors > 0) {
        !           633:         if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
        !           634:             return -EIO;
        !           635:         sector_num += nb_sectors;
        !           636:         len = nb_sectors << SECTOR_BITS;
        !           637:         buf += len;
        !           638:         count -= len;
        !           639:     }
        !           640: 
        !           641:     /* add data from the last sector */
        !           642:     if (count > 0) {
        !           643:         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
        !           644:             return -EIO;
        !           645:         memcpy(tmp_buf, buf, count);
        !           646:         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
        !           647:             return -EIO;
        !           648:     }
        !           649:     return count1;
        !           650: }
        !           651: 
        !           652: /**
        !           653:  * Read with byte offsets (needed only for file protocols) 
        !           654:  */
        !           655: int bdrv_pread(BlockDriverState *bs, int64_t offset, 
        !           656:                void *buf1, int count1)
        !           657: {
        !           658:     BlockDriver *drv = bs->drv;
        !           659: 
        !           660:     if (!drv)
        !           661:         return -ENOMEDIUM;
        !           662:     if (!drv->bdrv_pread)
        !           663:         return bdrv_pread_em(bs, offset, buf1, count1);
        !           664:     return drv->bdrv_pread(bs, offset, buf1, count1);
        !           665: }
        !           666: 
        !           667: /** 
        !           668:  * Write with byte offsets (needed only for file protocols) 
        !           669:  */
        !           670: int bdrv_pwrite(BlockDriverState *bs, int64_t offset, 
        !           671:                 const void *buf1, int count1)
        !           672: {
        !           673:     BlockDriver *drv = bs->drv;
        !           674: 
        !           675:     if (!drv)
        !           676:         return -ENOMEDIUM;
        !           677:     if (!drv->bdrv_pwrite)
        !           678:         return bdrv_pwrite_em(bs, offset, buf1, count1);
        !           679:     return drv->bdrv_pwrite(bs, offset, buf1, count1);
        !           680: }
        !           681: 
        !           682: /**
        !           683:  * Truncate file to 'offset' bytes (needed only for file protocols)
        !           684:  */
        !           685: int bdrv_truncate(BlockDriverState *bs, int64_t offset)
        !           686: {
        !           687:     BlockDriver *drv = bs->drv;
        !           688:     if (!drv)
        !           689:         return -ENOMEDIUM;
        !           690:     if (!drv->bdrv_truncate)
        !           691:         return -ENOTSUP;
        !           692:     return drv->bdrv_truncate(bs, offset);
        !           693: }
        !           694: 
        !           695: /**
        !           696:  * Length of a file in bytes. Return < 0 if error or unknown.
        !           697:  */
        !           698: int64_t bdrv_getlength(BlockDriverState *bs)
        !           699: {
        !           700:     BlockDriver *drv = bs->drv;
        !           701:     if (!drv)
        !           702:         return -ENOMEDIUM;
        !           703:     if (!drv->bdrv_getlength) {
        !           704:         /* legacy mode */
        !           705:         return bs->total_sectors * SECTOR_SIZE;
        !           706:     }
        !           707:     return drv->bdrv_getlength(bs);
        !           708: }
        !           709: 
        !           710: /* return 0 as number of sectors if no device present or error */
1.1       root      711: void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
                    712: {
1.1.1.5 ! root      713:     int64_t length;
        !           714:     length = bdrv_getlength(bs);
        !           715:     if (length < 0)
        !           716:         length = 0;
        !           717:     else
        !           718:         length = length >> SECTOR_BITS;
        !           719:     *nb_sectors_ptr = length;
1.1       root      720: }
                    721: 
                    722: /* force a given boot sector. */
                    723: void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
                    724: {
                    725:     bs->boot_sector_enabled = 1;
                    726:     if (size > 512)
                    727:         size = 512;
                    728:     memcpy(bs->boot_sector_data, data, size);
                    729:     memset(bs->boot_sector_data + size, 0, 512 - size);
                    730: }
                    731: 
                    732: void bdrv_set_geometry_hint(BlockDriverState *bs, 
                    733:                             int cyls, int heads, int secs)
                    734: {
                    735:     bs->cyls = cyls;
                    736:     bs->heads = heads;
                    737:     bs->secs = secs;
                    738: }
                    739: 
                    740: void bdrv_set_type_hint(BlockDriverState *bs, int type)
                    741: {
                    742:     bs->type = type;
                    743:     bs->removable = ((type == BDRV_TYPE_CDROM ||
                    744:                       type == BDRV_TYPE_FLOPPY));
                    745: }
                    746: 
                    747: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
                    748: {
                    749:     bs->translation = translation;
                    750: }
                    751: 
                    752: void bdrv_get_geometry_hint(BlockDriverState *bs, 
                    753:                             int *pcyls, int *pheads, int *psecs)
                    754: {
                    755:     *pcyls = bs->cyls;
                    756:     *pheads = bs->heads;
                    757:     *psecs = bs->secs;
                    758: }
                    759: 
                    760: int bdrv_get_type_hint(BlockDriverState *bs)
                    761: {
                    762:     return bs->type;
                    763: }
                    764: 
                    765: int bdrv_get_translation_hint(BlockDriverState *bs)
                    766: {
                    767:     return bs->translation;
                    768: }
                    769: 
                    770: int bdrv_is_removable(BlockDriverState *bs)
                    771: {
                    772:     return bs->removable;
                    773: }
                    774: 
                    775: int bdrv_is_read_only(BlockDriverState *bs)
                    776: {
                    777:     return bs->read_only;
                    778: }
                    779: 
1.1.1.5 ! root      780: /* XXX: no longer used */
1.1       root      781: void bdrv_set_change_cb(BlockDriverState *bs, 
                    782:                         void (*change_cb)(void *opaque), void *opaque)
                    783: {
                    784:     bs->change_cb = change_cb;
                    785:     bs->change_opaque = opaque;
                    786: }
                    787: 
                    788: int bdrv_is_encrypted(BlockDriverState *bs)
                    789: {
                    790:     if (bs->backing_hd && bs->backing_hd->encrypted)
                    791:         return 1;
                    792:     return bs->encrypted;
                    793: }
                    794: 
                    795: int bdrv_set_key(BlockDriverState *bs, const char *key)
                    796: {
                    797:     int ret;
                    798:     if (bs->backing_hd && bs->backing_hd->encrypted) {
                    799:         ret = bdrv_set_key(bs->backing_hd, key);
                    800:         if (ret < 0)
                    801:             return ret;
                    802:         if (!bs->encrypted)
                    803:             return 0;
                    804:     }
                    805:     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
                    806:         return -1;
                    807:     return bs->drv->bdrv_set_key(bs, key);
                    808: }
                    809: 
                    810: void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
                    811: {
1.1.1.5 ! root      812:     if (!bs->drv) {
1.1       root      813:         buf[0] = '\0';
                    814:     } else {
                    815:         pstrcpy(buf, buf_size, bs->drv->format_name);
                    816:     }
                    817: }
                    818: 
                    819: void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
                    820:                          void *opaque)
                    821: {
                    822:     BlockDriver *drv;
                    823: 
                    824:     for (drv = first_drv; drv != NULL; drv = drv->next) {
                    825:         it(opaque, drv->format_name);
                    826:     }
                    827: }
                    828: 
                    829: BlockDriverState *bdrv_find(const char *name)
                    830: {
                    831:     BlockDriverState *bs;
                    832: 
                    833:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
                    834:         if (!strcmp(name, bs->device_name))
                    835:             return bs;
                    836:     }
                    837:     return NULL;
                    838: }
                    839: 
                    840: void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
                    841: {
                    842:     BlockDriverState *bs;
                    843: 
                    844:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
                    845:         it(opaque, bs->device_name);
                    846:     }
                    847: }
                    848: 
                    849: const char *bdrv_get_device_name(BlockDriverState *bs)
                    850: {
                    851:     return bs->device_name;
                    852: }
                    853: 
1.1.1.4   root      854: void bdrv_flush(BlockDriverState *bs)
                    855: {
                    856:     if (bs->drv->bdrv_flush)
                    857:         bs->drv->bdrv_flush(bs);
                    858:     if (bs->backing_hd)
                    859:         bdrv_flush(bs->backing_hd);
                    860: }
                    861: 
1.1       root      862: void bdrv_info(void)
                    863: {
                    864:     BlockDriverState *bs;
                    865: 
                    866:     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
                    867:         term_printf("%s:", bs->device_name);
                    868:         term_printf(" type=");
                    869:         switch(bs->type) {
                    870:         case BDRV_TYPE_HD:
                    871:             term_printf("hd");
                    872:             break;
                    873:         case BDRV_TYPE_CDROM:
                    874:             term_printf("cdrom");
                    875:             break;
                    876:         case BDRV_TYPE_FLOPPY:
                    877:             term_printf("floppy");
                    878:             break;
                    879:         }
                    880:         term_printf(" removable=%d", bs->removable);
                    881:         if (bs->removable) {
                    882:             term_printf(" locked=%d", bs->locked);
                    883:         }
1.1.1.5 ! root      884:         if (bs->drv) {
        !           885:             term_printf(" file=");
        !           886:            term_print_filename(bs->filename);
        !           887:             if (bs->backing_file[0] != '\0') {
        !           888:                 term_printf(" backing_file=");
        !           889:                term_print_filename(bs->backing_file);
        !           890:            }
1.1       root      891:             term_printf(" ro=%d", bs->read_only);
                    892:             term_printf(" drv=%s", bs->drv->format_name);
                    893:             if (bs->encrypted)
                    894:                 term_printf(" encrypted");
                    895:         } else {
                    896:             term_printf(" [not inserted]");
                    897:         }
                    898:         term_printf("\n");
                    899:     }
                    900: }
                    901: 
1.1.1.5 ! root      902: void bdrv_get_backing_filename(BlockDriverState *bs, 
        !           903:                                char *filename, int filename_size)
        !           904: {
        !           905:     if (!bs->backing_hd) {
        !           906:         pstrcpy(filename, filename_size, "");
        !           907:     } else {
        !           908:         pstrcpy(filename, filename_size, bs->backing_file);
        !           909:     }
        !           910: }
        !           911: 
        !           912: int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
        !           913:                           const uint8_t *buf, int nb_sectors)
        !           914: {
        !           915:     BlockDriver *drv = bs->drv;
        !           916:     if (!drv)
        !           917:         return -ENOMEDIUM;
        !           918:     if (!drv->bdrv_write_compressed)
        !           919:         return -ENOTSUP;
        !           920:     return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
        !           921: }
        !           922:     
        !           923: int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
        !           924: {
        !           925:     BlockDriver *drv = bs->drv;
        !           926:     if (!drv)
        !           927:         return -ENOMEDIUM;
        !           928:     if (!drv->bdrv_get_info)
        !           929:         return -ENOTSUP;
        !           930:     memset(bdi, 0, sizeof(*bdi));
        !           931:     return drv->bdrv_get_info(bs, bdi);
        !           932: }
        !           933: 
1.1       root      934: /**************************************************************/
1.1.1.5 ! root      935: /* handling of snapshots */
1.1       root      936: 
1.1.1.5 ! root      937: int bdrv_snapshot_create(BlockDriverState *bs, 
        !           938:                          QEMUSnapshotInfo *sn_info)
        !           939: {
        !           940:     BlockDriver *drv = bs->drv;
        !           941:     if (!drv)
        !           942:         return -ENOMEDIUM;
        !           943:     if (!drv->bdrv_snapshot_create)
        !           944:         return -ENOTSUP;
        !           945:     return drv->bdrv_snapshot_create(bs, sn_info);
        !           946: }
1.1       root      947: 
1.1.1.5 ! root      948: int bdrv_snapshot_goto(BlockDriverState *bs, 
        !           949:                        const char *snapshot_id)
1.1       root      950: {
1.1.1.5 ! root      951:     BlockDriver *drv = bs->drv;
        !           952:     if (!drv)
        !           953:         return -ENOMEDIUM;
        !           954:     if (!drv->bdrv_snapshot_goto)
        !           955:         return -ENOTSUP;
        !           956:     return drv->bdrv_snapshot_goto(bs, snapshot_id);
1.1       root      957: }
                    958: 
1.1.1.5 ! root      959: int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
1.1       root      960: {
1.1.1.5 ! root      961:     BlockDriver *drv = bs->drv;
        !           962:     if (!drv)
        !           963:         return -ENOMEDIUM;
        !           964:     if (!drv->bdrv_snapshot_delete)
        !           965:         return -ENOTSUP;
        !           966:     return drv->bdrv_snapshot_delete(bs, snapshot_id);
        !           967: }
1.1       root      968: 
1.1.1.5 ! root      969: int bdrv_snapshot_list(BlockDriverState *bs, 
        !           970:                        QEMUSnapshotInfo **psn_info)
        !           971: {
        !           972:     BlockDriver *drv = bs->drv;
        !           973:     if (!drv)
        !           974:         return -ENOMEDIUM;
        !           975:     if (!drv->bdrv_snapshot_list)
        !           976:         return -ENOTSUP;
        !           977:     return drv->bdrv_snapshot_list(bs, psn_info);
        !           978: }
        !           979: 
        !           980: #define NB_SUFFIXES 4
        !           981: 
        !           982: char *get_human_readable_size(char *buf, int buf_size, int64_t size)
        !           983: {
        !           984:     static const char suffixes[NB_SUFFIXES] = "KMGT";
        !           985:     int64_t base;
        !           986:     int i;
        !           987: 
        !           988:     if (size <= 999) {
        !           989:         snprintf(buf, buf_size, "%" PRId64, size);
        !           990:     } else {
        !           991:         base = 1024;
        !           992:         for(i = 0; i < NB_SUFFIXES; i++) {
        !           993:             if (size < (10 * base)) {
        !           994:                 snprintf(buf, buf_size, "%0.1f%c", 
        !           995:                          (double)size / base,
        !           996:                          suffixes[i]);
        !           997:                 break;
        !           998:             } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
        !           999:                 snprintf(buf, buf_size, "%" PRId64 "%c", 
        !          1000:                          ((size + (base >> 1)) / base),
        !          1001:                          suffixes[i]);
        !          1002:                 break;
        !          1003:             }
        !          1004:             base = base * 1024;
        !          1005:         }
1.1       root     1006:     }
1.1.1.5 ! root     1007:     return buf;
        !          1008: }
        !          1009: 
        !          1010: char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
        !          1011: {
        !          1012:     char buf1[128], date_buf[128], clock_buf[128];
        !          1013: #ifdef _WIN32
        !          1014:     struct tm *ptm;
1.1.1.2   root     1015: #else
1.1.1.5 ! root     1016:     struct tm tm;
1.1.1.2   root     1017: #endif
1.1.1.5 ! root     1018:     time_t ti;
        !          1019:     int64_t secs;
        !          1020: 
        !          1021:     if (!sn) {
        !          1022:         snprintf(buf, buf_size, 
        !          1023:                  "%-10s%-20s%7s%20s%15s", 
        !          1024:                  "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
        !          1025:     } else {
        !          1026:         ti = sn->date_sec;
1.1       root     1027: #ifdef _WIN32
1.1.1.5 ! root     1028:         ptm = localtime(&ti);
        !          1029:         strftime(date_buf, sizeof(date_buf),
        !          1030:                  "%Y-%m-%d %H:%M:%S", ptm);
        !          1031: #else
        !          1032:         localtime_r(&ti, &tm);
        !          1033:         strftime(date_buf, sizeof(date_buf),
        !          1034:                  "%Y-%m-%d %H:%M:%S", &tm);
1.1       root     1035: #endif
1.1.1.5 ! root     1036:         secs = sn->vm_clock_nsec / 1000000000;
        !          1037:         snprintf(clock_buf, sizeof(clock_buf),
        !          1038:                  "%02d:%02d:%02d.%03d",
        !          1039:                  (int)(secs / 3600),
        !          1040:                  (int)((secs / 60) % 60),
        !          1041:                  (int)(secs % 60), 
        !          1042:                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
        !          1043:         snprintf(buf, buf_size,
        !          1044:                  "%-10s%-20s%7s%20s%15s", 
        !          1045:                  sn->id_str, sn->name,
        !          1046:                  get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
        !          1047:                  date_buf,
        !          1048:                  clock_buf);
        !          1049:     }
        !          1050:     return buf;
1.1       root     1051: }
                   1052: 
                   1053: 
1.1.1.5 ! root     1054: /**************************************************************/
        !          1055: /* async I/Os */
        !          1056: 
        !          1057: BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
        !          1058:                                 uint8_t *buf, int nb_sectors,
        !          1059:                                 BlockDriverCompletionFunc *cb, void *opaque)
1.1       root     1060: {
1.1.1.5 ! root     1061:     BlockDriver *drv = bs->drv;
        !          1062: 
        !          1063:     if (!drv)
        !          1064:         return NULL;
1.1       root     1065:     
1.1.1.5 ! root     1066:     /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
        !          1067:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
        !          1068:         memcpy(buf, bs->boot_sector_data, 512);
        !          1069:         sector_num++;
        !          1070:         nb_sectors--;
        !          1071:         buf += 512;
        !          1072:     }
        !          1073: 
        !          1074:     return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
1.1       root     1075: }
                   1076: 
1.1.1.5 ! root     1077: BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
        !          1078:                                  const uint8_t *buf, int nb_sectors,
        !          1079:                                  BlockDriverCompletionFunc *cb, void *opaque)
1.1       root     1080: {
1.1.1.5 ! root     1081:     BlockDriver *drv = bs->drv;
1.1       root     1082: 
1.1.1.5 ! root     1083:     if (!drv)
        !          1084:         return NULL;
        !          1085:     if (bs->read_only)
        !          1086:         return NULL;
        !          1087:     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
        !          1088:         memcpy(bs->boot_sector_data, buf, 512);   
        !          1089:     }
1.1.1.4   root     1090: 
1.1.1.5 ! root     1091:     return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
        !          1092: }
        !          1093: 
        !          1094: void bdrv_aio_cancel(BlockDriverAIOCB *acb)
1.1.1.4   root     1095: {
1.1.1.5 ! root     1096:     BlockDriver *drv = acb->bs->drv;
1.1.1.4   root     1097: 
1.1.1.5 ! root     1098:     drv->bdrv_aio_cancel(acb);
        !          1099: }
1.1.1.4   root     1100: 
                   1101: 
1.1.1.5 ! root     1102: /**************************************************************/
        !          1103: /* async block device emulation */
1.1.1.4   root     1104: 
1.1.1.5 ! root     1105: #ifdef QEMU_TOOL
        !          1106: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
        !          1107:         int64_t sector_num, uint8_t *buf, int nb_sectors,
        !          1108:         BlockDriverCompletionFunc *cb, void *opaque)
        !          1109: {
        !          1110:     int ret;
        !          1111:     ret = bdrv_read(bs, sector_num, buf, nb_sectors);
        !          1112:     cb(opaque, ret);
        !          1113:     return NULL;
        !          1114: }
1.1.1.4   root     1115: 
1.1.1.5 ! root     1116: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
        !          1117:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
        !          1118:         BlockDriverCompletionFunc *cb, void *opaque)
        !          1119: {
        !          1120:     int ret;
        !          1121:     ret = bdrv_write(bs, sector_num, buf, nb_sectors);
        !          1122:     cb(opaque, ret);
        !          1123:     return NULL;
1.1.1.4   root     1124: }
                   1125: 
1.1.1.5 ! root     1126: static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
1.1.1.4   root     1127: {
                   1128: }
                   1129: #else
1.1.1.5 ! root     1130: static void bdrv_aio_bh_cb(void *opaque)
1.1.1.4   root     1131: {
1.1.1.5 ! root     1132:     BlockDriverAIOCBSync *acb = opaque;
        !          1133:     acb->common.cb(acb->common.opaque, acb->ret);
        !          1134:     qemu_aio_release(acb);
1.1.1.4   root     1135: }
                   1136: 
1.1.1.5 ! root     1137: static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
        !          1138:         int64_t sector_num, uint8_t *buf, int nb_sectors,
        !          1139:         BlockDriverCompletionFunc *cb, void *opaque)
1.1       root     1140: {
1.1.1.5 ! root     1141:     BlockDriverAIOCBSync *acb;
        !          1142:     int ret;
1.1       root     1143: 
1.1.1.5 ! root     1144:     acb = qemu_aio_get(bs, cb, opaque);
        !          1145:     if (!acb->bh)
        !          1146:         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
        !          1147:     ret = bdrv_read(bs, sector_num, buf, nb_sectors);
        !          1148:     acb->ret = ret;
        !          1149:     qemu_bh_schedule(acb->bh);
        !          1150:     return &acb->common;
        !          1151: }
1.1       root     1152: 
1.1.1.5 ! root     1153: static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
        !          1154:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
        !          1155:         BlockDriverCompletionFunc *cb, void *opaque)
        !          1156: {
        !          1157:     BlockDriverAIOCBSync *acb;
        !          1158:     int ret;
        !          1159: 
        !          1160:     acb = qemu_aio_get(bs, cb, opaque);
        !          1161:     if (!acb->bh)
        !          1162:         acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
        !          1163:     ret = bdrv_write(bs, sector_num, buf, nb_sectors);
        !          1164:     acb->ret = ret;
        !          1165:     qemu_bh_schedule(acb->bh);
        !          1166:     return &acb->common;
        !          1167: }
        !          1168: 
        !          1169: static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
        !          1170: {
        !          1171:     BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
        !          1172:     qemu_bh_cancel(acb->bh);
        !          1173:     qemu_aio_release(acb);
1.1       root     1174: }
1.1.1.5 ! root     1175: #endif /* !QEMU_TOOL */
1.1       root     1176: 
1.1.1.5 ! root     1177: /**************************************************************/
        !          1178: /* sync block device emulation */
        !          1179: 
        !          1180: static void bdrv_rw_em_cb(void *opaque, int ret)
1.1.1.4   root     1181: {
1.1.1.5 ! root     1182:     *(int *)opaque = ret;
1.1.1.4   root     1183: }
                   1184: 
1.1.1.5 ! root     1185: #define NOT_DONE 0x7fffffff
        !          1186: 
        !          1187: static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
        !          1188:                         uint8_t *buf, int nb_sectors)
        !          1189: {
        !          1190:     int async_ret;
        !          1191:     BlockDriverAIOCB *acb;
        !          1192: 
        !          1193:     async_ret = NOT_DONE;
        !          1194:     qemu_aio_wait_start();
        !          1195:     acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, 
        !          1196:                         bdrv_rw_em_cb, &async_ret);
        !          1197:     if (acb == NULL) {
        !          1198:         qemu_aio_wait_end();
        !          1199:         return -1;
        !          1200:     }
        !          1201:     while (async_ret == NOT_DONE) {
        !          1202:         qemu_aio_wait();
        !          1203:     }
        !          1204:     qemu_aio_wait_end();
        !          1205:     return async_ret;
        !          1206: }
        !          1207: 
        !          1208: static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
        !          1209:                          const uint8_t *buf, int nb_sectors)
        !          1210: {
        !          1211:     int async_ret;
        !          1212:     BlockDriverAIOCB *acb;
        !          1213: 
        !          1214:     async_ret = NOT_DONE;
        !          1215:     qemu_aio_wait_start();
        !          1216:     acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, 
        !          1217:                          bdrv_rw_em_cb, &async_ret);
        !          1218:     if (acb == NULL) {
        !          1219:         qemu_aio_wait_end();
        !          1220:         return -1;
        !          1221:     }
        !          1222:     while (async_ret == NOT_DONE) {
        !          1223:         qemu_aio_wait();
        !          1224:     }
        !          1225:     qemu_aio_wait_end();
        !          1226:     return async_ret;
        !          1227: }
1.1       root     1228: 
                   1229: void bdrv_init(void)
                   1230: {
                   1231:     bdrv_register(&bdrv_raw);
1.1.1.5 ! root     1232:     bdrv_register(&bdrv_host_device);
1.1       root     1233: #ifndef _WIN32
                   1234:     bdrv_register(&bdrv_cow);
                   1235: #endif
                   1236:     bdrv_register(&bdrv_qcow);
                   1237:     bdrv_register(&bdrv_vmdk);
                   1238:     bdrv_register(&bdrv_cloop);
                   1239:     bdrv_register(&bdrv_dmg);
                   1240:     bdrv_register(&bdrv_bochs);
                   1241:     bdrv_register(&bdrv_vpc);
                   1242:     bdrv_register(&bdrv_vvfat);
1.1.1.5 ! root     1243:     bdrv_register(&bdrv_qcow2);
        !          1244: }
        !          1245: 
        !          1246: void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
        !          1247:                    void *opaque)
        !          1248: {
        !          1249:     BlockDriver *drv;
        !          1250:     BlockDriverAIOCB *acb;
        !          1251: 
        !          1252:     drv = bs->drv;
        !          1253:     if (drv->free_aiocb) {
        !          1254:         acb = drv->free_aiocb;
        !          1255:         drv->free_aiocb = acb->next;
        !          1256:     } else {
        !          1257:         acb = qemu_mallocz(drv->aiocb_size);
        !          1258:         if (!acb)
        !          1259:             return NULL;
        !          1260:     }
        !          1261:     acb->bs = bs;
        !          1262:     acb->cb = cb;
        !          1263:     acb->opaque = opaque;
        !          1264:     return acb;
        !          1265: }
        !          1266: 
        !          1267: void qemu_aio_release(void *p)
        !          1268: {
        !          1269:     BlockDriverAIOCB *acb = p;
        !          1270:     BlockDriver *drv = acb->bs->drv;
        !          1271:     acb->next = drv->free_aiocb;
        !          1272:     drv->free_aiocb = acb;
        !          1273: }
        !          1274: 
        !          1275: /**************************************************************/
        !          1276: /* removable device support */
        !          1277: 
        !          1278: /**
        !          1279:  * Return TRUE if the media is present
        !          1280:  */
        !          1281: int bdrv_is_inserted(BlockDriverState *bs)
        !          1282: {
        !          1283:     BlockDriver *drv = bs->drv;
        !          1284:     int ret;
        !          1285:     if (!drv)
        !          1286:         return 0;
        !          1287:     if (!drv->bdrv_is_inserted)
        !          1288:         return 1;
        !          1289:     ret = drv->bdrv_is_inserted(bs);
        !          1290:     return ret;
        !          1291: }
        !          1292: 
        !          1293: /**
        !          1294:  * Return TRUE if the media changed since the last call to this
        !          1295:  * function. It is currently only used for floppy disks 
        !          1296:  */
        !          1297: int bdrv_media_changed(BlockDriverState *bs)
        !          1298: {
        !          1299:     BlockDriver *drv = bs->drv;
        !          1300:     int ret;
        !          1301: 
        !          1302:     if (!drv || !drv->bdrv_media_changed)
        !          1303:         ret = -ENOTSUP;
        !          1304:     else
        !          1305:         ret = drv->bdrv_media_changed(bs);
        !          1306:     if (ret == -ENOTSUP)
        !          1307:         ret = bs->media_changed;
        !          1308:     bs->media_changed = 0;
        !          1309:     return ret;
        !          1310: }
        !          1311: 
        !          1312: /**
        !          1313:  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
        !          1314:  */
        !          1315: void bdrv_eject(BlockDriverState *bs, int eject_flag)
        !          1316: {
        !          1317:     BlockDriver *drv = bs->drv;
        !          1318:     int ret;
        !          1319: 
        !          1320:     if (!drv || !drv->bdrv_eject) {
        !          1321:         ret = -ENOTSUP;
        !          1322:     } else {
        !          1323:         ret = drv->bdrv_eject(bs, eject_flag);
        !          1324:     }
        !          1325:     if (ret == -ENOTSUP) {
        !          1326:         if (eject_flag)
        !          1327:             bdrv_close(bs);
        !          1328:     }
        !          1329: }
        !          1330: 
        !          1331: int bdrv_is_locked(BlockDriverState *bs)
        !          1332: {
        !          1333:     return bs->locked;
        !          1334: }
        !          1335: 
        !          1336: /**
        !          1337:  * Lock or unlock the media (if it is locked, the user won't be able
        !          1338:  * to eject it manually).
        !          1339:  */
        !          1340: void bdrv_set_locked(BlockDriverState *bs, int locked)
        !          1341: {
        !          1342:     BlockDriver *drv = bs->drv;
        !          1343: 
        !          1344:     bs->locked = locked;
        !          1345:     if (drv && drv->bdrv_set_locked) {
        !          1346:         drv->bdrv_set_locked(bs, locked);
        !          1347:     }
1.1       root     1348: }

unix.superglobalmegacorp.com