block.c revision cb42a1b1461e02efb034582ac5d8f71534723b92
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"
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "monitor.h"
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "block_int.h"
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "module.h"
29cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "qemu-objects.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
312c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/stat.h>
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ioctl.h>
35cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <sys/queue.h>
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef __DragonFly__
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/disk.h>
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h>
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
51cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
52cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque);
53cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
54cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque);
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors);
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors);
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
60cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QTAILQ_HEAD(, BlockDriverState) bdrv_states =
61cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_HEAD_INITIALIZER(bdrv_states);
62cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
63cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QLIST_HEAD(, BlockDriver) bdrv_drivers =
64cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_HEAD_INITIALIZER(bdrv_drivers);
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
66cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/* The device to use for VM snapshots */
67cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverState *bs_snapshots;
68cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
69cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/* If non-zero, use only whitelisted block drivers */
70cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int use_bdrv_whitelist;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint _path_is_absolute(const char *path)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* specific case for names like: "\\.\d:" */
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*path == '/' || *path == '\\')
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr(path, ':');
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p)
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p++;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = path;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/' || *p == '\\');
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/');
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if filename is absolute, just copy it to dest. Otherwise, build a
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   path to it by considering it is relative to base_path. URL are
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   supported. */
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid path_combine(char *dest, int dest_size,
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *base_path,
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *filename)
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p, *p1;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dest_size <= 0)
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (_path_is_absolute(filename)) {
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(dest, dest_size, filename);
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = strchr(base_path, ':');
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p)
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p++;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = base_path;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p1 = strrchr(base_path, '/');
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char *p2;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p2 = strrchr(base_path, '\\');
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!p1 || p2 > p1)
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p1 = p2;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1)
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1++;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1 = base_path;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1 > p)
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = p1;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = p - base_path;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len > dest_size - 1)
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = dest_size - 1;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(dest, base_path, len);
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dest[len] = '\0';
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcat(dest, dest_size, filename);
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_register(BlockDriver *bdrv)
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv->bdrv_aio_readv) {
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add AIO emulation layer */
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bdrv->bdrv_read) {
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add synchronous IO emulation layer */
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_read = bdrv_read_em;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_write = bdrv_write_em;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
147cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
148cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bdrv->bdrv_aio_flush)
149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* create a new block device (by default it is empty) */
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_new(const char *device_name)
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
157cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = qemu_mallocz(sizeof(BlockDriverState));
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (device_name[0] != '\0') {
162cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriver *bdrv_find_format(const char *format_name)
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1;
170cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
171cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(drv1->format_name, format_name)) {
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return drv1;
173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
178cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int bdrv_is_whitelisted(BlockDriver *drv)
179cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    static const char *whitelist[] = {
181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        CONFIG_BDRV_WHITELIST
182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    };
183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char **p;
184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!whitelist[0])
186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 1;               /* no whitelist, anything goes */
187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (p = whitelist; *p; p++) {
189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(drv->format_name, *p)) {
190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return 1;
191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriver *bdrv_find_whitelisted_format(const char *format_name)
197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bdrv_find_format(format_name);
199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_create(BlockDriver *drv, const char* filename,
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *options)
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_create)
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_create(filename, options);
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
211cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_create_file(const char* filename, QEMUOptionParameter *options)
212cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv;
214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = bdrv_find_protocol(filename);
216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv == NULL) {
217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv = bdrv_find_format("file");
218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
219cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
220cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_create(drv, filename, options);
221cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
222cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char temp_dir[MAX_PATH];
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempPath(MAX_PATH, temp_dir);
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempFileName(temp_dir, "qem", 0, filename);
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *tmpdir;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: race condition possible */
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmpdir = getenv("TMPDIR");
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!tmpdir)
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmpdir = "/tmp";
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = mkstemp(filename);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close(fd);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int is_windows_drive_prefix(const char *filename)
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            filename[1] == ':');
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint is_windows_drive(const char *filename)
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_windows_drive_prefix(filename) &&
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename[2] == '\0')
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strstart(filename, "\\\\.\\", NULL) ||
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strstart(filename, "//./", NULL))
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Detect host devices. By convention, /dev/cdrom[N] is always
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * recognized as a host CDROM.
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriver *find_hdev_driver(const char *filename)
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int score_max = 0, score;
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = NULL, *d;
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
275cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(d, &bdrv_drivers, list) {
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (d->bdrv_probe_device) {
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            score = d->bdrv_probe_device(filename);
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (score > score_max) {
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                score_max = score;
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv = d;
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv;
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
288cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriver *bdrv_find_protocol(const char *filename)
289cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
290cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv1;
291cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char protocol[128];
292cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int len;
293cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *p;
294cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
295cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* TODO Drivers without bdrv_file_open must be specified explicitly */
296cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
297cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
298cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * XXX(hch): we really should not let host device detection
299cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * override an explicit protocol specification, but moving this
300cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * later breaks access to device names with colons in them.
301cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Thanks to the brain-dead persistent naming schemes on udev-
302cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * based Linux systems those actually are quite common.
303cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
304cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv1 = find_hdev_driver(filename);
305cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv1) {
306cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv1;
307cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
308cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
309cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef _WIN32
310cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     if (is_windows_drive(filename) ||
311cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         is_windows_drive_prefix(filename))
312cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         return bdrv_find_format("file");
313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
315cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    p = strchr(filename, ':');
316cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!p) {
317cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_find_format("file");
318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = p - filename;
320cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (len > sizeof(protocol) - 1)
321cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = sizeof(protocol) - 1;
322cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    memcpy(protocol, filename, len);
323cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    protocol[len] = '\0';
324cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
325cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (drv1->protocol_name &&
326cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            !strcmp(drv1->protocol_name, protocol)) {
327cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return drv1;
328cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
329cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
330cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return NULL;
331cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
332cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
333cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int find_image_format(const char *filename, BlockDriver **pdrv)
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, score, score_max;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1, *drv;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t buf[2048];
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
340cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_file_open(&bs, filename, 0);
341cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
342cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = NULL;
343cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
344cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
345cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
346cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
347cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->sg || !bdrv_is_inserted(bs)) {
348cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs);
349cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv = bdrv_find_format("raw");
350cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!drv) {
351cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = -ENOENT;
352cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
353cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = drv;
354cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
355cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_delete(bs);
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
360cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = NULL;
361cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    score_max = 0;
365cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = NULL;
366cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (drv1->bdrv_probe) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            score = drv1->bdrv_probe(buf, ret, filename);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (score > score_max) {
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                score_max = score;
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                drv = drv1;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
375cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
376cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = -ENOENT;
377cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
378cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *pdrv = drv;
379cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
382cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/**
383cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Set the current 'total_sectors' value
384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
389cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
390cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->sg)
391cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
392cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
393cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* query actual device if possible, otherwise just trust the hint */
394cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_getlength) {
395cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int64_t length = drv->bdrv_getlength(bs);
396cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (length < 0) {
397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return length;
398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        hint = length >> BDRV_SECTOR_BITS;
400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
401cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
402cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->total_sectors = hint;
403cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
404cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
405cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
406cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
407cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Common part for opening disk images and files
408cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
409cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int bdrv_open_common(BlockDriverState *bs, const char *filename,
410cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int flags, BlockDriver *drv)
411cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
412cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret, open_flags;
413cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
414cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(drv != NULL);
415cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
416cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->file = NULL;
417cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->total_sectors = 0;
418cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->encrypted = 0;
419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->valid_key = 0;
420cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->open_flags = flags;
421cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* buffer_alignment defaulted to 512, drivers can change this value */
422cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->buffer_alignment = 512;
423cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
424cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    pstrcpy(bs->filename, sizeof(bs->filename), filename);
425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
430cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->drv = drv;
431cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->opaque = qemu_mallocz(drv->instance_size);
432cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * write cache to the guest.  We do need the fdatasync to flush
436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * out transactions for block allocations, and we maybe have a
437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * volatile write cache in our backing device to deal with.
438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
439cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
440cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->enable_write_cache = 1;
441cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
442cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
443cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Clear flags that are internal to the block layer before opening the
444cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * image.
445cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
446cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
447cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
448cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
449cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Snapshots should be writeable.
450cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
451cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
452cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        open_flags |= BDRV_O_RDWR;
453cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
454cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
455cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Open the image, either directly or using a protocol */
456cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_file_open) {
457cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = drv->bdrv_file_open(bs, filename, open_flags);
458cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_file_open(&bs->file, filename, open_flags);
460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret >= 0) {
461cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = drv->bdrv_open(bs, open_flags);
462cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
463cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
464cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
465cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto free_and_fail;
467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
468cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
469cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
470cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
471cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = refresh_total_sectors(bs, bs->total_sectors);
472cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
473cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto free_and_fail;
474cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifndef _WIN32
477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unlink(filename);
479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
482cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
483cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfree_and_fail:
484cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
485cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->file);
486cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->file = NULL;
487cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
488cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_free(bs->opaque);
489cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->opaque = NULL;
490cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->drv = NULL;
491cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
492cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
493cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
494cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
495cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Opens a file using a protocol (file, host_device, nbd, ...)
496cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
500cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv;
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
503cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = bdrv_find_protocol(filename);
504cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
505cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOENT;
506cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
507cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = bdrv_new("");
509cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_open_common(bs, filename, flags, drv);
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs);
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ret;
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs->growable = 1;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pbs = bs;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
519cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
520cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Opens a disk image (raw, qcow2, vmdk, ...)
521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
522cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_open(BlockDriverState *bs, const char *filename, int flags,
523cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner              BlockDriver *drv)
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
525cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
526cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int probed = 0;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & BDRV_O_SNAPSHOT) {
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverState *bs1;
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int64_t total_size;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int is_protocol = 0;
5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *bdrv_qcow2;
5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        QEMUOptionParameter *options;
534cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char tmp_filename[PATH_MAX];
535cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char backing_filename[PATH_MAX];
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if snapshot, we create a temporary backing file and open it
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           instead of opening 'filename' directly */
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if there is a backing file, use it */
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs1 = bdrv_new("");
542cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs1, filename, 0, drv);
5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs1);
5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
547cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs1->drv && bs1->drv->protocol_name)
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            is_protocol = 1;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs1);
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Real path is meaningless for protocols */
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_protocol)
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            snprintf(backing_filename, sizeof(backing_filename),
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     "%s", filename);
560cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        else if (!realpath(filename, backing_filename))
561cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return -errno;
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_qcow2 = bdrv_find_format("qcow2");
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
566cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (drv) {
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv->format_name);
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
574cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        free_option_parameters(options);
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename = tmp_filename;
5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        drv = bdrv_qcow2;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->is_temporary = 1;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
584cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Find the right image format driver */
585cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
586cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = find_image_format(filename, &drv);
587cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        probed = 1;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
589cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv) {
5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto unlink_and_fail;
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
593cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
594cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Open the image */
595cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_open_common(bs, filename, flags, drv);
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
597cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto unlink_and_fail;
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
599cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
600cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->probed = probed;
601cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
602cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* If there is a backing file, use it */
603cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
604cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char backing_filename[PATH_MAX];
605cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int back_flags;
6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *back_drv = NULL;
607cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->backing_hd = bdrv_new("");
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        path_combine(backing_filename, sizeof(backing_filename),
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     filename, bs->backing_file);
6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->backing_format[0] != '\0')
6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            back_drv = bdrv_find_format(bs->backing_format);
613cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
614cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* backing files always opened read-only */
615cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        back_flags =
616cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
617cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bdrv_close(bs);
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
623cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->is_temporary) {
624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* base image inherits from "parent" */
627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd->keep_read_only = bs->keep_read_only;
628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_key_required(bs)) {
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback */
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerunlink_and_fail:
641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unlink(filename);
643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_close(BlockDriverState *bs)
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->drv) {
650cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs == bs_snapshots) {
651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_snapshots = NULL;
652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->backing_hd) {
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs->backing_hd);
655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd = NULL;
656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_close(bs);
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free(bs->opaque);
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->is_temporary) {
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unlink(bs->filename);
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->opaque = NULL;
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv = NULL;
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
667cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->file != NULL) {
668cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_close(bs->file);
669cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
670cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* call the change callback */
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->media_changed = 1;
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->change_cb)
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bs->change_cb(bs->change_opaque);
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
678cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_close_all(void)
679cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
680cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
681cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
682cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
683cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_close(bs);
684cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
685cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
686cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_delete(BlockDriverState *bs)
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
689cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(!bs->peer);
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
691cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* remove from list, if necessary */
692cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->device_name[0] != '\0') {
693cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_REMOVE(&bdrv_states, bs, list);
694cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_close(bs);
697cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file != NULL) {
698cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->file);
699cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
700cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
701cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs != bs_snapshots);
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_free(bs);
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
705cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_attach(BlockDriverState *bs, DeviceState *qdev)
706cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
707cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->peer) {
708cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EBUSY;
709cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
710cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->peer = qdev;
711cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
712cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
713cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
714cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
715cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
716cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs->peer == qdev);
717cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->peer = NULL;
718cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
719cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
720cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerDeviceState *bdrv_get_attached(BlockDriverState *bs)
721cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
722cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->peer;
723cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
724cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Run consistency checks on an image
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
728cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 if the check could be completed (it doesn't mean that the image is
729cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * free of errors) or -errno when an internal error occured. The results of the
730cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * check are stored in res.
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
732cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->drv->bdrv_check == NULL) {
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
738cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    memset(res, 0, sizeof(*res));
739cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->drv->bdrv_check(bs, res);
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
742cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#define COMMIT_BUF_SECTORS 2048
743cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* commit COW file into the raw image */
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_commit(BlockDriverState *bs)
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
748cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t sector, total_sectors;
749cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int n, ro, open_flags;
750cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = 0, rw_ret = 0;
751cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t *buf;
752cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char filename[1024];
753cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs_rw, *bs_ro;
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->backing_hd) {
759cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
762cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->backing_hd->keep_read_only) {
763cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EACCES;
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
766cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ro = bs->backing_hd->read_only;
767cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    strncpy(filename, bs->backing_hd->filename, sizeof(filename));
768cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    open_flags =  bs->backing_hd->open_flags;
769cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
770cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ro) {
771cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* re-open as RW */
772cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->backing_hd);
773cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = NULL;
774cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_rw = bdrv_new("");
775cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, drv);
776cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (rw_ret < 0) {
777cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs_rw);
778cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* try to re-open read-only */
779cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_ro = bdrv_new("");
780cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
781cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (ret < 0) {
782cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bdrv_delete(bs_ro);
783cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* drive not functional anymore */
784cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->drv = NULL;
785cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                return ret;
786cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
787cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd = bs_ro;
788cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return rw_ret;
789cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
790cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = bs_rw;
791cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
793cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
794cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    buf = qemu_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
795cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
796cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (sector = 0; sector < total_sectors; sector += n) {
797cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (drv->bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
798cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
799cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (bdrv_read(bs, sector, buf, n) != 0) {
800cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                ret = -EIO;
801cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto ro_cleanup;
802cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
803cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
804cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (bdrv_write(bs->backing_hd, sector, buf, n) != 0) {
805cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                ret = -EIO;
806cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto ro_cleanup;
807cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
811cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_make_empty) {
812cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = drv->bdrv_make_empty(bs);
813cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs);
814cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
816cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
817cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Make sure all data we wrote to the backing device is actually
818cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * stable on disk.
819cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
820cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->backing_hd)
821cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs->backing_hd);
822cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
823cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerro_cleanup:
824cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_free(buf);
825cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
826cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ro) {
827cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* re-open as RO */
828cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->backing_hd);
829cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = NULL;
830cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_ro = bdrv_new("");
831cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
832cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret < 0) {
833cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs_ro);
834cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* drive not functional anymore */
835cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->drv = NULL;
836cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
837cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
838cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = bs_ro;
839cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd->keep_read_only = 0;
840cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
841cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
842cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
843cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
844cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
845cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_commit_all(void)
846cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
847cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
848cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
849cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
850cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_commit(bs);
851cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
852cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
853cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
854cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
855cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Return values:
856cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * 0        - success
857cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -EINVAL  - backing format specified, but no file
858cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -ENOSPC  - can't update the backing file because no space is left in the
859cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *            image file header
860cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -ENOTSUP - format driver doesn't support changing the backing file
861cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
862cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_change_backing_file(BlockDriverState *bs,
863cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *backing_file, const char *backing_fmt)
864cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
865cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
866cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
867cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_change_backing_file != NULL) {
868cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_change_backing_file(bs, backing_file, backing_fmt);
869cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
870cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
871cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   size_t size)
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t len;
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_is_inserted(bs))
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->growable)
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = bdrv_getlength(bs);
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (offset < 0)
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((offset > len) || (len - offset < size))
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              int nb_sectors)
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
899cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
900cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                   nb_sectors * BDRV_SECTOR_SIZE);
9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return < 0 if error. See bdrv_write() for the return codes */
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_read(BlockDriverState *bs, int64_t sector_num,
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              uint8_t *buf, int nb_sectors)
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
917cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void set_dirty_bitmap(BlockDriverState *bs, int64_t sector_num,
918cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             int nb_sectors, int dirty)
919cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
920cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t start, end;
921cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    unsigned long val, idx, bit;
922cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
923cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
924cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
925cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
926cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (; start <= end; start++) {
927cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        idx = start / (sizeof(unsigned long) * 8);
928cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bit = start % (sizeof(unsigned long) * 8);
929cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        val = bs->dirty_bitmap[idx];
930cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (dirty) {
931cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (!(val & (1 << bit))) {
932cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->dirty_count++;
933cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                val |= 1 << bit;
934cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
935cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
936cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (val & (1 << bit)) {
937cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->dirty_count--;
938cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                val &= ~(1 << bit);
939cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
940cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
941cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->dirty_bitmap[idx] = val;
942cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
943cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
944cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return < 0 if error. Important errors are:
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EIO         generic I/O error (may happen for all errors)
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -ENOMEDIUM   No media inserted.
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EINVAL      Invalid sector number or nb_sectors
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EACCES      Trying to write a read-only device
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_write(BlockDriverState *bs, int64_t sector_num,
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               const uint8_t *buf, int nb_sectors)
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv)
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only)
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -EACCES;
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
962cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap) {
963cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
964cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
965cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
966cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
967cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->wr_highest_sector = sector_num + nb_sectors - 1;
968cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
969cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_pread(BlockDriverState *bs, int64_t offset,
9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               void *buf, int count1)
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
976cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t tmp_buf[BDRV_SECTOR_SIZE];
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len, nb_sectors, count;
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t sector_num;
979cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = count1;
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first read to align to sector start */
983cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > count)
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = count;
986cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sector_num = offset >> BDRV_SECTOR_BITS;
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > 0) {
988cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
989cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
990cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len);
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count == 0)
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return count1;
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num++;
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* read the sectors "in place" */
999cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    nb_sectors = count >> BDRV_SECTOR_BITS;
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_sectors > 0) {
1001cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, buf, nb_sectors)) < 0)
1002cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num += nb_sectors;
1004cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = nb_sectors << BDRV_SECTOR_BITS;
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* add data from the last sector */
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
1011cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
1012cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(buf, tmp_buf, count);
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count1;
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_pwrite(BlockDriverState *bs, int64_t offset,
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const void *buf, int count1)
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1021cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t tmp_buf[BDRV_SECTOR_SIZE];
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len, nb_sectors, count;
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t sector_num;
1024cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = count1;
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first write to align to sector start */
1028cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > count)
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = count;
1031cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    sector_num = offset >> BDRV_SECTOR_BITS;
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > 0) {
1033cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
1034cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
1035cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);
1036cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
1037cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count == 0)
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return count1;
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num++;
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* write the sectors "in place" */
1046cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    nb_sectors = count >> BDRV_SECTOR_BITS;
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_sectors > 0) {
1048cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0)
1049cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num += nb_sectors;
1051cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = nb_sectors << BDRV_SECTOR_BITS;
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* add data from the last sector */
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
1058cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
1059cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(tmp_buf, buf, count);
1061cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
1062cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count1;
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1067cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
1068cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Writes to the file and ensures that no writes are reordered across this
1069cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * request (acts as a barrier)
1070cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
1071cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 on success, -errno in error cases.
1072cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
1073cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
1074cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const void *buf, int count)
1075cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1076cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
1077cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1078cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_pwrite(bs, offset, buf, count);
1079cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
1080cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
1081cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1082cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1083cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* No flush needed for cache=writethrough, it uses O_DSYNC */
1084cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if ((bs->open_flags & BDRV_O_CACHE_MASK) != 0) {
1085cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs);
1086cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1087cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1088cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
1089cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1090cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1091cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
1092cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Writes to the file and ensures that no writes are reordered across this
1093cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * request (acts as a barrier)
1094cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
1095cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 on success, -errno in error cases.
1096cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
1097cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
1098cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const uint8_t *buf, int nb_sectors)
1099cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1100cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_pwrite_sync(bs, BDRV_SECTOR_SIZE * sector_num,
1101cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        buf, BDRV_SECTOR_SIZE * nb_sectors);
1102cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1103cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Truncate file to 'offset' bytes (needed only for file protocols)
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_truncate(BlockDriverState *bs, int64_t offset)
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
1110cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_truncate)
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
1115cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->read_only)
1116cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EACCES;
1117cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = drv->bdrv_truncate(bs, offset);
1118cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret == 0) {
1119cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
1120cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1121cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Length of a file in bytes. Return < 0 if error or unknown.
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint64_t bdrv_getlength(BlockDriverState *bs)
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1132cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1133cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Fixed size devices use the total_sectors value for speed instead of
1134cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner       issuing a length query (like lseek) on each call.  Also, legacy block
1135cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner       drivers don't provide a bdrv_getlength function and must use
1136cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner       total_sectors. */
1137cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->growable || !drv->bdrv_getlength) {
1138cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs->total_sectors * BDRV_SECTOR_SIZE;
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_getlength(bs);
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return 0 as number of sectors if no device present or error */
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t length;
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    length = bdrv_getlength(bs);
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (length < 0)
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        length = 0;
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
1151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        length = length >> BDRV_SECTOR_BITS;
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *nb_sectors_ptr = length;
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct partition {
11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t boot_ind;           /* 0x80 - active */
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t head;               /* starting head */
11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t sector;             /* starting sector */
11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t cyl;                /* starting cylinder */
11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t sys_ind;            /* What partition type */
11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_head;           /* end head */
11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_sector;         /* end sector */
11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_cyl;            /* end cylinder */
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t start_sect;        /* starting sector counting from 0 */
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t nr_sects;          /* nr of sectors in partition */
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} __attribute__((packed));
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int guess_disk_lchs(BlockDriverState *bs,
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           int *pcylinders, int *pheads, int *psectors)
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t buf[BDRV_SECTOR_SIZE];
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret, i, heads, sectors, cylinders;
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct partition *p;
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t nr_sects;
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t nb_sectors;
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry(bs, &nb_sectors);
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bdrv_read(bs, 0, buf, 1);
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* test msdos magic */
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (buf[510] != 0x55 || buf[511] != 0xaa)
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < 4; i++) {
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p = ((struct partition *)(buf + 0x1be)) + i;
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        nr_sects = le32_to_cpu(p->nr_sects);
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (nr_sects && p->end_head) {
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* We make the assumption that the partition terminates on
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               a cylinder boundary */
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            heads = p->end_head + 1;
11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            sectors = p->end_sector & 63;
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sectors == 0)
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cylinders = nb_sectors / (heads * sectors);
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (cylinders < 1 || cylinders > 16383)
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pheads = heads;
12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *psectors = sectors;
12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pcylinders = cylinders;
12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            printf("guessed geometry: LCHS=%d %d %d\n",
12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   cylinders, heads, sectors);
12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int translation, lba_detected = 0;
12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int cylinders, heads, secs;
12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t nb_sectors;
12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* if a geometry hint is available, use it */
12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry(bs, &nb_sectors);
12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    translation = bdrv_get_translation_hint(bs);
12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (cylinders != 0) {
12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *pcyls = cylinders;
12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *pheads = heads;
12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *psecs = secs;
12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (heads > 16) {
12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* if heads > 16, it means that a BIOS LBA
12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   translation was active, so the default
12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   hardware geometry is OK */
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                lba_detected = 1;
12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto default_geometry;
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *pcyls = cylinders;
12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *pheads = heads;
12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *psecs = secs;
12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* disable any translation to be in sync with
12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   the logical geometry */
12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (translation == BIOS_ATA_TRANSLATION_AUTO) {
12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_NONE);
12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default_geometry:
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* if no geometry, use a standard physical disk geometry */
12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cylinders = nb_sectors / (16 * 63);
12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (cylinders > 16383)
12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                cylinders = 16383;
12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else if (cylinders < 2)
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                cylinders = 2;
12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pcyls = cylinders;
12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pheads = 16;
12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *psecs = 63;
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if ((*pcyls * *pheads) <= 131072) {
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_LARGE);
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_LBA);
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_geometry_hint(BlockDriverState *bs,
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int cyls, int heads, int secs)
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->cyls = cyls;
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->heads = heads;
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->secs = secs;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_type_hint(BlockDriverState *bs, int type)
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->type = type;
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->removable = ((type == BDRV_TYPE_CDROM ||
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      type == BDRV_TYPE_FLOPPY));
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_translation_hint(BlockDriverState *bs, int translation)
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->translation = translation;
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_geometry_hint(BlockDriverState *bs,
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int *pcyls, int *pheads, int *psecs)
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcyls = bs->cyls;
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pheads = bs->heads;
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *psecs = bs->secs;
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_type_hint(BlockDriverState *bs)
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->type;
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_translation_hint(BlockDriverState *bs)
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->translation;
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1309cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
1310cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                       BlockErrorAction on_write_error)
1311cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1312cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->on_read_error = on_read_error;
1313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->on_write_error = on_write_error;
1314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1315cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1316cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read)
1317cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return is_read ? bs->on_read_error : bs->on_write_error;
1319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1320cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1321cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_set_removable(BlockDriverState *bs, int removable)
1322cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1323cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->removable = removable;
1324cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (removable && bs == bs_snapshots) {
1325cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_snapshots = NULL;
1326cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1327cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1328cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_removable(BlockDriverState *bs)
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->removable;
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_read_only(BlockDriverState *bs)
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->read_only;
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_sg(BlockDriverState *bs)
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->sg;
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1344cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_enable_write_cache(BlockDriverState *bs)
1345cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1346cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->enable_write_cache;
1347cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1348cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: no longer used */
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_change_cb(BlockDriverState *bs,
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        void (*change_cb)(void *opaque), void *opaque)
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->change_cb = change_cb;
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->change_opaque = opaque;
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_encrypted(BlockDriverState *bs)
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd && bs->backing_hd->encrypted)
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->encrypted;
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_key_required(BlockDriverState *bs)
13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *backing_hd = bs->backing_hd;
13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return (bs->encrypted && !bs->valid_key);
13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_set_key(BlockDriverState *bs, const char *key)
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd && bs->backing_hd->encrypted) {
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = bdrv_set_key(bs->backing_hd, key);
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0)
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return ret;
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!bs->encrypted)
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1383cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->encrypted) {
1384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EINVAL;
1385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else if (!bs->drv || !bs->drv->bdrv_set_key) {
1386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOMEDIUM;
1387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bs->drv->bdrv_set_key(bs, key);
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->valid_key = 0;
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bs->valid_key) {
13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->valid_key = 1;
13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback now, we skipped it on open */
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv) {
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[0] = '\0';
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(buf, buf_size, bs->drv->format_name);
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_iterate_format(void (*it)(void *opaque, const char *name),
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         void *opaque)
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv;
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1415cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv, &bdrv_drivers, list) {
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        it(opaque, drv->format_name);
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_find(const char *name)
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1424cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(name, bs->device_name)) {
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bs;
1427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1432cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverState *bdrv_next(BlockDriverState *bs)
1433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs) {
1435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return QTAILQ_FIRST(&bdrv_states);
1436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return QTAILQ_NEXT(bs, list);
1438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1439cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1444cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        it(opaque, bs);
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char *bdrv_get_device_name(BlockDriverState *bs)
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->device_name;
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_flush(BlockDriverState *bs)
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1456cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->open_flags & BDRV_O_NO_FLUSH) {
14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
1458cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->drv && bs->drv->bdrv_flush)
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_flush(bs);
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_flush_all(void)
14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1468cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1469cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->drv && !bdrv_is_read_only(bs) &&
1470cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs))) {
1471cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_flush(bs);
1472cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1473cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1474cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_has_zero_init(BlockDriverState *bs)
1477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs->drv);
14795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->drv->bdrv_has_zero_init) {
1481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs->drv->bdrv_has_zero_init(bs);
1482cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1483cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1484cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 1;
14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Returns true iff the specified sector is present in the disk image. Drivers
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * not implementing the functionality are assumed to not support backing files,
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * hence all their sectors are reported as allocated.
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 'pnum' is set to the number of sectors (including and immediately following
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the specified sector) that are known to be in the same
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * allocated/unallocated state.
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 'nb_sectors' is the max value 'pnum' should be set to.
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int *pnum)
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t n;
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv->bdrv_is_allocated) {
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sector_num >= bs->total_sectors) {
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnum = 0;
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = bs->total_sectors - sector_num;
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1514cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_mon_event(const BlockDriverState *bdrv,
1515cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    BlockMonEventAction action, int is_read)
1516cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1517cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QObject *data;
1518cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *action_str;
1519cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1520cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    switch (action) {
1521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    case BDRV_ACTION_REPORT:
1522cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        action_str = "report";
1523cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
1524cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    case BDRV_ACTION_IGNORE:
1525cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        action_str = "ignore";
1526cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
1527cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    case BDRV_ACTION_STOP:
1528cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        action_str = "stop";
1529cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        break;
1530cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    default:
1531cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        abort();
1532cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1533cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1534cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    data = qobject_from_jsonf("{ 'device': %s, 'action': %s, 'operation': %s }",
1535cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              bdrv->device_name,
1536cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              action_str,
1537cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                              is_read ? "read" : "write");
1538cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_protocol_event(QEVENT_BLOCK_IO_ERROR, data);
1539cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1540cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qobject_decref(data);
1541cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1542cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1543cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void bdrv_print_dict(QObject *obj, void *opaque)
1544cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1545cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QDict *bs_dict;
1546cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    Monitor *mon = opaque;
1547cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1548cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs_dict = qobject_to_qdict(obj);
1549cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1550cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, "%s: type=%s removable=%d",
1551cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_str(bs_dict, "device"),
1552cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_str(bs_dict, "type"),
1553cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_bool(bs_dict, "removable"));
1554cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1555cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (qdict_get_bool(bs_dict, "removable")) {
1556cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked"));
1557cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1558cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1559cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (qdict_haskey(bs_dict, "inserted")) {
1560cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted"));
1561cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1562cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " file=");
1563cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_print_filename(mon, qdict_get_str(qdict, "file"));
1564cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (qdict_haskey(qdict, "backing_file")) {
1565cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            monitor_printf(mon, " backing_file=");
1566cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            monitor_print_filename(mon, qdict_get_str(qdict, "backing_file"));
1567cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1568cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
1569cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                            qdict_get_bool(qdict, "ro"),
1570cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                            qdict_get_str(qdict, "drv"),
1571cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                            qdict_get_bool(qdict, "encrypted"));
1572cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
1573cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        monitor_printf(mon, " [not inserted]");
1574cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1575cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1576cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, "\n");
1577cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1578cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1579cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_info_print(Monitor *mon, const QObject *data)
1580cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1581cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
1582cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1583cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1584cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_info(Monitor *mon, QObject **ret_data)
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1586cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QList *bs_list;
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1589cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs_list = qlist_new();
1590cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1591cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1592cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QObject *bs_obj;
1593cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        const char *type = "unknown";
1594cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(bs->type) {
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_HD:
1597cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            type = "hd";
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_CDROM:
1600cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            type = "cdrom";
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_FLOPPY:
1603cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            type = "floppy";
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1606cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1607cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': %s, "
1608cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                    "'removable': %i, 'locked': %i }",
1609cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                    bs->device_name, type, bs->removable,
1610cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                    bs->locked);
1611cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->drv) {
1613cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            QObject *obj;
1614cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            QDict *bs_dict = qobject_to_qdict(bs_obj);
1615cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1616cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, "
1617cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     "'encrypted': %i }",
1618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     bs->filename, bs->read_only,
1619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     bs->drv->format_name,
1620cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                                     bdrv_is_encrypted(bs));
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (bs->backing_file[0] != '\0') {
1622cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                QDict *qdict = qobject_to_qdict(obj);
1623cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                qdict_put(qdict, "backing_file",
1624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                          qstring_from_str(bs->backing_file));
16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
1626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qdict_put_obj(bs_dict, "inserted", obj);
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1629cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qlist_append_obj(bs_list, bs_obj);
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1631cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1632cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *ret_data = QOBJECT(bs_list);
1633cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1634cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1635cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void bdrv_stats_iter(QObject *data, void *opaque)
1636cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QDict *qdict;
1638cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    Monitor *mon = opaque;
1639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qdict = qobject_to_qdict(data);
1641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, "%s:", qdict_get_str(qdict, "device"));
1642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qdict = qobject_to_qdict(qdict_get(qdict, "stats"));
1644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    monitor_printf(mon, " rd_bytes=%" PRId64
1645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        " wr_bytes=%" PRId64
1646cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        " rd_operations=%" PRId64
1647cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        " wr_operations=%" PRId64
1648cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        "\n",
1649cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "rd_bytes"),
1650cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "wr_bytes"),
1651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "rd_operations"),
1652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                        qdict_get_int(qdict, "wr_operations"));
1653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_stats_print(Monitor *mon, const QObject *data)
1656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
1658cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1659cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1660cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QObject* bdrv_info_stats_bs(BlockDriverState *bs)
1661cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1662cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QObject *res;
1663cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QDict *dict;
1664cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1665cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    res = qobject_from_jsonf("{ 'stats': {"
1666cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'rd_bytes': %" PRId64 ","
1667cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'wr_bytes': %" PRId64 ","
1668cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'rd_operations': %" PRId64 ","
1669cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'wr_operations': %" PRId64 ","
1670cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "'wr_highest_offset': %" PRId64
1671cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             "} }",
1672cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             bs->rd_bytes, bs->wr_bytes,
1673cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             bs->rd_ops, bs->wr_ops,
1674cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             bs->wr_highest_sector *
1675cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                             (uint64_t)BDRV_SECTOR_SIZE);
1676cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    dict  = qobject_to_qdict(res);
1677cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1678cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (*bs->device_name) {
1679cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qdict_put(dict, "device", qstring_from_str(bs->device_name));
1680cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1681cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1682cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
1683cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QObject *parent = bdrv_info_stats_bs(bs->file);
1684cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qdict_put_obj(dict, "parent", parent);
1685cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1686cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1687cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return res;
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1690cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_info_stats(Monitor *mon, QObject **ret_data)
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1692cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QObject *obj;
1693cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QList *devices;
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1696cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    devices = qlist_new();
1697cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1698cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
1699cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        obj = bdrv_info_stats_bs(bs);
1700cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qlist_append_obj(devices, obj);
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1702cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1703cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *ret_data = QOBJECT(devices);
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char *bdrv_get_encrypted_filename(BlockDriverState *bs)
17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->backing_hd && bs->backing_hd->encrypted)
17095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs->backing_file;
17105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (bs->encrypted)
17115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs->filename;
17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_backing_filename(BlockDriverState *bs,
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               char *filename, int filename_size)
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1719cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->backing_file) {
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(filename, filename_size, "");
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(filename, filename_size, bs->backing_file);
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          const uint8_t *buf, int nb_sectors)
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_write_compressed)
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
1736cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1737cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap) {
1738cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
1739cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1740cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_get_info)
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(bdi, 0, sizeof(*bdi));
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_get_info(bs, bdi);
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1755cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
1756cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                      int64_t pos, int size)
17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
17595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv)
17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
1761cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_save_vmstate)
1762cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_save_vmstate(bs, buf, pos, size);
1763cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1764cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_save_vmstate(bs->file, buf, pos, size);
1765cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
17665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1768cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
1769cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                      int64_t pos, int size)
17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv)
17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
1774cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_load_vmstate)
1775cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_load_vmstate(bs, buf, pos, size);
1776cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1777cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_load_vmstate(bs->file, buf, pos, size);
1778cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
1779cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1780cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1781cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
1782cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1783cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
1784cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1785cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv || !drv->bdrv_debug_event) {
1786cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return;
1787cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1788cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1789cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv->bdrv_debug_event(bs, event);
1790cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* handling of snapshots */
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17968f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thijeint bdrv_can_snapshot(BlockDriverState *bs)
17978f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije{
1798cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
1799cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv || bdrv_is_removable(bs) || bdrv_is_read_only(bs)) {
1800cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
1801cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1802cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1803cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv->bdrv_snapshot_create) {
1804cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->file != NULL) {
1805cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return bdrv_can_snapshot(bs->file);
1806cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1807cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
1808cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1809cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1810cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 1;
1811cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1812cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1813cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_is_snapshot(BlockDriverState *bs)
1814cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1815cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return !!(bs->open_flags & BDRV_O_SNAPSHOT);
1816cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
1817cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1818cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverState *bdrv_snapshots(void)
1819cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
1820cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1821cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1822cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs_snapshots) {
1823cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs_snapshots;
1824cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1825cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1826cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = NULL;
1827cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs = bdrv_next(bs))) {
1828cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bdrv_can_snapshot(bs)) {
1829cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_snapshots = bs;
1830cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return bs;
1831cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1832cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1833cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return NULL;
18348f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije}
18358f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_create(BlockDriverState *bs,
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         QEMUSnapshotInfo *sn_info)
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1842cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_create)
1843cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_create(bs, sn_info);
1844cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1845cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_snapshot_create(bs->file, sn_info);
1846cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_goto(BlockDriverState *bs,
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       const char *snapshot_id)
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
1853cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret, open_ret;
1854cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1857cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_goto)
1858cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_goto(bs, snapshot_id);
1859cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1860cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
1861cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv->bdrv_close(bs);
1862cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_snapshot_goto(bs->file, snapshot_id);
1863cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        open_ret = drv->bdrv_open(bs, bs->open_flags);
1864cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (open_ret < 0) {
1865cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs->file);
1866cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->drv = NULL;
1867cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return open_ret;
1868cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1869cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
1870cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
1871cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
1872cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1880cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_delete)
1881cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_delete(bs, snapshot_id);
1882cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1883cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_snapshot_delete(bs->file, snapshot_id);
1884cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_list(BlockDriverState *bs,
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       QEMUSnapshotInfo **psn_info)
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
1893cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_snapshot_list)
1894cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv->bdrv_snapshot_list(bs, psn_info);
1895cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file)
1896cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_snapshot_list(bs->file, psn_info);
1897cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -ENOTSUP;
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NB_SUFFIXES 4
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar *get_human_readable_size(char *buf, int buf_size, int64_t size)
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char suffixes[NB_SUFFIXES] = "KMGT";
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t base;
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size <= 999) {
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size, "%" PRId64, size);
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        base = 1024;
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(i = 0; i < NB_SUFFIXES; i++) {
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size < (10 * base)) {
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                snprintf(buf, buf_size, "%0.1f%c",
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (double)size / base,
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         suffixes[i]);
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                snprintf(buf, buf_size, "%" PRId64 "%c",
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         ((size + (base >> 1)) / base),
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         suffixes[i]);
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            base = base * 1024;
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf1[128], date_buf[128], clock_buf[128];
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm *ptm;
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm tm;
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    time_t ti;
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t secs;
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sn) {
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size,
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%-10s%-20s%7s%20s%15s",
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ti = sn->date_sec;
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ptm = localtime(&ti);
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strftime(date_buf, sizeof(date_buf),
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%Y-%m-%d %H:%M:%S", ptm);
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        localtime_r(&ti, &tm);
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strftime(date_buf, sizeof(date_buf),
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%Y-%m-%d %H:%M:%S", &tm);
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        secs = sn->vm_clock_nsec / 1000000000;
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(clock_buf, sizeof(clock_buf),
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%02d:%02d:%02d.%03d",
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)(secs / 3600),
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)((secs / 60) % 60),
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)(secs % 60),
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size,
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%-10s%-20s%7s%20s%15s",
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 sn->id_str, sn->name,
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 date_buf,
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 clock_buf);
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* async I/Os */
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 QEMUIOVector *qiov, int nb_sectors,
19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 BlockDriverCompletionFunc *cb, void *opaque)
19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *ret;
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              cb, opaque);
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret) {
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update stats even though technically transfer has not happened. */
1994cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner	bs->rd_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bs->rd_ops ++;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
20025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  QEMUIOVector *qiov, int nb_sectors,
20035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  BlockDriverCompletionFunc *cb, void *opaque)
20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *ret;
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only)
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
20125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2015cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap) {
2016cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
2017cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2018cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
20195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               cb, opaque);
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret) {
2023cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* Update stats even though technically transfer has not happened. */
2024cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
2025cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->wr_ops ++;
2026cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
2027cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->wr_highest_sector = sector_num + nb_sectors - 1;
2028cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2034cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2035cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnertypedef struct MultiwriteCB {
2036cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int error;
2037cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int num_requests;
2038cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int num_callbacks;
2039cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    struct {
2040cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb;
2041cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        void *opaque;
2042cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QEMUIOVector *free_qiov;
2043cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        void *free_buf;
2044cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } callbacks[];
2045cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner} MultiwriteCB;
2046cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2047cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void multiwrite_user_cb(MultiwriteCB *mcb)
2048cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2049cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int i;
2050cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2051cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < mcb->num_callbacks; i++) {
2052cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);
2053cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (mcb->callbacks[i].free_qiov) {
2054cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_destroy(mcb->callbacks[i].free_qiov);
2055cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2056cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_free(mcb->callbacks[i].free_qiov);
2057cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_vfree(mcb->callbacks[i].free_buf);
2058cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2059cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2060cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2061cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic void multiwrite_cb(void *opaque, int ret)
2062cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2063cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    MultiwriteCB *mcb = opaque;
2064cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2065cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0 && !mcb->error) {
2066cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->error = ret;
2067cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2068cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2069cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_requests--;
2070cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (mcb->num_requests == 0) {
2071cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        multiwrite_user_cb(mcb);
2072cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        qemu_free(mcb);
2073cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2074cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2075cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2076cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int multiwrite_req_compare(const void *a, const void *b)
2077cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2078cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const BlockRequest *req1 = a, *req2 = b;
2079cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2080cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
2081cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Note that we can't simply subtract req2->sector from req1->sector
2082cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * here as that could overflow the return value.
2083cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
2084cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (req1->sector > req2->sector) {
2085cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 1;
2086cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else if (req1->sector < req2->sector) {
2087cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -1;
2088cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
2089cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
2090cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2091cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2092cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2093cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
2094cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Takes a bunch of requests and tries to merge them. Returns the number of
2095cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * requests that remain after merging.
2096cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
2097cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
2098cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int num_reqs, MultiwriteCB *mcb)
2099cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2100cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int i, outidx;
2101cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2102cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Sort requests by start sector
2103cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qsort(reqs, num_reqs, sizeof(*reqs), &multiwrite_req_compare);
2104cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2105cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Check if adjacent requests touch the same clusters. If so, combine them,
2106cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // filling up gaps with zero sectors.
2107cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    outidx = 0;
2108cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 1; i < num_reqs; i++) {
2109cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int merge = 0;
2110cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int64_t oldreq_last = reqs[outidx].sector + reqs[outidx].nb_sectors;
2111cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2112cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // This handles the cases that are valid for all block drivers, namely
2113cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // exactly sequential writes and overlapping writes.
2114cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (reqs[i].sector <= oldreq_last) {
2115cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            merge = 1;
2116cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2117cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2118cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // The block driver may decide that it makes sense to combine requests
2119cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // even if there is a gap of some sectors between them. In this case,
2120cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // the gap is filled with zeros (therefore only applicable for yet
2121cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        // unused space in format like qcow2).
2122cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!merge && bs->drv->bdrv_merge_requests) {
2123cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);
2124cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2125cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2126cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
2127cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            merge = 0;
2128cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2129cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2130cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (merge) {
2131cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            size_t size;
2132cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov));
2133cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_init(qiov,
2134cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1);
2135cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2136cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // Add the first request to the merged one. If the requests are
2137cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // overlapping, drop the last sectors of the first request.
2138cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            size = (reqs[i].sector - reqs[outidx].sector) << 9;
2139cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_concat(qiov, reqs[outidx].qiov, size);
2140cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2141cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // We might need to add some zeros between the two requests
2142cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (reqs[i].sector > oldreq_last) {
2143cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                size_t zero_bytes = (reqs[i].sector - oldreq_last) << 9;
2144cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                uint8_t *buf = qemu_blockalign(bs, zero_bytes);
2145cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                memset(buf, 0, zero_bytes);
2146cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                qemu_iovec_add(qiov, buf, zero_bytes);
2147cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                mcb->callbacks[i].free_buf = buf;
2148cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
2149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // Add the second request
2151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);
2152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2153cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].nb_sectors = qiov->size >> 9;
2154cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].qiov = qiov;
2155cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2156cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            mcb->callbacks[i].free_qiov = reqs[outidx].qiov;
2157cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
2158cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            outidx++;
2159cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].sector     = reqs[i].sector;
2160cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].nb_sectors = reqs[i].nb_sectors;
2161cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[outidx].qiov       = reqs[i].qiov;
2162cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2163cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2164cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2165cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return outidx + 1;
2166cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2167cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2168cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
2169cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Submit multiple AIO write requests at once.
2170cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
2171cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * On success, the function returns 0 and all requests in the reqs array have
2172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * been submitted. In error case this function returns -1, and any of the
2173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * requests may or may not be submitted yet. In particular, this means that the
2174cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * callback will be called for some of the requests, for others it won't. The
2175cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * caller must check the error field of the BlockRequest to wait for the right
2176cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * callbacks (if error != 0, no callback will be called).
2177cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner *
2178cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * The implementation may modify the contents of the reqs array, e.g. to merge
2179cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * requests. However, the fields opaque and error are left unmodified as they
2180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * are used to signal failure for a single request to the caller.
2181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
2182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
2183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCB *acb;
2185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    MultiwriteCB *mcb;
2186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int i;
2187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (num_reqs == 0) {
2189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
2190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Create MultiwriteCB structure
2193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb = qemu_mallocz(sizeof(*mcb) + num_reqs * sizeof(*mcb->callbacks));
2194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_requests = 0;
2195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_callbacks = num_reqs;
2196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < num_reqs; i++) {
2198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->callbacks[i].cb = reqs[i].cb;
2199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->callbacks[i].opaque = reqs[i].opaque;
2200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2202cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    // Check for mergable requests
2203cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb);
2204cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2205cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
2206cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Run the aio requests. As soon as one request can't be submitted
2207cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * successfully, fail all requests that are not yet submitted (we must
2208cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * return failure for all requests anyway)
2209cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     *
2210cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * num_requests cannot be set to the right value immediately: If
2211cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * bdrv_aio_writev fails for some request, num_requests would be too high
2212cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * and therefore multiwrite_cb() would never recognize the multiwrite
2213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * request as completed. We also cannot use the loop variable i to set it
2214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * when the first request fails because the callback may already have been
2215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * called for previously submitted requests. Thus, num_requests must be
2216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * incremented for each request that is submitted.
2217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     *
2218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * The problem that callbacks may be called early also means that we need
2219cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * to take care that num_requests doesn't become 0 before all requests are
2220cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * submitted - multiwrite_cb() would consider the multiwrite request
2221cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * completed. A dummy request that is "completed" by a manual call to
2222cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * multiwrite_cb() takes care of this.
2223cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
2224cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    mcb->num_requests = 1;
2225cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2226cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < num_reqs; i++) {
2227cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        mcb->num_requests++;
2228cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
2229cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            reqs[i].nb_sectors, multiwrite_cb, mcb);
2230cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2231cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (acb == NULL) {
2232cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // We can only fail the whole thing if no request has been
2233cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // submitted yet. Otherwise we'll wait for the submitted AIOs to
2234cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            // complete and report the error in the callback.
2235cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (i == 0) {
2236cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto fail;
2237cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            } else {
2238cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                multiwrite_cb(mcb, -EIO);
2239cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                break;
2240cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
2241cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2242cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2243cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2244cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Complete the dummy request */
2245cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    multiwrite_cb(mcb, 0);
2246cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2247cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
2248cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2249cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfail:
2250cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (i = 0; i < mcb->num_callbacks; i++) {
2251cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        reqs[i].error = -EIO;
2252cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2253cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_free(mcb);
2254cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return -1;
2255cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2256cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2257cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
2258cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
2259cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2260cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
2261cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2262cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->open_flags & BDRV_O_NO_FLUSH) {
2263cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_aio_noop_em(bs, cb, opaque);
2264cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2265cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2266cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv)
2267cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return NULL;
2268cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv->bdrv_aio_flush(bs, cb, opaque);
2269cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2270cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_aio_cancel(BlockDriverAIOCB *acb)
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->pool->cancel(acb);
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* async block device emulation */
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct BlockDriverAIOCBSync {
22815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCB common;
22825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUBH *bh;
22835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
22845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* vector translation state */
22855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector *qiov;
22865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *bounce;
22875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_write;
22885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} BlockDriverAIOCBSync;
22895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
22915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2292cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCBSync *acb =
2293cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        container_of(blockacb, BlockDriverAIOCBSync, common);
22945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(acb->bh);
2295cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bh = NULL;
22965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_release(acb);
22975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
22985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic AIOPool bdrv_em_aio_pool = {
23005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
23015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    .cancel             = bdrv_aio_cancel_em,
23025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
23035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void bdrv_aio_bh_cb(void *opaque)
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCBSync *acb = opaque;
23075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!acb->is_write)
23095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
23105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_vfree(acb->bounce);
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->common.cb(acb->common.opaque, acb->ret);
23125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(acb->bh);
2313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bh = NULL;
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_aio_release(acb);
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
23185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int64_t sector_num,
23195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            QEMUIOVector *qiov,
23205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int nb_sectors,
23215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            BlockDriverCompletionFunc *cb,
23225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            void *opaque,
23235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int is_write)
23245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCBSync *acb;
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
23295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->is_write = is_write;
23305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->qiov = qiov;
23315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->bounce = qemu_blockalign(bs, qiov->size);
23325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!acb->bh)
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
23355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_write) {
23375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_iovec_to_buffer(acb->qiov, acb->bounce);
23385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
23395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
23405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors);
23415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
23425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_bh_schedule(acb->bh);
23445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return &acb->common;
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
23495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque)
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
23565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
23575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2362cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
2363cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
2364cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2365cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCBSync *acb;
2366cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2367cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
2368cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->is_write = 1; /* don't bounce in the completion hadler */
2369cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->qiov = NULL;
2370cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bounce = NULL;
2371cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->ret = 0;
2372cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2373cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb->bh)
2374cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
2375cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2376cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bdrv_flush(bs);
2377cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_bh_schedule(acb->bh);
2378cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return &acb->common;
2379cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2380cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2381cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
2382cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
2383cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverAIOCBSync *acb;
2385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
2387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->is_write = 1; /* don't bounce in the completion handler */
2388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->qiov = NULL;
2389cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->bounce = NULL;
2390cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    acb->ret = 0;
2391cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2392cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!acb->bh) {
2393cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
2394cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2395cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2396cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    qemu_bh_schedule(acb->bh);
2397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return &acb->common;
2398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sync block device emulation */
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void bdrv_rw_em_cb(void *opaque, int ret)
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *(int *)opaque = ret;
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NOT_DONE 0x7fffffff
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors)
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int async_ret;
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
24155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct iovec iov;
24165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector qiov;
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2418cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_push();
2419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    async_ret = NOT_DONE;
24215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_base = (void *)buf;
2422cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
24235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_iovec_init_external(&qiov, &iov, 1);
24245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
24255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_rw_em_cb, &async_ret);
2426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (acb == NULL) {
2427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        async_ret = -1;
2428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto fail;
2429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (async_ret == NOT_DONE) {
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_aio_wait();
24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfail:
2437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_pop();
24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return async_ret;
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
24428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors)
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int async_ret;
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
24465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct iovec iov;
24475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector qiov;
24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2449cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_push();
2450cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    async_ret = NOT_DONE;
24525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_base = (void *)buf;
2453cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
24545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_iovec_init_external(&qiov, &iov, 1);
24555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
24565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_rw_em_cb, &async_ret);
2457cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (acb == NULL) {
2458cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        async_ret = -1;
2459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto fail;
2460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (async_ret == NOT_DONE) {
24628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_aio_wait();
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2464cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2465cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfail:
2466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    async_context_pop();
24678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return async_ret;
24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_init(void)
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    module_call_init(MODULE_INIT_BLOCK);
24738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_init_with_whitelist(void)
2476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    use_bdrv_whitelist = 1;
2478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bdrv_init();
2479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
24815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
24825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   BlockDriverCompletionFunc *cb, void *opaque)
24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (pool->free_aiocb) {
24875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb = pool->free_aiocb;
24885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pool->free_aiocb = acb->next;
24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb = qemu_mallocz(pool->aiocb_size);
24915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->pool = pool;
24928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->bs = bs;
24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->cb = cb;
24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->opaque = opaque;
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return acb;
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid qemu_aio_release(void *p)
25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
25025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AIOPool *pool = acb->pool;
25035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->next = pool->free_aiocb;
25045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pool->free_aiocb = acb;
25058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
25088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* removable device support */
25098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TRUE if the media is present
25128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_inserted(BlockDriverState *bs)
25148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
25178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
25188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
25198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_is_inserted)
2520cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return !bs->tray_open;
25218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = drv->bdrv_is_inserted(bs);
25228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
25238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TRUE if the media changed since the last call to this
25278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * function. It is currently only used for floppy disks
25288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_media_changed(BlockDriverState *bs)
25308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
25338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv || !drv->bdrv_media_changed)
25358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = -ENOTSUP;
25368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
25378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = drv->bdrv_media_changed(bs);
25388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == -ENOTSUP)
25398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = bs->media_changed;
25408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->media_changed = 0;
25418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
25428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If eject_flag is TRUE, eject the media. Otherwise, close the tray
25468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_eject(BlockDriverState *bs, int eject_flag)
25488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->locked) {
25535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EBUSY;
25545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
25555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
25568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv || !drv->bdrv_eject) {
25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = -ENOTSUP;
25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
25598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = drv->bdrv_eject(bs, eject_flag);
25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == -ENOTSUP) {
25625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = 0;
25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2564cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret >= 0) {
2565cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->tray_open = eject_flag;
2566cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
25675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
25685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_locked(BlockDriverState *bs)
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->locked;
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lock or unlock the media (if it is locked, the user won't be able
25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to eject it manually).
25798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
25808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_locked(BlockDriverState *bs, int locked)
25818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->locked = locked;
25858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv && drv->bdrv_set_locked) {
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        drv->bdrv_set_locked(bs, locked);
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* needed for generic scsi interface */
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
25938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv && drv->bdrv_ioctl)
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return drv->bdrv_ioctl(bs, req, buf);
25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -ENOTSUP;
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
26015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
26025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        unsigned long int req, void *buf,
26035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
26045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
26055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
26065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
26075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (drv && drv->bdrv_aio_ioctl)
26085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
26095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
26105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
26115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2612cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2613cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
26145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_blockalign(BlockDriverState *bs, size_t size)
26155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
26165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);
26175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_set_dirty_tracking(BlockDriverState *bs, int enable)
2620cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2621cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t bitmap_size;
2622cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2623cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->dirty_count = 0;
2624cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (enable) {
2625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!bs->dirty_bitmap) {
2626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
2627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                    BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
2628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
2629cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2630cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->dirty_bitmap = qemu_mallocz(bitmap_size);
2631cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2632cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
2633cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->dirty_bitmap) {
2634cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            qemu_free(bs->dirty_bitmap);
2635cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->dirty_bitmap = NULL;
2636cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
2637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2638cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2640cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_get_dirty(BlockDriverState *bs, int64_t sector)
2641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
2643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->dirty_bitmap &&
2645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        (sector << BDRV_SECTOR_BITS) < bdrv_getlength(bs)) {
2646cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bs->dirty_bitmap[chunk / (sizeof(unsigned long) * 8)] &
2647cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            (1 << (chunk % (sizeof(unsigned long) * 8)));
2648cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
2649cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
2650cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
2651cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
2654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                      int nr_sectors)
2655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2656cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    set_dirty_bitmap(bs, cur_sector, nr_sectors, 0);
2657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2658cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2659cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint64_t bdrv_get_dirty_count(BlockDriverState *bs)
2660cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
2661cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->dirty_count;
2662cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
2663