Annotation of qemu/block.c, revision 1.1.1.7

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

unix.superglobalmegacorp.com