Annotation of qemu/block.c, revision 1.1.1.9

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

unix.superglobalmegacorp.com