mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
Block layer patches:
- qcow2: Fix data corruption bug that is triggered in partial cluster allocation with default options - qapi: add support for blkreplay driver - doc: Describe missing generic -blockdev options - iotests: Fix 118 when run as root - Minor code cleanups -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJdsvZIAAoJEH8JsnLIjy/W14oP/1vcfFbet4tOzFU8Wx1rOwR6 1sCWN41Wwj60wNIS4npDTj1iKVXFXShkOOZyufQ/1AE5yEnP+Qod03rURqQTZKeS UT11Cwqx6hyqCJRgNMFBmdlQiGXW3rJWlSM0E5zV10hPwDGEK3c9rjox0b7MdTjD h7oOXk26hILV4ig6OFXsUghNP6jAuRLsWWeMd2/0xl6PcniU4XHLuMvmdwxMHoDU q3CEAxJe0xG2M6Fu7oEnJss+C/18lk7vlQ/3g93jUe54NVlme6r9FNErdBBDr/MF Jo8u4GTS2lp3uNaNmKL+yECkiigRxIBGoPeRGHQRk0rMl2KR3/NwbMXYFFer8jsi aRzVziNC0L+LWyU0I1Taf9IlyyHVhZkhoU6NU5c0fqs9mOBy1E/5LxoP7zUWqbUC 7ZZg8Hhv+9gZJdk62/vqm4y/tEQmYmUxA6/GSb3Yn5aogCiGBsMsTsq9zge3Fkrq wl/CwmtcngZzENUreGTMv/MbPbRx+A8QWA/TRVdg0AGcvosQfqR1a1i421X4AGuB 9bx0wSfnrnRS43BPTkY2Wqhq4GMfHWxf80S9a0xlZxnZZLt2vef+vDhgV/d2yd56 RRTUC5jqBPtxPT98frgjGRdr74DqEInSrtOf/9DpJ79SgoLFNylp31kqJRQ/qNJN iSKyGWA7nn+8VQi+1ufh =JZpU -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block layer patches: - qcow2: Fix data corruption bug that is triggered in partial cluster allocation with default options - qapi: add support for blkreplay driver - doc: Describe missing generic -blockdev options - iotests: Fix 118 when run as root - Minor code cleanups # gpg: Signature made Fri 25 Oct 2019 14:19:04 BST # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: qcow2: Fix corruption bug in qcow2_detect_metadata_preallocation() coroutine: Add qemu_co_mutex_assert_locked() doc: Describe missing generic -blockdev options block/backup: drop dead code from backup_job_create blockdev: Use error_report() in hmp_commit() iotests: Skip read-only cases in 118 when run as root qapi: add support for blkreplay driver Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
03bf012e52
9 changed files with 73 additions and 12 deletions
|
@ -474,10 +474,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|||
if (sync_bitmap) {
|
||||
bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL);
|
||||
}
|
||||
if (job) {
|
||||
backup_clean(&job->common.job);
|
||||
job_early_fail(&job->common.job);
|
||||
} else if (backup_top) {
|
||||
if (backup_top) {
|
||||
bdrv_backup_top_drop(backup_top);
|
||||
}
|
||||
|
||||
|
|
|
@ -3455,6 +3455,8 @@ int qcow2_detect_metadata_preallocation(BlockDriverState *bs)
|
|||
int64_t i, end_cluster, cluster_count = 0, threshold;
|
||||
int64_t file_length, real_allocation, real_clusters;
|
||||
|
||||
qemu_co_mutex_assert_locked(&s->lock);
|
||||
|
||||
file_length = bdrv_getlength(bs->file->bs);
|
||||
if (file_length < 0) {
|
||||
return file_length;
|
||||
|
|
|
@ -1916,6 +1916,8 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
|
|||
unsigned int bytes;
|
||||
int status = 0;
|
||||
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
if (!s->metadata_preallocation_checked) {
|
||||
ret = qcow2_detect_metadata_preallocation(bs);
|
||||
s->metadata_preallocation = (ret == 1);
|
||||
|
@ -1923,7 +1925,6 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
|
|||
}
|
||||
|
||||
bytes = MIN(INT_MAX, count);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -1088,11 +1088,11 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
|||
|
||||
blk = blk_by_name(device);
|
||||
if (!blk) {
|
||||
monitor_printf(mon, "Device '%s' not found\n", device);
|
||||
error_report("Device '%s' not found", device);
|
||||
return;
|
||||
}
|
||||
if (!blk_is_available(blk)) {
|
||||
monitor_printf(mon, "Device '%s' has no medium\n", device);
|
||||
error_report("Device '%s' has no medium", device);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1105,8 +1105,7 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
|||
aio_context_release(aio_context);
|
||||
}
|
||||
if (ret < 0) {
|
||||
monitor_printf(mon, "'commit' error for '%s': %s\n", device,
|
||||
strerror(-ret));
|
||||
error_report("'commit' error for '%s': %s", device, strerror(-ret));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,21 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
|
|||
*/
|
||||
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
|
||||
|
||||
/**
|
||||
* Assert that the current coroutine holds @mutex.
|
||||
*/
|
||||
static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex)
|
||||
{
|
||||
/*
|
||||
* mutex->holder doesn't need any synchronisation if the assertion holds
|
||||
* true because the mutex protects it. If it doesn't hold true, we still
|
||||
* don't mind if another thread takes or releases mutex behind our back,
|
||||
* because the condition will be false no matter whether we read NULL or
|
||||
* the pointer for any other coroutine.
|
||||
*/
|
||||
assert(atomic_read(&mutex->locked) &&
|
||||
mutex->holder == qemu_coroutine_self());
|
||||
}
|
||||
|
||||
/**
|
||||
* CoQueues are a mechanism to queue coroutines in order to continue executing
|
||||
|
|
|
@ -2883,12 +2883,13 @@
|
|||
# @nvme: Since 2.12
|
||||
# @copy-on-read: Since 3.0
|
||||
# @blklogwrites: Since 3.0
|
||||
# @blkreplay: Since 4.2
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'enum': 'BlockdevDriver',
|
||||
'data': [ 'blkdebug', 'blklogwrites', 'blkverify', 'bochs', 'cloop',
|
||||
'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
|
||||
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
|
||||
'cloop', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
|
||||
'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
|
||||
'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
|
||||
'qcow2', 'qed', 'quorum', 'raw', 'rbd',
|
||||
|
@ -3501,6 +3502,18 @@
|
|||
'data': { 'test': 'BlockdevRef',
|
||||
'raw': 'BlockdevRef' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsBlkreplay:
|
||||
#
|
||||
# Driver specific block device options for blkreplay.
|
||||
#
|
||||
# @image: disk image which should be controlled with blkreplay
|
||||
#
|
||||
# Since: 4.2
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsBlkreplay',
|
||||
'data': { 'image': 'BlockdevRef' } }
|
||||
|
||||
##
|
||||
# @QuorumReadPattern:
|
||||
#
|
||||
|
@ -4028,6 +4041,7 @@
|
|||
'blkdebug': 'BlockdevOptionsBlkdebug',
|
||||
'blklogwrites':'BlockdevOptionsBlklogwrites',
|
||||
'blkverify': 'BlockdevOptionsBlkverify',
|
||||
'blkreplay': 'BlockdevOptionsBlkreplay',
|
||||
'bochs': 'BlockdevOptionsGenericFormat',
|
||||
'cloop': 'BlockdevOptionsGenericFormat',
|
||||
'copy-on-read':'BlockdevOptionsGenericFormat',
|
||||
|
|
|
@ -864,7 +864,8 @@ ETEXI
|
|||
DEF("blockdev", HAS_ARG, QEMU_OPTION_blockdev,
|
||||
"-blockdev [driver=]driver[,node-name=N][,discard=ignore|unmap]\n"
|
||||
" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
|
||||
" [,read-only=on|off][,detect-zeroes=on|off|unmap]\n"
|
||||
" [,read-only=on|off][,auto-read-only=on|off]\n"
|
||||
" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
|
||||
" [,driver specific parameters...]\n"
|
||||
" configure a block backend\n", QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
|
@ -900,6 +901,25 @@ name is not intended to be predictable and changes between QEMU invocations.
|
|||
For the top level, an explicit node name must be specified.
|
||||
@item read-only
|
||||
Open the node read-only. Guest write attempts will fail.
|
||||
|
||||
Note that some block drivers support only read-only access, either generally or
|
||||
in certain configurations. In this case, the default value
|
||||
@option{read-only=off} does not work and the option must be specified
|
||||
explicitly.
|
||||
@item auto-read-only
|
||||
If @option{auto-read-only=on} is set, QEMU may fall back to read-only usage
|
||||
even when @option{read-only=off} is requested, or even switch between modes as
|
||||
needed, e.g. depending on whether the image file is writable or whether a
|
||||
writing user is attached to the node.
|
||||
@item force-share
|
||||
Override the image locking system of QEMU by forcing the node to utilize
|
||||
weaker shared access for permissions where it would normally request exclusive
|
||||
access. When there is the potential for multiple instances to have the same
|
||||
file open (whether this invocation of QEMU is the first or the second
|
||||
instance), both instances must permit shared access for the second instance to
|
||||
succeed at opening the file.
|
||||
|
||||
Enabling @option{force-share=on} requires @option{read-only=on}.
|
||||
@item cache.direct
|
||||
The host page cache can be avoided with @option{cache.direct=on}. This will
|
||||
attempt to do disk IO directly to the guest's memory. QEMU may still perform an
|
||||
|
|
|
@ -446,6 +446,7 @@ class TestChangeReadOnly(ChangeBaseClass):
|
|||
self.assert_qmp(result, 'return[0]/inserted/ro', True)
|
||||
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
|
||||
|
||||
@iotests.skip_if_user_is_root
|
||||
def test_rw_ro_retain(self):
|
||||
os.chmod(new_img, 0o444)
|
||||
self.vm.add_drive(old_img, 'media=disk', 'none')
|
||||
|
@ -530,6 +531,7 @@ class TestChangeReadOnly(ChangeBaseClass):
|
|||
self.assert_qmp(result, 'return[0]/inserted/ro', True)
|
||||
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
|
||||
|
||||
@iotests.skip_if_user_is_root
|
||||
def test_make_ro_rw(self):
|
||||
os.chmod(new_img, 0o444)
|
||||
self.vm.add_drive(old_img, 'media=disk', 'none')
|
||||
|
@ -571,6 +573,7 @@ class TestChangeReadOnly(ChangeBaseClass):
|
|||
self.assert_qmp(result, 'return[0]/inserted/ro', True)
|
||||
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
|
||||
|
||||
@iotests.skip_if_user_is_root
|
||||
def test_make_ro_rw_by_retain(self):
|
||||
os.chmod(new_img, 0o444)
|
||||
self.vm.add_drive(old_img, 'media=disk', 'none')
|
||||
|
|
|
@ -931,6 +931,16 @@ def func_wrapper(*args, **kwargs):
|
|||
return func_wrapper
|
||||
return skip_test_decorator
|
||||
|
||||
def skip_if_user_is_root(func):
|
||||
'''Skip Test Decorator
|
||||
Runs the test only without root permissions'''
|
||||
def func_wrapper(*args, **kwargs):
|
||||
if os.getuid() == 0:
|
||||
case_notrun('{}: cannot be run as root'.format(args[0]))
|
||||
else:
|
||||
return func(*args, **kwargs)
|
||||
return func_wrapper
|
||||
|
||||
def execute_unittest(output, verbosity, debug):
|
||||
runner = unittest.TextTestRunner(stream=output, descriptions=True,
|
||||
verbosity=verbosity)
|
||||
|
|
Loading…
Reference in a new issue