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