diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 6cbae1d205..6b83b3e267 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -949,19 +949,21 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) } free_in_cluster = s->cluster_size - offset_into_cluster(s, offset); - if (!offset || free_in_cluster < size) { - int64_t new_cluster = alloc_clusters_noref(bs, s->cluster_size); - if (new_cluster < 0) { - return new_cluster; - } + do { + if (!offset || free_in_cluster < size) { + int64_t new_cluster = alloc_clusters_noref(bs, s->cluster_size); + if (new_cluster < 0) { + return new_cluster; + } - if (!offset || ROUND_UP(offset, s->cluster_size) != new_cluster) { - offset = new_cluster; + if (!offset || ROUND_UP(offset, s->cluster_size) != new_cluster) { + offset = new_cluster; + } } - } - assert(offset); - ret = update_refcount(bs, offset, size, 1, false, QCOW2_DISCARD_NEVER); + assert(offset); + ret = update_refcount(bs, offset, size, 1, false, QCOW2_DISCARD_NEVER); + } while (ret == -EAGAIN); if (ret < 0) { return ret; } diff --git a/block/raw-win32.c b/block/raw-win32.c index dae5d2fee9..9ee92791ef 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -35,6 +35,7 @@ #define FTYPE_FILE 0 #define FTYPE_CD 1 #define FTYPE_HARDDISK 2 +#define WINDOWS_VISTA 6 typedef struct RawWin32AIOData { BlockDriverState *bs; @@ -53,6 +54,10 @@ typedef struct BDRVRawState { QEMUWin32AIOState *aio; } BDRVRawState; +typedef struct BDRVRawReopenState { + HANDLE hfile; +} BDRVRawReopenState; + /* * Read/writes the data to/from a given linear buffer. * @@ -193,12 +198,14 @@ int qemu_ftruncate64(int fd, int64_t length) return res ? 0 : -1; } +/* static int set_sparse(int fd) { DWORD returned; return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &returned, NULL); } +*/ static void raw_detach_aio_context(BlockDriverState *bs) { @@ -292,6 +299,100 @@ static QemuOptsList raw_runtime_opts = { }, }; +static int raw_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) +{ + BDRVRawState *s; + BDRVRawReopenState *raw_s; + int ret = 0; + int access_flags; + DWORD overlapped; + OSVERSIONINFO osvi; + + assert(state != NULL); + assert(state->bs != NULL); + + s = state->bs->opaque; + + state->opaque = g_malloc0(sizeof(BDRVRawReopenState)); + raw_s = state->opaque; + + raw_parse_flags(state->flags, &access_flags, &overlapped); + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + raw_s->hfile = INVALID_HANDLE_VALUE; + + if (osvi.dwMajorVersion >= WINDOWS_VISTA) { + raw_s->hfile = ReOpenFile(s->hfile, access_flags, FILE_SHARE_READ, + overlapped); + } + + /* could not reopen the file handle, so fall back to opening + * new file (CreateFile) */ + if (raw_s->hfile == INVALID_HANDLE_VALUE) { + raw_s->hfile = CreateFile(state->bs->filename, access_flags, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + overlapped, NULL); + if (raw_s->hfile == INVALID_HANDLE_VALUE) { + /* this could happen because the access_flags requested are + * incompatible with the existing share mode of s->hfile, + * so our only option now is to close s->hfile, and try again. + * This could end badly */ + CloseHandle(s->hfile); + s->hfile = INVALID_HANDLE_VALUE; + raw_s->hfile = CreateFile(state->bs->filename, access_flags, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + overlapped, NULL); + if (raw_s->hfile == INVALID_HANDLE_VALUE) { + /* Unrecoverable error */ + error_set(errp, ERROR_CLASS_GENERIC_ERROR, + "Fatal error reopening %s file; file closed and cannot be opened\n", + state->bs->filename); + ret = -1; + } else{ + /* since we had to close the original, go ahead and + * re-assign here */ + s->hfile = raw_s->hfile; + raw_s->hfile = INVALID_HANDLE_VALUE; + } + } + } + + return ret; +} + +static void raw_reopen_commit(BDRVReopenState *state) +{ + BDRVRawReopenState *raw_s = state->opaque; + BDRVRawState *s = state->bs->opaque; + + if (raw_s->hfile != INVALID_HANDLE_VALUE) { + CloseHandle(s->hfile); + s->hfile = raw_s->hfile; + } + + g_free(state->opaque); + state->opaque = NULL; +} + +static void raw_reopen_abort(BDRVReopenState *state) +{ + BDRVRawReopenState *raw_s = state->opaque; + + /* nothing to do if NULL, we didn't get far enough */ + if (raw_s == NULL) { + return; + } + + if (raw_s->hfile != INVALID_HANDLE_VALUE) { + CloseHandle(raw_s->hfile); + } + g_free(state->opaque); + state->opaque = NULL; +} + static int raw_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -329,7 +430,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, } s->hfile = CreateFile(filename, access_flags, - FILE_SHARE_READ, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, overlapped, NULL); if (s->hfile == INVALID_HANDLE_VALUE) { int err = GetLastError(); @@ -520,7 +621,7 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp) error_setg_errno(errp, errno, "Could not create file"); return -EIO; } - set_sparse(fd); + //set_sparse(fd); ftruncate(fd, total_size); qemu_close(fd); return 0; @@ -547,6 +648,9 @@ BlockDriver bdrv_file = { .bdrv_needs_filename = true, .bdrv_parse_filename = raw_parse_filename, .bdrv_file_open = raw_open, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_close = raw_close, .bdrv_create = raw_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, diff --git a/block/vhdx.c b/block/vhdx.c index bb3ed45d5c..e24062f22a 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1269,7 +1269,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, iov1.iov_base = qemu_blockalign(bs, iov1.iov_len); memset(iov1.iov_base, 0, iov1.iov_len); qemu_iovec_concat_iov(&hd_qiov, &iov1, 1, 0, - sinfo.block_offset); + iov1.iov_len); sectors_to_write += iov1.iov_len >> BDRV_SECTOR_BITS; } @@ -1285,7 +1285,7 @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num, iov2.iov_base = qemu_blockalign(bs, iov2.iov_len); memset(iov2.iov_base, 0, iov2.iov_len); qemu_iovec_concat_iov(&hd_qiov, &iov2, 1, 0, - sinfo.block_offset); + iov2.iov_len); sectors_to_write += iov2.iov_len >> BDRV_SECTOR_BITS; } }