block.c revision e7216d82dbaa19892ad62b07402d512234559a6e
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU System Emulator block driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "config-host.h"
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h"
266af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
27e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "block/block_int.h"
28e90d665cd63a0bc5c3306e1ee3e98ad362546b16David 'Digit' Turner#include "qemu/module.h"
29e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner//#include "qemu-objects.h"
30e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "qapi/qmp/qjson.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
322c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/stat.h>
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ioctl.h>
36cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <sys/queue.h>
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef __DragonFly__
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/disk.h>
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h>
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
52cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
53cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque);
54cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
55cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque);
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors);
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors);
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
61cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QTAILQ_HEAD(, BlockDriverState) bdrv_states =
62cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_HEAD_INITIALIZER(bdrv_states);
63cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
64cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QLIST_HEAD(, BlockDriver) bdrv_drivers =
65cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_HEAD_INITIALIZER(bdrv_drivers);
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
67cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/* The device to use for VM snapshots */
68cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverState *bs_snapshots;
69cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
70cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/* If non-zero, use only whitelisted block drivers */
71cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int use_bdrv_whitelist;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint _path_is_absolute(const char *path)
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* specific case for names like: "\\.\d:" */
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*path == '/' || *path == '\\')
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr(path, ':');
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p)
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p++;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = path;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/' || *p == '\\');
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/');
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if filename is absolute, just copy it to dest. Otherwise, build a
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   path to it by considering it is relative to base_path. URL are
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   supported. */
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid path_combine(char *dest, int dest_size,
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *base_path,
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *filename)
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p, *p1;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dest_size <= 0)
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (_path_is_absolute(filename)) {
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(dest, dest_size, filename);
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = strchr(base_path, ':');
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p)
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p++;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = base_path;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p1 = strrchr(base_path, '/');
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char *p2;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p2 = strrchr(base_path, '\\');
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!p1 || p2 > p1)
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p1 = p2;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1)
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1++;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1 = base_path;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1 > p)
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = p1;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = p - base_path;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len > dest_size - 1)
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = dest_size - 1;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(dest, base_path, len);
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dest[len] = '\0';
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcat(dest, dest_size, filename);
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_register(BlockDriver *bdrv)
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv->bdrv_aio_readv) {
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add AIO emulation layer */
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bdrv->bdrv_read) {
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add synchronous IO emulation layer */
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_read = bdrv_read_em;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_write = bdrv_write_em;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
148cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bdrv->bdrv_aio_flush)
150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* create a new block device (by default it is empty) */
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_new(const char *device_name)
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
158cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = qemu_mallocz(sizeof(BlockDriverState));
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (device_name[0] != '\0') {
163cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs;
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriver *bdrv_find_format(const char *format_name)
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1;
171cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(drv1->format_name, format_name)) {
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return drv1;
174cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
179cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int bdrv_is_whitelisted(BlockDriver *drv)
180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    static const char *whitelist[] = {
182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        CONFIG_BDRV_WHITELIST
183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    };
184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char **p;
185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!whitelist[0])
187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 1;               /* no whitelist, anything goes */
188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (p = whitelist; *p; p++) {
190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(drv->format_name, *p)) {
191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return 1;
192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriver *bdrv_find_whitelisted_format(const char *format_name)
198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bdrv_find_format(format_name);
200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
202cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_create(BlockDriver *drv, const char* filename,
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *options)
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_create)
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_create(filename, options);
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
212cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_create_file(const char* filename, QEMUOptionParameter *options)
213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv;
215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = bdrv_find_protocol(filename);
217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv == NULL) {
218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv = bdrv_find_format("file");
219cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
220cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
221cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_create(drv, filename, options);
222cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
223cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char temp_dir[MAX_PATH];
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempPath(MAX_PATH, temp_dir);
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempFileName(temp_dir, "qem", 0, filename);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *tmpdir;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: race condition possible */
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmpdir = getenv("TMPDIR");
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!tmpdir)
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmpdir = "/tmp";
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = mkstemp(filename);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close(fd);
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int is_windows_drive_prefix(const char *filename)
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            filename[1] == ':');
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint is_windows_drive(const char *filename)
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_windows_drive_prefix(filename) &&
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename[2] == '\0')
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strstart(filename, "\\\\.\\", NULL) ||
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strstart(filename, "//./", NULL))
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Detect host devices. By convention, /dev/cdrom[N] is always
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * recognized as a host CDROM.
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriver *find_hdev_driver(const char *filename)
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int score_max = 0, score;
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = NULL, *d;
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
276cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(d, &bdrv_drivers, list) {
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (d->bdrv_probe_device) {
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            score = d->bdrv_probe_device(filename);
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (score > score_max) {
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                score_max = score;
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv = d;
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv;
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
289cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriver *bdrv_find_protocol(const char *filename)
290cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
291cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv1;
292cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char protocol[128];
293cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int len;
294cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *p;
295cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
296cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* TODO Drivers without bdrv_file_open must be specified explicitly */
297cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
298cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
299cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * XXX(hch): we really should not let host device detection
300cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * override an explicit protocol specification, but moving this
301cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * later breaks access to device names with colons in them.
302cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Thanks to the brain-dead persistent naming schemes on udev-
303cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * based Linux systems those actually are quite common.
304cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
305cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv1 = find_hdev_driver(filename);
306cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv1) {
307cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv1;
308cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
309cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
310cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef _WIN32
311cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     if (is_windows_drive(filename) ||
312cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         is_windows_drive_prefix(filename))
313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         return bdrv_find_format("file");
314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
315cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
316cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    p = strchr(filename, ':');
317cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!p) {
318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_find_format("file");
319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
320cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = p - filename;
321cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (len > sizeof(protocol) - 1)
322cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = sizeof(protocol) - 1;
323cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    memcpy(protocol, filename, len);
324cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    protocol[len] = '\0';
325cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
326cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (drv1->protocol_name &&
327cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            !strcmp(drv1->protocol_name, protocol)) {
328cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return drv1;
329cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
330cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
331cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return NULL;
332cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
333cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
334cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int find_image_format(const char *filename, BlockDriver **pdrv)
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, score, score_max;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1, *drv;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t buf[2048];
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
341cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_file_open(&bs, filename, 0);
342cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
343cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = NULL;
344cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
345cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
346cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
347cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
348cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->sg || !bdrv_is_inserted(bs)) {
349cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs);
350cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv = bdrv_find_format("raw");
351cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!drv) {
352cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = -ENOENT;
353cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
354cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = drv;
355cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
356cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_delete(bs);
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
361cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = NULL;
362cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    score_max = 0;
366cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = NULL;
367cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (drv1->bdrv_probe) {
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            score = drv1->bdrv_probe(buf, ret, filename);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (score > score_max) {
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                score_max = score;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                drv = drv1;
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
376cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
377cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = -ENOENT;
378cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
379cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *pdrv = drv;
380cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
383cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/**
384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Set the current 'total_sectors' value
385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
389cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
390cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
391cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->sg)
392cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
393cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
394cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* query actual device if possible, otherwise just trust the hint */
395cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_getlength) {
396cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int64_t length = drv->bdrv_getlength(bs);
397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (length < 0) {
398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return length;
399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        hint = length >> BDRV_SECTOR_BITS;
401cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
402cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
403cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->total_sectors = hint;
404cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
405cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
406cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
407cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
408cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Common part for opening disk images and files
409cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
410cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int bdrv_open_common(BlockDriverState *bs, const char *filename,
411cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int flags, BlockDriver *drv)
412cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
413cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret, open_flags;
414cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
415cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(drv != NULL);
416cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
417cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->file = NULL;
418cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->total_sectors = 0;
419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->encrypted = 0;
420cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->valid_key = 0;
421cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->open_flags = flags;
422cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* buffer_alignment defaulted to 512, drivers can change this value */
423cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->buffer_alignment = 512;
424cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    pstrcpy(bs->filename, sizeof(bs->filename), filename);
426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
430cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
431cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->drv = drv;
432cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->opaque = qemu_mallocz(drv->instance_size);
433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * write cache to the guest.  We do need the fdatasync to flush
437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * out transactions for block allocations, and we maybe have a
438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * volatile write cache in our backing device to deal with.
439cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
440cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
441cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->enable_write_cache = 1;
442cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
443cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
444cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Clear flags that are internal to the block layer before opening the
445cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * image.
446cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
447cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
448cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
449cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
450cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Snapshots should be writeable.
451cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
452cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
453cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        open_flags |= BDRV_O_RDWR;
454cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
455cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
456cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Open the image, either directly or using a protocol */
457cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_file_open) {
458cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = drv->bdrv_file_open(bs, filename, open_flags);
459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_file_open(&bs->file, filename, open_flags);
461cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret >= 0) {
462cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = drv->bdrv_open(bs, open_flags);
463cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
464cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
465cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto free_and_fail;
468cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
469cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
470cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
471cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
472cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = refresh_total_sectors(bs, bs->total_sectors);
473cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
474cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto free_and_fail;
475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifndef _WIN32
478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unlink(filename);
480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
482cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
483cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
484cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfree_and_fail:
485cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
486cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->file);
487cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->file = NULL;
488cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
489cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_free(bs->opaque);
490cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->opaque = NULL;
491cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->drv = NULL;
492cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
493cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
494cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
495cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
496cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Opens a file using a protocol (file, host_device, nbd, ...)
497cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
501cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
504cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = bdrv_find_protocol(filename);
505cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
506cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOENT;
507cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
508cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = bdrv_new("");
510cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_open_common(bs, filename, flags, drv);
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs);
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ret;
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs->growable = 1;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pbs = bs;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
520cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Opens a disk image (raw, qcow2, vmdk, ...)
522cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
523cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_open(BlockDriverState *bs, const char *filename, int flags,
524cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner              BlockDriver *drv)
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
526cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
527cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int probed = 0;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & BDRV_O_SNAPSHOT) {
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverState *bs1;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int64_t total_size;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int is_protocol = 0;
5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *bdrv_qcow2;
5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        QEMUOptionParameter *options;
535cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char tmp_filename[PATH_MAX];
536cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char backing_filename[PATH_MAX];
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if snapshot, we create a temporary backing file and open it
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           instead of opening 'filename' directly */
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if there is a backing file, use it */
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs1 = bdrv_new("");
543cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs1, filename, 0, drv);
5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs1);
5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
548cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs1->drv && bs1->drv->protocol_name)
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            is_protocol = 1;
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs1);
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Real path is meaningless for protocols */
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_protocol)
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            snprintf(backing_filename, sizeof(backing_filename),
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     "%s", filename);
561cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        else if (!realpath(filename, backing_filename))
562cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return -errno;
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_qcow2 = bdrv_find_format("qcow2");
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
567cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (drv) {
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv->format_name);
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
575cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        free_option_parameters(options);
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename = tmp_filename;
5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        drv = bdrv_qcow2;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->is_temporary = 1;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
585cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Find the right image format driver */
586cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
587cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = find_image_format(filename, &drv);
588cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        probed = 1;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
590cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv) {
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto unlink_and_fail;
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
594cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
595cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Open the image */
596cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_open_common(bs, filename, flags, drv);
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
598cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto unlink_and_fail;
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
600cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
601cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->probed = probed;
602cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
603cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* If there is a backing file, use it */
604cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
605cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char backing_filename[PATH_MAX];
606cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int back_flags;
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *back_drv = NULL;
608cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->backing_hd = bdrv_new("");
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        path_combine(backing_filename, sizeof(backing_filename),
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     filename, bs->backing_file);
6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->backing_format[0] != '\0')
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            back_drv = bdrv_find_format(bs->backing_format);
614cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
615cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* backing files always opened read-only */
616cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        back_flags =
617cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bdrv_close(bs);
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->is_temporary) {
625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* base image inherits from "parent" */
628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd->keep_read_only = bs->keep_read_only;
629cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_key_required(bs)) {
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback */
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
638cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerunlink_and_fail:
642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unlink(filename);
644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_close(BlockDriverState *bs)
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->drv) {
651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs == bs_snapshots) {
652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_snapshots = NULL;
653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->backing_hd) {
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs->backing_hd);
656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd = NULL;
657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_close(bs);
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free(bs->opaque);
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->is_temporary) {
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unlink(bs->filename);
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->opaque = NULL;
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv = NULL;
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->file != NULL) {
669cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_close(bs->file);
670cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
671cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* call the change callback */
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->media_changed = 1;
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->change_cb)
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bs->change_cb(bs->change_opaque);
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
679cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_close_all(void)
680cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
681cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
682cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
683cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
684cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_close(bs);
685cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
686cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
687cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_delete(BlockDriverState *bs)
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
690cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(!bs->peer);
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
692cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* remove from list, if necessary */
693cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->device_name[0] != '\0') {
694cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_REMOVE(&bdrv_states, bs, list);
695cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_close(bs);
698cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file != NULL) {
699cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->file);
700cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
701cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
702cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs != bs_snapshots);
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_free(bs);
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
706cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_attach(BlockDriverState *bs, DeviceState *qdev)
707cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
708cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->peer) {
709cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EBUSY;
710cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
711cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->peer = qdev;
712cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
713cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
714cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
715cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
716cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
717cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs->peer == qdev);
718cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->peer = NULL;
719cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
720cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
721cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerDeviceState *bdrv_get_attached(BlockDriverState *bs)
722cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
723cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->peer;
724cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
725cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Run consistency checks on an image
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
729cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 if the check could be completed (it doesn't mean that the image is
730cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * free of errors) or -errno when an internal error occured. The results of the
731cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * check are stored in res.
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
733cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->drv->bdrv_check == NULL) {
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
739cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    memset(res, 0, sizeof(*res));
740cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->drv->bdrv_check(bs, res);
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
743cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#define COMMIT_BUF_SECTORS 2048
744cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* commit COW file into the raw image */
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_commit(BlockDriverState *bs)
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
749cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t sector, total_sectors;
750cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int n, ro, open_flags;
751cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = 0, rw_ret = 0;
752cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t *buf;
753cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char filename[1024];
754cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs_rw, *bs_ro;
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
759cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->backing_hd) {
760cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
763cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->backing_hd->keep_read_only) {
764cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EACCES;
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
767cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ro = bs->backing_hd->read_only;
768cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    strncpy(filename, bs->backing_hd->filename, sizeof(filename));
769cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    open_flags =  bs->backing_hd->open_flags;
770cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
771cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ro) {
772cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* re-open as RW */
773cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->backing_hd);
774cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = NULL;
775cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_rw = bdrv_new("");
776cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, drv);
777cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (rw_ret < 0) {
778cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs_rw);
779cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* try to re-open read-only */
780cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_ro = bdrv_new("");
781cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
782cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (ret < 0) {
783cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bdrv_delete(bs_ro);
784cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* drive not functional anymore */
785cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->drv = NULL;
786cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                return ret;
787cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
788cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd = bs_ro;
789cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return rw_ret;
790cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
791cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = bs_rw;
792cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
794cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
795cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    buf = qemu_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
796cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
797cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (sector = 0; sector < total_sectors; sector += n) {
798cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (drv->bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
799cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
800cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (bdrv_read(bs, sector, buf, n) != 0) {
801cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                ret = -EIO;
802cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto ro_cleanup;
803cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
804cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
805cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (bdrv_write(bs->backing_hd, sector, buf, n) != 0) {
806cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                ret = -EIO;
807cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto ro_cleanup;
808cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
812cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_make_empty) {
813cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = drv->bdrv_make_empty(bs);
814cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs);
815cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
817cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
818cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Make sure all data we wrote to the backing device is actually
819cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * stable on disk.
820cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
821cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->backing_hd)
822cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs->backing_hd);
823cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
824cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerro_cleanup:
825cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_free(buf);
826cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
827cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ro) {
828cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* re-open as RO */
829cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->backing_hd);
830cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = NULL;
831cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_ro = bdrv_new("");
832cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
833cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret < 0) {
834cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs_ro);
835cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* drive not functional anymore */
836cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->drv = NULL;
837cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
838cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
839cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = bs_ro;
840cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd->keep_read_only = 0;
841cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
842cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
843cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
844cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
845cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
846cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_commit_all(void)
847cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
848cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
849cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
850cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
851cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_commit(bs);
852cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
853cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
854cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
855cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
856cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Return values:
857cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * 0        - success
858cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -EINVAL  - backing format specified, but no file
859cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -ENOSPC  - can't update the backing file because no space is left in the
860cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *            image file header
861cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -ENOTSUP - format driver doesn't support changing the backing file
862cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
863cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_change_backing_file(BlockDriverState *bs,
864cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *backing_file, const char *backing_fmt)
865cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
866cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
867cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
868cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_change_backing_file != NULL) {
869cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_change_backing_file(bs, backing_file, backing_fmt);
870cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
871cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
872cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   size_t size)
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t len;
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_is_inserted(bs))
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->growable)
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = bdrv_getlength(bs);
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (offset < 0)
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((offset > len) || (len - offset < size))
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              int nb_sectors)
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
900cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
901cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                   nb_sectors * BDRV_SECTOR_SIZE);
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return < 0 if error. See bdrv_write() for the return codes */
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_read(BlockDriverState *bs, int64_t sector_num,
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              uint8_t *buf, int nb_sectors)
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
918cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num,
919cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             int nb_sectors, int dirty)
920cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
921cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t start, end;
922cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    unsigned long val, idx, bit;
923cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
924cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
925cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
926cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
927cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (; start <= end; start++) {
928cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        idx = start / (sizeof(unsigned long) * 8);
929cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bit = start % (sizeof(unsigned long) * 8);
930cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        val = bs->dirty_bitmap[idx];
931cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (dirty) {
932cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (!(val & (1 << bit))) {
933cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->dirty_count++;
934cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                val |= 1 << bit;
935cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
936cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
937cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (val & (1 << bit)) {
938cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->dirty_count--;
939cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                val &= ~(1 << bit);
940cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
941cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
942cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->dirty_bitmap[idx] = val;
943cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
944cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
945cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return < 0 if error. Important errors are:
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EIO         generic I/O error (may happen for all errors)
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -ENOMEDIUM   No media inserted.
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EINVAL      Invalid sector number or nb_sectors
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EACCES      Trying to write a read-only device
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_write(BlockDriverState *bs, int64_t sector_num,
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               const uint8_t *buf, int nb_sectors)
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv)
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only)
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -EACCES;
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
963cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap) {
964cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
965cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
966cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
967cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
968cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->wr_highest_sector = sector_num + nb_sectors - 1;
969cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
970cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_pread(BlockDriverState *bs, int64_t offset,
9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               void *buf, int count1)
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
977cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t tmp_buf[BDRV_SECTOR_SIZE];
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len, nb_sectors, count;
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t sector_num;
980cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = count1;
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first read to align to sector start */
984cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > count)
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = count;
987cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sector_num = offset >> BDRV_SECTOR_BITS;
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > 0) {
989cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
990cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
991cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len);
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count == 0)
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return count1;
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num++;
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* read the sectors "in place" */
1000cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    nb_sectors = count >> BDRV_SECTOR_BITS;
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_sectors > 0) {
1002cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, buf, nb_sectors)) < 0)
1003cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num += nb_sectors;
1005cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = nb_sectors << BDRV_SECTOR_BITS;
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* add data from the last sector */
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
1012cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
1013cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(buf, tmp_buf, count);
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count1;
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_pwrite(BlockDriverState *bs, int64_t offset,
10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const void *buf, int count1)
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1022cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t tmp_buf[BDRV_SECTOR_SIZE];
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len, nb_sectors, count;
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t sector_num;
1025cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = count1;
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first write to align to sector start */
1029cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > count)
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = count;
1032cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sector_num = offset >> BDRV_SECTOR_BITS;
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > 0) {
1034cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
1035cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
1036cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);
1037cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
1038cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count == 0)
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return count1;
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num++;
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* write the sectors "in place" */
1047cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    nb_sectors = count >> BDRV_SECTOR_BITS;
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_sectors > 0) {
1049cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0)
1050cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num += nb_sectors;
1052cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = nb_sectors << BDRV_SECTOR_BITS;
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* add data from the last sector */
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
1059cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
1060cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(tmp_buf, buf, count);
1062cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
1063cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count1;
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
1069cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Writes to the file and ensures that no writes are reordered across this
1070cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * request (acts as a barrier)
1071cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
1072cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 on success, -errno in error cases.
1073cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
1074cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
1075cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const void *buf, int count)
1076cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1077cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
1078cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1079cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_pwrite(bs, offset, buf, count);
1080cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
1081cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
1082cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1083cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1084cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* No flush needed for cache=writethrough, it uses O_DSYNC */
1085cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if ((bs->open_flags & BDRV_O_CACHE_MASK) != 0) {
1086cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs);
1087cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1088cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1089cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
1090cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1091cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1092cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
1093cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Writes to the file and ensures that no writes are reordered across this
1094cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * request (acts as a barrier)
1095cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
1096cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 on success, -errno in error cases.
1097cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
1098cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
1099cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const uint8_t *buf, int nb_sectors)
1100cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1101cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_pwrite_sync(bs, BDRV_SECTOR_SIZE * sector_num,
1102cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        buf, BDRV_SECTOR_SIZE * nb_sectors);
1103cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1104cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Truncate file to 'offset' bytes (needed only for file protocols)
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_truncate(BlockDriverState *bs, int64_t offset)
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
1111cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_truncate)
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
1116cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->read_only)
1117cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EACCES;
1118cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = drv->bdrv_truncate(bs, offset);
1119cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret == 0) {
1120cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
1121cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1122cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Length of a file in bytes. Return < 0 if error or unknown.
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint64_t bdrv_getlength(BlockDriverState *bs)
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1133cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1134cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Fixed size devices use the total_sectors value for speed instead of
1135cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner       issuing a length query (like lseek) on each call.  Also, legacy block
1136cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner       drivers don't provide a bdrv_getlength function and must use
1137cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner       total_sectors. */
1138cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->growable || !drv->bdrv_getlength) {
1139cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs->total_sectors * BDRV_SECTOR_SIZE;
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_getlength(bs);
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return 0 as number of sectors if no device present or error */
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t length;
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    length = bdrv_getlength(bs);
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (length < 0)
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        length = 0;
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
1152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        length = length >> BDRV_SECTOR_BITS;
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *nb_sectors_ptr = length;
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct partition {
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t boot_ind;           /* 0x80 - active */
11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t head;               /* starting head */
11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t sector;             /* starting sector */
11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t cyl;                /* starting cylinder */
11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t sys_ind;            /* What partition type */
11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_head;           /* end head */
11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_sector;         /* end sector */
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_cyl;            /* end cylinder */
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t start_sect;        /* starting sector counting from 0 */
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t nr_sects;          /* nr of sectors in partition */
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} __attribute__((packed));
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int guess_disk_lchs(BlockDriverState *bs,
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           int *pcylinders, int *pheads, int *psectors)
11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t buf[BDRV_SECTOR_SIZE];
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret, i, heads, sectors, cylinders;
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct partition *p;
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t nr_sects;
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t nb_sectors;
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry(bs, &nb_sectors);
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bdrv_read(bs, 0, buf, 1);
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* test msdos magic */
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (buf[510] != 0x55 || buf[511] != 0xaa)
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < 4; i++) {
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p = ((struct partition *)(buf + 0x1be)) + i;
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        nr_sects = le32_to_cpu(p->nr_sects);
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (nr_sects && p->end_head) {
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* We make the assumption that the partition terminates on
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               a cylinder boundary */
11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            heads = p->end_head + 1;
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            sectors = p->end_sector & 63;
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sectors == 0)
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cylinders = nb_sectors / (heads * sectors);
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (cylinders < 1 || cylinders > 16383)
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pheads = heads;
12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *psectors = sectors;
12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pcylinders = cylinders;
12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            printf("guessed geometry: LCHS=%d %d %d\n",
12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   cylinders, heads, sectors);
12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int translation, lba_detected = 0;
12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int cylinders, heads, secs;
12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t nb_sectors;
12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* if a geometry hint is available, use it */
12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry(bs, &nb_sectors);
12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    translation = bdrv_get_translation_hint(bs);
12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (cylinders != 0) {
12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *pcyls = cylinders;
12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *pheads = heads;
12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *psecs = secs;
12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (heads > 16) {
12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* if heads > 16, it means that a BIOS LBA
12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   translation was active, so the default
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   hardware geometry is OK */
12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                lba_detected = 1;
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto default_geometry;
12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *pcyls = cylinders;
12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *pheads = heads;
12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *psecs = secs;
12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* disable any translation to be in sync with
12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   the logical geometry */
12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (translation == BIOS_ATA_TRANSLATION_AUTO) {
12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_NONE);
12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default_geometry:
12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* if no geometry, use a standard physical disk geometry */
12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cylinders = nb_sectors / (16 * 63);
12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (cylinders > 16383)
12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                cylinders = 16383;
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else if (cylinders < 2)
12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                cylinders = 2;
12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pcyls = cylinders;
12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pheads = 16;
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *psecs = 63;
12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if ((*pcyls * *pheads) <= 131072) {
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_LARGE);
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_LBA);
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_geometry_hint(BlockDriverState *bs,
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int cyls, int heads, int secs)
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->cyls = cyls;
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->heads = heads;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->secs = secs;
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_type_hint(BlockDriverState *bs, int type)
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->type = type;
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->removable = ((type == BDRV_TYPE_CDROM ||
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      type == BDRV_TYPE_FLOPPY));
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_translation_hint(BlockDriverState *bs, int translation)
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->translation = translation;
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_geometry_hint(BlockDriverState *bs,
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int *pcyls, int *pheads, int *psecs)
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcyls = bs->cyls;
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pheads = bs->heads;
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *psecs = bs->secs;
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_type_hint(BlockDriverState *bs)
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->type;
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_translation_hint(BlockDriverState *bs)
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->translation;
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1310cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
1311cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                       BlockErrorAction on_write_error)
1312cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->on_read_error = on_read_error;
1314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->on_write_error = on_write_error;
1315cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1316cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1317cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read)
1318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return is_read ? bs->on_read_error : bs->on_write_error;
1320cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1321cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1322cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_set_removable(BlockDriverState *bs, int removable)
1323cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1324cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->removable = removable;
1325cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (removable && bs == bs_snapshots) {
1326cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_snapshots = NULL;
1327cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1328cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1329cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_removable(BlockDriverState *bs)
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->removable;
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_read_only(BlockDriverState *bs)
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->read_only;
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_sg(BlockDriverState *bs)
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->sg;
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1345cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_enable_write_cache(BlockDriverState *bs)
1346cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1347cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->enable_write_cache;
1348cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1349cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: no longer used */
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_change_cb(BlockDriverState *bs,
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        void (*change_cb)(void *opaque), void *opaque)
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->change_cb = change_cb;
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->change_opaque = opaque;
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_encrypted(BlockDriverState *bs)
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd && bs->backing_hd->encrypted)
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->encrypted;
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_key_required(BlockDriverState *bs)
13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *backing_hd = bs->backing_hd;
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return (bs->encrypted && !bs->valid_key);
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_set_key(BlockDriverState *bs, const char *key)
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd && bs->backing_hd->encrypted) {
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = bdrv_set_key(bs->backing_hd, key);
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0)
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return ret;
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!bs->encrypted)
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->encrypted) {
1385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EINVAL;
1386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else if (!bs->drv || !bs->drv->bdrv_set_key) {
1387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOMEDIUM;
1388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bs->drv->bdrv_set_key(bs, key);
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->valid_key = 0;
13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bs->valid_key) {
13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->valid_key = 1;
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback now, we skipped it on open */
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv) {
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[0] = '\0';
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(buf, buf_size, bs->drv->format_name);
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_iterate_format(void (*it)(void *opaque, const char *name),
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         void *opaque)
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv;
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1416cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv, &bdrv_drivers, list) {
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        it(opaque, drv->format_name);
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_find(const char *name)
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(name, bs->device_name)) {
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bs;
1428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverState *bdrv_next(BlockDriverState *bs)
1434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs) {
1436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return QTAILQ_FIRST(&bdrv_states);
1437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return QTAILQ_NEXT(bs, list);
1439cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1440cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1445cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        it(opaque, bs);
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char *bdrv_get_device_name(BlockDriverState *bs)
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->device_name;
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_flush(BlockDriverState *bs)
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1457cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->open_flags & BDRV_O_NO_FLUSH) {
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
1459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1461cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->drv && bs->drv->bdrv_flush)
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_flush(bs);
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_flush_all(void)
14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1468cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1469cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1470cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->drv && !bdrv_is_read_only(bs) &&
1471cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs))) {
1472cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_flush(bs);
1473cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1474cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_has_zero_init(BlockDriverState *bs)
1478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs->drv);
14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->drv->bdrv_has_zero_init) {
1482cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs->drv->bdrv_has_zero_init(bs);
1483cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1484cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1485cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 1;
14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Returns true iff the specified sector is present in the disk image. Drivers
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * not implementing the functionality are assumed to not support backing files,
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * hence all their sectors are reported as allocated.
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 'pnum' is set to the number of sectors (including and immediately following
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the specified sector) that are known to be in the same
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * allocated/unallocated state.
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 'nb_sectors' is the max value 'pnum' should be set to.
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int *pnum)
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t n;
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv->bdrv_is_allocated) {
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sector_num >= bs->total_sectors) {
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnum = 0;
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = bs->total_sectors - sector_num;
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1515cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_mon_event(const BlockDriverState *bdrv,
1516cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    BlockMonEventAction action, int is_read)
1517cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1518cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QObject *data;
1519cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *action_str;
1520cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    switch (action) {
1522cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    case BDRV_ACTION_REPORT:
1523cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        action_str = "report";
1524cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
1525cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    case BDRV_ACTION_IGNORE:
1526cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        action_str = "ignore";
1527cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
1528cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    case BDRV_ACTION_STOP:
1529cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        action_str = "stop";
1530cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
1531cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    default:
1532cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        abort();
1533cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1534cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1535cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    data = qobject_from_jsonf("{ 'device': %s, 'action': %s, 'operation': %s }",
1536cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              bdrv->device_name,
1537cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              action_str,
1538cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              is_read ? "read" : "write");
1539cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_protocol_event(QEVENT_BLOCK_IO_ERROR, data);
1540cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1541cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qobject_decref(data);
1542cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1543cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1544cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void bdrv_print_dict(QObject *obj, void *opaque)
1545cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1546cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QDict *bs_dict;
1547cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    Monitor *mon = opaque;
1548cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1549cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs_dict = qobject_to_qdict(obj);
1550cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1551cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, "%s: type=%s removable=%d",
1552cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_str(bs_dict, "device"),
1553cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_str(bs_dict, "type"),
1554cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_bool(bs_dict, "removable"));
1555cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1556cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (qdict_get_bool(bs_dict, "removable")) {
1557cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked"));
1558cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1559cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1560cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (qdict_haskey(bs_dict, "inserted")) {
1561cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted"));
1562cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1563cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " file=");
1564cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_print_filename(mon, qdict_get_str(qdict, "file"));
1565cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (qdict_haskey(qdict, "backing_file")) {
1566cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            monitor_printf(mon, " backing_file=");
1567cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            monitor_print_filename(mon, qdict_get_str(qdict, "backing_file"));
1568cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1569cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
1570cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                            qdict_get_bool(qdict, "ro"),
1571cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                            qdict_get_str(qdict, "drv"),
1572cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                            qdict_get_bool(qdict, "encrypted"));
1573cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
1574cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " [not inserted]");
1575cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1576cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1577cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, "\n");
1578cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1579cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1580cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_info_print(Monitor *mon, const QObject *data)
1581cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1582cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
1583cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1584cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1585cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_info(Monitor *mon, QObject **ret_data)
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1587cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QList *bs_list;
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1590cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs_list = qlist_new();
1591cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1592cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1593cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QObject *bs_obj;
1594cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        const char *type = "unknown";
1595cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(bs->type) {
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_HD:
1598cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            type = "hd";
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_CDROM:
1601cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            type = "cdrom";
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_FLOPPY:
1604cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            type = "floppy";
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1607cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1608cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': %s, "
1609cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                    "'removable': %i, 'locked': %i }",
1610cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                    bs->device_name, type, bs->removable,
1611cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                    bs->locked);
1612cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->drv) {
1614cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            QObject *obj;
1615cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            QDict *bs_dict = qobject_to_qdict(bs_obj);
1616cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1617cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, "
1618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     "'encrypted': %i }",
1619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     bs->filename, bs->read_only,
1620cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     bs->drv->format_name,
1621cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     bdrv_is_encrypted(bs));
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (bs->backing_file[0] != '\0') {
1623cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                QDict *qdict = qobject_to_qdict(obj);
1624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                qdict_put(qdict, "backing_file",
1625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                          qstring_from_str(bs->backing_file));
16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
1627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qdict_put_obj(bs_dict, "inserted", obj);
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1630cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qlist_append_obj(bs_list, bs_obj);
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1632cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1633cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *ret_data = QOBJECT(bs_list);
1634cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1635cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1636cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void bdrv_stats_iter(QObject *data, void *opaque)
1637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1638cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QDict *qdict;
1639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    Monitor *mon = opaque;
1640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qdict = qobject_to_qdict(data);
1642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, "%s:", qdict_get_str(qdict, "device"));
1643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qdict = qobject_to_qdict(qdict_get(qdict, "stats"));
1645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, " rd_bytes=%" PRId64
1646cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        " wr_bytes=%" PRId64
1647cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        " rd_operations=%" PRId64
1648cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        " wr_operations=%" PRId64
1649cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        "\n",
1650cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "rd_bytes"),
1651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "wr_bytes"),
1652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "rd_operations"),
1653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "wr_operations"));
1654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_stats_print(Monitor *mon, const QObject *data)
1657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1658cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
1659cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1660cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1661cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QObject* bdrv_info_stats_bs(BlockDriverState *bs)
1662cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1663cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QObject *res;
1664cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QDict *dict;
1665cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1666cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    res = qobject_from_jsonf("{ 'stats': {"
1667cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'rd_bytes': %" PRId64 ","
1668cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'wr_bytes': %" PRId64 ","
1669cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'rd_operations': %" PRId64 ","
1670cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'wr_operations': %" PRId64 ","
1671cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'wr_highest_offset': %" PRId64
1672cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "} }",
1673cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             bs->rd_bytes, bs->wr_bytes,
1674cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             bs->rd_ops, bs->wr_ops,
1675cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             bs->wr_highest_sector *
1676cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             (uint64_t)BDRV_SECTOR_SIZE);
1677cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    dict  = qobject_to_qdict(res);
1678cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1679cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (*bs->device_name) {
1680cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qdict_put(dict, "device", qstring_from_str(bs->device_name));
1681cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1682cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1683cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
1684cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QObject *parent = bdrv_info_stats_bs(bs->file);
1685cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qdict_put_obj(dict, "parent", parent);
1686cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1687cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1688cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return res;
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1691cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_info_stats(Monitor *mon, QObject **ret_data)
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1693cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QObject *obj;
1694cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QList *devices;
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1697cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    devices = qlist_new();
1698cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1699cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1700cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        obj = bdrv_info_stats_bs(bs);
1701cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qlist_append_obj(devices, obj);
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1703cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1704cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *ret_data = QOBJECT(devices);
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char *bdrv_get_encrypted_filename(BlockDriverState *bs)
17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->backing_hd && bs->backing_hd->encrypted)
17105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs->backing_file;
17115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (bs->encrypted)
17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs->filename;
17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_backing_filename(BlockDriverState *bs,
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               char *filename, int filename_size)
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1720cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->backing_file) {
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(filename, filename_size, "");
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(filename, filename_size, bs->backing_file);
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          const uint8_t *buf, int nb_sectors)
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_write_compressed)
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
17365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
1737cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1738cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap) {
1739cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
1740cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1741cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_get_info)
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(bdi, 0, sizeof(*bdi));
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_get_info(bs, bdi);
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1756cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
1757cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                      int64_t pos, int size)
17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv)
17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
1762cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_save_vmstate)
1763cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_save_vmstate(bs, buf, pos, size);
1764cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1765cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_save_vmstate(bs->file, buf, pos, size);
1766cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1769cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
1770cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                      int64_t pos, int size)
17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv)
17745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
1775cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_load_vmstate)
1776cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_load_vmstate(bs, buf, pos, size);
1777cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1778cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_load_vmstate(bs->file, buf, pos, size);
1779cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
1780cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1781cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1782cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
1783cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1784cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
1785cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1786cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv || !drv->bdrv_debug_event) {
1787cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return;
1788cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1789cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1790cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv->bdrv_debug_event(bs, event);
1791cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* handling of snapshots */
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17978f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thijeint bdrv_can_snapshot(BlockDriverState *bs)
17988f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije{
1799cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
1800cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv || bdrv_is_removable(bs) || bdrv_is_read_only(bs)) {
1801cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
1802cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1803cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1804cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv->bdrv_snapshot_create) {
1805cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->file != NULL) {
1806cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return bdrv_can_snapshot(bs->file);
1807cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1808cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
1809cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1810cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1811cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 1;
1812cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1813cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1814cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_is_snapshot(BlockDriverState *bs)
1815cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1816cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return !!(bs->open_flags & BDRV_O_SNAPSHOT);
1817cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1818cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1819cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverState *bdrv_snapshots(void)
1820cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1821cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1822cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1823cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs_snapshots) {
1824cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs_snapshots;
1825cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1826cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1827cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = NULL;
1828cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs = bdrv_next(bs))) {
1829cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bdrv_can_snapshot(bs)) {
1830cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_snapshots = bs;
1831cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return bs;
1832cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1833cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1834cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return NULL;
18358f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije}
18368f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_create(BlockDriverState *bs,
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         QEMUSnapshotInfo *sn_info)
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1843cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_create)
1844cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_create(bs, sn_info);
1845cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1846cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_snapshot_create(bs->file, sn_info);
1847cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_goto(BlockDriverState *bs,
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       const char *snapshot_id)
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
1854cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret, open_ret;
1855cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1858cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_goto)
1859cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_goto(bs, snapshot_id);
1860cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1861cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
1862cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv->bdrv_close(bs);
1863cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_snapshot_goto(bs->file, snapshot_id);
1864cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        open_ret = drv->bdrv_open(bs, bs->open_flags);
1865cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (open_ret < 0) {
1866cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs->file);
1867cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->drv = NULL;
1868cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return open_ret;
1869cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1870cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
1871cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1872cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1873cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1881cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_delete)
1882cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_delete(bs, snapshot_id);
1883cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1884cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_snapshot_delete(bs->file, snapshot_id);
1885cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_list(BlockDriverState *bs,
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       QEMUSnapshotInfo **psn_info)
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1894cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_list)
1895cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_list(bs, psn_info);
1896cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1897cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_snapshot_list(bs->file, psn_info);
1898cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NB_SUFFIXES 4
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar *get_human_readable_size(char *buf, int buf_size, int64_t size)
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char suffixes[NB_SUFFIXES] = "KMGT";
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t base;
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size <= 999) {
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size, "%" PRId64, size);
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        base = 1024;
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(i = 0; i < NB_SUFFIXES; i++) {
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size < (10 * base)) {
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                snprintf(buf, buf_size, "%0.1f%c",
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (double)size / base,
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         suffixes[i]);
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                snprintf(buf, buf_size, "%" PRId64 "%c",
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         ((size + (base >> 1)) / base),
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         suffixes[i]);
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            base = base * 1024;
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf1[128], date_buf[128], clock_buf[128];
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm *ptm;
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm tm;
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    time_t ti;
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t secs;
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sn) {
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size,
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%-10s%-20s%7s%20s%15s",
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ti = sn->date_sec;
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ptm = localtime(&ti);
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strftime(date_buf, sizeof(date_buf),
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%Y-%m-%d %H:%M:%S", ptm);
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        localtime_r(&ti, &tm);
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strftime(date_buf, sizeof(date_buf),
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%Y-%m-%d %H:%M:%S", &tm);
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        secs = sn->vm_clock_nsec / 1000000000;
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(clock_buf, sizeof(clock_buf),
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%02d:%02d:%02d.%03d",
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)(secs / 3600),
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)((secs / 60) % 60),
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)(secs % 60),
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size,
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%-10s%-20s%7s%20s%15s",
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 sn->id_str, sn->name,
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 date_buf,
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 clock_buf);
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* async I/Os */
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 QEMUIOVector *qiov, int nb_sectors,
19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 BlockDriverCompletionFunc *cb, void *opaque)
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *ret;
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
19885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
19915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              cb, opaque);
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret) {
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update stats even though technically transfer has not happened. */
1995cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner	bs->rd_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bs->rd_ops ++;
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
20035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  QEMUIOVector *qiov, int nb_sectors,
20045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  BlockDriverCompletionFunc *cb, void *opaque)
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *ret;
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only)
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
20145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2016cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap) {
2017cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
2018cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2019cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
20215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               cb, opaque);
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret) {
2024cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* Update stats even though technically transfer has not happened. */
2025cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
2026cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->wr_ops ++;
2027cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
2028cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->wr_highest_sector = sector_num + nb_sectors - 1;
2029cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2035cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2036cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnertypedef struct MultiwriteCB {
2037cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int error;
2038cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int num_requests;
2039cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int num_callbacks;
2040cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct {
2041cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb;
2042cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        void *opaque;
2043cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QEMUIOVector *free_qiov;
2044cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        void *free_buf;
2045cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } callbacks[];
2046cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner} MultiwriteCB;
2047cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2048cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void multiwrite_user_cb(MultiwriteCB *mcb)
2049cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2050cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int i;
2051cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2052cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < mcb->num_callbacks; i++) {
2053cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);
2054cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (mcb->callbacks[i].free_qiov) {
2055cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_destroy(mcb->callbacks[i].free_qiov);
2056cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2057cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_free(mcb->callbacks[i].free_qiov);
2058cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_vfree(mcb->callbacks[i].free_buf);
2059cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2060cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2061cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2062cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void multiwrite_cb(void *opaque, int ret)
2063cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2064cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    MultiwriteCB *mcb = opaque;
2065cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2066cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0 && !mcb->error) {
2067cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->error = ret;
2068cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2069cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2070cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_requests--;
2071cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (mcb->num_requests == 0) {
2072cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        multiwrite_user_cb(mcb);
2073cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_free(mcb);
2074cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2075cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2076cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2077cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int multiwrite_req_compare(const void *a, const void *b)
2078cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2079cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const BlockRequest *req1 = a, *req2 = b;
2080cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2081cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
2082cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Note that we can't simply subtract req2->sector from req1->sector
2083cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * here as that could overflow the return value.
2084cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
2085cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (req1->sector > req2->sector) {
2086cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 1;
2087cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else if (req1->sector < req2->sector) {
2088cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -1;
2089cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
2090cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
2091cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2092cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2093cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2094cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
2095cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Takes a bunch of requests and tries to merge them. Returns the number of
2096cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * requests that remain after merging.
2097cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
2098cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
2099cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int num_reqs, MultiwriteCB *mcb)
2100cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2101cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int i, outidx;
2102cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2103cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Sort requests by start sector
2104cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qsort(reqs, num_reqs, sizeof(*reqs), &multiwrite_req_compare);
2105cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2106cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Check if adjacent requests touch the same clusters. If so, combine them,
2107cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // filling up gaps with zero sectors.
2108cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    outidx = 0;
2109cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 1; i < num_reqs; i++) {
2110cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int merge = 0;
2111cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int64_t oldreq_last = reqs[outidx].sector + reqs[outidx].nb_sectors;
2112cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2113cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // This handles the cases that are valid for all block drivers, namely
2114cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // exactly sequential writes and overlapping writes.
2115cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (reqs[i].sector <= oldreq_last) {
2116cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            merge = 1;
2117cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2118cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2119cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // The block driver may decide that it makes sense to combine requests
2120cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // even if there is a gap of some sectors between them. In this case,
2121cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // the gap is filled with zeros (therefore only applicable for yet
2122cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // unused space in format like qcow2).
2123cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!merge && bs->drv->bdrv_merge_requests) {
2124cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);
2125cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2126cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2127cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
2128cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            merge = 0;
2129cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2130cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2131cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (merge) {
2132cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            size_t size;
2133cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov));
2134cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_init(qiov,
2135cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1);
2136cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2137cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // Add the first request to the merged one. If the requests are
2138cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // overlapping, drop the last sectors of the first request.
2139cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            size = (reqs[i].sector - reqs[outidx].sector) << 9;
2140cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_concat(qiov, reqs[outidx].qiov, size);
2141cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2142cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // We might need to add some zeros between the two requests
2143cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (reqs[i].sector > oldreq_last) {
2144cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                size_t zero_bytes = (reqs[i].sector - oldreq_last) << 9;
2145cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                uint8_t *buf = qemu_blockalign(bs, zero_bytes);
2146cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                memset(buf, 0, zero_bytes);
2147cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                qemu_iovec_add(qiov, buf, zero_bytes);
2148cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                mcb->callbacks[i].free_buf = buf;
2149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
2150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // Add the second request
2152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);
2153cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2154cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].nb_sectors = qiov->size >> 9;
2155cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].qiov = qiov;
2156cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2157cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            mcb->callbacks[i].free_qiov = reqs[outidx].qiov;
2158cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
2159cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            outidx++;
2160cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].sector     = reqs[i].sector;
2161cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].nb_sectors = reqs[i].nb_sectors;
2162cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].qiov       = reqs[i].qiov;
2163cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2164cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2165cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2166cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return outidx + 1;
2167cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2168cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2169cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
2170cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Submit multiple AIO write requests at once.
2171cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
2172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * On success, the function returns 0 and all requests in the reqs array have
2173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * been submitted. In error case this function returns -1, and any of the
2174cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * requests may or may not be submitted yet. In particular, this means that the
2175cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * callback will be called for some of the requests, for others it won't. The
2176cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * caller must check the error field of the BlockRequest to wait for the right
2177cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * callbacks (if error != 0, no callback will be called).
2178cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
2179cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * The implementation may modify the contents of the reqs array, e.g. to merge
2180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * requests. However, the fields opaque and error are left unmodified as they
2181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * are used to signal failure for a single request to the caller.
2182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
2183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
2184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCB *acb;
2186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    MultiwriteCB *mcb;
2187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int i;
2188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (num_reqs == 0) {
2190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
2191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Create MultiwriteCB structure
2194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb = qemu_mallocz(sizeof(*mcb) + num_reqs * sizeof(*mcb->callbacks));
2195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_requests = 0;
2196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_callbacks = num_reqs;
2197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < num_reqs; i++) {
2199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->callbacks[i].cb = reqs[i].cb;
2200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->callbacks[i].opaque = reqs[i].opaque;
2201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2202cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2203cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Check for mergable requests
2204cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb);
2205cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2206cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
2207cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Run the aio requests. As soon as one request can't be submitted
2208cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * successfully, fail all requests that are not yet submitted (we must
2209cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * return failure for all requests anyway)
2210cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     *
2211cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * num_requests cannot be set to the right value immediately: If
2212cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * bdrv_aio_writev fails for some request, num_requests would be too high
2213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * and therefore multiwrite_cb() would never recognize the multiwrite
2214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * request as completed. We also cannot use the loop variable i to set it
2215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * when the first request fails because the callback may already have been
2216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * called for previously submitted requests. Thus, num_requests must be
2217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * incremented for each request that is submitted.
2218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     *
2219cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * The problem that callbacks may be called early also means that we need
2220cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * to take care that num_requests doesn't become 0 before all requests are
2221cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * submitted - multiwrite_cb() would consider the multiwrite request
2222cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * completed. A dummy request that is "completed" by a manual call to
2223cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * multiwrite_cb() takes care of this.
2224cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
2225cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_requests = 1;
2226cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2227cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < num_reqs; i++) {
2228cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->num_requests++;
2229cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
2230cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[i].nb_sectors, multiwrite_cb, mcb);
2231cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2232cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (acb == NULL) {
2233cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // We can only fail the whole thing if no request has been
2234cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // submitted yet. Otherwise we'll wait for the submitted AIOs to
2235cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // complete and report the error in the callback.
2236cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (i == 0) {
2237cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto fail;
2238cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            } else {
2239cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                multiwrite_cb(mcb, -EIO);
2240cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                break;
2241cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
2242cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2243cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2244cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2245cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Complete the dummy request */
2246cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    multiwrite_cb(mcb, 0);
2247cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2248cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
2249cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2250cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfail:
2251cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < mcb->num_callbacks; i++) {
2252cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        reqs[i].error = -EIO;
2253cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2254cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_free(mcb);
2255cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -1;
2256cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2257cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2258cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
2259cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
2260cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2261cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
2262cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2263cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->open_flags & BDRV_O_NO_FLUSH) {
2264cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_aio_noop_em(bs, cb, opaque);
2265cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2266cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2267cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv)
2268cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return NULL;
2269cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv->bdrv_aio_flush(bs, cb, opaque);
2270cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2271cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_aio_cancel(BlockDriverAIOCB *acb)
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->pool->cancel(acb);
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* async block device emulation */
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct BlockDriverAIOCBSync {
22825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCB common;
22835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUBH *bh;
22845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
22855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* vector translation state */
22865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector *qiov;
22875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *bounce;
22885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_write;
22895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} BlockDriverAIOCBSync;
22905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
22925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2293cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCBSync *acb =
2294cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        container_of(blockacb, BlockDriverAIOCBSync, common);
22955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(acb->bh);
2296cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bh = NULL;
22975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_release(acb);
22985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
22995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic AIOPool bdrv_em_aio_pool = {
23015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
23025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    .cancel             = bdrv_aio_cancel_em,
23035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
23045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void bdrv_aio_bh_cb(void *opaque)
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCBSync *acb = opaque;
23085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!acb->is_write)
23105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
23115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_vfree(acb->bounce);
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->common.cb(acb->common.opaque, acb->ret);
23135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(acb->bh);
2314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bh = NULL;
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_aio_release(acb);
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
23195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int64_t sector_num,
23205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            QEMUIOVector *qiov,
23215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int nb_sectors,
23225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            BlockDriverCompletionFunc *cb,
23235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            void *opaque,
23245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int is_write)
23255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCBSync *acb;
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
23305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->is_write = is_write;
23315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->qiov = qiov;
23325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->bounce = qemu_blockalign(bs, qiov->size);
23335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!acb->bh)
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
23365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_write) {
23385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_iovec_to_buffer(acb->qiov, acb->bounce);
23395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
23405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
23415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors);
23425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
23435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_bh_schedule(acb->bh);
23455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return &acb->common;
23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
23505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque)
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
23575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
23585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2363cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
2364cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
2365cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2366cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCBSync *acb;
2367cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2368cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
2369cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->is_write = 1; /* don't bounce in the completion hadler */
2370cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->qiov = NULL;
2371cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bounce = NULL;
2372cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->ret = 0;
2373cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2374cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb->bh)
2375cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
2376cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2377cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bdrv_flush(bs);
2378cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_bh_schedule(acb->bh);
2379cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return &acb->common;
2380cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2381cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2382cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
2383cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
2384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCBSync *acb;
2386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
2388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->is_write = 1; /* don't bounce in the completion handler */
2389cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->qiov = NULL;
2390cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bounce = NULL;
2391cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->ret = 0;
2392cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2393cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb->bh) {
2394cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
2395cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2396cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_bh_schedule(acb->bh);
2398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return &acb->common;
2399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sync block device emulation */
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void bdrv_rw_em_cb(void *opaque, int ret)
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *(int *)opaque = ret;
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NOT_DONE 0x7fffffff
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors)
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int async_ret;
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
24165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct iovec iov;
24175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector qiov;
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_push();
2420cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    async_ret = NOT_DONE;
24225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_base = (void *)buf;
2423cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
24245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_iovec_init_external(&qiov, &iov, 1);
24255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
24265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_rw_em_cb, &async_ret);
2427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (acb == NULL) {
2428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        async_ret = -1;
2429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto fail;
2430cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (async_ret == NOT_DONE) {
24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_aio_wait();
24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfail:
2438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_pop();
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return async_ret;
24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors)
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int async_ret;
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
24475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct iovec iov;
24485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector qiov;
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2450cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_push();
2451cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    async_ret = NOT_DONE;
24535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_base = (void *)buf;
2454cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
24555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_iovec_init_external(&qiov, &iov, 1);
24565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
24575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_rw_em_cb, &async_ret);
2458cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (acb == NULL) {
2459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        async_ret = -1;
2460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto fail;
2461cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
24628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (async_ret == NOT_DONE) {
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_aio_wait();
24648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2465cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfail:
2467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_pop();
24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return async_ret;
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_init(void)
24728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    module_call_init(MODULE_INIT_BLOCK);
24748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_init_with_whitelist(void)
2477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    use_bdrv_whitelist = 1;
2479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bdrv_init();
2480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
24835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   BlockDriverCompletionFunc *cb, void *opaque)
24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
24868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (pool->free_aiocb) {
24885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb = pool->free_aiocb;
24895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pool->free_aiocb = acb->next;
24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb = qemu_mallocz(pool->aiocb_size);
24925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->pool = pool;
24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->bs = bs;
24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->cb = cb;
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->opaque = opaque;
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return acb;
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid qemu_aio_release(void *p)
25018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
25035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AIOPool *pool = acb->pool;
25045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->next = pool->free_aiocb;
25055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pool->free_aiocb = acb;
25068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
25098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* removable device support */
25108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TRUE if the media is present
25138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_inserted(BlockDriverState *bs)
25158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
25188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
25198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
25208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_is_inserted)
2521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return !bs->tray_open;
25228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = drv->bdrv_is_inserted(bs);
25238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
25248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TRUE if the media changed since the last call to this
25288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * function. It is currently only used for floppy disks
25298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_media_changed(BlockDriverState *bs)
25318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
25348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv || !drv->bdrv_media_changed)
25368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = -ENOTSUP;
25378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
25388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = drv->bdrv_media_changed(bs);
25398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == -ENOTSUP)
25408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = bs->media_changed;
25418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->media_changed = 0;
25428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
25438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If eject_flag is TRUE, eject the media. Otherwise, close the tray
25478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_eject(BlockDriverState *bs, int eject_flag)
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
25528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->locked) {
25545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EBUSY;
25555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
25565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv || !drv->bdrv_eject) {
25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = -ENOTSUP;
25598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = drv->bdrv_eject(bs, eject_flag);
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == -ENOTSUP) {
25635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = 0;
25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2565cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret >= 0) {
2566cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->tray_open = eject_flag;
2567cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
25685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
25695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_locked(BlockDriverState *bs)
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->locked;
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lock or unlock the media (if it is locked, the user won't be able
25798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to eject it manually).
25808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_locked(BlockDriverState *bs, int locked)
25828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->locked = locked;
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv && drv->bdrv_set_locked) {
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        drv->bdrv_set_locked(bs, locked);
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* needed for generic scsi interface */
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
25948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv && drv->bdrv_ioctl)
25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return drv->bdrv_ioctl(bs, req, buf);
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -ENOTSUP;
26008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
26025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
26035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        unsigned long int req, void *buf,
26045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
26055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
26065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
26075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
26085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (drv && drv->bdrv_aio_ioctl)
26095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
26105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
26115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
26125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2613cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2614cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
26155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_blockalign(BlockDriverState *bs, size_t size)
26165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
26175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);
26185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2620cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_set_dirty_tracking(BlockDriverState *bs, int enable)
2621cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2622cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t bitmap_size;
2623cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->dirty_count = 0;
2625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (enable) {
2626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!bs->dirty_bitmap) {
2627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
2628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
2629cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
2630cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2631cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->dirty_bitmap = qemu_mallocz(bitmap_size);
2632cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2633cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
2634cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->dirty_bitmap) {
2635cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_free(bs->dirty_bitmap);
2636cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->dirty_bitmap = NULL;
2637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2638cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
2642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
2644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap &&
2646cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) {
2647cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] &
2648cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            (1 << (chunk % (sizeof(unsigned long) * 8)));
2649cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
2650cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
2651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
2655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                      int nr_sectors)
2656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    set_dirty_bitmap(bs, cur_sector, nr_sectors, 0);
2658cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2659cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2660cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint64_t bdrv_get_dirty_count(BlockDriverState *bs)
2661cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2662cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->dirty_count;
2663cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2664