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