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