mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches # gpg: Signature made Mon 05 Mar 2018 17:45:51 GMT # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (38 commits) block: Fix NULL dereference on empty drive error qcow2: Replace align_offset() with ROUND_UP() block/ssh: Add basic .bdrv_truncate() block/ssh: Make ssh_grow_file() blocking block/ssh: Pull ssh_grow_file() from ssh_create() qemu-img: Make resize error message more general qcow2: make qcow2_co_create2() a coroutine_fn block: rename .bdrv_create() to .bdrv_co_create_opts() Revert "IDE: Do not flush empty CDROM drives" block: test blk_aio_flush() with blk->root == NULL block: add BlockBackend->in_flight counter block: extract AIO_WAIT_WHILE() from BlockDriverState aio: rename aio_context_in_iothread() to in_aio_context_home_thread() docs: document how to use the l2-cache-entry-size parameter specs/qcow2: Fix documentation of the compressed cluster descriptor iotest 033: add misaligned write-zeroes test via truncate block: fix write with zero flag set and iovector provided block: Drop unused .bdrv_co_get_block_status() vvfat: Switch to .bdrv_co_block_status() vpc: Switch to .bdrv_co_block_status() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # include/block/block.h
This commit is contained in:
@@ -418,7 +418,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
|
||||
CreateCo *cco = opaque;
|
||||
assert(cco->drv);
|
||||
|
||||
ret = cco->drv->bdrv_create(cco->filename, cco->opts, &local_err);
|
||||
ret = cco->drv->bdrv_co_create_opts(cco->filename, cco->opts, &local_err);
|
||||
error_propagate(&cco->err, local_err);
|
||||
cco->ret = ret;
|
||||
}
|
||||
@@ -437,7 +437,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
|
||||
.err = NULL,
|
||||
};
|
||||
|
||||
if (!drv->bdrv_create) {
|
||||
if (!drv->bdrv_co_create_opts) {
|
||||
error_setg(errp, "Driver '%s' does not support image creation", drv->format_name);
|
||||
ret = -ENOTSUP;
|
||||
goto out;
|
||||
@@ -4711,7 +4711,12 @@ out:
|
||||
|
||||
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
return bs->aio_context;
|
||||
return bs ? bs->aio_context : qemu_get_aio_context();
|
||||
}
|
||||
|
||||
AioWait *bdrv_get_aio_wait(BlockDriverState *bs)
|
||||
{
|
||||
return bs ? &bs->wait : NULL;
|
||||
}
|
||||
|
||||
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
|
||||
|
||||
+11
-9
@@ -627,15 +627,17 @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
|
||||
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn blkdebug_co_get_block_status(
|
||||
BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset,
|
||||
int64_t bytes,
|
||||
int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
assert(QEMU_IS_ALIGNED(sector_num | nb_sectors,
|
||||
DIV_ROUND_UP(bs->bl.request_alignment,
|
||||
BDRV_SECTOR_SIZE)));
|
||||
return bdrv_co_get_block_status_from_file(bs, sector_num, nb_sectors,
|
||||
pnum, file);
|
||||
assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
|
||||
return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes,
|
||||
pnum, map, file);
|
||||
}
|
||||
|
||||
static void blkdebug_close(BlockDriverState *bs)
|
||||
@@ -907,7 +909,7 @@ static BlockDriver bdrv_blkdebug = {
|
||||
.bdrv_co_flush_to_disk = blkdebug_co_flush,
|
||||
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
|
||||
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
|
||||
.bdrv_co_get_block_status = blkdebug_co_get_block_status,
|
||||
.bdrv_co_block_status = blkdebug_co_block_status,
|
||||
|
||||
.bdrv_debug_event = blkdebug_debug_event,
|
||||
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
|
||||
|
||||
+56
-9
@@ -73,6 +73,14 @@ struct BlockBackend {
|
||||
int quiesce_counter;
|
||||
VMChangeStateEntry *vmsh;
|
||||
bool force_allow_inactivate;
|
||||
|
||||
/* Number of in-flight aio requests. BlockDriverState also counts
|
||||
* in-flight requests but aio requests can exist even when blk->root is
|
||||
* NULL, so we cannot rely on its counter for that case.
|
||||
* Accessed with atomic ops.
|
||||
*/
|
||||
unsigned int in_flight;
|
||||
AioWait wait;
|
||||
};
|
||||
|
||||
typedef struct BlockBackendAIOCB {
|
||||
@@ -1225,11 +1233,22 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
|
||||
return bdrv_make_zero(blk->root, flags);
|
||||
}
|
||||
|
||||
static void blk_inc_in_flight(BlockBackend *blk)
|
||||
{
|
||||
atomic_inc(&blk->in_flight);
|
||||
}
|
||||
|
||||
static void blk_dec_in_flight(BlockBackend *blk)
|
||||
{
|
||||
atomic_dec(&blk->in_flight);
|
||||
aio_wait_kick(&blk->wait);
|
||||
}
|
||||
|
||||
static void error_callback_bh(void *opaque)
|
||||
{
|
||||
struct BlockBackendAIOCB *acb = opaque;
|
||||
|
||||
bdrv_dec_in_flight(acb->common.bs);
|
||||
blk_dec_in_flight(acb->blk);
|
||||
acb->common.cb(acb->common.opaque, acb->ret);
|
||||
qemu_aio_unref(acb);
|
||||
}
|
||||
@@ -1240,7 +1259,7 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
|
||||
{
|
||||
struct BlockBackendAIOCB *acb;
|
||||
|
||||
bdrv_inc_in_flight(blk_bs(blk));
|
||||
blk_inc_in_flight(blk);
|
||||
acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
|
||||
acb->blk = blk;
|
||||
acb->ret = ret;
|
||||
@@ -1263,7 +1282,7 @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
|
||||
static void blk_aio_complete(BlkAioEmAIOCB *acb)
|
||||
{
|
||||
if (acb->has_returned) {
|
||||
bdrv_dec_in_flight(acb->common.bs);
|
||||
blk_dec_in_flight(acb->rwco.blk);
|
||||
acb->common.cb(acb->common.opaque, acb->rwco.ret);
|
||||
qemu_aio_unref(acb);
|
||||
}
|
||||
@@ -1284,7 +1303,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
|
||||
BlkAioEmAIOCB *acb;
|
||||
Coroutine *co;
|
||||
|
||||
bdrv_inc_in_flight(blk_bs(blk));
|
||||
blk_inc_in_flight(blk);
|
||||
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
|
||||
acb->rwco = (BlkRwCo) {
|
||||
.blk = blk,
|
||||
@@ -1521,14 +1540,41 @@ int blk_flush(BlockBackend *blk)
|
||||
|
||||
void blk_drain(BlockBackend *blk)
|
||||
{
|
||||
if (blk_bs(blk)) {
|
||||
bdrv_drain(blk_bs(blk));
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
if (bs) {
|
||||
bdrv_drained_begin(bs);
|
||||
}
|
||||
|
||||
/* We may have -ENOMEDIUM completions in flight */
|
||||
AIO_WAIT_WHILE(&blk->wait,
|
||||
blk_get_aio_context(blk),
|
||||
atomic_mb_read(&blk->in_flight) > 0);
|
||||
|
||||
if (bs) {
|
||||
bdrv_drained_end(bs);
|
||||
}
|
||||
}
|
||||
|
||||
void blk_drain_all(void)
|
||||
{
|
||||
bdrv_drain_all();
|
||||
BlockBackend *blk = NULL;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
|
||||
while ((blk = blk_all_next(blk)) != NULL) {
|
||||
AioContext *ctx = blk_get_aio_context(blk);
|
||||
|
||||
aio_context_acquire(ctx);
|
||||
|
||||
/* We may have -ENOMEDIUM completions in flight */
|
||||
AIO_WAIT_WHILE(&blk->wait, ctx,
|
||||
atomic_mb_read(&blk->in_flight) > 0);
|
||||
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
|
||||
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
||||
@@ -1569,10 +1615,11 @@ static void send_qmp_error_event(BlockBackend *blk,
|
||||
bool is_read, int error)
|
||||
{
|
||||
IoOperationType optype;
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
|
||||
qapi_event_send_block_io_error(blk_name(blk),
|
||||
bdrv_get_node_name(blk_bs(blk)), optype,
|
||||
qapi_event_send_block_io_error(blk_name(blk), !!bs,
|
||||
bs ? bdrv_get_node_name(bs) : NULL, optype,
|
||||
action, blk_iostatus_is_enabled(blk),
|
||||
error == ENOSPC, strerror(error),
|
||||
&error_abort);
|
||||
|
||||
+1
-1
@@ -265,7 +265,7 @@ static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||
static BlockDriver bdrv_commit_top = {
|
||||
.format_name = "commit_top",
|
||||
.bdrv_co_preadv = bdrv_commit_top_preadv,
|
||||
.bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
|
||||
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
||||
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
|
||||
.bdrv_close = bdrv_commit_top_close,
|
||||
.bdrv_child_perm = bdrv_commit_top_child_perm,
|
||||
|
||||
+4
-4
@@ -556,9 +556,9 @@ static int block_crypto_open_luks(BlockDriverState *bs,
|
||||
bs, options, flags, errp);
|
||||
}
|
||||
|
||||
static int block_crypto_create_luks(const char *filename,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
return block_crypto_create_generic(Q_CRYPTO_BLOCK_FORMAT_LUKS,
|
||||
filename, opts, errp);
|
||||
@@ -617,7 +617,7 @@ BlockDriver bdrv_crypto_luks = {
|
||||
.bdrv_open = block_crypto_open_luks,
|
||||
.bdrv_close = block_crypto_close,
|
||||
.bdrv_child_perm = bdrv_format_default_perms,
|
||||
.bdrv_create = block_crypto_create_luks,
|
||||
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
|
||||
.bdrv_truncate = block_crypto_truncate,
|
||||
.create_opts = &block_crypto_create_opts_luks,
|
||||
|
||||
|
||||
+37
-40
@@ -1982,7 +1982,8 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int result = 0;
|
||||
@@ -2131,25 +2132,24 @@ static int find_allocation(BlockDriverState *bs, off_t start,
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the allocation status of the specified sectors.
|
||||
* Returns the allocation status of the specified offset.
|
||||
*
|
||||
* If 'sector_num' is beyond the end of the disk image the return value is 0
|
||||
* and 'pnum' is set to 0.
|
||||
* The block layer guarantees 'offset' and 'bytes' are within bounds.
|
||||
*
|
||||
* 'pnum' is set to the number of sectors (including and immediately following
|
||||
* the specified sector) that are known to be in the same
|
||||
* 'pnum' is set to the number of bytes (including and immediately following
|
||||
* the specified offset) that are known to be in the same
|
||||
* allocated/unallocated state.
|
||||
*
|
||||
* 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
|
||||
* beyond the end of the disk image it will be clamped.
|
||||
* 'bytes' is the max value 'pnum' should be set to.
|
||||
*/
|
||||
static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset,
|
||||
int64_t bytes, int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
off_t start, data = 0, hole = 0;
|
||||
int64_t total_size;
|
||||
off_t data = 0, hole = 0;
|
||||
int ret;
|
||||
|
||||
ret = fd_open(bs);
|
||||
@@ -2157,39 +2157,36 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
start = sector_num * BDRV_SECTOR_SIZE;
|
||||
total_size = bdrv_getlength(bs);
|
||||
if (total_size < 0) {
|
||||
return total_size;
|
||||
} else if (start >= total_size) {
|
||||
*pnum = 0;
|
||||
return 0;
|
||||
} else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
|
||||
nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
|
||||
if (!want_zero) {
|
||||
*pnum = bytes;
|
||||
*map = offset;
|
||||
*file = bs;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
ret = find_allocation(bs, start, &data, &hole);
|
||||
ret = find_allocation(bs, offset, &data, &hole);
|
||||
if (ret == -ENXIO) {
|
||||
/* Trailing hole */
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
ret = BDRV_BLOCK_ZERO;
|
||||
} else if (ret < 0) {
|
||||
/* No info available, so pretend there are no holes */
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else if (data == start) {
|
||||
/* On a data extent, compute sectors to the end of the extent,
|
||||
} else if (data == offset) {
|
||||
/* On a data extent, compute bytes to the end of the extent,
|
||||
* possibly including a partial sector at EOF. */
|
||||
*pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
|
||||
*pnum = MIN(bytes, hole - offset);
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else {
|
||||
/* On a hole, compute sectors to the beginning of the next extent. */
|
||||
assert(hole == start);
|
||||
*pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
|
||||
/* On a hole, compute bytes to the beginning of the next extent. */
|
||||
assert(hole == offset);
|
||||
*pnum = MIN(bytes, data - offset);
|
||||
ret = BDRV_BLOCK_ZERO;
|
||||
}
|
||||
*map = offset;
|
||||
*file = bs;
|
||||
return ret | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
return ret | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs,
|
||||
@@ -2280,9 +2277,9 @@ BlockDriver bdrv_file = {
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
.bdrv_co_create_opts = raw_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_co_get_block_status = raw_co_get_block_status,
|
||||
.bdrv_co_block_status = raw_co_block_status,
|
||||
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
|
||||
|
||||
.bdrv_co_preadv = raw_co_preadv,
|
||||
@@ -2684,8 +2681,8 @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int hdev_create(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int ret = 0;
|
||||
@@ -2758,7 +2755,7 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.bdrv_co_create_opts = hdev_co_create_opts,
|
||||
.create_opts = &raw_create_opts,
|
||||
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
|
||||
|
||||
@@ -2880,7 +2877,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.bdrv_co_create_opts = hdev_co_create_opts,
|
||||
.create_opts = &raw_create_opts,
|
||||
|
||||
|
||||
@@ -3011,7 +3008,7 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_reopen_prepare = raw_reopen_prepare,
|
||||
.bdrv_reopen_commit = raw_reopen_commit,
|
||||
.bdrv_reopen_abort = raw_reopen_abort,
|
||||
.bdrv_create = hdev_create,
|
||||
.bdrv_co_create_opts = hdev_co_create_opts,
|
||||
.create_opts = &raw_create_opts,
|
||||
|
||||
.bdrv_co_preadv = raw_co_preadv,
|
||||
|
||||
+3
-2
@@ -553,7 +553,8 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int64_t total_size = 0;
|
||||
@@ -599,7 +600,7 @@ BlockDriver bdrv_file = {
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_refresh_limits = raw_probe_alignment,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
.bdrv_co_create_opts = raw_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
|
||||
+41
-42
@@ -1021,8 +1021,9 @@ static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qemu_gluster_create(const char *filename,
|
||||
QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
BlockdevOptionsGluster *gconf;
|
||||
struct glfs *glfs;
|
||||
@@ -1362,68 +1363,66 @@ exit:
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the allocation status of the specified sectors.
|
||||
* Returns the allocation status of the specified offset.
|
||||
*
|
||||
* If 'sector_num' is beyond the end of the disk image the return value is 0
|
||||
* and 'pnum' is set to 0.
|
||||
* The block layer guarantees 'offset' and 'bytes' are within bounds.
|
||||
*
|
||||
* 'pnum' is set to the number of sectors (including and immediately following
|
||||
* the specified sector) that are known to be in the same
|
||||
* 'pnum' is set to the number of bytes (including and immediately following
|
||||
* the specified offset) that are known to be in the same
|
||||
* allocated/unallocated state.
|
||||
*
|
||||
* 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
|
||||
* beyond the end of the disk image it will be clamped.
|
||||
* 'bytes' is the max value 'pnum' should be set to.
|
||||
*
|
||||
* (Based on raw_co_get_block_status() from file-posix.c.)
|
||||
* (Based on raw_co_block_status() from file-posix.c.)
|
||||
*/
|
||||
static int64_t coroutine_fn qemu_gluster_co_get_block_status(
|
||||
BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset,
|
||||
int64_t bytes,
|
||||
int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
BDRVGlusterState *s = bs->opaque;
|
||||
off_t start, data = 0, hole = 0;
|
||||
int64_t total_size;
|
||||
off_t data = 0, hole = 0;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!s->fd) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
start = sector_num * BDRV_SECTOR_SIZE;
|
||||
total_size = bdrv_getlength(bs);
|
||||
if (total_size < 0) {
|
||||
return total_size;
|
||||
} else if (start >= total_size) {
|
||||
*pnum = 0;
|
||||
return 0;
|
||||
} else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) {
|
||||
nb_sectors = DIV_ROUND_UP(total_size - start, BDRV_SECTOR_SIZE);
|
||||
if (!want_zero) {
|
||||
*pnum = bytes;
|
||||
*map = offset;
|
||||
*file = bs;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
ret = find_allocation(bs, start, &data, &hole);
|
||||
ret = find_allocation(bs, offset, &data, &hole);
|
||||
if (ret == -ENXIO) {
|
||||
/* Trailing hole */
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
ret = BDRV_BLOCK_ZERO;
|
||||
} else if (ret < 0) {
|
||||
/* No info available, so pretend there are no holes */
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else if (data == start) {
|
||||
/* On a data extent, compute sectors to the end of the extent,
|
||||
} else if (data == offset) {
|
||||
/* On a data extent, compute bytes to the end of the extent,
|
||||
* possibly including a partial sector at EOF. */
|
||||
*pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
|
||||
*pnum = MIN(bytes, hole - offset);
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
} else {
|
||||
/* On a hole, compute sectors to the beginning of the next extent. */
|
||||
assert(hole == start);
|
||||
*pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
|
||||
/* On a hole, compute bytes to the beginning of the next extent. */
|
||||
assert(hole == offset);
|
||||
*pnum = MIN(bytes, data - offset);
|
||||
ret = BDRV_BLOCK_ZERO;
|
||||
}
|
||||
|
||||
*map = offset;
|
||||
*file = bs;
|
||||
|
||||
return ret | BDRV_BLOCK_OFFSET_VALID | start;
|
||||
return ret | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
|
||||
@@ -1437,7 +1436,7 @@ static BlockDriver bdrv_gluster = {
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
||||
.bdrv_truncate = qemu_gluster_truncate,
|
||||
@@ -1451,7 +1450,7 @@ static BlockDriver bdrv_gluster = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||
#endif
|
||||
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
||||
.bdrv_co_block_status = qemu_gluster_co_block_status,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
@@ -1465,7 +1464,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
||||
.bdrv_truncate = qemu_gluster_truncate,
|
||||
@@ -1479,7 +1478,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||
#endif
|
||||
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
||||
.bdrv_co_block_status = qemu_gluster_co_block_status,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
@@ -1493,7 +1492,7 @@ static BlockDriver bdrv_gluster_unix = {
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
||||
.bdrv_truncate = qemu_gluster_truncate,
|
||||
@@ -1507,7 +1506,7 @@ static BlockDriver bdrv_gluster_unix = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||
#endif
|
||||
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
||||
.bdrv_co_block_status = qemu_gluster_co_block_status,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
@@ -1527,7 +1526,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
||||
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
|
||||
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
|
||||
.bdrv_close = qemu_gluster_close,
|
||||
.bdrv_create = qemu_gluster_create,
|
||||
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
|
||||
.bdrv_getlength = qemu_gluster_getlength,
|
||||
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
|
||||
.bdrv_truncate = qemu_gluster_truncate,
|
||||
@@ -1541,7 +1540,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||
#endif
|
||||
.bdrv_co_get_block_status = qemu_gluster_co_get_block_status,
|
||||
.bdrv_co_block_status = qemu_gluster_co_block_status,
|
||||
.create_opts = &qemu_gluster_create_opts,
|
||||
};
|
||||
|
||||
|
||||
+38
-60
@@ -25,6 +25,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/aio-wait.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "block/blockjob_int.h"
|
||||
#include "block/block_int.h"
|
||||
@@ -587,16 +588,9 @@ void bdrv_inc_in_flight(BlockDriverState *bs)
|
||||
atomic_inc(&bs->in_flight);
|
||||
}
|
||||
|
||||
static void dummy_bh_cb(void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
void bdrv_wakeup(BlockDriverState *bs)
|
||||
{
|
||||
/* The barrier (or an atomic op) is in the caller. */
|
||||
if (atomic_read(&bs->wakeup)) {
|
||||
aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
|
||||
}
|
||||
aio_wait_kick(bdrv_get_aio_wait(bs));
|
||||
}
|
||||
|
||||
void bdrv_dec_in_flight(BlockDriverState *bs)
|
||||
@@ -1701,7 +1695,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
||||
*/
|
||||
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_WRITE);
|
||||
|
||||
if (!qiov) {
|
||||
if (flags & BDRV_REQ_ZERO_WRITE) {
|
||||
ret = bdrv_co_do_zero_pwritev(child, offset, bytes, flags, &req);
|
||||
goto out;
|
||||
}
|
||||
@@ -1868,30 +1862,34 @@ typedef struct BdrvCoBlockStatusData {
|
||||
bool done;
|
||||
} BdrvCoBlockStatusData;
|
||||
|
||||
int64_t coroutine_fn bdrv_co_get_block_status_from_file(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors,
|
||||
int *pnum,
|
||||
BlockDriverState **file)
|
||||
int coroutine_fn bdrv_co_block_status_from_file(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset,
|
||||
int64_t bytes,
|
||||
int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
assert(bs->file && bs->file->bs);
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
*map = offset;
|
||||
*file = bs->file->bs;
|
||||
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
|
||||
(sector_num << BDRV_SECTOR_BITS);
|
||||
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors,
|
||||
int *pnum,
|
||||
BlockDriverState **file)
|
||||
int coroutine_fn bdrv_co_block_status_from_backing(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset,
|
||||
int64_t bytes,
|
||||
int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
assert(bs->backing && bs->backing->bs);
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
*map = offset;
|
||||
*file = bs->backing->bs;
|
||||
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
|
||||
(sector_num << BDRV_SECTOR_BITS);
|
||||
return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1899,10 +1897,10 @@ int64_t coroutine_fn bdrv_co_get_block_status_from_backing(BlockDriverState *bs,
|
||||
* Drivers not implementing the functionality are assumed to not support
|
||||
* backing files, hence all their sectors are reported as allocated.
|
||||
*
|
||||
* If 'want_zero' is true, the caller is querying for mapping purposes,
|
||||
* and the result should include BDRV_BLOCK_OFFSET_VALID and
|
||||
* BDRV_BLOCK_ZERO where possible; otherwise, the result may omit those
|
||||
* bits particularly if it allows for a larger value in 'pnum'.
|
||||
* If 'want_zero' is true, the caller is querying for mapping
|
||||
* purposes, with a focus on valid BDRV_BLOCK_OFFSET_VALID, _DATA, and
|
||||
* _ZERO where possible; otherwise, the result favors larger 'pnum',
|
||||
* with a focus on accurate BDRV_BLOCK_ALLOCATED.
|
||||
*
|
||||
* If 'offset' is beyond the end of the disk image the return value is
|
||||
* BDRV_BLOCK_EOF and 'pnum' is set to 0.
|
||||
@@ -1959,7 +1957,7 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
||||
|
||||
/* Must be non-NULL or bdrv_getlength() would have failed */
|
||||
assert(bs->drv);
|
||||
if (!bs->drv->bdrv_co_get_block_status) {
|
||||
if (!bs->drv->bdrv_co_block_status) {
|
||||
*pnum = bytes;
|
||||
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
|
||||
if (offset + bytes == total_size) {
|
||||
@@ -1976,44 +1974,24 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
||||
bdrv_inc_in_flight(bs);
|
||||
|
||||
/* Round out to request_alignment boundaries */
|
||||
/* TODO: until we have a byte-based driver callback, we also have to
|
||||
* round out to sectors, even if that is bigger than request_alignment */
|
||||
align = MAX(bs->bl.request_alignment, BDRV_SECTOR_SIZE);
|
||||
align = bs->bl.request_alignment;
|
||||
aligned_offset = QEMU_ALIGN_DOWN(offset, align);
|
||||
aligned_bytes = ROUND_UP(offset + bytes, align) - aligned_offset;
|
||||
|
||||
{
|
||||
int count; /* sectors */
|
||||
int64_t longret;
|
||||
|
||||
assert(QEMU_IS_ALIGNED(aligned_offset | aligned_bytes,
|
||||
BDRV_SECTOR_SIZE));
|
||||
/*
|
||||
* The contract allows us to return pnum smaller than bytes, even
|
||||
* if the next query would see the same status; we truncate the
|
||||
* request to avoid overflowing the driver's 32-bit interface.
|
||||
*/
|
||||
longret = bs->drv->bdrv_co_get_block_status(
|
||||
bs, aligned_offset >> BDRV_SECTOR_BITS,
|
||||
MIN(INT_MAX, aligned_bytes) >> BDRV_SECTOR_BITS, &count,
|
||||
&local_file);
|
||||
if (longret < 0) {
|
||||
assert(INT_MIN <= longret);
|
||||
ret = longret;
|
||||
goto out;
|
||||
}
|
||||
if (longret & BDRV_BLOCK_OFFSET_VALID) {
|
||||
local_map = longret & BDRV_BLOCK_OFFSET_MASK;
|
||||
}
|
||||
ret = longret & ~BDRV_BLOCK_OFFSET_MASK;
|
||||
*pnum = count * BDRV_SECTOR_SIZE;
|
||||
ret = bs->drv->bdrv_co_block_status(bs, want_zero, aligned_offset,
|
||||
aligned_bytes, pnum, &local_map,
|
||||
&local_file);
|
||||
if (ret < 0) {
|
||||
*pnum = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The driver's result must be a multiple of request_alignment.
|
||||
* The driver's result must be a non-zero multiple of request_alignment.
|
||||
* Clamp pnum and adjust map to original request.
|
||||
*/
|
||||
assert(QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset);
|
||||
assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) &&
|
||||
align > offset - aligned_offset);
|
||||
*pnum -= offset - aligned_offset;
|
||||
if (*pnum > bytes) {
|
||||
*pnum = bytes;
|
||||
|
||||
+87
-77
@@ -86,7 +86,7 @@ typedef struct IscsiLun {
|
||||
unsigned long *allocmap;
|
||||
unsigned long *allocmap_valid;
|
||||
long allocmap_size;
|
||||
int cluster_sectors;
|
||||
int cluster_size;
|
||||
bool use_16_for_rw;
|
||||
bool write_protected;
|
||||
bool lbpme;
|
||||
@@ -430,9 +430,10 @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
|
||||
{
|
||||
iscsi_allocmap_free(iscsilun);
|
||||
|
||||
assert(iscsilun->cluster_size);
|
||||
iscsilun->allocmap_size =
|
||||
DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks, iscsilun),
|
||||
iscsilun->cluster_sectors);
|
||||
DIV_ROUND_UP(iscsilun->num_blocks * iscsilun->block_size,
|
||||
iscsilun->cluster_size);
|
||||
|
||||
iscsilun->allocmap = bitmap_try_new(iscsilun->allocmap_size);
|
||||
if (!iscsilun->allocmap) {
|
||||
@@ -440,7 +441,7 @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
|
||||
}
|
||||
|
||||
if (open_flags & BDRV_O_NOCACHE) {
|
||||
/* in case that cache.direct = on all allocmap entries are
|
||||
/* when cache.direct = on all allocmap entries are
|
||||
* treated as invalid to force a relookup of the block
|
||||
* status on every read request */
|
||||
return 0;
|
||||
@@ -457,8 +458,8 @@ static int iscsi_allocmap_init(IscsiLun *iscsilun, int open_flags)
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
|
||||
int nb_sectors, bool allocated, bool valid)
|
||||
iscsi_allocmap_update(IscsiLun *iscsilun, int64_t offset,
|
||||
int64_t bytes, bool allocated, bool valid)
|
||||
{
|
||||
int64_t cl_num_expanded, nb_cls_expanded, cl_num_shrunk, nb_cls_shrunk;
|
||||
|
||||
@@ -466,13 +467,13 @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
|
||||
return;
|
||||
}
|
||||
/* expand to entirely contain all affected clusters */
|
||||
cl_num_expanded = sector_num / iscsilun->cluster_sectors;
|
||||
nb_cls_expanded = DIV_ROUND_UP(sector_num + nb_sectors,
|
||||
iscsilun->cluster_sectors) - cl_num_expanded;
|
||||
assert(iscsilun->cluster_size);
|
||||
cl_num_expanded = offset / iscsilun->cluster_size;
|
||||
nb_cls_expanded = DIV_ROUND_UP(offset + bytes,
|
||||
iscsilun->cluster_size) - cl_num_expanded;
|
||||
/* shrink to touch only completely contained clusters */
|
||||
cl_num_shrunk = DIV_ROUND_UP(sector_num, iscsilun->cluster_sectors);
|
||||
nb_cls_shrunk = (sector_num + nb_sectors) / iscsilun->cluster_sectors
|
||||
- cl_num_shrunk;
|
||||
cl_num_shrunk = DIV_ROUND_UP(offset, iscsilun->cluster_size);
|
||||
nb_cls_shrunk = (offset + bytes) / iscsilun->cluster_size - cl_num_shrunk;
|
||||
if (allocated) {
|
||||
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
|
||||
} else {
|
||||
@@ -495,26 +496,26 @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
iscsi_allocmap_set_allocated(IscsiLun *iscsilun, int64_t offset,
|
||||
int64_t bytes)
|
||||
{
|
||||
iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, true, true);
|
||||
iscsi_allocmap_update(iscsilun, offset, bytes, true, true);
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
iscsi_allocmap_set_unallocated(IscsiLun *iscsilun, int64_t offset,
|
||||
int64_t bytes)
|
||||
{
|
||||
/* Note: if cache.direct=on the fifth argument to iscsi_allocmap_update
|
||||
* is ignored, so this will in effect be an iscsi_allocmap_set_invalid.
|
||||
*/
|
||||
iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, true);
|
||||
iscsi_allocmap_update(iscsilun, offset, bytes, false, true);
|
||||
}
|
||||
|
||||
static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
static void iscsi_allocmap_set_invalid(IscsiLun *iscsilun, int64_t offset,
|
||||
int64_t bytes)
|
||||
{
|
||||
iscsi_allocmap_update(iscsilun, sector_num, nb_sectors, false, false);
|
||||
iscsi_allocmap_update(iscsilun, offset, bytes, false, false);
|
||||
}
|
||||
|
||||
static void iscsi_allocmap_invalidate(IscsiLun *iscsilun)
|
||||
@@ -528,28 +529,30 @@ static void iscsi_allocmap_invalidate(IscsiLun *iscsilun)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t sector_num,
|
||||
int nb_sectors)
|
||||
iscsi_allocmap_is_allocated(IscsiLun *iscsilun, int64_t offset,
|
||||
int64_t bytes)
|
||||
{
|
||||
unsigned long size;
|
||||
if (iscsilun->allocmap == NULL) {
|
||||
return true;
|
||||
}
|
||||
size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
|
||||
assert(iscsilun->cluster_size);
|
||||
size = DIV_ROUND_UP(offset + bytes, iscsilun->cluster_size);
|
||||
return !(find_next_bit(iscsilun->allocmap, size,
|
||||
sector_num / iscsilun->cluster_sectors) == size);
|
||||
offset / iscsilun->cluster_size) == size);
|
||||
}
|
||||
|
||||
static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
|
||||
int64_t sector_num, int nb_sectors)
|
||||
int64_t offset, int64_t bytes)
|
||||
{
|
||||
unsigned long size;
|
||||
if (iscsilun->allocmap_valid == NULL) {
|
||||
return false;
|
||||
}
|
||||
size = DIV_ROUND_UP(sector_num + nb_sectors, iscsilun->cluster_sectors);
|
||||
assert(iscsilun->cluster_size);
|
||||
size = DIV_ROUND_UP(offset + bytes, iscsilun->cluster_size);
|
||||
return (find_next_zero_bit(iscsilun->allocmap_valid, size,
|
||||
sector_num / iscsilun->cluster_sectors) == size);
|
||||
offset / iscsilun->cluster_size) == size);
|
||||
}
|
||||
|
||||
static int coroutine_fn
|
||||
@@ -631,14 +634,16 @@ retry:
|
||||
}
|
||||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors);
|
||||
iscsi_allocmap_set_invalid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE);
|
||||
error_report("iSCSI WRITE10/16 failed at lba %" PRIu64 ": %s", lba,
|
||||
iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iscsi_allocmap_set_allocated(iscsilun, sector_num, nb_sectors);
|
||||
iscsi_allocmap_set_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE);
|
||||
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
@@ -648,36 +653,36 @@ out_unlock:
|
||||
|
||||
|
||||
|
||||
static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
struct scsi_get_lba_status *lbas = NULL;
|
||||
struct scsi_lba_status_descriptor *lbasd = NULL;
|
||||
struct IscsiTask iTask;
|
||||
uint64_t lba;
|
||||
int64_t ret;
|
||||
int ret;
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
|
||||
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
assert(QEMU_IS_ALIGNED(offset | bytes, iscsilun->block_size));
|
||||
|
||||
/* default to all sectors allocated */
|
||||
ret = BDRV_BLOCK_DATA;
|
||||
ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;
|
||||
*pnum = nb_sectors;
|
||||
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
if (map) {
|
||||
*map = offset;
|
||||
}
|
||||
*pnum = bytes;
|
||||
|
||||
/* LUN does not support logical block provisioning */
|
||||
if (!iscsilun->lbpme) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||
lba = offset / iscsilun->block_size;
|
||||
|
||||
qemu_mutex_lock(&iscsilun->mutex);
|
||||
retry:
|
||||
@@ -722,12 +727,12 @@ retry:
|
||||
|
||||
lbasd = &lbas->descriptors[0];
|
||||
|
||||
if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {
|
||||
if (lba != lbasd->lba) {
|
||||
ret = -EIO;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
*pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);
|
||||
*pnum = lbasd->num_blocks * iscsilun->block_size;
|
||||
|
||||
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
|
||||
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
|
||||
@@ -738,13 +743,13 @@ retry:
|
||||
}
|
||||
|
||||
if (ret & BDRV_BLOCK_ZERO) {
|
||||
iscsi_allocmap_set_unallocated(iscsilun, sector_num, *pnum);
|
||||
iscsi_allocmap_set_unallocated(iscsilun, offset, *pnum);
|
||||
} else {
|
||||
iscsi_allocmap_set_allocated(iscsilun, sector_num, *pnum);
|
||||
iscsi_allocmap_set_allocated(iscsilun, offset, *pnum);
|
||||
}
|
||||
|
||||
if (*pnum > nb_sectors) {
|
||||
*pnum = nb_sectors;
|
||||
if (*pnum > bytes) {
|
||||
*pnum = bytes;
|
||||
}
|
||||
out_unlock:
|
||||
qemu_mutex_unlock(&iscsilun->mutex);
|
||||
@@ -753,7 +758,7 @@ out:
|
||||
if (iTask.task != NULL) {
|
||||
scsi_free_scsi_task(iTask.task);
|
||||
}
|
||||
if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID) {
|
||||
if (ret > 0 && ret & BDRV_BLOCK_OFFSET_VALID && file) {
|
||||
*file = bs;
|
||||
}
|
||||
return ret;
|
||||
@@ -780,29 +785,37 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
||||
/* if cache.direct is off and we have a valid entry in our allocation map
|
||||
* we can skip checking the block status and directly return zeroes if
|
||||
* the request falls within an unallocated area */
|
||||
if (iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) &&
|
||||
!iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
|
||||
if (iscsi_allocmap_is_valid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE) &&
|
||||
!iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE)) {
|
||||
qemu_iovec_memset(iov, 0, 0x00, iov->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nb_sectors >= ISCSI_CHECKALLOC_THRES &&
|
||||
!iscsi_allocmap_is_valid(iscsilun, sector_num, nb_sectors) &&
|
||||
!iscsi_allocmap_is_allocated(iscsilun, sector_num, nb_sectors)) {
|
||||
int pnum;
|
||||
BlockDriverState *file;
|
||||
!iscsi_allocmap_is_valid(iscsilun, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE) &&
|
||||
!iscsi_allocmap_is_allocated(iscsilun, sector_num * BDRV_SECTOR_SIZE,
|
||||
nb_sectors * BDRV_SECTOR_SIZE)) {
|
||||
int64_t pnum;
|
||||
/* check the block status from the beginning of the cluster
|
||||
* containing the start sector */
|
||||
int64_t ret = iscsi_co_get_block_status(bs,
|
||||
sector_num - sector_num % iscsilun->cluster_sectors,
|
||||
BDRV_REQUEST_MAX_SECTORS, &pnum, &file);
|
||||
int64_t head;
|
||||
int ret;
|
||||
|
||||
assert(iscsilun->cluster_size);
|
||||
head = (sector_num * BDRV_SECTOR_SIZE) % iscsilun->cluster_size;
|
||||
ret = iscsi_co_block_status(bs, true,
|
||||
sector_num * BDRV_SECTOR_SIZE - head,
|
||||
BDRV_REQUEST_MAX_BYTES, &pnum, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
/* if the whole request falls into an unallocated area we can avoid
|
||||
* to read and directly return zeroes instead */
|
||||
* reading and directly return zeroes instead */
|
||||
if (ret & BDRV_BLOCK_ZERO &&
|
||||
pnum >= nb_sectors + sector_num % iscsilun->cluster_sectors) {
|
||||
pnum >= nb_sectors * BDRV_SECTOR_SIZE + head) {
|
||||
qemu_iovec_memset(iov, 0, 0x00, iov->size);
|
||||
return 0;
|
||||
}
|
||||
@@ -1146,8 +1159,7 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
|
||||
|
||||
if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {
|
||||
/* the target might fail with a check condition if it
|
||||
@@ -1260,8 +1272,7 @@ retry:
|
||||
}
|
||||
|
||||
if (iTask.status != SCSI_STATUS_GOOD) {
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
|
||||
error_report("iSCSI WRITESAME10/16 failed at lba %" PRIu64 ": %s",
|
||||
lba, iTask.err_str);
|
||||
r = iTask.err_code;
|
||||
@@ -1269,11 +1280,9 @@ retry:
|
||||
}
|
||||
|
||||
if (flags & BDRV_REQ_MAY_UNMAP) {
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
iscsi_allocmap_set_invalid(iscsilun, offset, bytes);
|
||||
} else {
|
||||
iscsi_allocmap_set_allocated(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS);
|
||||
iscsi_allocmap_set_allocated(iscsilun, offset, bytes);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
@@ -1953,8 +1962,8 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
* reasonable size */
|
||||
if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&
|
||||
iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
|
||||
iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *
|
||||
iscsilun->block_size) >> BDRV_SECTOR_BITS;
|
||||
iscsilun->cluster_size = iscsilun->bl.opt_unmap_gran *
|
||||
iscsilun->block_size;
|
||||
if (iscsilun->lbprz) {
|
||||
ret = iscsi_allocmap_init(iscsilun, bs->open_flags);
|
||||
}
|
||||
@@ -2108,7 +2117,8 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
int64_t total_size = 0;
|
||||
@@ -2163,7 +2173,7 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
{
|
||||
IscsiLun *iscsilun = bs->opaque;
|
||||
bdi->unallocated_blocks_are_zero = iscsilun->lbprz;
|
||||
bdi->cluster_size = iscsilun->cluster_sectors * BDRV_SECTOR_SIZE;
|
||||
bdi->cluster_size = iscsilun->cluster_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2195,7 +2205,7 @@ static BlockDriver bdrv_iscsi = {
|
||||
.bdrv_parse_filename = iscsi_parse_filename,
|
||||
.bdrv_file_open = iscsi_open,
|
||||
.bdrv_close = iscsi_close,
|
||||
.bdrv_create = iscsi_create,
|
||||
.bdrv_co_create_opts = iscsi_co_create_opts,
|
||||
.create_opts = &iscsi_create_opts,
|
||||
.bdrv_reopen_prepare = iscsi_reopen_prepare,
|
||||
.bdrv_reopen_commit = iscsi_reopen_commit,
|
||||
@@ -2206,7 +2216,7 @@ static BlockDriver bdrv_iscsi = {
|
||||
.bdrv_truncate = iscsi_truncate,
|
||||
.bdrv_refresh_limits = iscsi_refresh_limits,
|
||||
|
||||
.bdrv_co_get_block_status = iscsi_co_get_block_status,
|
||||
.bdrv_co_block_status = iscsi_co_block_status,
|
||||
.bdrv_co_pdiscard = iscsi_co_pdiscard,
|
||||
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
|
||||
.bdrv_co_readv = iscsi_co_readv,
|
||||
@@ -2230,7 +2240,7 @@ static BlockDriver bdrv_iser = {
|
||||
.bdrv_parse_filename = iscsi_parse_filename,
|
||||
.bdrv_file_open = iscsi_open,
|
||||
.bdrv_close = iscsi_close,
|
||||
.bdrv_create = iscsi_create,
|
||||
.bdrv_co_create_opts = iscsi_co_create_opts,
|
||||
.create_opts = &iscsi_create_opts,
|
||||
.bdrv_reopen_prepare = iscsi_reopen_prepare,
|
||||
.bdrv_reopen_commit = iscsi_reopen_commit,
|
||||
@@ -2241,7 +2251,7 @@ static BlockDriver bdrv_iser = {
|
||||
.bdrv_truncate = iscsi_truncate,
|
||||
.bdrv_refresh_limits = iscsi_refresh_limits,
|
||||
|
||||
.bdrv_co_get_block_status = iscsi_co_get_block_status,
|
||||
.bdrv_co_block_status = iscsi_co_block_status,
|
||||
.bdrv_co_pdiscard = iscsi_co_pdiscard,
|
||||
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
|
||||
.bdrv_co_readv = iscsi_co_readv,
|
||||
|
||||
+1
-1
@@ -1094,7 +1094,7 @@ static BlockDriver bdrv_mirror_top = {
|
||||
.bdrv_co_pwrite_zeroes = bdrv_mirror_top_pwrite_zeroes,
|
||||
.bdrv_co_pdiscard = bdrv_mirror_top_pdiscard,
|
||||
.bdrv_co_flush = bdrv_mirror_top_flush,
|
||||
.bdrv_co_get_block_status = bdrv_co_get_block_status_from_backing,
|
||||
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
|
||||
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
|
||||
.bdrv_close = bdrv_mirror_top_close,
|
||||
.bdrv_child_perm = bdrv_mirror_top_child_perm,
|
||||
|
||||
+3
-2
@@ -684,7 +684,8 @@ static QemuOptsList nfs_create_opts = {
|
||||
}
|
||||
};
|
||||
|
||||
static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t ret, total_size;
|
||||
NFSClient *client = g_new0(NFSClient, 1);
|
||||
@@ -897,7 +898,7 @@ static BlockDriver bdrv_nfs = {
|
||||
|
||||
.bdrv_file_open = nfs_file_open,
|
||||
.bdrv_close = nfs_file_close,
|
||||
.bdrv_create = nfs_file_create,
|
||||
.bdrv_co_create_opts = nfs_file_co_create_opts,
|
||||
.bdrv_reopen_prepare = nfs_reopen_prepare,
|
||||
|
||||
.bdrv_co_preadv = nfs_co_preadv,
|
||||
|
||||
+12
-11
@@ -223,22 +223,23 @@ static int null_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn null_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
static int coroutine_fn null_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
BDRVNullState *s = bs->opaque;
|
||||
off_t start = sector_num * BDRV_SECTOR_SIZE;
|
||||
int ret = BDRV_BLOCK_OFFSET_VALID;
|
||||
|
||||
*pnum = nb_sectors;
|
||||
*pnum = bytes;
|
||||
*map = offset;
|
||||
*file = bs;
|
||||
|
||||
if (s->read_zeroes) {
|
||||
return BDRV_BLOCK_OFFSET_VALID | start | BDRV_BLOCK_ZERO;
|
||||
} else {
|
||||
return BDRV_BLOCK_OFFSET_VALID | start;
|
||||
ret |= BDRV_BLOCK_ZERO;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
|
||||
@@ -270,7 +271,7 @@ static BlockDriver bdrv_null_co = {
|
||||
.bdrv_co_flush_to_disk = null_co_flush,
|
||||
.bdrv_reopen_prepare = null_reopen_prepare,
|
||||
|
||||
.bdrv_co_get_block_status = null_co_get_block_status,
|
||||
.bdrv_co_block_status = null_co_block_status,
|
||||
|
||||
.bdrv_refresh_filename = null_refresh_filename,
|
||||
};
|
||||
@@ -290,7 +291,7 @@ static BlockDriver bdrv_null_aio = {
|
||||
.bdrv_aio_flush = null_aio_flush,
|
||||
.bdrv_reopen_prepare = null_reopen_prepare,
|
||||
|
||||
.bdrv_co_get_block_status = null_co_get_block_status,
|
||||
.bdrv_co_block_status = null_co_block_status,
|
||||
|
||||
.bdrv_refresh_filename = null_refresh_filename,
|
||||
};
|
||||
|
||||
@@ -1072,18 +1072,6 @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn nvme_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num,
|
||||
int nb_sectors, int *pnum,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
*pnum = nb_sectors;
|
||||
*file = bs;
|
||||
|
||||
return BDRV_BLOCK_ALLOCATED | BDRV_BLOCK_OFFSET_VALID |
|
||||
(sector_num << BDRV_SECTOR_BITS);
|
||||
}
|
||||
|
||||
static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
|
||||
{
|
||||
QINCREF(opts);
|
||||
@@ -1183,8 +1171,6 @@ static BlockDriver bdrv_nvme = {
|
||||
.bdrv_co_flush_to_disk = nvme_co_flush,
|
||||
.bdrv_reopen_prepare = nvme_reopen_prepare,
|
||||
|
||||
.bdrv_co_get_block_status = nvme_co_get_block_status,
|
||||
|
||||
.bdrv_refresh_filename = nvme_refresh_filename,
|
||||
.bdrv_refresh_limits = nvme_refresh_limits,
|
||||
|
||||
|
||||
+19
-9
@@ -261,23 +261,31 @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
|
||||
static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
|
||||
static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset,
|
||||
int64_t bytes,
|
||||
int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
BDRVParallelsState *s = bs->opaque;
|
||||
int64_t offset;
|
||||
int count;
|
||||
|
||||
assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
offset = block_status(s, sector_num, nb_sectors, pnum);
|
||||
offset = block_status(s, offset >> BDRV_SECTOR_BITS,
|
||||
bytes >> BDRV_SECTOR_BITS, &count);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
||||
*pnum = count * BDRV_SECTOR_SIZE;
|
||||
if (offset < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*map = offset * BDRV_SECTOR_SIZE;
|
||||
*file = bs->file->bs;
|
||||
return (offset << BDRV_SECTOR_BITS) |
|
||||
BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
|
||||
@@ -467,7 +475,9 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
}
|
||||
|
||||
|
||||
static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn parallels_co_create_opts(const char *filename,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int64_t total_size, cl_size;
|
||||
uint8_t tmp[BDRV_SECTOR_SIZE];
|
||||
@@ -782,13 +792,13 @@ static BlockDriver bdrv_parallels = {
|
||||
.bdrv_open = parallels_open,
|
||||
.bdrv_close = parallels_close,
|
||||
.bdrv_child_perm = bdrv_format_default_perms,
|
||||
.bdrv_co_get_block_status = parallels_co_get_block_status,
|
||||
.bdrv_co_block_status = parallels_co_block_status,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
|
||||
.bdrv_co_readv = parallels_co_readv,
|
||||
.bdrv_co_writev = parallels_co_writev,
|
||||
.supports_backing = true,
|
||||
.bdrv_create = parallels_create,
|
||||
.bdrv_co_create_opts = parallels_co_create_opts,
|
||||
.bdrv_check = parallels_check,
|
||||
.create_opts = ¶llels_create_opts,
|
||||
};
|
||||
|
||||
+19
-13
@@ -524,23 +524,28 @@ static int get_cluster_offset(BlockDriverState *bs,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file)
|
||||
static int coroutine_fn qcow_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset, int64_t bytes,
|
||||
int64_t *pnum, int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int index_in_cluster, n, ret;
|
||||
int index_in_cluster, ret;
|
||||
int64_t n;
|
||||
uint64_t cluster_offset;
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0, &cluster_offset);
|
||||
ret = get_cluster_offset(bs, offset, 0, 0, 0, 0, &cluster_offset);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
index_in_cluster = sector_num & (s->cluster_sectors - 1);
|
||||
n = s->cluster_sectors - index_in_cluster;
|
||||
if (n > nb_sectors)
|
||||
n = nb_sectors;
|
||||
index_in_cluster = offset & (s->cluster_size - 1);
|
||||
n = s->cluster_size - index_in_cluster;
|
||||
if (n > bytes) {
|
||||
n = bytes;
|
||||
}
|
||||
*pnum = n;
|
||||
if (!cluster_offset) {
|
||||
return 0;
|
||||
@@ -548,9 +553,9 @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
|
||||
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypto) {
|
||||
return BDRV_BLOCK_DATA;
|
||||
}
|
||||
cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
|
||||
*map = cluster_offset | index_in_cluster;
|
||||
*file = bs->file->bs;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | cluster_offset;
|
||||
return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
|
||||
@@ -805,7 +810,8 @@ static void qcow_close(BlockDriverState *bs)
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
static int coroutine_fn qcow_co_create_opts(const char *filename, QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
int header_size, backing_filename_len, l1_size, shift, i;
|
||||
QCowHeader header;
|
||||
@@ -1122,13 +1128,13 @@ static BlockDriver bdrv_qcow = {
|
||||
.bdrv_close = qcow_close,
|
||||
.bdrv_child_perm = bdrv_format_default_perms,
|
||||
.bdrv_reopen_prepare = qcow_reopen_prepare,
|
||||
.bdrv_create = qcow_create,
|
||||
.bdrv_co_create_opts = qcow_co_create_opts,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.supports_backing = true,
|
||||
|
||||
.bdrv_co_readv = qcow_co_readv,
|
||||
.bdrv_co_writev = qcow_co_writev,
|
||||
.bdrv_co_get_block_status = qcow_co_get_block_status,
|
||||
.bdrv_co_block_status = qcow_co_block_status,
|
||||
|
||||
.bdrv_make_empty = qcow_make_empty,
|
||||
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
|
||||
|
||||
@@ -413,8 +413,8 @@ static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
|
||||
|
||||
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
|
||||
{
|
||||
return align_offset(sizeof(Qcow2BitmapDirEntry) +
|
||||
name_size + extra_data_size, 8);
|
||||
int size = sizeof(Qcow2BitmapDirEntry) + name_size + extra_data_size;
|
||||
return ROUND_UP(size, 8);
|
||||
}
|
||||
|
||||
static inline int dir_entry_size(Qcow2BitmapDirEntry *entry)
|
||||
|
||||
@@ -126,11 +126,11 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
|
||||
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
|
||||
new_l1_table = qemu_try_blockalign(bs->file->bs,
|
||||
align_offset(new_l1_size2, 512));
|
||||
ROUND_UP(new_l1_size2, 512));
|
||||
if (new_l1_table == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(new_l1_table, 0, align_offset(new_l1_size2, 512));
|
||||
memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512));
|
||||
|
||||
if (s->l1_size) {
|
||||
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
|
||||
|
||||
@@ -1204,7 +1204,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
* l1_table_offset when it is the current s->l1_table_offset! Be careful
|
||||
* when changing this! */
|
||||
if (l1_table_offset != s->l1_table_offset) {
|
||||
l1_table = g_try_malloc0(align_offset(l1_size2, 512));
|
||||
l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512));
|
||||
if (l1_size2 && l1_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
@@ -2553,7 +2553,7 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
|
||||
}
|
||||
|
||||
/* align range to test to cluster boundaries */
|
||||
size = align_offset(offset_into_cluster(s, offset) + size, s->cluster_size);
|
||||
size = ROUND_UP(offset_into_cluster(s, offset) + size, s->cluster_size);
|
||||
offset = start_of_cluster(s, offset);
|
||||
|
||||
if ((chk & QCOW2_OL_ACTIVE_L1) && s->l1_size) {
|
||||
|
||||
@@ -66,7 +66,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
/* Read statically sized part of the snapshot header */
|
||||
offset = align_offset(offset, 8);
|
||||
offset = ROUND_UP(offset, 8);
|
||||
ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -155,7 +155,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
offset = 0;
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
sn = s->snapshots + i;
|
||||
offset = align_offset(offset, 8);
|
||||
offset = ROUND_UP(offset, 8);
|
||||
offset += sizeof(h);
|
||||
offset += sizeof(extra);
|
||||
offset += strlen(sn->id_str);
|
||||
@@ -215,7 +215,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
|
||||
assert(id_str_size <= UINT16_MAX && name_size <= UINT16_MAX);
|
||||
h.id_str_size = cpu_to_be16(id_str_size);
|
||||
h.name_size = cpu_to_be16(name_size);
|
||||
offset = align_offset(offset, 8);
|
||||
offset = ROUND_UP(offset, 8);
|
||||
|
||||
ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
|
||||
if (ret < 0) {
|
||||
@@ -441,7 +441,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
/* The VM state isn't needed any more in the active L1 table; in fact, it
|
||||
* hurts by causing expensive COW for the next snapshot. */
|
||||
qcow2_cluster_discard(bs, qcow2_vm_state_offset(s),
|
||||
align_offset(sn->vm_state_size, s->cluster_size),
|
||||
ROUND_UP(sn->vm_state_size, s->cluster_size),
|
||||
QCOW2_DISCARD_NEVER, false);
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
@@ -710,7 +710,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
|
||||
}
|
||||
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
|
||||
new_l1_table = qemu_try_blockalign(bs->file->bs,
|
||||
align_offset(new_l1_bytes, 512));
|
||||
ROUND_UP(new_l1_bytes, 512));
|
||||
if (new_l1_table == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user