Re: [Qemu-devel] [PATCH 4/4] vhost-scsi: add an ioctl interface to get target id
On 2015/1/26 20:16, Paolo Bonzini wrote: On 26/01/2015 13:13, Gonglei wrote: That's okay, alternatively you could add a boot_tpgt argument that defaults to 1 (is it correct that 0 is not a valid tpgt?). No, 0 is the minimize valid value. :) Paolo, where do you think we should add a boot_tpgt argument? To vhost-scsi-pci. (Property, not argument). Got it. Thanks. BTW, I will send the kernel patch later. :) Regards, -Gonglei
[Qemu-devel] [RFC] optimization for qcow2 cache get/put
Hi, all Regarding too large qcow2 image, e.g., 2TB, so long disruption happened when performing snapshot, which was caused by cache update and IO wait. perf top data shown as below, PerfTop:2554 irqs/sec kernel: 0.4% exact: 0.0% [4000Hz cycles], (target_pid: 34294) 33.80% qemu-system-x86_64 [.] qcow2_cache_do_get 27.59% qemu-system-x86_64 [.] qcow2_cache_put 15.19% qemu-system-x86_64 [.] qcow2_cache_entry_mark_dirty 5.49% qemu-system-x86_64 [.] update_refcount 3.02% libpthread-2.13.so [.] pthread_getspecific 2.26% qemu-system-x86_64 [.] get_refcount 1.95% qemu-system-x86_64 [.] coroutine_get_thread_state 1.32% qemu-system-x86_64 [.] qcow2_update_snapshot_refcount 1.20% qemu-system-x86_64 [.] qemu_coroutine_self 1.16% libz.so.1.2.7 [.] 0x3018 0.95% qemu-system-x86_64 [.] qcow2_update_cluster_refcount 0.91% qemu-system-x86_64 [.] qcow2_cache_get 0.76% libc-2.13.so[.] 0x00134e49 0.73% qemu-system-x86_64 [.] bdrv_debug_event 0.16% qemu-system-x86_64 [.] pthread_getspecific@plt 0.12% [kernel][k] _raw_spin_unlock_irqrestore 0.10% qemu-system-x86_64 [.] vga_draw_line24_32 0.09% [vdso] [.] 0x060c 0.09% qemu-system-x86_64 [.] qcow2_check_metadata_overlap 0.08% [kernel][k] do_blockdev_direct_IO If expand the cache table size, the IO will be decreased, but the calculation time will be grown. so it's worthy to optimize qcow2 cache get and put algorithm. My proposal: get: using ((use offset cluster_bits) % c-size) to locate the cache entry, raw implementation, index = (use offset cluster_bits) % c-size; if (c-entries[index].offset == offset) { goto found; } replace: c-entries[use offset cluster_bits) % c-size].offset = offset; ... put: using 64-entries cache table to cache the recently got c-entries, i.e., cache for cache, then during put process, firstly search the 64-entries cache, if not found, then the c-entries. Any idea? Thanks, Zhang Haoyu
Re: [Qemu-devel] [PATCH v2 00/14] block: Remove growable, add blk_new_open()
On Thu, 22 Jan 2015, Max Reitz wrote: This series removes the growable field from the BlockDriverState object. Its use was to clamp guest requests against the limits of the BDS; however, this can now be done more easily by moving those checks into the BlockBackend functions. In a future series, growable may be reintroduced (maybe with a different name); it will then signify whether a BDS is able to grow (in contrast to the current growable, which signifies whether it is allowed to). Maybe I will add it to the BlockDriver instead of the BDS, though. To be able to remove that field, qemu-io needs to be converted to BlockBackend, which is done by this series as well. While working on that I decided to convert blk_new_with_bs()+bdrv_open() to blk_new_open(). I was skeptical about that decision at first, but it seems good now that I was able to replace nearly every blk_new_with_bs() call by blk_new_open(). In a future series I may try to convert some remaining bdrv_open() calls to blk_new_open() as well. (And, in fact, in a future series I *will* replace the last remaining blk_new_with_bs() outside of blk_new_open() by blk_new_open().) Finally, the question needs to be asked: If, after this series, every BDS is allowed to grow, are there any users which do not use BB, but should still be disallowed from reading/writing beyond a BDS's limits? The only users I could see were the block jobs. Some of them should indeed be converted to BB; but none of them takes a user-supplied offset or size, all work on the full BDS (or only on parts which have been modified, etc.). Therefore, it is by design impossible for them to exceed the BDS's limits, which makes making all BDS's growable safe. Hello Max, I applied the first four patches in this series, and this is what I get: hw/block/xen_disk.c: In function ‘blk_connect’: hw/block/xen_disk.c:907:27: error: implicit declaration of function ‘qstring_from_str’ [-Werror=implicit-function-declaration] hw/block/xen_disk.c:907:27: error: nested extern declaration of ‘qstring_from_str’ [-Werror=nested-externs] hw/block/xen_disk.c:907:27: error: invalid type argument of ‘-’ (have ‘int’) hw/block/xen_disk.c:901:22: error: unused variable ‘drv’ [-Werror=unused-variable] hw/block/xen_disk.c:900:23: error: unused variable ‘blk’ [-Werror=unused-variable] it would be great if you could build test it. v2: - Rebased [Kevin] - Patch 2: Added a TODO comment about removing @filename and @flags from blk_new_open() when possible [Kevin] git-backport-diff against v1: Key: [] : patches are identical [] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/14:[] [--] 'block: Lift some BDS functions to the BlockBackend' 002/14:[0006] [FC] 'block: Add blk_new_open()' 003/14:[] [-C] 'blockdev: Use blk_new_open() in blockdev_init()' 004/14:[] [--] 'block/xen: Use blk_new_open() in blk_connect()' 005/14:[] [--] 'qemu-img: Use blk_new_open() in img_open()' 006/14:[] [--] 'qemu-img: Use blk_new_open() in img_rebase()' 007/14:[] [--] 'qemu-img: Use BlockBackend as far as possible' 008/14:[] [--] 'qemu-nbd: Use blk_new_open() in main()' 009/14:[] [--] 'qemu-io: Use blk_new_open() in openfile()' 010/14:[0002] [FC] 'qemu-io: Remove growable option' 011/14:[] [--] 'qemu-io: Use BlockBackend' 012/14:[] [--] 'block: Clamp BlockBackend requests' 013/14:[] [--] 'block: Remove growable from BDS' 014/14:[] [--] 'block: Keep bdrv_check*_request()'s return value' Max Reitz (14): block: Lift some BDS functions to the BlockBackend block: Add blk_new_open() blockdev: Use blk_new_open() in blockdev_init() block/xen: Use blk_new_open() in blk_connect() qemu-img: Use blk_new_open() in img_open() qemu-img: Use blk_new_open() in img_rebase() qemu-img: Use BlockBackend as far as possible qemu-nbd: Use blk_new_open() in main() qemu-io: Use blk_new_open() in openfile() qemu-io: Remove growable option qemu-io: Use BlockBackend block: Clamp BlockBackend requests block: Remove growable from BDS block: Keep bdrv_check*_request()'s return value block.c| 59 +- block/block-backend.c | 219 + block/qcow2.c | 6 -- block/raw-posix.c | 2 +- block/raw-win32.c | 2 +- block/sheepdog.c | 2 +- blockdev.c | 92 hmp.c | 9 +- hw/block/xen_disk.c| 24 ++--- include/block/block_int.h | 3 - include/qemu-io.h | 4 +- include/sysemu/block-backend.h | 12 +++ qemu-img.c | 171 ++--- qemu-io-cmds.c | 238
Re: [Qemu-devel] [PULL 0/1] Xen tree 2015-01-26
On 26 January 2015 at 12:00, Stefano Stabellini stefano.stabell...@eu.citrix.com wrote: The following changes since commit b3a4755a67a52aa7297eb8927b482d09dabdefec: Merge remote-tracking branch 'remotes/kraxel/tags/pull-vnc-20150122-1' into staging (2015-01-22 12:14:19 +) are available in the git repository at: git://xenbits.xen.org/people/sstabellini/qemu-dm.git xen-2015-01-26 for you to fetch changes up to d01a5a3fe19645f3cdea1566f0e518ea2152a029: fix QEMU build on Xen/ARM (2015-01-26 11:56:33 +) Stefano Stabellini (1): fix QEMU build on Xen/ARM Applied, thanks. -- PMM
[Qemu-devel] [PATCH v3 2/2] target-arm: Add checks that cpreg raw accesses are handled
Add assertion checking when cpreg structures are registered that they either forbid raw-access attempts or at least make an attempt at handling them. Also add an assert in the raw-accessor-of-last-resort, to avoid silently doing a read or write from offset zero, which is actually AArch32 CPU register r0. Signed-off-by: Peter Maydell peter.mayd...@linaro.org --- target-arm/helper.c | 31 +++ 1 file changed, 31 insertions(+) diff --git a/target-arm/helper.c b/target-arm/helper.c index 18f04b2..95b1679 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -119,6 +119,7 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) { +assert(ri-fieldoffset); if (cpreg_field_is_64bit(ri)) { return CPREG_FIELD64(env, ri); } else { @@ -129,6 +130,7 @@ static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { +assert(ri-fieldoffset); if (cpreg_field_is_64bit(ri)) { CPREG_FIELD64(env, ri) = value; } else { @@ -174,6 +176,27 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, } } +static bool raw_accessors_invalid(const ARMCPRegInfo *ri) +{ + /* Return true if the regdef would cause an assertion if you called +* read_raw_cp_reg() or write_raw_cp_reg() on it (ie if it is a +* program bug for it not to have the NO_RAW flag). +* NB that returning false here doesn't necessarily mean that calling +* read/write_raw_cp_reg() is safe, because we can't distinguish has +* read/write access functions which are safe for raw use from has +* read/write access functions which have side effects but has forgotten +* to provide raw access functions. +* The tests here line up with the conditions in read/write_raw_cp_reg() +* and assertions in raw_read()/raw_write(). +*/ +if ((ri-type ARM_CP_CONST) || +ri-fieldoffset || +((ri-raw_writefn || ri-writefn) (ri-raw_readfn || ri-readfn))) { +return false; +} +return true; +} + bool write_cpustate_to_list(ARMCPU *cpu) { /* Write the coprocessor state from cpu-env to the (index,value) list. */ @@ -3509,6 +3532,14 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, r2-type |= ARM_CP_ALIAS; } +/* Check that raw accesses are either forbidden or handled. Note that + * we can't assert this earlier because the setup of fieldoffset for + * banked registers has to be done first. + */ +if (!(r2-type ARM_CP_NO_RAW)) { +assert(!raw_accessors_invalid(r2)); +} + /* Overriding of an existing definition must be explicitly * requested. */ -- 1.9.1
Re: [Qemu-devel] [PATCH v2 00/14] block: Remove growable, add blk_new_open()
On 2015-01-26 at 07:18, Stefano Stabellini wrote: On Thu, 22 Jan 2015, Max Reitz wrote: This series removes the growable field from the BlockDriverState object. Its use was to clamp guest requests against the limits of the BDS; however, this can now be done more easily by moving those checks into the BlockBackend functions. In a future series, growable may be reintroduced (maybe with a different name); it will then signify whether a BDS is able to grow (in contrast to the current growable, which signifies whether it is allowed to). Maybe I will add it to the BlockDriver instead of the BDS, though. To be able to remove that field, qemu-io needs to be converted to BlockBackend, which is done by this series as well. While working on that I decided to convert blk_new_with_bs()+bdrv_open() to blk_new_open(). I was skeptical about that decision at first, but it seems good now that I was able to replace nearly every blk_new_with_bs() call by blk_new_open(). In a future series I may try to convert some remaining bdrv_open() calls to blk_new_open() as well. (And, in fact, in a future series I *will* replace the last remaining blk_new_with_bs() outside of blk_new_open() by blk_new_open().) Finally, the question needs to be asked: If, after this series, every BDS is allowed to grow, are there any users which do not use BB, but should still be disallowed from reading/writing beyond a BDS's limits? The only users I could see were the block jobs. Some of them should indeed be converted to BB; but none of them takes a user-supplied offset or size, all work on the full BDS (or only on parts which have been modified, etc.). Therefore, it is by design impossible for them to exceed the BDS's limits, which makes making all BDS's growable safe. Hello Max, I applied the first four patches in this series, and this is what I get: hw/block/xen_disk.c: In function ‘blk_connect’: hw/block/xen_disk.c:907:27: error: implicit declaration of function ‘qstring_from_str’ [-Werror=implicit-function-declaration] hw/block/xen_disk.c:907:27: error: nested extern declaration of ‘qstring_from_str’ [-Werror=nested-externs] hw/block/xen_disk.c:907:27: error: invalid type argument of ‘-’ (have ‘int’) hw/block/xen_disk.c:901:22: error: unused variable ‘drv’ [-Werror=unused-variable] hw/block/xen_disk.c:900:23: error: unused variable ‘blk’ [-Werror=unused-variable] it would be great if you could build test it. Sorry, of course I build test my patches, but I just don't have some subsystems enabled (there was no real reason not to have the Xen backends enabled, but that's just how it was; another example are Windows-specific areas), so I have to work blind on them. In this case I forgot to include the QMP type headers and to remove the now unused variables. Thank you for looking at my patches and finding this issue! I'll send a fixed v3. Max v2: - Rebased [Kevin] - Patch 2: Added a TODO comment about removing @filename and @flags from blk_new_open() when possible [Kevin] git-backport-diff against v1: Key: [] : patches are identical [] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/14:[] [--] 'block: Lift some BDS functions to the BlockBackend' 002/14:[0006] [FC] 'block: Add blk_new_open()' 003/14:[] [-C] 'blockdev: Use blk_new_open() in blockdev_init()' 004/14:[] [--] 'block/xen: Use blk_new_open() in blk_connect()' 005/14:[] [--] 'qemu-img: Use blk_new_open() in img_open()' 006/14:[] [--] 'qemu-img: Use blk_new_open() in img_rebase()' 007/14:[] [--] 'qemu-img: Use BlockBackend as far as possible' 008/14:[] [--] 'qemu-nbd: Use blk_new_open() in main()' 009/14:[] [--] 'qemu-io: Use blk_new_open() in openfile()' 010/14:[0002] [FC] 'qemu-io: Remove growable option' 011/14:[] [--] 'qemu-io: Use BlockBackend' 012/14:[] [--] 'block: Clamp BlockBackend requests' 013/14:[] [--] 'block: Remove growable from BDS' 014/14:[] [--] 'block: Keep bdrv_check*_request()'s return value' Max Reitz (14): block: Lift some BDS functions to the BlockBackend block: Add blk_new_open() blockdev: Use blk_new_open() in blockdev_init() block/xen: Use blk_new_open() in blk_connect() qemu-img: Use blk_new_open() in img_open() qemu-img: Use blk_new_open() in img_rebase() qemu-img: Use BlockBackend as far as possible qemu-nbd: Use blk_new_open() in main() qemu-io: Use blk_new_open() in openfile() qemu-io: Remove growable option qemu-io: Use BlockBackend block: Clamp BlockBackend requests block: Remove growable from BDS block: Keep bdrv_check*_request()'s return value block.c| 59 +- block/block-backend.c | 219 + block/qcow2.c | 6 -- block/raw-posix.c | 2 +- block/raw-win32.c | 2
Re: [Qemu-devel] [PATCH 05/11] target-arm: Use correct mmu_idx for unprivileged loads and stores
On Fri, Jan 23, 2015 at 12:20 PM, Peter Maydell peter.mayd...@linaro.org wrote: The MMU index to use for unprivileged loads and stores is more complicated than we currently implement: * for A64, it should be if at EL1, access as if EL0; otherwise access at current EL * for A32/T32, it should be if EL2, UNPREDICTABLE; otherwise access as if at EL0. The wording between the specs appears to be almost identical, curious why the handling is different? In both cases, if we want to make the access for Secure EL0 this is not the same mmu_idx as for Non-Secure EL0. Signed-off-by: Peter Maydell peter.mayd...@linaro.org --- target-arm/translate-a64.c | 19 ++- target-arm/translate.c | 26 -- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 96f14ff..acf4b16 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -123,6 +123,23 @@ void a64_translate_init(void) #endif } +static inline ARMMMUIdx get_a64_user_mem_index(DisasContext *s) +{ +/* Return the mmu_idx to use for A64 unprivileged load/store insns: + * if EL1, access as if EL0; otherwise access at current EL + */ +switch (s-mmu_idx) { +case ARMMMUIdx_S12NSE1: +return ARMMMUIdx_S12NSE0; +case ARMMMUIdx_S1SE1: +return ARMMMUIdx_S1SE0; +case ARMMMUIdx_S2NS: +g_assert_not_reached(); +default: +return s-mmu_idx; +} +} + void aarch64_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { @@ -2107,7 +2124,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) } } else { TCGv_i64 tcg_rt = cpu_reg(s, rt); -int memidx = is_unpriv ? MMU_USER_IDX : get_mem_index(s); +int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s); if (is_store) { do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx); diff --git a/target-arm/translate.c b/target-arm/translate.c index 7163649..715f65d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -113,6 +113,28 @@ void arm_translate_init(void) a64_translate_init(); } +static inline ARMMMUIdx get_a32_user_mem_index(DisasContext *s) +{ +/* Return the mmu_idx to use for A32/T32 unprivileged load/store + * insns: + * if PL2, UNPREDICTABLE (we choose to implement as if PL0) + * otherwise, access as if at PL0. + */ +switch (s-mmu_idx) { +case ARMMMUIdx_S1E2:/* this one is UNPREDICTABLE */ +case ARMMMUIdx_S12NSE0: +case ARMMMUIdx_S12NSE1: +return ARMMMUIdx_S12NSE0; +case ARMMMUIdx_S1E3: +case ARMMMUIdx_S1SE0: +case ARMMMUIdx_S1SE1: +return ARMMMUIdx_S1SE0; +case ARMMMUIdx_S2NS: +default: +g_assert_not_reached(); +} +} + static inline TCGv_i32 load_cpu_offset(int offset) { TCGv_i32 tmp = tcg_temp_new_i32(); @@ -8793,7 +8815,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) tmp2 = load_reg(s, rn); if ((insn 0x0120) == 0x0020) { /* ldrt/strt */ -i = MMU_USER_IDX; +i = get_a32_user_mem_index(s); } else { i = get_mem_index(s); } @@ -10173,7 +10195,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw break; case 0xe: /* User privilege. */ tcg_gen_addi_i32(addr, addr, imm); -memidx = MMU_USER_IDX; +memidx = get_a32_user_mem_index(s); break; case 0x9: /* Post-decrement. */ imm = -imm; -- 1.9.1 Otherwise, Reviewed-by: Greg Bellows greg.bell...@linaro.org
[Qemu-devel] [PATCH v3 1/2] target-arm: Split NO_MIGRATE into ALIAS and NO_RAW
We currently mark ARM coprocessor/system register definitions with the flag ARM_CP_NO_MIGRATE for two different reasons: 1) register is an alias on to state that's also visible via some other register, and that other register is the one responsible for migrating the state 2) register is not actually state at all (for instance the TLB or cache maintenance operation registers) and it makes no sense to attempt to migrate it or otherwise access the raw state This works fine for identifying which registers should be ignored when performing migration, but we also use the same functions for synchronizing system register state between QEMU and the kernel when using KVM. In this case we don't want to try to sync state into registers in category 2, but we do want to sync into registers in category 1, because the kernel might have picked a different one of the aliases as its choice for which one to expose for migration. (In particular, on 32 bit hosts the kernel will expose the state in the AArch32 version of the register, but TCG's convention is to mark the AArch64 version as the version to migrate, even if the CPU being emulated happens to be 32 bit, so almost all system registers will hit this issue now that we've added AArch64 system emulation.) Fix this by splitting the NO_MIGRATE flag in two (ALIAS and NO_RAW) corresponding to the two different reasons we might not want to migrate a register. When setting up the TCG list of registers to migrate we honour both flags; when populating the list from KVM, only ignore registers which are NO_RAW. Signed-off-by: Peter Maydell peter.mayd...@linaro.org Reviewed-by: Greg Bellows greg.bell...@linaro.org --- target-arm/cpu.h| 15 +++- target-arm/helper.c | 206 ++-- 2 files changed, 115 insertions(+), 106 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7ba55f0..831a841 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1112,8 +1112,14 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) * a register definition to override a previous definition for the * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the * old must have the OVERRIDE bit set. - * NO_MIGRATE indicates that this register should be ignored for migration; - * (eg because any state is accessed via some other coprocessor register). + * ALIAS indicates that this register is an alias view of some underlying + * state which is also visible via another register, and that the other + * register is handling migration; registers marked ALIAS will not be migrated + * but may have their state set by syncing of register state from KVM. + * NO_RAW indicates that this register has no underlying state and does not + * support raw access for state saving/loading; it will not be used for either + * migration or KVM state synchronization. (Typically this is for registers + * which are actually used as instructions for cache maintenance and so on.) * IO indicates that this register does I/O and therefore its accesses * need to be surrounded by gen_io_start()/gen_io_end(). In particular, * registers which implement clocks or timers require this. @@ -1123,8 +1129,9 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) #define ARM_CP_64BIT 4 #define ARM_CP_SUPPRESS_TB_END 8 #define ARM_CP_OVERRIDE 16 -#define ARM_CP_NO_MIGRATE 32 +#define ARM_CP_ALIAS 32 #define ARM_CP_IO 64 +#define ARM_CP_NO_RAW 128 #define ARM_CP_NOP (ARM_CP_SPECIAL | (1 8)) #define ARM_CP_WFI (ARM_CP_SPECIAL | (2 8)) #define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 8)) @@ -1134,7 +1141,7 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) /* Used only as a terminator for ARMCPRegInfo lists */ #define ARM_CP_SENTINEL 0x /* Mask of only the flag bits in a type field */ -#define ARM_CP_FLAG_MASK 0x7f +#define ARM_CP_FLAG_MASK 0xff /* Valid values for ARMCPRegInfo state field, indicating which of * the AArch32 and AArch64 execution states this register is visible in. diff --git a/target-arm/helper.c b/target-arm/helper.c index 1a5e067..18f04b2 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -189,7 +189,7 @@ bool write_cpustate_to_list(ARMCPU *cpu) ok = false; continue; } -if (ri-type ARM_CP_NO_MIGRATE) { +if (ri-type ARM_CP_NO_RAW) { continue; } cpu-cpreg_values[i] = read_raw_cp_reg(cpu-env, ri); @@ -212,7 +212,7 @@ bool write_list_to_cpustate(ARMCPU *cpu) ok = false; continue; } -if (ri-type ARM_CP_NO_MIGRATE) { +if (ri-type ARM_CP_NO_RAW) { continue; } /* Write value and confirm it reads back as written @@ -236,7 +236,7 @@ static void add_cpreg_to_list(gpointer key, gpointer opaque) regidx = *(uint32_t *)key; ri = get_arm_cp_reginfo(cpu-cp_regs, regidx); -if (!(ri-type ARM_CP_NO_MIGRATE)) { +if (!(ri-type
Re: [Qemu-devel] [PATCH] linux-user/syscall.c: Let all lock_user_struct() and unlock_user_struct() paired with each other
On 1/26/15 06:10, Peter Maydell wrote: On 25 January 2015 at 21:59, Chen Gang S gang.c...@sunrus.com.cn wrote: On 1/25/15 20:49, Peter Maydell wrote: Are you claiming that you've reviewed *all* the code in this file for mismatched lock/unlock calls? If so, it would be nice to say so explicitly in the commit message. If not, it would be nice if the commit message was clearer about what areas of the code it applied to. The code changes are correct, though. At present, I finished all lock_user_struct() and unlock_user_struct() in linux-user/syscall.c. For me, after this patch, they are all OK. But for all lock/unlock in linux-user/syscall.c, for me, I am doubting several areas, but I did not send patch for them: - I need check them carefully again to be sure they are really issue: Read the related code again and again, if I really treat it as an issue, I shall make related patch (and pass compiling, at least). - I have no enough time resources on it: That's fine. I'm definitely not asking you to do this work. OK, thanks. :-) I would just like the commit message to be clear about the scope of the work the patch covers. If the patch is just Fix mismatched lock/unlock calls in IPC struct conversion functions then that's fine, but the commit message should say that. At the moment the commit message is very vague. OK, thanks. I am not quite familiar with this file, so I describe the modification by function name, e.g. lock_user_struct() and unlick_user_struct() in the patch subject. Welcome to help improve the patch comments. If necessary to send patch v2, please let me know, I shall try. Thanks. -- Chen Gang Open, share, and attitude like air, water, and life which God blessed
[Qemu-devel] [PATCH v3 0/2] target-arm: fix broken sync of sysregs between QEMU and KVM 32
This patchset fixes a regression in the synchronization of system registers between QEMU and KVM for 32-bit ARM hosts. The most obvious effect of the bug is that trying to access memory via the gdbstub doesn't work, because gdbstub thinks the MMU is off and doesn't get the virt-to-phys translation right. (Migration would not be broken.) The underlying cause of this is that we are using the cpreg definition flag ARM_CP_NO_MIGRATE for two different purposes: 1) register is an alias on to state that's also visible via some other register, and that other register is the one responsible for migrating the state 2) register is not actually state at all (for instance the TLB or cache maintenance operation registers) and it makes no sense to attempt to migrate it or otherwise access the raw state This works fine for identifying which registers should be ignored when performing migration, but we also use the same functions for synchronizing system register state between QEMU and the kernel when using KVM. In this case we don't want to try to sync state into registers in category 2, but we do want to sync into registers in category 1, because the kernel might have picked a different one of the aliases as its choice for which one to expose for migration. (In particular, on 32 bit hosts the kernel will expose the state in the AArch32 version of the register, but TCG's convention is to mark the AArch64 version as the version to migrate, even if the CPU being emulated happens to be 32 bit, so almost all system registers will hit this issue now that we've added AArch64 system emulation.) Fix this by splitting the NO_MIGRATE flag in two (ALIAS and NO_RAW) corresponding to the two different reasons we might not want to migrate a register. When setting up the TCG list of registers to migrate we honour both flags; when populating the list from KVM, only ignore registers which are NO_RAW. Changes v1-v2: * change raw_accessors_valid() to raw_accessors_invalid() and beef up its comment, following confusion during review of v1 Changes v2-v3: * actually change behaviour of the raw_accessors_invalid() function rather than merely its name... Peter Maydell (2): target-arm: Split NO_MIGRATE into ALIAS and NO_RAW target-arm: Add checks that cpreg raw accesses are handled target-arm/cpu.h| 15 +++- target-arm/helper.c | 237 ++-- 2 files changed, 146 insertions(+), 106 deletions(-) -- 1.9.1
[Qemu-devel] [PATCH 1/2] disas/libvixl: Update to upstream VIXL 1.7
Update our copy of libvixl to upstream's 1.7 release. This includes upstream's fix for the issue we had a local patch for in commit 94cc44a9e. Signed-off-by: Peter Maydell peter.mayd...@linaro.org --- disas/libvixl/README | 2 +- disas/libvixl/a64/assembler-a64.h | 290 +- disas/libvixl/a64/constants-a64.h | 61 +-- disas/libvixl/a64/decoder-a64.h | 2 +- disas/libvixl/a64/disasm-a64.cc | 142 ++--- disas/libvixl/a64/disasm-a64.h| 48 -- disas/libvixl/a64/instructions-a64.cc | 63 disas/libvixl/a64/instructions-a64.h | 110 - disas/libvixl/globals.h | 2 +- disas/libvixl/utils.cc| 13 ++ disas/libvixl/utils.h | 14 +- 11 files changed, 537 insertions(+), 210 deletions(-) diff --git a/disas/libvixl/README b/disas/libvixl/README index cba31b4..58db41c 100644 --- a/disas/libvixl/README +++ b/disas/libvixl/README @@ -2,7 +2,7 @@ The code in this directory is a subset of libvixl: https://github.com/armvixl/vixl (specifically, it is the set of files needed for disassembly only, -taken from libvixl 1.6). +taken from libvixl 1.7). Bugfixes should preferably be sent upstream initially. The disassembler does not currently support the entire A64 instruction diff --git a/disas/libvixl/a64/assembler-a64.h b/disas/libvixl/a64/assembler-a64.h index 16a704b..35aaf20 100644 --- a/disas/libvixl/a64/assembler-a64.h +++ b/disas/libvixl/a64/assembler-a64.h @@ -151,21 +151,21 @@ class CPURegister { return Aliases(other) (size_ == other.size_); } - inline bool IsZero() const { + bool IsZero() const { VIXL_ASSERT(IsValid()); return IsRegister() (code_ == kZeroRegCode); } - inline bool IsSP() const { + bool IsSP() const { VIXL_ASSERT(IsValid()); return IsRegister() (code_ == kSPRegInternalCode); } - inline bool IsRegister() const { + bool IsRegister() const { return type_ == kRegister; } - inline bool IsFPRegister() const { + bool IsFPRegister() const { return type_ == kFPRegister; } @@ -179,7 +179,7 @@ class CPURegister { const FPRegister S() const; const FPRegister D() const; - inline bool IsSameSizeAndType(const CPURegister other) const { + bool IsSameSizeAndType(const CPURegister other) const { return (size_ == other.size_) (type_ == other.type_); } @@ -198,7 +198,7 @@ class CPURegister { class Register : public CPURegister { public: Register() : CPURegister() {} - inline explicit Register(const CPURegister other) + explicit Register(const CPURegister other) : CPURegister(other.code(), other.size(), other.type()) { VIXL_ASSERT(IsValidRegister()); } @@ -213,10 +213,6 @@ class Register : public CPURegister { static const Register WRegFromCode(unsigned code); static const Register XRegFromCode(unsigned code); - // V8 compatibility. - static const int kNumRegisters = kNumberOfRegisters; - static const int kNumAllocatableRegisters = kNumberOfRegisters - 1; - private: static const Register wregisters[]; static const Register xregisters[]; @@ -225,12 +221,12 @@ class Register : public CPURegister { class FPRegister : public CPURegister { public: - inline FPRegister() : CPURegister() {} - inline explicit FPRegister(const CPURegister other) + FPRegister() : CPURegister() {} + explicit FPRegister(const CPURegister other) : CPURegister(other.code(), other.size(), other.type()) { VIXL_ASSERT(IsValidFPRegister()); } - inline FPRegister(unsigned code, unsigned size) + FPRegister(unsigned code, unsigned size) : CPURegister(code, size, kFPRegister) {} bool IsValid() const { @@ -241,10 +237,6 @@ class FPRegister : public CPURegister { static const FPRegister SRegFromCode(unsigned code); static const FPRegister DRegFromCode(unsigned code); - // V8 compatibility. - static const int kNumRegisters = kNumberOfFPRegisters; - static const int kNumAllocatableRegisters = kNumberOfFPRegisters - 1; - private: static const FPRegister sregisters[]; static const FPRegister dregisters[]; @@ -312,23 +304,23 @@ bool AreSameSizeAndType(const CPURegister reg1, // Lists of registers. class CPURegList { public: - inline explicit CPURegList(CPURegister reg1, - CPURegister reg2 = NoCPUReg, - CPURegister reg3 = NoCPUReg, - CPURegister reg4 = NoCPUReg) + explicit CPURegList(CPURegister reg1, + CPURegister reg2 = NoCPUReg, + CPURegister reg3 = NoCPUReg, + CPURegister reg4 = NoCPUReg) : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), size_(reg1.size()), type_(reg1.type()) { VIXL_ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4)); VIXL_ASSERT(IsValid()); } - inline CPURegList(CPURegister::RegisterType type,
[Qemu-devel] [PATCH] vhost-scsi: introduce an ioctl to get the minimum tpgt
From: Gonglei arei.gong...@huawei.com In order to support to assign a boot order for vhost-scsi device, we should get the tpgt for user level (such as Qemu). and at present, we only support the minimum tpgt can boot. Signed-off-by: Gonglei arei.gong...@huawei.com Signed-off-by: Bo Su su...@huawei.com --- drivers/vhost/scsi.c | 41 + include/uapi/linux/vhost.h | 2 ++ 2 files changed, 43 insertions(+) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index d695b16..12e79b9 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1522,6 +1522,38 @@ err_dev: return ret; } +static int vhost_scsi_get_first_tpgt( + struct vhost_scsi *vs, + struct vhost_scsi_target *t) +{ + struct tcm_vhost_tpg *tv_tpg; + struct tcm_vhost_tport *tv_tport; + int tpgt = -1; + + mutex_lock(tcm_vhost_mutex); + mutex_lock(vs-dev.mutex); + + list_for_each_entry(tv_tpg, tcm_vhost_list, tv_tpg_list) { + tv_tport = tv_tpg-tport; + + if (!strcmp(tv_tport-tport_name, t-vhost_wwpn)) { + if (tpgt 0) + tpgt = tv_tpg-tport_tpgt; + else if (tpgt tv_tpg-tport_tpgt) + tpgt = tv_tpg-tport_tpgt; + } + } + + mutex_unlock(vs-dev.mutex); + mutex_unlock(tcm_vhost_mutex); + + if (tpgt 0) + return -ENXIO; + + t-vhost_tpgt = tpgt; + return 0; +} + static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) { struct vhost_virtqueue *vq; @@ -1657,6 +1689,15 @@ vhost_scsi_ioctl(struct file *f, if (put_user(events_missed, eventsp)) return -EFAULT; return 0; + case VHOST_SCSI_GET_TPGT: + if (copy_from_user(backend, argp, sizeof(backend))) + return -EFAULT; + r = vhost_scsi_get_first_tpgt(vs, backend); + if (r 0) + return r; + if (copy_to_user(argp, backend, sizeof(backend))) + return -EFAULT; + return 0; case VHOST_GET_FEATURES: features = VHOST_SCSI_FEATURES; if (copy_to_user(featurep, features, sizeof features)) diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h index bb6a5b4..5d350f7 100644 --- a/include/uapi/linux/vhost.h +++ b/include/uapi/linux/vhost.h @@ -155,4 +155,6 @@ struct vhost_scsi_target { #define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32) #define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32) +#define VHOST_SCSI_GET_TPGT _IOW(VHOST_VIRTIO, 0x45, struct vhost_scsi_target) + #endif -- 1.7.12.4
[Qemu-devel] [PATCH] target-ppc: Use right page size with hash table lookup
We look at two sizes specified in ISA (4K, 64K). If not found matching, we consider it 16MB. Without this patch we would fail to lookup address above 16MB range. Below 16MB happened to work before because the kernel have a liner mapping and we always looked up hash for 0xc000. The actual real address was computed by using the 16MB offset with the real address found with the above hash. Without Fix: (gdb) x/16x 0xc100 0xc100 list_entries+453208: Cannot access memory at address 0xc100 (gdb) With Fix: (gdb) x/16x 0xc100 0xc100 list_entries+453208: 0x 0x 0x 0x 0xc110 list_entries+453224: 0x 0x 0x 0x 0xc120 list_entries+453240: 0x 0x 0x 0x 0xc130 list_entries+453256: 0x 0x 0x 0x Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com --- target-ppc/cpu.h| 1 + target-ppc/mmu-hash64.c | 37 ++--- target-ppc/mmu-hash64.h | 3 +++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index aae33a9237d7..b706b9fdf6c3 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -45,6 +45,7 @@ # define TARGET_VIRT_ADDR_SPACE_BITS 64 #endif +#define TARGET_PAGE_BITS_64K 16 #define TARGET_PAGE_BITS_16M 24 #else /* defined (TARGET_PPC64) */ diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index b0278c95e1d3..971751f7de89 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -388,6 +388,24 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr hash, return -1; } +static uint64_t ppc_hash64_page_shift(ppc_slb_t *slb) +{ +uint64_t epnshift; + +/* Page size according to the SLB, which we use to generate the + * EPN for hash table lookup.. When we implement more recent MMU + * extensions this might be different from the actual page size + * encoded in the PTE */ +if ((slb-vsid SLB_VSID_LLP_MASK) == SLB_VSID_4K) { +epnshift = TARGET_PAGE_BITS; +} else if ((slb-vsid SLB_VSID_LLP_MASK) == SLB_VSID_64K) { +epnshift = TARGET_PAGE_BITS_64K; +} else { +epnshift = TARGET_PAGE_BITS_16M; +} +return epnshift; +} + static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, ppc_slb_t *slb, target_ulong eaddr, ppc_hash_pte64_t *pte) @@ -396,12 +414,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, hwaddr hash; uint64_t vsid, epnshift, epnmask, epn, ptem; -/* Page size according to the SLB, which we use to generate the - * EPN for hash table lookup.. When we implement more recent MMU - * extensions this might be different from the actual page size - * encoded in the PTE */ -epnshift = (slb-vsid SLB_VSID_L) -? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; +epnshift = ppc_hash64_page_shift(slb); epnmask = ~((1ULL epnshift) - 1); if (slb-vsid SLB_VSID_B) { @@ -448,12 +461,14 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte, target_ulong eaddr) { +hwaddr mask; +int target_page_bits; hwaddr rpn = pte.pte1 HPTE64_R_RPN; -/* FIXME: Add support for SLLP extended page sizes */ -int target_page_bits = (slb-vsid SLB_VSID_L) -? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; -hwaddr mask = (1ULL target_page_bits) - 1; - +/* + * We support 4K, 64K and 16M now + */ +target_page_bits = ppc_hash64_page_shift(slb); +mask = (1ULL target_page_bits) - 1; return (rpn ~mask) | (eaddr mask); } diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h index 49e385db90fb..291750f3e5a5 100644 --- a/target-ppc/mmu-hash64.h +++ b/target-ppc/mmu-hash64.h @@ -37,6 +37,9 @@ void ppc_hash64_store_hpte(CPUPPCState *env, target_ulong index, #define SLB_VSID_C 0x0080ULL /* class */ #define SLB_VSID_LP 0x0030ULL #define SLB_VSID_ATTR 0x0FFFULL +#define SLB_VSID_LLP_MASK (SLB_VSID_L | SLB_VSID_LP) +#define SLB_VSID_4K 0xULL +#define SLB_VSID_64K0x0110ULL /* * Hash page table definitions -- 2.1.0
Re: [Qemu-devel] [PATCH 1/2] hw/ppc/spapr.c Set default boot order
Dinar Valeev dval...@suse.de writes: On 01/26/2015 10:11 AM, Markus Armbruster wrote: dval...@suse.de writes: From: Dinar Valeev dval...@suse.com In order to use -boot once=X option we need to have default list where restore to on reset. Really? What happens without this patch? qemu segfaults on reset. 0 reset-all Segmentation fault Next time, include a backtrace, please. Here's what I think happens. Boot order comes from --boot parameter once, order, or else the machine type's .default_boot_order. The latter is null for you. It gets passed via ppc_spapr_init() to spapr_create_fdt_skel(), which sets qemu,boot-device in the FDT to it, but only when it isn't null. If it comes from parameter once, we additionally register a reset handler to switch it to parameter order or else .default_boot_order on reset. If you specify once, but not order, this is null for you. On reset, reset handler restore_boot_order() runs. Unlike spapr_create_fdt_skel(), it doesn't check for null, and crashes in validate_bootdevices(). Correct? For me, a null .default_boot_order means machine type does not support boot order (this is how commit c165473 treats it). Arguably, --boot order and once should be rejected then. If I understand you correctly, your machine type does support boot order. Giving it a non-null .default_boot_order makes sense then. The appropriate value depends on firmware. It could even be . The null check in spapr_create_fdt_skel() looks superfluous then. Consider dropping it. Makes sense?
Re: [Qemu-devel] [PULL v2 00/19] i386, KVM, misc changes for 2015-01-26
On 26 January 2015 at 11:46, Paolo Bonzini pbonz...@redhat.com wrote: The following changes since commit a46b3aaf6bb038d4f6f192a84df204f10929e75c: Merge remote-tracking branch 'remotes/otubo/tags/pull-seccomp-20150123' into staging (2015-01-23 13:24:17 +) are available in the git repository at: git://github.com/bonzini/qemu.git tags/for-upstream for you to fetch changes up to fc116efad0aadb2f8a49d51240bddbfe21b631a0: kvm_stat: Add RESET support for perf event ioctl (2015-01-26 12:27:05 +0100) - Many fixes from the floor as usual - New edu device (v1-v2: fix 32-bit compilation) - Disabling HLE and RTM on Haswell Broadwell - kvm_stat updates - Added --enable-modules to Travis, in preparation for switching the default Applied, thanks. -- PMM
[Qemu-devel] [PATCH 2/2] disas/arm-a64.cc: Tell libvixl correct code addresses
From 1.7, libvixl supports giving correct target addresses when disassembling relative branches in code which doesn't reside at what the guest CPU would think its execution address is. Use the new MapCodeAddress() API to tell libvixl where the code is from the guest CPU's point of view so it can get the target addresses right. Previous disassembly: 0x4000: 58c0 ldr x0, pc+24 (addr 0x7f6cb7020434) 0x4004: aa1f03e1 mov x1, xzr 0x4008: aa1f03e2 mov x2, xzr 0x400c: aa1f03e3 mov x3, xzr 0x4010: 5884 ldr x4, pc+16 (addr 0x7f6cb702042c) 0x4014: d61f0080 br x4 Fixed disassembly: 0x4000: 58c0 ldr x0, pc+24 (addr 0x4018) 0x4004: aa1f03e1 mov x1, xzr 0x4008: aa1f03e2 mov x2, xzr 0x400c: aa1f03e3 mov x3, xzr 0x4010: 5884 ldr x4, pc+16 (addr 0x4020) 0x4014: d61f0080 br x4 Signed-off-by: Peter Maydell peter.mayd...@linaro.org --- disas/arm-a64.cc | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/disas/arm-a64.cc b/disas/arm-a64.cc index ca29f6f..e04f946 100644 --- a/disas/arm-a64.cc +++ b/disas/arm-a64.cc @@ -67,7 +67,8 @@ static void vixl_init(FILE *f) { int print_insn_arm_a64(uint64_t addr, disassemble_info *info) { uint8_t bytes[INSN_SIZE]; -uint32_t instr; +uint32_t instrval; +const Instruction *instr; int status; status = info-read_memory_func(addr, bytes, INSN_SIZE, info); @@ -80,8 +81,10 @@ int print_insn_arm_a64(uint64_t addr, disassemble_info *info) vixl_init(info-stream); } -instr = bytes[0] | bytes[1] 8 | bytes[2] 16 | bytes[3] 24; -vixl_decoder-Decode(reinterpret_castInstruction*(instr)); +instrval = bytes[0] | bytes[1] 8 | bytes[2] 16 | bytes[3] 24; +instr = reinterpret_castconst Instruction *(instrval); +vixl_disasm-MapCodeAddress(addr, instr); +vixl_decoder-Decode(instr); return INSN_SIZE; } -- 1.9.1
[Qemu-devel] [PATCH 0/2] disas/libvixl: Update to VIXL 1.7
This patchseries brings our copy of libvixl up to upstream's 1.7 release. Patch 1 is the usual straight copy of upstream's files into our tree (note that this includes a fix for the compile warnings we previously dealt with locally in commit 94cc44a9e5). Patch 2 uses a new-in-1.7 feature to correct our disassembly of target addresses for relative jumps and offsets: Previous disassembly: 0x4000: 58c0 ldr x0, pc+24 (addr 0x7f6cb7020434) 0x4004: aa1f03e1 mov x1, xzr 0x4008: aa1f03e2 mov x2, xzr 0x400c: aa1f03e3 mov x3, xzr 0x4010: 5884 ldr x4, pc+16 (addr 0x7f6cb702042c) 0x4014: d61f0080 br x4 Fixed disassembly: 0x4000: 58c0 ldr x0, pc+24 (addr 0x4018) 0x4004: aa1f03e1 mov x1, xzr 0x4008: aa1f03e2 mov x2, xzr 0x400c: aa1f03e3 mov x3, xzr 0x4010: 5884 ldr x4, pc+16 (addr 0x4020) 0x4014: d61f0080 br x4 (previous versions of vixl assumed that the host address of the instruction was the address the ARM CPU would see, since the primary usecase was disassembly of code generated by JITs targeting AArch64.) Peter Maydell (2): disas/libvixl: Update to upstream VIXL 1.7 disas/arm-a64.cc: Tell libvixl correct code addresses disas/arm-a64.cc | 9 +- disas/libvixl/README | 2 +- disas/libvixl/a64/assembler-a64.h | 290 +- disas/libvixl/a64/constants-a64.h | 61 +-- disas/libvixl/a64/decoder-a64.h | 2 +- disas/libvixl/a64/disasm-a64.cc | 142 ++--- disas/libvixl/a64/disasm-a64.h| 48 -- disas/libvixl/a64/instructions-a64.cc | 63 disas/libvixl/a64/instructions-a64.h | 110 - disas/libvixl/globals.h | 2 +- disas/libvixl/utils.cc| 13 ++ disas/libvixl/utils.h | 14 +- 12 files changed, 543 insertions(+), 213 deletions(-) -- 1.9.1
Re: [Qemu-devel] [question] incremental backup a running vm
On 2015-01-26 19:29:03, Paolo Bonzini wrote: On 26/01/2015 12:13, Zhang Haoyu wrote: Thanks, Paolo, but too many internal snapshots were saved by customers, switching to external snapshot mechanism has significant impaction on subsequent upgrade. In that case, patches are welcome. :) Another problem: drive_backup just implement one time backup, but I want VMWare's VDP-like backup mechanism. The initial backup of a virtual machine takes comparatively more time, because all of the data for that virtual machine is being backed up. Subsequent backups of the same virtual machine take less time, because changed block tracking (log dirty) mechanism is used to only backup the dirty data. After inittial backup done, even the VM shutdown, but subsequent backup also only copy the changed data. As mentioned before, patches for this are on the list. I see, thanks, Paolo. Paolo
[Qemu-devel] [PATCH v3 03/14] blockdev: Use blk_new_open() in blockdev_init()
Due to different error propagation, this breaks tests 051 and 087; fix their output. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 92 +- tests/qemu-iotests/051.out | 60 +++--- tests/qemu-iotests/087.out | 8 ++-- 3 files changed, 76 insertions(+), 84 deletions(-) diff --git a/blockdev.c b/blockdev.c index d59efd3..7573746 100644 --- a/blockdev.c +++ b/blockdev.c @@ -354,13 +354,11 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, ThrottleConfig cfg; int snapshot = 0; bool copy_on_read; -int ret; Error *error = NULL; QemuOpts *opts; const char *id; bool has_driver_specific_opts; BlockdevDetectZeroesOptions detect_zeroes; -BlockDriver *drv = NULL; /* Check common options by copying from bs_opts to opts, all other options * stay in bs_opts for processing by bdrv_open(). */ @@ -426,11 +424,11 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, goto early_err; } -drv = bdrv_find_format(buf); -if (!drv) { -error_setg(errp, '%s' invalid format, buf); +if (qdict_haskey(bs_opts, driver)) { +error_setg(errp, Cannot specify both 'driver' and 'format'); goto early_err; } +qdict_put_obj(bs_opts, driver, QOBJECT(qstring_from_str(buf))); } /* disk I/O throttling */ @@ -505,70 +503,64 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, } /* init */ -blk = blk_new_with_bs(qemu_opts_id(opts), errp); -if (!blk) { -goto early_err; -} -bs = blk_bs(blk); -bs-open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; -bs-read_only = ro; -bs-detect_zeroes = detect_zeroes; - -bdrv_set_on_error(bs, on_read_error, on_write_error); +if ((!file || !*file) !has_driver_specific_opts) { +blk = blk_new_with_bs(qemu_opts_id(opts), errp); +if (!blk) { +goto early_err; +} -/* disk I/O throttling */ -if (throttle_enabled(cfg)) { -bdrv_io_limits_enable(bs); -bdrv_set_io_limits(bs, cfg); -} +bs = blk_bs(blk); +bs-open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; +bs-read_only = ro; -if (!file || !*file) { -if (has_driver_specific_opts) { +QDECREF(bs_opts); +} else { +if (file !*file) { file = NULL; -} else { -QDECREF(bs_opts); -qemu_opts_del(opts); -return blk; } -} -if (snapshot) { -/* always use cache=unsafe with snapshot */ -bdrv_flags = ~BDRV_O_CACHE_MASK; -bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); -} -if (copy_on_read) { -bdrv_flags |= BDRV_O_COPY_ON_READ; -} +if (snapshot) { +/* always use cache=unsafe with snapshot */ +bdrv_flags = ~BDRV_O_CACHE_MASK; +bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); +} + +if (copy_on_read) { +bdrv_flags |= BDRV_O_COPY_ON_READ; +} + +if (runstate_check(RUN_STATE_INMIGRATE)) { +bdrv_flags |= BDRV_O_INCOMING; +} -if (runstate_check(RUN_STATE_INMIGRATE)) { -bdrv_flags |= BDRV_O_INCOMING; +bdrv_flags |= ro ? 0 : BDRV_O_RDWR; + +blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags, + errp); +if (!blk) { +goto err_no_bs_opts; +} +bs = blk_bs(blk); } -bdrv_flags |= ro ? 0 : BDRV_O_RDWR; +bs-detect_zeroes = detect_zeroes; -QINCREF(bs_opts); -ret = bdrv_open(bs, file, NULL, bs_opts, bdrv_flags, drv, error); -assert(bs == blk_bs(blk)); +bdrv_set_on_error(bs, on_read_error, on_write_error); -if (ret 0) { -error_setg(errp, could not open disk image %s: %s, - file ?: blk_name(blk), error_get_pretty(error)); -error_free(error); -goto err; +/* disk I/O throttling */ +if (throttle_enabled(cfg)) { +bdrv_io_limits_enable(bs); +bdrv_set_io_limits(bs, cfg); } if (bdrv_key_required(bs)) { autostart = 0; } -QDECREF(bs_opts); +err_no_bs_opts: qemu_opts_del(opts); - return blk; -err: -blk_unref(blk); early_err: qemu_opts_del(opts); err_no_opts: diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index f497c57..ecf0a31 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -5,43 +5,43 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR === Unknown option === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt= -QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: could not open disk image
[Qemu-devel] [PATCH v3 08/14] qemu-nbd: Use blk_new_open() in main()
Signed-off-by: Max Reitz mre...@redhat.com --- qemu-nbd.c | 25 + 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index d222512..fdc9590 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -386,7 +386,6 @@ int main(int argc, char **argv) { BlockBackend *blk; BlockDriverState *bs; -BlockDriver *drv; off_t dev_offset = 0; uint32_t nbdflags = 0; bool disconnect = false; @@ -429,7 +428,7 @@ int main(int argc, char **argv) char *end; int flags = BDRV_O_RDWR; int partition = -1; -int ret; +int ret = 0; int fd; bool seen_cache = false; bool seen_discard = false; @@ -440,6 +439,7 @@ int main(int argc, char **argv) const char *fmt = NULL; Error *local_err = NULL; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; +QDict *options = NULL; /* The client thread uses SIGTERM to interrupt the server. A signal * handler ensures that qemu-nbd -v -c exits with a nice status code. @@ -684,24 +684,17 @@ int main(int argc, char **argv) atexit(bdrv_close_all); if (fmt) { -drv = bdrv_find_format(fmt); -if (!drv) { -errx(EXIT_FAILURE, Unknown file format '%s', fmt); -} -} else { -drv = NULL; +options = qdict_new(); +qdict_put_obj(options, driver, QOBJECT(qstring_from_str(fmt))); } -blk = blk_new_with_bs(hda, error_abort); -bs = blk_bs(blk); - srcpath = argv[optind]; -ret = bdrv_open(bs, srcpath, NULL, NULL, flags, drv, local_err); -if (ret 0) { -errno = -ret; -err(EXIT_FAILURE, Failed to bdrv_open '%s': %s, argv[optind], -error_get_pretty(local_err)); +blk = blk_new_open(hda, srcpath, NULL, options, flags, local_err); +if (!blk) { +errx(EXIT_FAILURE, Failed to blk_new_open '%s': %s, argv[optind], + error_get_pretty(local_err)); } +bs = blk_bs(blk); if (sn_opts) { ret = bdrv_snapshot_load_tmp(bs, -- 2.1.0
Re: [Qemu-devel] [PATCH 2/2] target-openrisc: Add l.lwa/l.swa support
Hi Jia. On Mon, Jan 26, 2015 at 9:50 AM, Jia Liu pro...@gmail.com wrote: Is it a new instruction new added into OpenRISC? Yes. Please see the latest architecture specification for details. It should be blank lines in here in [patch 1/2]. Care to elaborate why?
[Qemu-devel] [PATCH v2 2/4] target-tricore: Add instructions of RR2 opcode format
Signed-off-by: Bastian Koppelmann kbast...@mail.uni-paderborn.de --- target-tricore/translate.c | 37 + 1 file changed, 37 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 804d181..8f9679e 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -4957,6 +4957,39 @@ static void decode_rr1_mulq(CPUTriCoreState *env, DisasContext *ctx) tcg_temp_free(temp2); } +/* RR2 format */ +static void decode_rr2_mul(CPUTriCoreState *env, DisasContext *ctx) +{ +uint32_t op2; +int r1, r2, r3; + +op2 = MASK_OP_RR2_OP2(ctx-opcode); +r1 = MASK_OP_RR2_S1(ctx-opcode); +r2 = MASK_OP_RR2_S2(ctx-opcode); +r3 = MASK_OP_RR2_D(ctx-opcode); +switch (op2) { +case OPC2_32_RR2_MUL_32: +gen_mul_i32s(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); +break; +case OPC2_32_RR2_MUL_64: +gen_mul_i64s(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], + cpu_gpr_d[r2]); +break; +case OPC2_32_RR2_MULS_32: +gen_helper_mul_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], +cpu_gpr_d[r2]); +break; +case OPC2_32_RR2_MUL_U_64: +gen_mul_i64u(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], + cpu_gpr_d[r2]); +break; +case OPC2_32_RR2_MULS_U_32: +gen_helper_mul_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], +cpu_gpr_d[r2]); +break; +} +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -5217,6 +5250,10 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_RR1_MULQ: decode_rr1_mulq(env, ctx); break; +/* RR2 format */ +case OPCM_32_RR2_MUL: +decode_rr2_mul(env, ctx); +break; } } -- 2.2.2
[Qemu-devel] [Bug 1368815] Change abandoned on cinder (master)
Change abandoned by Mike Perez (thin...@gmail.com) on branch: master Review: https://review.openstack.org/143575 Reason: 1 month, no update. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1368815 Title: qemu-img convert intermittently corrupts output images Status in Cinder: In Progress Status in OpenStack Compute (Nova): In Progress Status in QEMU: In Progress Status in qemu package in Ubuntu: Fix Released Status in qemu source package in Trusty: Fix Released Status in qemu source package in Utopic: Fix Released Status in qemu source package in Vivid: Fix Released Bug description: == Impact: occasional image corruption (any format on local filesystem) Test case: see the qemu-img command below Regression potential: this cherrypicks a patch from upstream to a not-insignificantly older qemu source tree. While the cherrypick seems sane, it's possible that there are subtle interactions with the other delta. I'd really like for a full qa-regression-test qemu testcase to be run against this package. == -- Found in releases qemu-2.0.0, qemu-2.0.2, qemu-2.1.0. Tested on Ubuntu 14.04 using Ext4 filesystems. The command qemu-img convert -O raw inputimage.qcow2 outputimage.raw intermittently creates corrupted output images, when the input image is not yet fully synchronized to disk. While the issue has actually been discovered in operation of of OpenStack nova, it can be reproduced easily on command line using cat $SRC_PATH $TMP_PATH $QEMU_IMG_PATH convert -O raw $TMP_PATH $DST_PATH cksum $DST_PATH on filesystems exposing this behavior. (The difficult part of this exercise is to prepare a filesystem to reliably trigger this race. On my test machine some filesystems are affected while other aren't, and unfortunately I haven't found the relevant difference between them, yet. Possible it's timing issues completely out of userspace control ...) The root cause, however, is the same as in http://lists.gnu.org/archive/html/coreutils/2011-04/msg00069.html and it can be solved the same way as suggested in http://lists.gnu.org/archive/html/coreutils/2011-04/msg00102.html In qemu, file block/raw-posix.c use the FIEMAP_FLAG_SYNC, i.e change f.fm.fm_flags = 0; to f.fm.fm_flags = FIEMAP_FLAG_SYNC; As discussed in the thread mentioned above, retrieving a page cache coherent map of file extents is possible only after fsync on that file. See also https://bugs.launchpad.net/nova/+bug/1350766 In that bug report filed against nova, fsync had been suggested to be performed by the framework invoking qemu-img. However, as the choice of fiemap -- implying this otherwise unneeded fsync of a temporary file -- is not made by the caller but by qemu-img, I agree with the nova bug reviewer's objection to put it into nova. The fsync should instead be triggered by qemu-img utilizing the FIEMAP_FLAG_SYNC, specifically intended for that purpose. To manage notifications about this bug go to: https://bugs.launchpad.net/cinder/+bug/1368815/+subscriptions
[Qemu-devel] [PATCH 12/50] block: Move I/O status and error actions into BB
These options are only relevant for the user of a whole BDS tree (like a guest device or a block job) and should thus be moved into the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- block.c| 125 - block/backup.c | 17 -- block/block-backend.c | 116 -- block/commit.c | 3 +- block/mirror.c | 17 -- block/qapi.c | 4 +- block/stream.c | 3 +- blockdev.c | 6 +- blockjob.c | 5 +- include/block/block.h | 11 include/block/block_int.h | 6 -- include/sysemu/block-backend.h | 7 +++ qmp.c | 6 +- 13 files changed, 158 insertions(+), 168 deletions(-) diff --git a/block.c b/block.c index 17e4ee3..9a0a510 100644 --- a/block.c +++ b/block.c @@ -371,7 +371,6 @@ BlockDriverState *bdrv_new(void) for (i = 0; i BLOCK_OP_TYPE_MAX; i++) { QLIST_INIT(bs-op_blockers[i]); } -bdrv_iostatus_disable(bs); notifier_list_init(bs-close_notifiers); notifier_with_return_list_init(bs-before_write_notifiers); qemu_co_queue_init(bs-throttled_reqs[0]); @@ -2050,14 +2049,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, bs_dest-throttled_reqs[1] = bs_src-throttled_reqs[1]; bs_dest-io_limits_enabled = bs_src-io_limits_enabled; -/* r/w error */ -bs_dest-on_read_error = bs_src-on_read_error; -bs_dest-on_write_error = bs_src-on_write_error; - -/* i/o status */ -bs_dest-iostatus_enabled = bs_src-iostatus_enabled; -bs_dest-iostatus = bs_src-iostatus; - /* dirty bitmap */ bs_dest-dirty_bitmaps = bs_src-dirty_bitmaps; @@ -3562,82 +3553,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr) *nb_sectors_ptr = nb_sectors 0 ? 0 : nb_sectors; } -void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error, - BlockdevOnError on_write_error) -{ -bs-on_read_error = on_read_error; -bs-on_write_error = on_write_error; -} - -BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read) -{ -return is_read ? bs-on_read_error : bs-on_write_error; -} - -BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error) -{ -BlockdevOnError on_err = is_read ? bs-on_read_error : bs-on_write_error; - -switch (on_err) { -case BLOCKDEV_ON_ERROR_ENOSPC: -return (error == ENOSPC) ? - BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT; -case BLOCKDEV_ON_ERROR_STOP: -return BLOCK_ERROR_ACTION_STOP; -case BLOCKDEV_ON_ERROR_REPORT: -return BLOCK_ERROR_ACTION_REPORT; -case BLOCKDEV_ON_ERROR_IGNORE: -return BLOCK_ERROR_ACTION_IGNORE; -default: -abort(); -} -} - -static void send_qmp_error_event(BlockDriverState *bs, - BlockErrorAction action, - bool is_read, int error) -{ -IoOperationType optype; - -optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE; -qapi_event_send_block_io_error(bdrv_get_device_name(bs), optype, action, - bdrv_iostatus_is_enabled(bs), - error == ENOSPC, strerror(error), - error_abort); -} - -/* This is done by device models because, while the block layer knows - * about the error, it does not know whether an operation comes from - * the device or the block layer (from a job, for example). - */ -void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action, - bool is_read, int error) -{ -assert(error = 0); - -if (action == BLOCK_ERROR_ACTION_STOP) { -/* First set the iostatus, so that info block returns an iostatus - * that matches the events raised so far (an additional error iostatus - * is fine, but not a lost one). - */ -bdrv_iostatus_set_err(bs, error); - -/* Then raise the request to stop the VM and the event. - * qemu_system_vmstop_request_prepare has two effects. First, - * it ensures that the STOP event always comes after the - * BLOCK_IO_ERROR event. Second, it ensures that even if management - * can observe the STOP event and do a cont before the STOP - * event is issued, the VM will not stop. In this case, vm_start() - * also ensures that the STOP/RESUME pair of events is emitted. - */ -qemu_system_vmstop_request_prepare(); -send_qmp_error_event(bs, action, is_read, error); -qemu_system_vmstop_request(RUN_STATE_IO_ERROR); -} else { -send_qmp_error_event(bs, action, is_read, error); -} -} - int bdrv_is_read_only(BlockDriverState *bs)
[Qemu-devel] [PATCH 22/50] blockdev: Check BB validity in drive-backup TA
In the drive-backup transaction, call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index 012c603..5f7eef5 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1507,23 +1507,28 @@ typedef struct DriveBackupState { static void drive_backup_prepare(BlkTransactionState *common, Error **errp) { DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); -BlockDriverState *bs; +BlockBackend *blk; DriveBackup *backup; Error *local_err = NULL; assert(common-action-kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); backup = common-action-drive_backup; -bs = bdrv_find(backup-device); -if (!bs) { +blk = blk_by_name(backup-device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, backup-device); return; } /* AioContext is released in .clean() */ -state-aio_context = bdrv_get_aio_context(bs); +state-aio_context = blk_get_aio_context(blk); aio_context_acquire(state-aio_context); +if (!blk_is_available(blk)) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, backup-device); +return; +} + qmp_drive_backup(backup-device, backup-target, backup-has_format, backup-format, backup-sync, @@ -1537,7 +1542,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) return; } -state-bs = bs; +state-bs = blk_bs(blk); state-job = state-bs-job; } -- 2.1.0
[Qemu-devel] [PATCH 31/50] block: Add blk_insert_bs()
This function associates the given BlockDriverState with the given BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 16 include/sysemu/block-backend.h | 1 + 2 files changed, 17 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index 760558f..656ebfc 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -312,6 +312,22 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) } /* + * Associates a new BlockDriverState with @blk. + */ +void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs) +{ +if (bs-blk == blk) { +return; +} + +assert(!blk-bs); +assert(!bs-blk); +bdrv_ref(bs); +blk-bs = bs; +bs-blk = blk; +} + +/* * Attach device model @dev to @blk. * Return 0 on success, -EBUSY when a device model is attached already. */ diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index afb62e1..b6cf5bf 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -72,6 +72,7 @@ BlockBackend *blk_by_name(const char *name); BlockBackend *blk_next(BlockBackend *blk); BlockDriverState *blk_bs(BlockBackend *blk); +void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs); void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk); -- 2.1.0
[Qemu-devel] [PATCH 37/50] block: Add blk_remove_bs()
This function removes the BlockDriverState associated with the given BlockBackend from that BB and sets the BDS pointer in the BB to NULL. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 22 +- include/sysemu/block-backend.h | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/block/block-backend.c b/block/block-backend.c index 656ebfc..d2c1bff 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -312,6 +312,22 @@ void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk) } /* + * Disassociates the currently associated BlockDriverState from @blk. + */ +void blk_remove_bs(BlockBackend *blk) +{ +if (!blk-bs) { +return; +} + +blk_update_root_state(blk); + +bdrv_unref(blk-bs); +blk-bs-blk = NULL; +blk-bs = NULL; +} + +/* * Associates a new BlockDriverState with @blk. */ void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs) @@ -321,9 +337,13 @@ void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs) } assert(!blk-bs); -assert(!bs-blk); bdrv_ref(bs); blk-bs = bs; + +if (bs-blk) { +blk_remove_bs(bs-blk); +} + bs-blk = blk; } diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index b6cf5bf..c8b47f7 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -72,6 +72,7 @@ BlockBackend *blk_by_name(const char *name); BlockBackend *blk_next(BlockBackend *blk); BlockDriverState *blk_bs(BlockBackend *blk); +void blk_remove_bs(BlockBackend *blk); void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs); void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk); -- 2.1.0
[Qemu-devel] [PATCH 40/50] blockdev: Add blockdev-remove-medium
Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 25 + qapi/block-core.json | 13 + qmp-commands.hx | 43 +++ 3 files changed, 81 insertions(+) diff --git a/blockdev.c b/blockdev.c index d6a3fdf..17785b8 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2063,6 +2063,31 @@ void qmp_blockdev_close_tray(const char *device, Error **errp) blk_dev_change_media_cb(blk, true); } +void qmp_blockdev_remove_medium(const char *device, Error **errp) +{ +BlockBackend *blk; + +blk = blk_by_name(device); +if (!blk) { +error_set(errp, QERR_DEVICE_NOT_FOUND, device); +return; +} + +if (!blk_dev_has_removable_media(blk)) { +error_setg(errp, Device '%s' is not removable, device); +return; +} + +if (!blk_dev_is_tray_open(blk)) { +error_setg(errp, Tray of device '%s' is not open, device); +return; +} + +if (blk_bs(blk)) { +blk_remove_bs(blk); +} +} + /* throttling disk I/O limits */ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, int64_t bps_wr, diff --git a/qapi/block-core.json b/qapi/block-core.json index 802734a..1ace69d 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1753,6 +1753,19 @@ { 'command': 'blockdev-close-tray', 'data': { 'device': 'str' } } +## +# @blockdev-remove-medium: +# +# Removes a medium (a block driver state tree) from a block device. That block +# device's tray must currently be open. +# +# @device: block device name +# +# Since: 2.3 +## +{ 'command': 'blockdev-remove-medium', + 'data': { 'device': 'str' } } + ## # @BlockErrorAction diff --git a/qmp-commands.hx b/qmp-commands.hx index 5927507..3d5c10c 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3711,6 +3711,49 @@ Example (1): EQMP { +.name = blockdev-remove-medium, +.args_type = device:s, +.mhandler.cmd_new = qmp_marshal_input_blockdev_remove_medium, +}, + +SQMP +blockdev-remove-medium +-- + +Removes a medium (a block driver state tree) from a block device. That block +device's tray must currently be open. + +Arguments: + +- device: block device name (json-string) + +Example (1): + +- { execute: blockdev-remove-medium, + arguments: { device: ide1-cd0 } } + +- { error: { class: GenericError, +desc: Tray of device 'ide1-cd0' is not open } } + +- { execute: blockdev-open-tray, + arguments: { device: ide1-cd0 } } + +- { timestamp: { seconds: 1418751627, +microseconds: 549958 }, + event: DEVICE_TRAY_MOVED, + data: { device: ide1-cd0, + tray-open: true } } + +- { return: {} } + +- { execute: blockdev-remove-medium, + arguments: { device: ide1-cd0 } } + +- { return: {} } + +EQMP + +{ .name = query-named-block-nodes, .args_type = , .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes, -- 2.1.0
[Qemu-devel] [PATCH 42/50] blockdev: Implement eject with basic operations
Implement 'eject' by calling blockdev-open-tray and blockdev-remove-medium. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index e4588b3..0b204eb 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1865,15 +1865,15 @@ out: void qmp_eject(const char *device, bool has_force, bool force, Error **errp) { -BlockBackend *blk; +Error *local_err = NULL; -blk = blk_by_name(device); -if (!blk) { -error_set(errp, QERR_DEVICE_NOT_FOUND, device); +qmp_blockdev_open_tray(device, has_force, force, local_err); +if (local_err) { +error_propagate(errp, local_err); return; } -eject_device(blk, force, errp); +qmp_blockdev_remove_medium(device, errp); } void qmp_block_passwd(bool has_device, const char *device, -- 2.1.0
[Qemu-devel] [PATCH] target-mips: ll and lld cause AdEL exception for unaligned address
Signed-off-by: Leon Alrae leon.al...@imgtec.com --- target-mips/op_helper.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index ea7d95f..73a8e45 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -304,16 +304,20 @@ static inline hwaddr do_translate_address(CPUMIPSState *env, } } -#define HELPER_LD_ATOMIC(name, insn) \ +#define HELPER_LD_ATOMIC(name, insn, almask) \ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \ { \ +if (arg almask) { \ +env-CP0_BadVAddr = arg; \ +helper_raise_exception(env, EXCP_AdEL); \ +} \ env-lladdr = do_translate_address(env, arg, 0); \ env-llval = do_##insn(env, arg, mem_idx);\ return env-llval;\ } -HELPER_LD_ATOMIC(ll, lw) +HELPER_LD_ATOMIC(ll, lw, 0x3) #ifdef TARGET_MIPS64 -HELPER_LD_ATOMIC(lld, ld) +HELPER_LD_ATOMIC(lld, ld, 0x7) #endif #undef HELPER_LD_ATOMIC -- 2.1.0
[Qemu-devel] [PATCH 48/50] hmp: Add read-only option to change command
Expose the new read-only option of 'blockdev-change-medium' for the 'change' HMP command. Signed-off-by: Max Reitz mre...@redhat.com Reviewed-by: Eric Blake ebl...@redhat.com --- hmp-commands.hx | 20 +--- hmp.c | 21 - 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index e37bc8b..70cb7d7 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -196,8 +196,8 @@ ETEXI { .name = change, -.args_type = device:B,target:F,arg:s?, -.params = device filename [format], +.args_type = device:B,target:F,arg:s?,read-only:s?, +.params = device filename [format [read-only]], .help = change a removable medium, optional format, .mhandler.cmd = hmp_change, }, @@ -209,7 +209,7 @@ STEXI Change the configuration of a device. @table @option -@item change @var{diskdevice} @var{filename} [@var{format}] +@item change @var{diskdevice} @var{filename} [@var{format} [@var{read-only}]] Change the medium for a removable disk device to point to @var{filename}. eg @example @@ -218,6 +218,20 @@ Change the medium for a removable disk device to point to @var{filename}. eg @var{format} is optional. +@var{read-only} may be used to change the read-only status of the device. It +accepts the following values: + +@table @var +@item retain +Retains the current status; this is the default. + +@item ro +Makes the device read-only. + +@item rw +Makes the device writable. +@end table + @item change vnc @var{display},@var{options} Change the configuration of the VNC server. The valid syntax for @var{display} and @var{options} are described at @ref{sec_invocation}. eg diff --git a/hmp.c b/hmp.c index dbf0947..8e75771 100644 --- a/hmp.c +++ b/hmp.c @@ -24,6 +24,7 @@ #include monitor/monitor.h #include qapi/opts-visitor.h #include qapi/string-output-visitor.h +#include qapi/util.h #include qapi-visit.h #include ui/console.h #include block/qapi.h @@ -1178,9 +1179,15 @@ void hmp_change(Monitor *mon, const QDict *qdict) const char *device = qdict_get_str(qdict, device); const char *target = qdict_get_str(qdict, target); const char *arg = qdict_get_try_str(qdict, arg); +const char *read_only = qdict_get_try_str(qdict, read-only); +BlockdevChangeReadOnlyMode read_only_mode = 0; Error *err = NULL; if (strcmp(device, vnc) == 0) { +if (read_only) { +monitor_printf(mon, Parameter 'read-only' is invalid for VNC); +return; +} if (strcmp(target, passwd) == 0 || strcmp(target, password) == 0) { if (!arg) { @@ -1190,7 +1197,19 @@ void hmp_change(Monitor *mon, const QDict *qdict) } qmp_change(vnc, target, !!arg, arg, err); } else { -qmp_blockdev_change_medium(device, target, !!arg, arg, false, 0, err); +if (read_only) { +read_only_mode = +qapi_enum_parse(BlockdevChangeReadOnlyMode_lookup, +read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_MAX, +BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, err); +if (err) { +hmp_handle_error(mon, err); +return; +} +} + +qmp_blockdev_change_medium(device, target, !!arg, arg, + !!read_only, read_only_mode, err); if (err error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { error_free(err); -- 2.1.0
[Qemu-devel] [PATCH v3 11/14] qemu-io: Use BlockBackend
qemu-io should behave like a guest, therefore it should use BlockBackend to access the block layer. There are a couple of places where that is infeasible: First, the bdrv_debug_* functions could theoretically be mirrored in the BlockBackend, but since these are functions internal to the block layer, they should not be visible externally (qemu-io as a test tool is excempt from this). Second, bdrv_get_info() and bdrv_get_specific_info() work on a single BDS alone, therefore they should stay BDS-specific. Third, bdrv_is_allocated() mainly works on a single BDS as well. Some data may be passed through from the BDS's file (if sectors which are apparently allocated in the file are not really allocated there but just zero). Signed-off-by: Max Reitz mre...@redhat.com --- hmp.c | 9 ++- include/qemu-io.h | 4 +- qemu-io-cmds.c| 238 -- qemu-io.c | 12 +-- 4 files changed, 138 insertions(+), 125 deletions(-) diff --git a/hmp.c b/hmp.c index 481be80..f806387 100644 --- a/hmp.c +++ b/hmp.c @@ -16,6 +16,7 @@ #include hmp.h #include net/net.h #include sysemu/char.h +#include sysemu/block-backend.h #include qemu/option.h #include qemu/timer.h #include qmp-commands.h @@ -1714,14 +1715,14 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict) void hmp_qemu_io(Monitor *mon, const QDict *qdict) { -BlockDriverState *bs; +BlockBackend *blk; const char* device = qdict_get_str(qdict, device); const char* command = qdict_get_str(qdict, command); Error *err = NULL; -bs = bdrv_find(device); -if (bs) { -qemuio_command(bs, command); +blk = blk_by_name(device); +if (blk) { +qemuio_command(blk, command); } else { error_set(err, QERR_DEVICE_NOT_FOUND, device); } diff --git a/include/qemu-io.h b/include/qemu-io.h index 5d6006f..4d402b9 100644 --- a/include/qemu-io.h +++ b/include/qemu-io.h @@ -22,7 +22,7 @@ #define CMD_FLAG_GLOBAL ((int)0x8000) /* don't iterate args */ -typedef int (*cfunc_t)(BlockDriverState *bs, int argc, char **argv); +typedef int (*cfunc_t)(BlockBackend *blk, int argc, char **argv); typedef void (*helpfunc_t)(void); typedef struct cmdinfo { @@ -40,7 +40,7 @@ typedef struct cmdinfo { extern bool qemuio_misalign; -bool qemuio_command(BlockDriverState *bs, const char *cmd); +bool qemuio_command(BlockBackend *blk, const char *cmd); void qemuio_add_command(const cmdinfo_t *ci); int qemuio_command_usage(const cmdinfo_t *ci); diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index e708552..fa21fc8 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -9,7 +9,9 @@ */ #include qemu-io.h -#include block/block_int.h +#include sysemu/block-backend.h +#include block/block.h +#include block/block_int.h /* for info_f() */ #include block/qapi.h #include qemu/main-loop.h #include qemu/timer.h @@ -40,24 +42,24 @@ int qemuio_command_usage(const cmdinfo_t *ci) return 0; } -static int init_check_command(BlockDriverState *bs, const cmdinfo_t *ct) +static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct) { if (ct-flags CMD_FLAG_GLOBAL) { return 1; } -if (!(ct-flags CMD_NOFILE_OK) !bs) { +if (!(ct-flags CMD_NOFILE_OK) !blk) { fprintf(stderr, no file open, try 'help open'\n); return 0; } return 1; } -static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc, +static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc, char **argv) { char *cmd = argv[0]; -if (!init_check_command(bs, ct)) { +if (!init_check_command(blk, ct)) { return 0; } @@ -78,7 +80,7 @@ static int command(BlockDriverState *bs, const cmdinfo_t *ct, int argc, return 0; } optind = 0; -return ct-cfunc(bs, argc, argv); +return ct-cfunc(blk, argc, argv); } static const cmdinfo_t *find_command(const char *cmd) @@ -267,14 +269,14 @@ static int parse_pattern(const char *arg) */ #define MISALIGN_OFFSET 16 -static void *qemu_io_alloc(BlockDriverState *bs, size_t len, int pattern) +static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern) { void *buf; if (qemuio_misalign) { len += MISALIGN_OFFSET; } -buf = qemu_blockalign(bs, len); +buf = blk_blockalign(blk, len); memset(buf, pattern, len); if (qemuio_misalign) { buf += MISALIGN_OFFSET; @@ -340,7 +342,7 @@ static void print_report(const char *op, struct timeval *t, int64_t offset, * vector matching it. */ static void * -create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov, +create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov, int pattern) { size_t *sizes = g_new0(size_t, nr_iov); @@ -377,7 +379,7 @@ create_iovec(BlockDriverState *bs, QEMUIOVector *qiov, char **argv, int nr_iov,
[Qemu-devel] [PATCH 03/50] hw/block/fdc: Implement tray status
The tray of an FDD is open iff there is no medium inserted (there are only two states for an FDD: medium inserted or no medium inserted). This results in the tray being reported as open if qemu has been started with the default floppy drive, which breaks some tests. Fix them. Signed-off-by: Max Reitz mre...@redhat.com --- hw/block/fdc.c | 20 +--- tests/fdc-test.c | 4 +--- tests/qemu-iotests/067.out | 60 +++--- tests/qemu-iotests/071.out | 2 -- tests/qemu-iotests/081.out | 1 - tests/qemu-iotests/087.out | 5 6 files changed, 26 insertions(+), 66 deletions(-) diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 2bf87c9..0c5a6b4 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -192,6 +192,8 @@ typedef struct FDrive { uint8_t ro; /* Is read-only */ uint8_t media_changed;/* Is media changed */ uint8_t media_rate; /* Data rate of medium*/ + +bool media_inserted; /* Is there a medium in the tray */ } FDrive; static void fd_init(FDrive *drv) @@ -261,7 +263,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, #endif drv-head = head; if (drv-track != track) { -if (drv-blk != NULL blk_is_inserted(drv-blk)) { +if (drv-media_inserted) { drv-media_changed = 0; } ret = 1; @@ -270,7 +272,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, drv-sect = sect; } -if (drv-blk == NULL || !blk_is_inserted(drv-blk)) { +if (!drv-media_inserted) { ret = 2; } @@ -296,7 +298,7 @@ static void fd_revalidate(FDrive *drv) ro = blk_is_read_only(drv-blk); pick_geometry(drv-blk, nb_heads, max_track, last_sect, drv-drive, drive, rate); -if (!blk_is_inserted(drv-blk)) { +if (!drv-media_inserted) { FLOPPY_DPRINTF(No disk in drive\n); } else { FLOPPY_DPRINTF(Floppy disk (%d h %d t %d s) %s\n, nb_heads, @@ -2062,12 +2064,21 @@ static void fdctrl_change_cb(void *opaque, bool load) { FDrive *drive = opaque; +drive-media_inserted = load drive-blk blk_is_inserted(drive-blk); + drive-media_changed = 1; fd_revalidate(drive); } +static bool fdctrl_is_tray_open(void *opaque) +{ +FDrive *drive = opaque; +return !drive-media_inserted; +} + static const BlockDevOps fdctrl_block_ops = { .change_media_cb = fdctrl_change_cb, +.is_tray_open = fdctrl_is_tray_open, }; /* Init functions */ @@ -2095,6 +2106,9 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp) fdctrl_change_cb(drive, 0); if (drive-blk) { blk_set_dev_ops(drive-blk, fdctrl_block_ops, drive); +if (blk_is_inserted(drive-blk)) { +drive-media_inserted = true; +} } } } diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 3c6c83c..f287c10 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -293,9 +293,7 @@ static void test_media_insert(void) qmp_discard_response({'execute':'change', 'arguments':{ 'device':'floppy0', 'target': %s, 'arg': 'raw' }}, test_image); -qmp_discard_response(); /* ignore event - (FIXME open - open transition?!) */ -qmp_discard_response(); /* ignore event */ +qmp_discard_response(); /* ignore event (open - close) */ dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 00b3eae..42bae32 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -69,7 +69,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti device: floppy0, locked: false, removable: true, -tray_open: false, +tray_open: true, type: unknown }, { @@ -131,7 +131,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti device: floppy0, locked: false, removable: true, -tray_open: false, +tray_open: true, type: unknown }, { @@ -165,17 +165,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti tray-open: true } } -{ -timestamp: { -seconds: TIMESTAMP, -microseconds: TIMESTAMP -}, -event: DEVICE_TRAY_MOVED, -data: { -device: floppy0, -tray-open: true -} -} === -drive/device_add and device_del === @@ -246,7 +235,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk device: floppy0, locked: false, removable: true, -
[Qemu-devel] [PATCH 06/50] block: Add blk_is_available()
blk_is_available() returns true iff the BDS is inserted (which means blk_bs() is not NULL and bdrv_is_inserted() returns true) and if the tray of the guest device is closed. blk_is_inserted() is changed to return true only if blk_bs() is not NULL. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 7 ++- include/sysemu/block-backend.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/block/block-backend.c b/block/block-backend.c index 4c40747..4a2428e 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -738,7 +738,12 @@ void blk_invalidate_cache(BlockBackend *blk, Error **errp) int blk_is_inserted(BlockBackend *blk) { -return bdrv_is_inserted(blk-bs); +return blk-bs bdrv_is_inserted(blk-bs); +} + +bool blk_is_available(BlockBackend *blk) +{ +return blk_is_inserted(blk) !blk_dev_is_tray_open(blk); } void blk_lock_medium(BlockBackend *blk, bool locked) diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index f39bb5c..f91f3c7 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -127,6 +127,7 @@ int blk_enable_write_cache(BlockBackend *blk); void blk_set_enable_write_cache(BlockBackend *blk, bool wce); void blk_invalidate_cache(BlockBackend *blk, Error **errp); int blk_is_inserted(BlockBackend *blk); +bool blk_is_available(BlockBackend *blk); void blk_lock_medium(BlockBackend *blk, bool locked); void blk_eject(BlockBackend *blk, bool eject_flag); int blk_get_flags(BlockBackend *blk); -- 2.1.0
[Qemu-devel] [PATCH 07/50] block: Make bdrv_is_inserted() recursive
If bdrv_is_inserted() is called on the top level BDS, it should make sure all nodes in the BDS tree are actually inserted. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index 4a5f8fc..aff7682 100644 --- a/block.c +++ b/block.c @@ -5208,11 +5208,12 @@ int bdrv_is_inserted(BlockDriverState *bs) { BlockDriver *drv = bs-drv; -if (!drv) +if (!drv) { return 0; -if (!drv-bdrv_is_inserted) -return 1; -return drv-bdrv_is_inserted(bs); +} +return (!drv-bdrv_is_inserted || drv-bdrv_is_inserted(bs)) + (!bs-file || bdrv_is_inserted(bs-file)) + (!bs-backing_hd|| bdrv_is_inserted(bs-backing_hd)); } /** -- 2.1.0
[Qemu-devel] [PATCH 27/50] blockdev: Check BB validity in blockdev-backup
Call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/blockdev.c b/blockdev.c index 9476c72..e335d06 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2452,6 +2452,7 @@ void qmp_blockdev_backup(const char *device, const char *target, BlockdevOnError on_target_error, Error **errp) { +BlockBackend *blk; BlockDriverState *bs; BlockDriverState *target_bs; Error *local_err = NULL; @@ -2467,15 +2468,21 @@ void qmp_blockdev_backup(const char *device, const char *target, on_target_error = BLOCKDEV_ON_ERROR_REPORT; } -bs = bdrv_find(device); -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } -aio_context = bdrv_get_aio_context(bs); +aio_context = blk_get_aio_context(blk); aio_context_acquire(aio_context); +if (!blk_is_available(blk)) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); +goto out; +} +bs = blk_bs(blk); + target_bs = bdrv_find(target); if (!target_bs) { error_set(errp, QERR_DEVICE_NOT_FOUND, target); -- 2.1.0
[Qemu-devel] [PATCH 10/50] block: Remove wr_highest_offset from BlockAcctStats
BlockAcctStats contains statistics about the data transferred from and to the device; wr_highest_offset does not fit in with the rest. Furthermore, those statistics are supposed to be specific for a certain device and not necessarily for a BDS (see the comment above bdrv_get_stats()); on the other hand, wr_highest_offset may be a rather important information to know for each BDS. When BlockAcctStats is finally removed from the BDS, we will want to keep wr_highest_offset in the BDS. Signed-off-by: Max Reitz mre...@redhat.com --- block.c| 4 +++- block/accounting.c | 9 - block/qapi.c | 4 ++-- include/block/accounting.h | 3 --- include/block/block_int.h | 3 +++ 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index eff92ca..5db71c6 100644 --- a/block.c +++ b/block.c @@ -3312,7 +3312,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, bdrv_set_dirty(bs, sector_num, nb_sectors); -block_acct_highest_sector(bs-stats, sector_num, nb_sectors); +if (bs-wr_highest_sector sector_num + nb_sectors - 1) { +bs-wr_highest_sector = sector_num + nb_sectors - 1; +} if (ret = 0) { bs-total_sectors = MAX(bs-total_sectors, sector_num + nb_sectors); diff --git a/block/accounting.c b/block/accounting.c index 18102f0..c77b6c2 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -45,12 +45,3 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie) stats-total_time_ns[cookie-type] += qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - cookie-start_time_ns; } - - -void block_acct_highest_sector(BlockAcctStats *stats, int64_t sector_num, - unsigned int nb_sectors) -{ -if (stats-wr_highest_sector sector_num + nb_sectors - 1) { -stats-wr_highest_sector = sector_num + nb_sectors - 1; -} -} diff --git a/block/qapi.c b/block/qapi.c index 8c3b9d9..4e97574 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -338,13 +338,13 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs, s-stats-wr_bytes = bs-stats.nr_bytes[BLOCK_ACCT_WRITE]; s-stats-rd_operations = bs-stats.nr_ops[BLOCK_ACCT_READ]; s-stats-wr_operations = bs-stats.nr_ops[BLOCK_ACCT_WRITE]; -s-stats-wr_highest_offset = -bs-stats.wr_highest_sector * BDRV_SECTOR_SIZE; s-stats-flush_operations = bs-stats.nr_ops[BLOCK_ACCT_FLUSH]; s-stats-wr_total_time_ns = bs-stats.total_time_ns[BLOCK_ACCT_WRITE]; s-stats-rd_total_time_ns = bs-stats.total_time_ns[BLOCK_ACCT_READ]; s-stats-flush_total_time_ns = bs-stats.total_time_ns[BLOCK_ACCT_FLUSH]; +s-stats-wr_highest_offset = bs-wr_highest_sector * BDRV_SECTOR_SIZE; + if (bs-file) { s-has_parent = true; s-parent = bdrv_query_stats(bs-file, query_backing); diff --git a/include/block/accounting.h b/include/block/accounting.h index 50b42b3..9089b67 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -39,7 +39,6 @@ typedef struct BlockAcctStats { uint64_t nr_bytes[BLOCK_MAX_IOTYPE]; uint64_t nr_ops[BLOCK_MAX_IOTYPE]; uint64_t total_time_ns[BLOCK_MAX_IOTYPE]; -uint64_t wr_highest_sector; } BlockAcctStats; typedef struct BlockAcctCookie { @@ -51,7 +50,5 @@ typedef struct BlockAcctCookie { void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, int64_t bytes, enum BlockAcctType type); void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie); -void block_acct_highest_sector(BlockAcctStats *stats, int64_t sector_num, - unsigned int nb_sectors); #endif diff --git a/include/block/block_int.h b/include/block/block_int.h index c6ab73a..e309d8a 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -366,6 +366,9 @@ struct BlockDriverState { /* I/O stats (display with info blockstats). */ BlockAcctStats stats; +/* Highest sector index written to */ +uint64_t wr_highest_sector; + /* I/O Limits */ BlockLimits bl; -- 2.1.0
[Qemu-devel] [PATCH 18/50] block: Respect empty BB in bdrv_query_info()
Signed-off-by: Max Reitz mre...@redhat.com --- block/qapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/qapi.c b/block/qapi.c index 9a44d40..db42a6e 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -282,12 +282,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, info-io_status = blk_iostatus(blk); } -if (!QLIST_EMPTY(bs-dirty_bitmaps)) { +if (bs !QLIST_EMPTY(bs-dirty_bitmaps)) { info-has_dirty_bitmaps = true; info-dirty_bitmaps = bdrv_query_dirty_bitmaps(bs); } -if (bs-drv) { +if (bs bs-drv) { info-has_inserted = true; info-inserted = bdrv_block_device_info(bs); -- 2.1.0
[Qemu-devel] [PATCH 26/50] blockdev: Check BB validity in drive-backup
Call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend (instead of calling bdrv_is_inserted() after bdrv_find()). Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 431afcd..9476c72 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2323,6 +2323,7 @@ void qmp_drive_backup(const char *device, const char *target, bool has_on_target_error, BlockdevOnError on_target_error, Error **errp) { +BlockBackend *blk; BlockDriverState *bs; BlockDriverState *target_bs; BlockDriverState *source = NULL; @@ -2346,21 +2347,22 @@ void qmp_drive_backup(const char *device, const char *target, mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; } -bs = bdrv_find(device); -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } -aio_context = bdrv_get_aio_context(bs); +aio_context = blk_get_aio_context(blk); aio_context_acquire(aio_context); /* Although backup_run has this check too, we need to use bs-drv below, so * do an early check redundantly. */ -if (!bdrv_is_inserted(bs)) { +if (!blk_is_available(blk)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); goto out; } +bs = blk_bs(blk); if (!has_format) { format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs-drv-format_name; -- 2.1.0
[Qemu-devel] [PATCH 34/50] blockdev: Do not create BDS for empty drive
Do not use rudimentary BDSs for empty drives any longer (for freshly created drives). With this change, bdrv_close_all() has no effect on empty drives (whose media were not changed) any longer. This breaks some test outputs, fix them. After a follow-up patch, empty drives will generally use a NULL BDS, not only the freshly created drives. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 68 ++ tests/qemu-iotests/067.out | 44 -- tests/qemu-iotests/071.out | 2 -- tests/qemu-iotests/081.out | 1 - tests/qemu-iotests/087.out | 5 5 files changed, 38 insertions(+), 82 deletions(-) diff --git a/blockdev.c b/blockdev.c index f82b20c..d99edbb 100644 --- a/blockdev.c +++ b/blockdev.c @@ -502,16 +502,40 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, goto early_err; } +if (snapshot) { +/* always use cache=unsafe with snapshot */ +bdrv_flags = ~BDRV_O_CACHE_MASK; +bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); +} + +if (copy_on_read) { +bdrv_flags |= BDRV_O_COPY_ON_READ; +} + +if (runstate_check(RUN_STATE_INMIGRATE)) { +bdrv_flags |= BDRV_O_INCOMING; +} + +bdrv_flags |= ro ? 0 : BDRV_O_RDWR; + /* init */ if ((!file || !*file) !has_driver_specific_opts) { -blk = blk_new_with_bs(qemu_opts_id(opts), errp); +BlockBackendRootState *blk_rs; + +blk = blk_new(qemu_opts_id(opts), errp); if (!blk) { goto early_err; } -bs = blk_bs(blk); -bs-open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; -bs-read_only = ro; +blk_rs = blk_get_root_state(blk); +blk_rs-open_flags= bdrv_flags; +blk_rs-read_only = ro; +blk_rs-detect_zeroes = detect_zeroes; + +if (throttle_enabled(cfg)) { +blk_rs-io_limits_enabled = true; +blk_rs-throttle_config = cfg; +} QDECREF(bs_opts); } else { @@ -519,43 +543,27 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, file = NULL; } -if (snapshot) { -/* always use cache=unsafe with snapshot */ -bdrv_flags = ~BDRV_O_CACHE_MASK; -bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); -} - -if (copy_on_read) { -bdrv_flags |= BDRV_O_COPY_ON_READ; -} - -if (runstate_check(RUN_STATE_INMIGRATE)) { -bdrv_flags |= BDRV_O_INCOMING; -} - -bdrv_flags |= ro ? 0 : BDRV_O_RDWR; - blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags, errp); if (!blk) { goto err_no_bs_opts; } bs = blk_bs(blk); -} -bs-detect_zeroes = detect_zeroes; +bs-detect_zeroes = detect_zeroes; -blk_set_on_error(blk, on_read_error, on_write_error); +/* disk I/O throttling */ +if (throttle_enabled(cfg)) { +bdrv_io_limits_enable(bs); +bdrv_set_io_limits(bs, cfg); +} -/* disk I/O throttling */ -if (throttle_enabled(cfg)) { -bdrv_io_limits_enable(bs); -bdrv_set_io_limits(bs, cfg); +if (bdrv_key_required(bs)) { +autostart = 0; +} } -if (bdrv_key_required(bs)) { -autostart = 0; -} +blk_set_on_error(blk, on_read_error, on_write_error); err_no_bs_opts: qemu_opts_del(opts); diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 42bae32..47b0b68 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -154,17 +154,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti }, event: SHUTDOWN } -{ -timestamp: { -seconds: TIMESTAMP, -microseconds: TIMESTAMP -}, -event: DEVICE_TRAY_MOVED, -data: { -device: ide1-cd0, -tray-open: true -} -} === -drive/device_add and device_del === @@ -324,17 +313,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk }, event: SHUTDOWN } -{ -timestamp: { -seconds: TIMESTAMP, -microseconds: TIMESTAMP -}, -event: DEVICE_TRAY_MOVED, -data: { -device: ide1-cd0, -tray-open: true -} -} === drive_add/device_add and device_del === @@ -497,17 +475,6 @@ Testing: }, event: SHUTDOWN } -{ -timestamp: { -seconds: TIMESTAMP, -microseconds: TIMESTAMP -}, -event: DEVICE_TRAY_MOVED, -data: { -device: ide1-cd0, -tray-open: true -} -} === blockdev_add/device_add and device_del === @@ -716,16 +683,5 @@ Testing: }, event: SHUTDOWN } -{ -timestamp: { -seconds: TIMESTAMP, -microseconds: TIMESTAMP -}, -
[Qemu-devel] [PATCH 30/50] blockdev: Check BB validity in change-backing-file
Call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 15 +++ 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 4bd52b8..7f4470f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2821,7 +2821,8 @@ void qmp_change_backing_file(const char *device, const char *backing_file, Error **errp) { -BlockDriverState *bs = NULL; +BlockBackend *blk; +BlockDriverState *bs; AioContext *aio_context; BlockDriverState *image_bs = NULL; Error *local_err = NULL; @@ -2830,15 +2831,21 @@ void qmp_change_backing_file(const char *device, int ret; /* find the top layer BDS of the chain */ -bs = bdrv_find(device); -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } -aio_context = bdrv_get_aio_context(bs); +aio_context = blk_get_aio_context(blk); aio_context_acquire(aio_context); +if (!blk_is_available(blk)) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); +goto out; +} +bs = blk_bs(blk); + image_bs = bdrv_lookup_bs(NULL, image_node_name, local_err); if (local_err) { error_propagate(errp, local_err); -- 2.1.0
Re: [Qemu-devel] [Spice-devel] [PATCH] [RFC] LZ4 compression option for SPICE
On 01/26/2015 01:48 AM, Javier Celaya wrote: Sorry, I forgot to patch the command-line help. Hope it helps. Recently, SPICE included the lz4 compression algorithm. This patch adds a command line option to select it. How is libvirt going to introspect whether the command line supports this option? Is there some QMP command that lists the set of valid compression formats understood by a given qemu binary? No, patching the command line --help does NOT help libvirt. It needs to be discoverable via QMP to be introspectible, as scraping --help output is not machine-friendly. (That said, you DO want to expose it in --help output; I'm just complaining that --help output alone is not enough). -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
[Qemu-devel] [PATCH 46/50] hmp: Use blockdev-change-medium for change command
Use separate code paths for the two overloaded functions of the 'change' HMP command, and invoke the 'blockdev-change-medium' QMP command if used on a block device (by calling qmp_blockdev_change_medium()). Signed-off-by: Max Reitz mre...@redhat.com Reviewed-by: Eric Blake ebl...@redhat.com --- hmp.c | 27 +++ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/hmp.c b/hmp.c index f806387..300e7d8 100644 --- a/hmp.c +++ b/hmp.c @@ -1180,22 +1180,25 @@ void hmp_change(Monitor *mon, const QDict *qdict) const char *arg = qdict_get_try_str(qdict, arg); Error *err = NULL; -if (strcmp(device, vnc) == 0 -(strcmp(target, passwd) == 0 || - strcmp(target, password) == 0)) { -if (!arg) { -monitor_read_password(mon, hmp_change_read_arg, NULL); +if (strcmp(device, vnc) == 0) { +if (strcmp(target, passwd) == 0 || +strcmp(target, password) == 0) { +if (!arg) { +monitor_read_password(mon, hmp_change_read_arg, NULL); +return; +} +} +qmp_change(vnc, target, !!arg, arg, err); +} else { +qmp_blockdev_change_medium(device, target, !!arg, arg, err); +if (err +error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { +error_free(err); +monitor_read_block_device_key(mon, device, NULL, NULL); return; } } -qmp_change(device, target, !!arg, arg, err); -if (err -error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { -error_free(err); -monitor_read_block_device_key(mon, device, NULL, NULL); -return; -} hmp_handle_error(mon, err); } -- 2.1.0
[Qemu-devel] [PATCH v3 09/14] qemu-io: Use blk_new_open() in openfile()
Signed-off-by: Max Reitz mre...@redhat.com --- qemu-io.c | 31 --- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/qemu-io.c b/qemu-io.c index 91a445a..81f8f64 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -39,7 +39,6 @@ static ReadLineState *readline_state; static int close_f(BlockDriverState *bs, int argc, char **argv) { blk_unref(qemuio_blk); -qemuio_bs = NULL; qemuio_blk = NULL; return 0; } @@ -51,34 +50,29 @@ static const cmdinfo_t close_cmd = { .oneline= close the current open file, }; -static int openfile(char *name, BlockDriver *drv, int flags, int growable, -QDict *opts) +static int openfile(char *name, int flags, int growable, QDict *opts) { Error *local_err = NULL; -if (qemuio_bs) { +if (qemuio_blk) { fprintf(stderr, file open already, try 'help close'\n); QDECREF(opts); return 1; } -qemuio_blk = blk_new_with_bs(hda, error_abort); -qemuio_bs = blk_bs(qemuio_blk); - if (growable) { flags |= BDRV_O_PROTOCOL; } -if (bdrv_open(qemuio_bs, name, NULL, opts, flags, drv, local_err) 0) { +qemuio_blk = blk_new_open(hda, name, NULL, opts, flags, local_err); +if (!qemuio_blk) { fprintf(stderr, %s: can't open%s%s: %s\n, progname, name ? device : , name ?: , error_get_pretty(local_err)); error_free(local_err); -blk_unref(qemuio_blk); -qemuio_bs = NULL; -qemuio_blk = NULL; return 1; } +qemuio_bs = blk_bs(qemuio_blk); return 0; } @@ -170,9 +164,9 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) qemu_opts_reset(empty_opts); if (optind == argc - 1) { -return openfile(argv[optind], NULL, flags, growable, opts); +return openfile(argv[optind], flags, growable, opts); } else if (optind == argc) { -return openfile(NULL, NULL, flags, growable, opts); +return openfile(NULL, flags, growable, opts); } else { QDECREF(opts); return qemuio_command_usage(open_cmd); @@ -387,8 +381,8 @@ int main(int argc, char **argv) int c; int opt_index = 0; int flags = BDRV_O_UNMAP; -BlockDriver *drv = NULL; Error *local_error = NULL; +QDict *opts = NULL; #ifdef CONFIG_POSIX signal(SIGPIPE, SIG_IGN); @@ -414,11 +408,10 @@ int main(int argc, char **argv) } break; case 'f': -drv = bdrv_find_format(optarg); -if (!drv) { -error_report(Invalid format '%s', optarg); -exit(EXIT_FAILURE); +if (!opts) { +opts = qdict_new(); } +qdict_put_obj(opts, driver, QOBJECT(qstring_from_str(optarg))); break; case 'c': add_user_command(optarg); @@ -489,7 +482,7 @@ int main(int argc, char **argv) } if ((argc - optind) == 1) { -openfile(argv[optind], drv, flags, growable, NULL); +openfile(argv[optind], flags, growable, opts); } command_loop(); -- 2.1.0
[Qemu-devel] [PATCH v3 05/14] qemu-img: Use blk_new_open() in img_open()
Signed-off-by: Max Reitz mre...@redhat.com --- qemu-img.c | 20 ++-- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 4e9a7f5..be1953d 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -291,32 +291,24 @@ static BlockBackend *img_open(const char *id, const char *filename, { BlockBackend *blk; BlockDriverState *bs; -BlockDriver *drv; char password[256]; Error *local_err = NULL; -int ret; - -blk = blk_new_with_bs(id, error_abort); -bs = blk_bs(blk); +QDict *options = NULL; if (fmt) { -drv = bdrv_find_format(fmt); -if (!drv) { -error_report(Unknown file format '%s', fmt); -goto fail; -} -} else { -drv = NULL; +options = qdict_new(); +qdict_put_obj(options, driver, QOBJECT(qstring_from_str(fmt))); } -ret = bdrv_open(bs, filename, NULL, NULL, flags, drv, local_err); -if (ret 0) { +blk = blk_new_open(id, filename, NULL, options, flags, local_err); +if (!blk) { error_report(Could not open '%s': %s, filename, error_get_pretty(local_err)); error_free(local_err); goto fail; } +bs = blk_bs(blk); if (bdrv_is_encrypted(bs) require_io) { qprintf(quiet, Disk image '%s' is encrypted.\n, filename); if (read_password(password, sizeof(password)) 0) { -- 2.1.0
[Qemu-devel] [PATCH v3 12/14] block: Clamp BlockBackend requests
BlockBackend is used as the interface between the block layer and guest devices. It should therefore assure that all requests are clamped to the image size. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 152 ++ 1 file changed, 152 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index 543edaa..96a5bc6 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -31,6 +31,16 @@ struct BlockBackend { void *dev_opaque; }; +typedef struct BlockBackendAIOCB { +BlockAIOCB common; +QEMUBH *bh; +int ret; +} BlockBackendAIOCB; + +static const AIOCBInfo block_backend_aiocb_info = { +.aiocb_size = sizeof(BlockBackendAIOCB), +}; + static void drive_info_del(DriveInfo *dinfo); /* All the BlockBackends (except for hidden ones) */ @@ -428,39 +438,137 @@ void blk_iostatus_enable(BlockBackend *blk) bdrv_iostatus_enable(blk-bs); } +static int blk_check_byte_request(BlockBackend *blk, int64_t offset, + size_t size) +{ +int64_t len; + +if (size INT_MAX) { +return -EIO; +} + +if (!blk_is_inserted(blk)) { +return -ENOMEDIUM; +} + +len = blk_getlength(blk); +if (len 0) { +return len; +} + +if (offset 0) { +return -EIO; +} + +if (offset len || len - offset size) { +return -EIO; +} + +return 0; +} + +static int blk_check_request(BlockBackend *blk, int64_t sector_num, + int nb_sectors) +{ +if (sector_num 0 || sector_num INT64_MAX / BDRV_SECTOR_SIZE) { +return -EIO; +} + +if (nb_sectors 0 || nb_sectors INT_MAX / BDRV_SECTOR_SIZE) { +return -EIO; +} + +return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE, + nb_sectors * BDRV_SECTOR_SIZE); +} + int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf, int nb_sectors) { +int ret = blk_check_request(blk, sector_num, nb_sectors); +if (ret 0) { +return ret; +} + return bdrv_read(blk-bs, sector_num, buf, nb_sectors); } int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf, int nb_sectors) { +int ret = blk_check_request(blk, sector_num, nb_sectors); +if (ret 0) { +return ret; +} + return bdrv_read_unthrottled(blk-bs, sector_num, buf, nb_sectors); } int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf, int nb_sectors) { +int ret = blk_check_request(blk, sector_num, nb_sectors); +if (ret 0) { +return ret; +} + return bdrv_write(blk-bs, sector_num, buf, nb_sectors); } +static void error_callback_bh(void *opaque) +{ +struct BlockBackendAIOCB *acb = opaque; +qemu_bh_delete(acb-bh); +acb-common.cb(acb-common.opaque, acb-ret); +qemu_aio_unref(acb); +} + +static BlockAIOCB *abort_aio_request(BlockBackend *blk, BlockCompletionFunc *cb, + void *opaque, int ret) +{ +struct BlockBackendAIOCB *acb; +QEMUBH *bh; + +acb = blk_aio_get(block_backend_aiocb_info, blk, cb, opaque); +acb-ret = ret; + +bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb); +acb-bh = bh; +qemu_bh_schedule(bh); + +return acb-common; +} + BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) { +int ret = blk_check_request(blk, sector_num, nb_sectors); +if (ret 0) { +return abort_aio_request(blk, cb, opaque, ret); +} + return bdrv_aio_write_zeroes(blk-bs, sector_num, nb_sectors, flags, cb, opaque); } int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count) { +int ret = blk_check_byte_request(blk, offset, count); +if (ret 0) { +return ret; +} + return bdrv_pread(blk-bs, offset, buf, count); } int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count) { +int ret = blk_check_byte_request(blk, offset, count); +if (ret 0) { +return ret; +} + return bdrv_pwrite(blk-bs, offset, buf, count); } @@ -478,6 +586,11 @@ BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, QEMUIOVector *iov, int nb_sectors, BlockCompletionFunc *cb, void *opaque) { +int ret = blk_check_request(blk, sector_num, nb_sectors); +if (ret 0) { +return abort_aio_request(blk, cb, opaque, ret); +} + return bdrv_aio_readv(blk-bs, sector_num, iov, nb_sectors, cb, opaque); } @@ -485,6 +598,11 @@ BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
Re: [Qemu-devel] [PATCH 05/11] target-arm: Use correct mmu_idx for unprivileged loads and stores
On 26 January 2015 at 14:40, Greg Bellows greg.bell...@linaro.org wrote: On Fri, Jan 23, 2015 at 12:20 PM, Peter Maydell peter.mayd...@linaro.org wrote: The MMU index to use for unprivileged loads and stores is more complicated than we currently implement: * for A64, it should be if at EL1, access as if EL0; otherwise access at current EL * for A32/T32, it should be if EL2, UNPREDICTABLE; otherwise access as if at EL0. The wording between the specs appears to be almost identical, curious why the handling is different? Because that's what the ARM ARM specifies. Compare C3.2.5 (A64 LDT c) with F7.1.95 (A32/T32 LDRT). -- PMM
[Qemu-devel] [PATCH 1/2] vl.c: Fix error messages when parsing maxmem parameters
Produce more human readable error messages and fix few spelling mistakes. Also remove a redundant check for the max memory size. Signed-off-by: Peter Krempa pkre...@redhat.com --- vl.c | 22 +++--- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/vl.c b/vl.c index 983259b..cdc920c 100644 --- a/vl.c +++ b/vl.c @@ -2694,29 +2694,21 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size) uint64_t slots; sz = qemu_opt_get_size(opts, maxmem, 0); -if (sz ram_size) { -error_report(invalid -m option value: maxmem -(0x% PRIx64 ) = initial memory (0x -RAM_ADDR_FMT ), sz, ram_size); +if (sz = ram_size) { +error_report(invalid value of -m option maxmem: + maximum memory size (0x% PRIx64 ) must be greater + than initial memory size (0x RAM_ADDR_FMT ), + sz, ram_size); exit(EXIT_FAILURE); } slots = qemu_opt_get_number(opts, slots, 0); if ((sz ram_size) !slots) { -error_report(invalid -m option value: maxmem -(0x% PRIx64 ) more than initial memory (0x -RAM_ADDR_FMT ) but no hotplug slots where -specified, sz, ram_size); +error_report(invalid value of -m option: maxmem was specified, + but no hotplug slots were specified); exit(EXIT_FAILURE); } -if ((sz = ram_size) slots) { -error_report(invalid -m option value: % -PRIu64 hotplug slots where specified but -maxmem (0x% PRIx64 ) = initial memory (0x -RAM_ADDR_FMT ), slots, sz, ram_size); -exit(EXIT_FAILURE); -} *maxram_size = sz; *ram_slots = slots; } else if ((!maxmem_str slots_str) || -- 2.2.1
[Qemu-devel] [PATCH 13/50] block: Add BlockBackendRootState
This structure will store some of the state of the root BDS if the BDS tree is removed, so that state can be restored once a new BDS tree is inserted. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 26 ++ include/block/block_int.h | 9 + include/qemu/typedefs.h| 1 + include/sysemu/block-backend.h | 2 ++ 4 files changed, 38 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index 2a48e82..7be03ee 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -37,6 +37,10 @@ struct BlockBackend { /* the block size for which the guest device expects atomicity */ int guest_block_size; +/* If the BDS tree is removed, some of its options are stored here (which + * can be used to restore those options in the new BDS on insert) */ +BlockBackendRootState root_state; + /* I/O stats (display with info blockstats). */ BlockAcctStats stats; @@ -1014,3 +1018,25 @@ int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size) { return bdrv_load_vmstate(blk-bs, buf, pos, size); } + +/* + * Updates the BlockBackendRootState object with data from the currently + * attached BlockDriverState. + */ +void blk_update_root_state(BlockBackend *blk) +{ +assert(blk-bs); + +blk-root_state.open_flags= blk-bs-open_flags; +blk-root_state.read_only = blk-bs-read_only; +blk-root_state.detect_zeroes = blk-bs-detect_zeroes; + +blk-root_state.io_limits_enabled = blk-bs-io_limits_enabled; +throttle_get_config(blk-bs-throttle_state, +blk-root_state.throttle_config); +} + +BlockBackendRootState *blk_get_root_state(BlockBackend *blk) +{ +return blk-root_state; +} diff --git a/include/block/block_int.h b/include/block/block_int.h index 69668e4..91d21c5 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -406,6 +406,15 @@ struct BlockDriverState { NotifierWithReturn write_threshold_notifier; }; +struct BlockBackendRootState { +int open_flags; +bool read_only; +BlockdevDetectZeroesOptions detect_zeroes; + +bool io_limits_enabled; +ThrottleConfig throttle_config; +}; + /* Essential block drivers which must always be statically linked into qemu, and * which therefore can be accessed without using bdrv_find_format() */ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index cde3314..39a95dd 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -11,6 +11,7 @@ typedef struct AddressSpace AddressSpace; typedef struct AioContext AioContext; typedef struct AudioState AudioState; typedef struct BlockBackend BlockBackend; +typedef struct BlockBackendRootState BlockBackendRootState; typedef struct BlockDriverState BlockDriverState; typedef struct BusClass BusClass; typedef struct BusState BusState; diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index c4a61c0..afb62e1 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -158,6 +158,8 @@ void blk_add_close_notifier(BlockBackend *blk, Notifier *notify); void blk_io_plug(BlockBackend *blk); void blk_io_unplug(BlockBackend *blk); BlockAcctStats *blk_get_stats(BlockBackend *blk); +BlockBackendRootState *blk_get_root_state(BlockBackend *blk); +void blk_update_root_state(BlockBackend *blk); void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, BlockCompletionFunc *cb, void *opaque); -- 2.1.0
[Qemu-devel] [PATCH 14/50] block: Make some BB functions fall back to BBRS
If there is no BDS tree attached to a BlockBackend, functions that can do so should fall back to the BlockBackendRootState structure (which are blk_is_read_only() and blk_get_flags(), because the read-only status and the open flags are part of the BBRS). Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 7be03ee..62be370 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -829,7 +829,11 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action, int blk_is_read_only(BlockBackend *blk) { -return bdrv_is_read_only(blk-bs); +if (blk-bs) { +return bdrv_is_read_only(blk-bs); +} else { +return blk-root_state.read_only; +} } int blk_is_sg(BlockBackend *blk) @@ -874,7 +878,11 @@ void blk_eject(BlockBackend *blk, bool eject_flag) int blk_get_flags(BlockBackend *blk) { -return bdrv_get_flags(blk-bs); +if (blk-bs) { +return bdrv_get_flags(blk-bs); +} else { +return blk-root_state.open_flags; +} } void blk_set_guest_block_size(BlockBackend *blk, int align) -- 2.1.0
[Qemu-devel] [PATCH 23/50] blockdev: Catch NULL BDS in block_set_io_throttle
Split bdrv_find() into blk_by_name() and blk_bs() to separate the no medium inserted case from the device not found case. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 20 ++-- 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/blockdev.c b/blockdev.c index 5f7eef5..9801a7e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1922,15 +1922,25 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, int64_t iops_size, Error **errp) { ThrottleConfig cfg; +BlockBackend *blk; BlockDriverState *bs; AioContext *aio_context; -bs = bdrv_find(device); -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } +aio_context = blk_get_aio_context(blk); +aio_context_acquire(aio_context); + +bs = blk_bs(blk); +if (!bs) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); +goto out; +} + memset(cfg, 0, sizeof(cfg)); cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps; cfg.buckets[THROTTLE_BPS_READ].avg = bps_rd; @@ -1964,12 +1974,9 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, } if (!check_throttle_config(cfg, errp)) { -return; +goto out; } -aio_context = bdrv_get_aio_context(bs); -aio_context_acquire(aio_context); - if (!bs-io_limits_enabled throttle_enabled(cfg)) { bdrv_io_limits_enable(bs); } else if (bs-io_limits_enabled !throttle_enabled(cfg)) { @@ -1980,6 +1987,7 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, bdrv_set_io_limits(bs, cfg); } +out: aio_context_release(aio_context); } -- 2.1.0
[Qemu-devel] [PATCH 05/50] block: Fix BB AIOCB AioContext without BDS
Fix the BlockBackend's AIOCB AioContext for aborting AIO in case there is no BDS. If there is no implementation of AIOCBInfo::get_aio_context() the AioContext is derived from the BDS the AIOCB belongs to. If that BDS is NULL (because it has been removed from the BB) this will not work. This patch makes blk_get_aio_context() fall back to the main loop context if the BDS pointer is NULL and implements AIOCBInfo::get_aio_context() (blk_aiocb_get_aio_context()) which invokes blk_get_aio_context(). Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 17 - 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/block/block-backend.c b/block/block-backend.c index 96a5bc6..4c40747 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -18,6 +18,8 @@ /* Number of coroutines to reserve per attached device model */ #define COROUTINE_POOL_RESERVATION 64 +static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb); + struct BlockBackend { char *name; int refcnt; @@ -34,10 +36,12 @@ struct BlockBackend { typedef struct BlockBackendAIOCB { BlockAIOCB common; QEMUBH *bh; +BlockBackend *blk; int ret; } BlockBackendAIOCB; static const AIOCBInfo block_backend_aiocb_info = { +.get_aio_context = blk_aiocb_get_aio_context, .aiocb_size = sizeof(BlockBackendAIOCB), }; @@ -530,6 +534,7 @@ static BlockAIOCB *abort_aio_request(BlockBackend *blk, BlockCompletionFunc *cb, QEMUBH *bh; acb = blk_aio_get(block_backend_aiocb_info, blk, cb, opaque); +acb-blk = blk; acb-ret = ret; bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb); @@ -783,7 +788,17 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason) AioContext *blk_get_aio_context(BlockBackend *blk) { -return bdrv_get_aio_context(blk-bs); +if (blk-bs) { +return bdrv_get_aio_context(blk-bs); +} else { +return qemu_get_aio_context(); +} +} + +static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb) +{ +BlockBackendAIOCB *blk_acb = DO_UPCAST(BlockBackendAIOCB, common, acb); +return blk_get_aio_context(blk_acb-blk); } void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) -- 2.1.0
[Qemu-devel] [PATCH 47/50] blockdev: Add read-only option to blockdev-change-medium
Add an option to qmp_blockdev_change_medium() which allows changing the read-only status of the block device whose medium is changed. Some drives do not have a inherently fixed read-only status; for instance, floppy disks can be set read-only or writable independently of the drive. Some users may find it useful to be able to therefore change the read-only status of a block device when changing the medium. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 25 - hmp.c| 2 +- qapi/block-core.json | 24 +++- qmp-commands.hx | 24 +++- qmp.c| 3 ++- 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index 2ada2b1..8ed2fec 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2014,6 +2014,8 @@ void qmp_blockdev_insert_medium(const char *device, const char *node_name, void qmp_blockdev_change_medium(const char *device, const char *filename, bool has_format, const char *format, +bool has_read_only, +BlockdevChangeReadOnlyMode read_only, Error **errp) { BlockBackend *blk; @@ -2034,7 +2036,28 @@ void qmp_blockdev_change_medium(const char *device, const char *filename, } blk_rs = blk_get_root_state(blk); -bdrv_flags = blk_rs-read_only ? 0 : BDRV_O_RDWR; + +if (!has_read_only) { +read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN; +} + +switch (read_only) { +case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN: +bdrv_flags = blk_rs-read_only ? 0 : BDRV_O_RDWR; +break; + +case BLOCKDEV_CHANGE_READ_ONLY_MODE_RO: +bdrv_flags = 0; +break; + +case BLOCKDEV_CHANGE_READ_ONLY_MODE_RW: +bdrv_flags = BDRV_O_RDWR; +break; + +default: +abort(); +} + bdrv_flags |= blk_rs-open_flags ~BDRV_O_RDWR; if (has_format) { diff --git a/hmp.c b/hmp.c index 300e7d8..dbf0947 100644 --- a/hmp.c +++ b/hmp.c @@ -1190,7 +1190,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) } qmp_change(vnc, target, !!arg, arg, err); } else { -qmp_blockdev_change_medium(device, target, !!arg, arg, err); +qmp_blockdev_change_medium(device, target, !!arg, arg, false, 0, err); if (err error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { error_free(err); diff --git a/qapi/block-core.json b/qapi/block-core.json index d3c3ca7..eb2724e 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1785,6 +1785,24 @@ ## +# @BlockdevChangeReadOnlyMode: +# +# Specifies the new read-only mode of a block device subject to the +# @blockdev-change-medium command. +# +# @retain: Retains the current read-only mode +# +# @ro: Makes the device read-only +# +# @rw: Makes the device writable +# +# Since: 2.3 +## +{ 'enum': 'BlockdevChangeReadOnlyMode', + 'data': ['retain', 'ro', 'rw'] } + + +## # @blockdev-change-medium: # # Changes the medium inserted into a block device by ejecting the current medium @@ -1799,12 +1817,16 @@ # @format: #optional, format to open the new image with (defaults to the # probed format) # +# @read-only: #optional, change the read-only mode of the device; defaults to +# 'retain' +# # Since: 2.3 ## { 'command': 'blockdev-change-medium', 'data': { 'device': 'str', 'filename': 'str', -'*format': 'str' } } +'*format': 'str', +'*read-only': 'BlockdevChangeReadOnlyMode' } } ## diff --git a/qmp-commands.hx b/qmp-commands.hx index 1987a09..f14953a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3855,7 +3855,7 @@ EQMP { .name = blockdev-change-medium, -.args_type = device:B,filename:F,format:s?, +.args_type = device:B,filename:F,format:s?,read-only:s?, .mhandler.cmd_new = qmp_marshal_input_blockdev_change_medium, }, @@ -3871,6 +3871,8 @@ Arguments: - device: device name (json-string) - filename: filename of the new image (json-string) - format: format of the new image (json-string, optional) +- read-only: new read-only mode (json-string, optional) + - Possible values: retain (default), ro, rw Examples: @@ -3882,6 +3884,26 @@ Examples: format: raw } } - { return: {} } +2. Load a read-only medium into a writable drive + +- { execute: blockdev-change-medium, + arguments: { device: isa-fd0, +filename: /srv/images/ro.img, +format: raw, +read-only: retain } } + +- { error: + { class: GenericError, + desc: Could not open '/srv/images/ro.img': Permission denied } } + +- { execute: blockdev-change-medium, + arguments: { device: isa-fd0, +
[Qemu-devel] [PATCH v3 06/14] qemu-img: Use blk_new_open() in img_rebase()
Signed-off-by: Max Reitz mre...@redhat.com --- qemu-img.c | 57 - 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index be1953d..0b23c87 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2430,7 +2430,6 @@ static int img_rebase(int argc, char **argv) { BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL; BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL; -BlockDriver *old_backing_drv, *new_backing_drv; char *filename; const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg; int c, flags, src_flags, ret; @@ -2524,54 +2523,46 @@ static int img_rebase(int argc, char **argv) } bs = blk_bs(blk); -/* Find the right drivers for the backing files */ -old_backing_drv = NULL; -new_backing_drv = NULL; - -if (!unsafe bs-backing_format[0] != '\0') { -old_backing_drv = bdrv_find_format(bs-backing_format); -if (old_backing_drv == NULL) { -error_report(Invalid format name: '%s', bs-backing_format); -ret = -1; -goto out; -} -} - -if (out_basefmt != NULL) { -new_backing_drv = bdrv_find_format(out_basefmt); -if (new_backing_drv == NULL) { -error_report(Invalid format name: '%s', out_basefmt); -ret = -1; -goto out; -} -} - /* For safe rebasing we need to compare old and new backing file */ if (!unsafe) { char backing_name[PATH_MAX]; +QDict *options = NULL; + +if (!unsafe bs-backing_format[0] != '\0') { +options = qdict_new(); +qdict_put_obj(options, driver, + QOBJECT(qstring_from_str(bs-backing_format))); +} -blk_old_backing = blk_new_with_bs(old_backing, error_abort); -bs_old_backing = blk_bs(blk_old_backing); bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name)); -ret = bdrv_open(bs_old_backing, backing_name, NULL, NULL, src_flags, -old_backing_drv, local_err); -if (ret) { +blk_old_backing = blk_new_open(old_backing, backing_name, NULL, + options, src_flags, local_err); +if (!blk_old_backing) { error_report(Could not open old backing file '%s': %s, backing_name, error_get_pretty(local_err)); error_free(local_err); goto out; } +bs_old_backing = blk_bs(blk_old_backing); + if (out_baseimg[0]) { -blk_new_backing = blk_new_with_bs(new_backing, error_abort); -bs_new_backing = blk_bs(blk_new_backing); -ret = bdrv_open(bs_new_backing, out_baseimg, NULL, NULL, src_flags, -new_backing_drv, local_err); -if (ret) { +if (out_basefmt) { +options = qdict_new(); +qdict_put_obj(options, driver, + QOBJECT(qstring_from_str(out_basefmt))); +} else { +options = NULL; +} + +blk_new_backing = blk_new_open(new_backing, out_baseimg, NULL, + options, src_flags, local_err); +if (!blk_new_backing) { error_report(Could not open new backing file '%s': %s, out_baseimg, error_get_pretty(local_err)); error_free(local_err); goto out; } +bs_new_backing = blk_bs(blk_new_backing); } } -- 2.1.0
[Qemu-devel] [PATCH v3 00/14] block: Remove growable, add blk_new_open()
This series removes the growable field from the BlockDriverState object. Its use was to clamp guest requests against the limits of the BDS; however, this can now be done more easily by moving those checks into the BlockBackend functions. In a future series, growable may be reintroduced (maybe with a different name); it will then signify whether a BDS is able to grow (in contrast to the current growable, which signifies whether it is allowed to). Maybe I will add it to the BlockDriver instead of the BDS, though. To be able to remove that field, qemu-io needs to be converted to BlockBackend, which is done by this series as well. While working on that I decided to convert blk_new_with_bs()+bdrv_open() to blk_new_open(). I was skeptical about that decision at first, but it seems good now that I was able to replace nearly every blk_new_with_bs() call by blk_new_open(). In a future series I may try to convert some remaining bdrv_open() calls to blk_new_open() as well. (And, in fact, in a future series I *will* replace the last remaining blk_new_with_bs() outside of blk_new_open() by blk_new_open().) Finally, the question needs to be asked: If, after this series, every BDS is allowed to grow, are there any users which do not use BB, but should still be disallowed from reading/writing beyond a BDS's limits? The only users I could see were the block jobs. Some of them should indeed be converted to BB; but none of them takes a user-supplied offset or size, all work on the full BDS (or only on parts which have been modified, etc.). Therefore, it is by design impossible for them to exceed the BDS's limits, which makes making all BDS's growable safe. v3: - Rebased (onto Stefan's branch rebased onto master) - Fixed patch 4 [Stefano] v2: - Rebased [Kevin] - Patch 2: Added a TODO comment about removing @filename and @flags from blk_new_open() when possible [Kevin] git-backport-diff against v2: Key: [] : patches are identical [] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/14:[] [--] 'block: Lift some BDS functions to the BlockBackend' 002/14:[] [--] 'block: Add blk_new_open()' 003/14:[] [--] 'blockdev: Use blk_new_open() in blockdev_init()' 004/14:[0004] [FC] 'block/xen: Use blk_new_open() in blk_connect()' 005/14:[] [--] 'qemu-img: Use blk_new_open() in img_open()' 006/14:[] [-C] 'qemu-img: Use blk_new_open() in img_rebase()' 007/14:[] [-C] 'qemu-img: Use BlockBackend as far as possible' 008/14:[] [--] 'qemu-nbd: Use blk_new_open() in main()' 009/14:[] [--] 'qemu-io: Use blk_new_open() in openfile()' 010/14:[] [--] 'qemu-io: Remove growable option' 011/14:[] [--] 'qemu-io: Use BlockBackend' 012/14:[] [--] 'block: Clamp BlockBackend requests' 013/14:[] [--] 'block: Remove growable from BDS' 014/14:[] [--] 'block: Keep bdrv_check*_request()'s return value' git-backport-diff against v1: Key: [] : patches are identical [] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/14:[] [--] 'block: Lift some BDS functions to the BlockBackend' 002/14:[0006] [FC] 'block: Add blk_new_open()' 003/14:[] [-C] 'blockdev: Use blk_new_open() in blockdev_init()' 004/14:[0004] [FC] 'block/xen: Use blk_new_open() in blk_connect()' 005/14:[] [--] 'qemu-img: Use blk_new_open() in img_open()' 006/14:[] [-C] 'qemu-img: Use blk_new_open() in img_rebase()' 007/14:[] [-C] 'qemu-img: Use BlockBackend as far as possible' 008/14:[] [--] 'qemu-nbd: Use blk_new_open() in main()' 009/14:[] [--] 'qemu-io: Use blk_new_open() in openfile()' 010/14:[0002] [FC] 'qemu-io: Remove growable option' 011/14:[] [--] 'qemu-io: Use BlockBackend' 012/14:[] [--] 'block: Clamp BlockBackend requests' 013/14:[] [--] 'block: Remove growable from BDS' 014/14:[] [--] 'block: Keep bdrv_check*_request()'s return value' Max Reitz (14): block: Lift some BDS functions to the BlockBackend block: Add blk_new_open() blockdev: Use blk_new_open() in blockdev_init() block/xen: Use blk_new_open() in blk_connect() qemu-img: Use blk_new_open() in img_open() qemu-img: Use blk_new_open() in img_rebase() qemu-img: Use BlockBackend as far as possible qemu-nbd: Use blk_new_open() in main() qemu-io: Use blk_new_open() in openfile() qemu-io: Remove growable option qemu-io: Use BlockBackend block: Clamp BlockBackend requests block: Remove growable from BDS block: Keep bdrv_check*_request()'s return value block.c| 59 +- block/block-backend.c | 219 + block/qcow2.c | 6 -- block/raw-posix.c | 2 +- block/raw-win32.c | 2 +- block/sheepdog.c
[Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RRR opcode format
Add microcode generator function gen_cond_sub. Add helper functions: * ixmax/ixmin: search for the max/min value and its related index in a vector of 16-bit values. * pack: dack two data registers into an IEEE-754 single precision floating point format number. * dvadj: divide-adjust the result after dvstep instructions. * dvstep: divide a reg by a divisor, producing 8-bits of quotient at a time. OPCM_32_RRR_FLOAT - OPCM_32_RRR_DIVIDE Signed-off-by: Bastian Koppelmann kbast...@mail.uni-paderborn.de Reviewed-by: Richard Henderson r...@twiddle.net --- target-tricore/helper.h | 8 ++ target-tricore/op_helper.c | 160 +++ target-tricore/translate.c | 150 target-tricore/tricore-opcodes.h | 2 +- 4 files changed, 319 insertions(+), 1 deletion(-) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 068dc7b..7405fee 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -60,10 +60,14 @@ DEF_HELPER_FLAGS_2(max_b, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(max_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(max_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(max_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(ixmax, TCG_CALL_NO_RWG_SE, i64, i64, i32) +DEF_HELPER_FLAGS_2(ixmax_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32) +DEF_HELPER_FLAGS_2(ixmin, TCG_CALL_NO_RWG_SE, i64, i64, i32) +DEF_HELPER_FLAGS_2(ixmin_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) /* count leading ... */ DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32) DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32) @@ -81,12 +85,16 @@ DEF_HELPER_FLAGS_2(bmerge, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_1(bsplit, TCG_CALL_NO_RWG_SE, i64, i32) DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32) /* float */ +DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32) DEF_HELPER_1(unpack, i64, i32) /* dvinit */ DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32) DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32) DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32) +DEF_HELPER_FLAGS_2(dvadj, TCG_CALL_NO_RWG_SE, i64, i64, i32) +DEF_HELPER_FLAGS_2(dvstep, TCG_CALL_NO_RWG_SE, i64, i64, i32) +DEF_HELPER_FLAGS_2(dvstep_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) /* mulh */ DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 13e2729..7047b7c 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -867,6 +867,50 @@ uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\ \ return ret; \ } \ + \ +uint64_t helper_ix##name(uint64_t r1, uint32_t r2)\ +{ \ +int64_t r2l, r2h, r1hl; \ +uint64_t ret = 0; \ + \ +ret = ((r1 + 2) 0x);\ +r2l = sextract64(r2, 0, 16); \ +r2h = sextract64(r2, 16, 16); \ +r1hl = sextract64(r1, 32, 16);\ + \ +if ((r2l op ## = r2h) (r2l op r1hl)) { \ +ret |= (r2l 0x) 32; \ +ret |= extract64(r1, 0, 16) 16;\ +} else if ((r2h op r2l) (r2h op r1hl)) { \ +ret |= extract64(r2, 16, 16) 32; \ +ret |= extract64(r1 + 1, 0, 16) 16;\ +} else { \ +ret |= r1 0xull;\ +} \ +return ret; \ +} \ + \ +uint64_t helper_ix##name ##_u(uint64_t r1, uint32_t r2) \ +{ \ +int64_t r2l, r2h, r1hl; \ +uint64_t ret = 0;
Re: [Qemu-devel] [PATCH v2 01/47] acpi: introduce AML composer aml_append()
On Mon, Jan 26, 2015 at 04:09:20PM +0100, Igor Mammedov wrote: On Mon, 26 Jan 2015 10:57:21 +0100 Igor Mammedov imamm...@redhat.com wrote: On Sat, 24 Jan 2015 18:33:50 +0200 Michael S. Tsirkin m...@redhat.com wrote: On Fri, Jan 23, 2015 at 06:56:20PM +0100, Igor Mammedov wrote: On Fri, 23 Jan 2015 15:55:11 +0200 Michael S. Tsirkin m...@redhat.com wrote: [...] I refuse to give up on cleaner and simpler API yet :) Your patches are almost there, they are pretty clean, the only issue I think is this passing of AcpiAml by value, sometimes freeing buffer in the process, sometimes not. Currently buffer is allocated by API and is always freed whenever it's passed to another API function. That's why it makes user not to care about memory mgmt. The only limitation of it is if you store AcpiAml return value into some variable you are responsible to use it only once for passing to another API function. Reusing this variable's value (pass it to API function second time) would cause cause use-after-free and freeing-freed bugs. Like this: AcpiAml table = acpi_definition_block(SSDT,...); AcpiAml scope = acpi_scope(PCI0); aml_append(table, scope); // - here scope becomes invalid // a bug aml_append(table, scope); // use-after-free + freeing-freed bugs There are several approaches to look for resolving above issues: 1. Adopt and use memory mgmt model used by GTK+ in nutshell: http://www.cs.hunter.cuny.edu/~sweiss/course_materials/csci493.70/lecture_notes/GTK_memory_mngmt.pdf In particular adopt behavior of GInitiallyUnowned usage model that will allow to keep convenient chained call style and if necessary reuse objects returned by API by explicitly referencing/dereferencing them if needed. Hmm, it's still easy to misuse. I think I prefer option 2 below. That's basically what we have/use in QOM with object_new(FOO) + object_unref() I have no idea why we invented our own Object infrastructure when we could just use GObject one from already used glib. 2. It's possible to drop freeing inside API completely and record(store in list) every new object inside a table context. When table is constructed, list of created objects could be safely freed. With that it would be safe to reuse every AcpiAml object and avoid free-after-use issues with limitation that created AcpiAml objects shouldn't be used after table was closed. It should cover all practical use of API, i.e. no cross table AcpiAml objects. So each aml_alloc function gets pointer to this list, and adds the new element there. Eventually we do free_all to free all elements, so there isn't even an aml_free to mis-use. I'm thinking a little bit different about implementation though. I still don't like the use of explicit alloc/free being called by API user since it doesn't allow chained API calls and I think it's unnecessary complication see below why. Here is what's true about current API and a I'd like to with it: 1. Every API call (except aml_append) makes aml_alloc(), it's just like a wrapper about object_new(FOO). (current + new impl.) 2 Every API call that takes AML type as input argument 2.1 consumes (frees) it (current impl.) (it's easy to fix use after free concern too, just pass AML by pointer and zero-out memory before it's freed and assert whenever one of input arguments is not correct, i.e. it was reused second time) There is no need for following steps after this one. 2.2 takes ownership of GInitiallyUnowned and adds it to its list of its children. 3. Free children when AML object is destroyed (i.e. ref count zero) That way when toplevel table object (definition block in 42/47) is added to ACPI blob we can unref it, which will cause its whole children tree freed, except for AML objects where API user explicitly took extra reference (i.e. wanted them to reuse in another table) I'd prefer: * 2.1 way to address your current concern of use-after-free as the most simplest one (no reuse is possible however) or * follow already used by QEMU QOM/GObject pattern of implicit alloc/free since they allow to construct AML in a more simple/manageable way i.e. aml_append(method, aml_store(aml_string(foo), aml_local(0))) ); v.s. explicit headache of alloc/free, which doesn't fix use-after-free anyway and just adds more boiler plate plus makes code har to read read str = aml_alloc(); aml_string(str, foo); loc0 = aml_alloc(); aml_local(loc0, 0); store = aml_alloc(); aml_store(store, str, loc0); aml_append(method, store); aml_free(store); aml_free(loc0);
[Qemu-devel] [PATCH 2/2] pc: memory: Validate alignment of maxram_size to page size
If the maxram_size is not aligned and dimm devices were added on the command line qemu would terminate with a rather unhelpful message: ERROR:hw/mem/pc-dimm.c:150:pc_dimm_get_free_addr: assertion failed: (QEMU_ALIGN_UP(address_space_size, align) == address_space_size) In case no dimm device was originally added on the commandline qemu exits on the assertion failure. Signed-off-by: Peter Krempa pkre...@redhat.com --- hw/i386/pc.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e07f1fa..157eefe 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1246,6 +1246,13 @@ FWCfgState *pc_memory_init(MachineState *machine, exit(EXIT_FAILURE); } +if (QEMU_ALIGN_UP(machine-maxram_size, + TARGET_PAGE_SIZE) != machine-maxram_size) { +error_report(maximum memory size must by aligned to multiple of + %d bytes, TARGET_PAGE_SIZE); +exit(EXIT_FAILURE); +} + pcms-hotplug_memory_base = ROUND_UP(0x1ULL + above_4g_mem_size, 1ULL 30); -- 2.2.1
Re: [Qemu-devel] [PATCH 1/2] hw/ppc/spapr.c Set default boot order
On 01/26/2015 01:57 PM, Dinar Valeev wrote: On 01/26/2015 01:37 PM, Markus Armbruster wrote: Dinar Valeev dval...@suse.de writes: On 01/26/2015 10:11 AM, Markus Armbruster wrote: dval...@suse.de writes: From: Dinar Valeev dval...@suse.com In order to use -boot once=X option we need to have default list where restore to on reset. Really? What happens without this patch? qemu segfaults on reset. 0 reset-all Segmentation fault Next time, include a backtrace, please. Ok, sorry for that. Here's what I think happens. Boot order comes from --boot parameter once, order, or else the machine type's .default_boot_order. The latter is null for you. It gets passed via ppc_spapr_init() to spapr_create_fdt_skel(), which sets qemu,boot-device in the FDT to it, but only when it isn't null. If it comes from parameter once, we additionally register a reset handler to switch it to parameter order or else .default_boot_order on reset. If you specify once, but not order, this is null for you. On reset, reset handler restore_boot_order() runs. Unlike spapr_create_fdt_skel(), it doesn't check for null, and crashes in validate_bootdevices(). Correct? Yes qemu_register_boot_set is implemented in PATCH 2/2. on reset boot_device is restored to NULL For me, a null .default_boot_order means machine type does not support boot order (this is how commit c165473 treats it). Arguably, --boot order and once should be rejected then. AFICS SLOF handles qemu,boot-device as boot device, if nothing passed then it goes disk, cdrom, network. Which is the same as cdn list. That's not entirely true. If SLOF doesn't see qemu,boot-device, it first goes via its NVRAM configured boot list and only if nothing is there it falls back to cdn. Maybe the actual appropriate thing would be mcdn with m meaning NVRAM. Alex If I understand you correctly, your machine type does support boot order. Giving it a non-null .default_boot_order makes sense then. The appropriate value depends on firmware. It could even be . The null check in spapr_create_fdt_skel() looks superfluous then. Consider dropping it. Makes sense?
[Qemu-devel] [PATCH 0/2] pc: Fix startup with memory hotplug enabled
Tweak error messages to make sense and add check to verify that maxmem_size is properly aligned right away rather than just crashing afterwards. Peter Krempa (2): vl.c: Fix error messages when parsing maxmem parameters pc: memory: Validate alignment of maxram_size to page size hw/i386/pc.c | 7 +++ vl.c | 22 +++--- 2 files changed, 14 insertions(+), 15 deletions(-) -- 2.2.1
Re: [Qemu-devel] [PATCH v2 0/4] target-arm: ARM64: Adding EL1 AARCH32 guest support
On Mon, Jan 26, 2015 at 5:03 AM, Christoffer Dall christoffer.d...@linaro.org wrote: On Wed, Jan 21, 2015 at 12:49:49PM -0600, Greg Bellows wrote: Added support for running an AArch32 guest on a AArch64 KVM host. Support has only been added to the QEMU machvirt machine. The addition of CPU properties specifiable from the command line were added to allow disablement of AArch64 execution state hereby forcing EL1 to be AArch32. The new CPU command line property is aarch64=on/off that is specified as follows: aarch64-softmmu/qemu-system-aarch64 -M virt -cpu cortex-a57,aarch64=off ... This patch set seems to break standard aarch64 KVM guest functionality, I never see my guest progressing -Christoffer Hmm... sounds like something I need to debug. I'll work with you on the environment.
[Qemu-devel] [PATCH 32/50] blockdev: Check BB validity in eject and change
Both commands will be reimplemented in a follow-up to this patch so this does not need to be nice, it just has to work. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 35 +-- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/blockdev.c b/blockdev.c index 7f4470f..f3091df 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1756,10 +1756,10 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) BlockDriverState *bs = blk_bs(blk); AioContext *aio_context; -aio_context = bdrv_get_aio_context(bs); +aio_context = blk_get_aio_context(blk); aio_context_acquire(aio_context); -if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { +if (bs bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { goto out; } if (!blk_dev_has_removable_media(blk)) { @@ -1777,7 +1777,9 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) } } -bdrv_close(bs); +if (bs) { +bdrv_close(bs); +} out: aio_context_release(aio_context); @@ -1830,18 +1832,21 @@ out: } /* Assumes AioContext is held */ -static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, +static void qmp_bdrv_open_encrypted(BlockDriverState **pbs, +const char *filename, int bdrv_flags, BlockDriver *drv, const char *password, Error **errp) { +BlockDriverState *bs; Error *local_err = NULL; int ret; -ret = bdrv_open(bs, filename, NULL, NULL, bdrv_flags, drv, local_err); +ret = bdrv_open(pbs, filename, NULL, NULL, bdrv_flags, drv, local_err); if (ret 0) { error_propagate(errp, local_err); return; } +bs = *pbs; if (bdrv_key_required(bs)) { if (password) { @@ -1865,6 +1870,7 @@ void qmp_change_blockdev(const char *device, const char *filename, AioContext *aio_context; BlockDriver *drv = NULL; int bdrv_flags; +bool new_bs; Error *err = NULL; blk = blk_by_name(device); @@ -1873,12 +1879,13 @@ void qmp_change_blockdev(const char *device, const char *filename, return; } bs = blk_bs(blk); +new_bs = !bs; -aio_context = bdrv_get_aio_context(bs); +aio_context = blk_get_aio_context(blk); aio_context_acquire(aio_context); if (format) { -drv = bdrv_find_whitelisted_format(format, bs-read_only); +drv = bdrv_find_whitelisted_format(format, blk_is_read_only(blk)); if (!drv) { error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); goto out; @@ -1891,10 +1898,18 @@ void qmp_change_blockdev(const char *device, const char *filename, goto out; } -bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR; -bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0; +bdrv_flags = blk_is_read_only(blk) ? 0 : BDRV_O_RDWR; +bdrv_flags |= blk_get_root_state(blk)-open_flags ~BDRV_O_RDWR; -qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp); +qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, err); +if (err) { +error_propagate(errp, err); +} else if (new_bs) { +blk_insert_bs(blk, bs); +/* Has been sent automatically by bdrv_open() if blk_bs(blk) was not + * NULL */ +blk_dev_change_media_cb(blk, true); +} out: aio_context_release(aio_context); -- 2.1.0
[Qemu-devel] [PATCH 19/50] blockdev: Use BlockBackend for blockdev-backup TA
When preparing a blockdev-backup transaction, the BlockBackend should be used because there may be no medium associated to the BB (which would make bdrv_find() fail, whereas blk_by_name() does not). This does not make a real difference because blockdev-backup will fail without a medium anyway; however, it will have an impact on the error returned (device not found vs. no medium). Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 17 ++--- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/blockdev.c b/blockdev.c index c9e9ab9..ae1137f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1562,27 +1562,27 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp) { BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); BlockdevBackup *backup; -BlockDriverState *bs, *target; +BlockBackend *blk, *target; Error *local_err = NULL; assert(common-action-kind == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); backup = common-action-blockdev_backup; -bs = bdrv_find(backup-device); -if (!bs) { +blk = blk_by_name(backup-device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, backup-device); return; } -target = bdrv_find(backup-target); +target = blk_by_name(backup-target); if (!target) { error_set(errp, QERR_DEVICE_NOT_FOUND, backup-target); return; } /* AioContext is released in .clean() */ -state-aio_context = bdrv_get_aio_context(bs); -if (state-aio_context != bdrv_get_aio_context(target)) { +state-aio_context = blk_get_aio_context(blk); +if (state-aio_context != blk_get_aio_context(target)) { state-aio_context = NULL; error_setg(errp, Backup between two IO threads is not implemented); return; @@ -1600,7 +1600,10 @@ static void blockdev_backup_prepare(BlkTransactionState *common, Error **errp) return; } -state-bs = bs; +/* qmp_blockdev_backup() would have failed otherwise */ +assert(blk_bs(blk)); + +state-bs = blk_bs(blk); state-job = state-bs-job; } -- 2.1.0
[Qemu-devel] [PATCH 49/50] iotests: More options for VM.add_drive()
This patch allows specifying the interface to be used for the drive, and makes specifying a path optional (if the path is None, the file option will be omitted, thus creating an empty drive). Signed-off-by: Max Reitz mre...@redhat.com --- tests/qemu-iotests/iotests.py | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 241b5ee..27b2490 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -94,13 +94,16 @@ class VM(object): self._args.append('-monitor') self._args.append(args) -def add_drive(self, path, opts=''): +def add_drive(self, path, opts='', interface='virtio'): '''Add a virtio-blk drive to the VM''' -options = ['if=virtio', +options = ['if=%s' % interface, 'format=%s' % imgfmt, 'cache=%s' % cachemode, - 'file=%s' % path, 'id=drive%d' % self._num_drives] + +if not path is None: +options.append('file=%s' % path) + if opts: options.append(opts) -- 2.1.0
[Qemu-devel] [PATCH v2 1/1] dataplane: endianness-aware accesses
The vring.c code currently assumes that guest and host endianness match, which is not true for a number of cases: - emulating targets with a different endianness than the host - bi-endian targets, where the correct endianness depends on the virtio device - upcoming support for the virtio-1 standard mandates little-endian accesses even for big-endian targets and hosts Make sure to use accessors that depend on the virtio device. Note that dataplane now needs to be built per-target. Cc: Stefan Hajnoczi stefa...@redhat.com Cc: Paolo Bonzini pbonz...@redhat.com Cc: Fam Zheng f...@redhat.com Reviewed-by: David Gibson da...@gibson.dropbear.id.au Tested-by: David Gibson da...@gibson.dropbear.id.au Signed-off-by: Cornelia Huck cornelia.h...@de.ibm.com --- hw/block/dataplane/virtio-blk.c | 4 +- hw/scsi/virtio-scsi-dataplane.c | 2 +- hw/virtio/Makefile.objs | 2 +- hw/virtio/dataplane/Makefile.objs | 2 +- hw/virtio/dataplane/vring.c | 53 --- include/hw/virtio/dataplane/vring-accessors.h | 75 +++ include/hw/virtio/dataplane/vring.h | 14 + 7 files changed, 117 insertions(+), 35 deletions(-) create mode 100644 include/hw/virtio/dataplane/vring-accessors.h diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 39c5d71..7ae4e03 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -16,7 +16,9 @@ #include qemu/iov.h #include qemu/thread.h #include qemu/error-report.h +#include hw/virtio/virtio-access.h #include hw/virtio/dataplane/vring.h +#include hw/virtio/dataplane/vring-accessors.h #include sysemu/block-backend.h #include hw/virtio/virtio-blk.h #include virtio-blk.h @@ -75,7 +77,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status) VirtIOBlockDataPlane *s = req-dev-dataplane; stb_p(req-in-status, status); -vring_push(req-dev-dataplane-vring, req-elem, +vring_push(s-vdev, req-dev-dataplane-vring, req-elem, req-qiov.size + sizeof(*req-in)); /* Suppress notification to guest by BH and its scheduled diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 03a1e8c..418d73b 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -94,7 +94,7 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req) { VirtIODevice *vdev = VIRTIO_DEVICE(req-vring-parent); -vring_push(req-vring-vring, req-elem, +vring_push(vdev, req-vring-vring, req-elem, req-qsgl.size + req-resp_iov.size); if (vring_should_notify(vdev, req-vring-vring)) { diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index d21c397..19b224a 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -2,7 +2,7 @@ common-obj-y += virtio-rng.o common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o common-obj-y += virtio-bus.o common-obj-y += virtio-mmio.o -common-obj-$(CONFIG_VIRTIO) += dataplane/ +obj-$(CONFIG_VIRTIO) += dataplane/ obj-y += virtio.o virtio-balloon.o obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o diff --git a/hw/virtio/dataplane/Makefile.objs b/hw/virtio/dataplane/Makefile.objs index 9a8cfc0..753a9ca 100644 --- a/hw/virtio/dataplane/Makefile.objs +++ b/hw/virtio/dataplane/Makefile.objs @@ -1 +1 @@ -common-obj-y += vring.o +obj-y += vring.o diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 61f6d83..87d9121 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -18,7 +18,9 @@ #include hw/hw.h #include exec/memory.h #include exec/address-spaces.h +#include hw/virtio/virtio-access.h #include hw/virtio/dataplane/vring.h +#include hw/virtio/dataplane/vring-accessors.h #include qemu/error-report.h /* vring_map can be coupled with vring_unmap or (if you still have the @@ -83,7 +85,7 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) vring_init(vring-vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096); vring-last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n); -vring-last_used_idx = vring-vr.used-idx; +vring-last_used_idx = vring_get_used_idx(vdev, vring); vring-signalled_used = 0; vring-signalled_used_valid = false; @@ -104,7 +106,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) void vring_disable_notification(VirtIODevice *vdev, Vring *vring) { if (!(vdev-guest_features (1 VIRTIO_RING_F_EVENT_IDX))) { -vring-vr.used-flags |= VRING_USED_F_NO_NOTIFY; +vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); } } @@ -117,10 +119,10 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) if (vdev-guest_features (1 VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(vring-vr) = vring-vr.avail-idx; } else { -vring-vr.used-flags = ~VRING_USED_F_NO_NOTIFY; +
[Qemu-devel] [PATCH v2 0/1] dataplane vs. endianness
Stefan: Here's v2 of my endianness patch for dataplane, with the extraneous vdev argument dropped from get_desc(). I orginally planned to send my virtio-1 patchset as well, but I haven't found the time for it; therefore, I think this should be applied independently. David: I take it your r-b still holds? Cornelia Huck (1): dataplane: endianness-aware accesses hw/block/dataplane/virtio-blk.c | 4 +- hw/scsi/virtio-scsi-dataplane.c | 2 +- hw/virtio/Makefile.objs | 2 +- hw/virtio/dataplane/Makefile.objs | 2 +- hw/virtio/dataplane/vring.c | 53 --- include/hw/virtio/dataplane/vring-accessors.h | 75 +++ include/hw/virtio/dataplane/vring.h | 14 + 7 files changed, 117 insertions(+), 35 deletions(-) create mode 100644 include/hw/virtio/dataplane/vring-accessors.h -- 2.1.4
[Qemu-devel] [PATCH v3 10/14] qemu-io: Remove growable option
Remove growable option from the open command and from the qemu-io command line. qemu-io is about to be converted to BlockBackend which will make sure that no request exceeds the image size, so the only way to keep growable would be to use BlockBackend if it is not given and to directly access the BDS if it is. qemu-io is a debugging tool, therefore removing a rarely used option will have only a very small impact, if any. There was only one qemu-iotest which used the option; since it is not critical, this patch just removes it. Signed-off-by: Max Reitz mre...@redhat.com --- qemu-io.c | 23 +++ tests/qemu-iotests/016 | 73 -- tests/qemu-iotests/016.out | 23 --- tests/qemu-iotests/group | 1 - 4 files changed, 4 insertions(+), 116 deletions(-) delete mode 100755 tests/qemu-iotests/016 delete mode 100644 tests/qemu-iotests/016.out diff --git a/qemu-io.c b/qemu-io.c index 81f8f64..0237ecb 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -50,7 +50,7 @@ static const cmdinfo_t close_cmd = { .oneline= close the current open file, }; -static int openfile(char *name, int flags, int growable, QDict *opts) +static int openfile(char *name, int flags, QDict *opts) { Error *local_err = NULL; @@ -60,10 +60,6 @@ static int openfile(char *name, int flags, int growable, QDict *opts) return 1; } -if (growable) { -flags |= BDRV_O_PROTOCOL; -} - qemuio_blk = blk_new_open(hda, name, NULL, opts, flags, local_err); if (!qemuio_blk) { fprintf(stderr, %s: can't open%s%s: %s\n, progname, @@ -90,7 +86,6 @@ static void open_help(void) -r, -- open file read-only\n -s, -- use snapshot file\n -n, -- disable host cache\n - -g, -- allow file to grow (only applies to protocols)\n -o, -- options to be given to the block driver \n); } @@ -123,7 +118,6 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) { int flags = 0; int readonly = 0; -int growable = 0; int c; QemuOpts *qopts; QDict *opts; @@ -139,9 +133,6 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) case 'r': readonly = 1; break; -case 'g': -growable = 1; -break; case 'o': if (!qemu_opts_parse(empty_opts, optarg, 0)) { printf(could not parse option list -- %s\n, optarg); @@ -164,9 +155,9 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) qemu_opts_reset(empty_opts); if (optind == argc - 1) { -return openfile(argv[optind], flags, growable, opts); +return openfile(argv[optind], flags, opts); } else if (optind == argc) { -return openfile(NULL, flags, growable, opts); +return openfile(NULL, flags, opts); } else { QDECREF(opts); return qemuio_command_usage(open_cmd); @@ -200,7 +191,6 @@ static void usage(const char *name) -r, --read-only export read-only\n -s, --snapshot use snapshot file\n -n, --nocachedisable host cache\n - -g, --growable allow file to grow (only applies to protocols)\n -m, --misalign misalign allocations for O_DIRECT\n -k, --native-aio use kernel AIO implementation (on Linux only)\n -t, --cache=MODE use the given cache mode for the image\n @@ -359,7 +349,6 @@ static void reenable_tty_echo(void) int main(int argc, char **argv) { int readonly = 0; -int growable = 0; const char *sopt = hVc:d:f:rsnmgkt:T:; const struct option lopt[] = { { help, 0, NULL, 'h' }, @@ -371,7 +360,6 @@ int main(int argc, char **argv) { snapshot, 0, NULL, 's' }, { nocache, 0, NULL, 'n' }, { misalign, 0, NULL, 'm' }, -{ growable, 0, NULL, 'g' }, { native-aio, 0, NULL, 'k' }, { discard, 1, NULL, 'd' }, { cache, 1, NULL, 't' }, @@ -422,9 +410,6 @@ int main(int argc, char **argv) case 'm': qemuio_misalign = true; break; -case 'g': -growable = 1; -break; case 'k': flags |= BDRV_O_NATIVE_AIO; break; @@ -482,7 +467,7 @@ int main(int argc, char **argv) } if ((argc - optind) == 1) { -openfile(argv[optind], flags, growable, opts); +openfile(argv[optind], flags, opts); } command_loop(); diff --git a/tests/qemu-iotests/016 b/tests/qemu-iotests/016 deleted file mode 100755 index 52397aa..000 --- a/tests/qemu-iotests/016 +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash -# -# Test I/O after EOF for growable images. -# -# Copyright (C) 2009 Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -#
[Qemu-devel] [PATCH v3 04/14] block/xen: Use blk_new_open() in blk_connect()
Signed-off-by: Max Reitz mre...@redhat.com --- hw/block/xen_disk.c | 28 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index 21842a0..1b0257c 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -40,6 +40,8 @@ #include xen_blkif.h #include sysemu/blockdev.h #include sysemu/block-backend.h +#include qapi/qmp/qdict.h +#include qapi/qmp/qstring.h /* - */ @@ -897,30 +899,24 @@ static int blk_connect(struct XenDevice *xendev) blkdev-dinfo = drive_get(IF_XEN, 0, index); if (!blkdev-dinfo) { Error *local_err = NULL; -BlockBackend *blk; -BlockDriver *drv; -BlockDriverState *bs; +QDict *options = NULL; -/* setup via xenbus - create new block driver instance */ -xen_be_printf(blkdev-xendev, 2, create new bdrv (xenbus setup)\n); -blk = blk_new_with_bs(blkdev-dev, NULL); -if (!blk) { -return -1; +if (strcmp(blkdev-fileproto, unset)) { +options = qdict_new(); +qdict_put_obj(options, driver, + QOBJECT(qstring_from_str(blkdev-fileproto))); } -blkdev-blk = blk; -bs = blk_bs(blk); -drv = bdrv_find_whitelisted_format(blkdev-fileproto, readonly); -if (bdrv_open(bs, blkdev-filename, NULL, NULL, qflags, - drv, local_err) != 0) { +/* setup via xenbus - create new block driver instance */ +xen_be_printf(blkdev-xendev, 2, create new bdrv (xenbus setup)\n); +blkdev-blk = blk_new_open(blkdev-dev, blkdev-filename, NULL, options, + qflags, local_err); +if (!blkdev-blk) { xen_be_printf(blkdev-xendev, 0, error: %s\n, error_get_pretty(local_err)); error_free(local_err); -blk_unref(blk); -blkdev-blk = NULL; return -1; } -assert(bs == blk_bs(blk)); } else { /* setup via qemu cmdline - already setup for us */ xen_be_printf(blkdev-xendev, 2, get configured bdrv (cmdline setup)\n); -- 2.1.0
[Qemu-devel] [PATCH v3 13/14] block: Remove growable from BDS
Now that request clamping is done in the BlockBackend, the growable field can be removed from the BlockDriverState. All BDSs are now treated as being growable (that is, they are allowed to grow; they are not necessarily actually able to). Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 24 +--- block/qcow2.c | 6 -- block/raw-posix.c | 2 +- block/raw-win32.c | 2 +- block/sheepdog.c | 2 +- include/block/block_int.h | 3 --- 6 files changed, 8 insertions(+), 31 deletions(-) diff --git a/block.c b/block.c index d45e4dd..356a857 100644 --- a/block.c +++ b/block.c @@ -970,7 +970,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, bs-zero_beyond_eof = true; open_flags = bdrv_open_flags(bs, flags); bs-read_only = !(open_flags BDRV_O_RDWR); -bs-growable = !!(flags BDRV_O_PROTOCOL); if (use_bdrv_whitelist !bdrv_is_whitelisted(drv, bs-read_only)) { error_setg(errp, @@ -1885,7 +1884,6 @@ void bdrv_close(BlockDriverState *bs) bs-encrypted = 0; bs-valid_key = 0; bs-sg = 0; -bs-growable = 0; bs-zero_beyond_eof = false; QDECREF(bs-options); bs-options = NULL; @@ -2645,25 +2643,13 @@ exit: static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, size_t size) { -int64_t len; - if (size INT_MAX) { return -EIO; } -if (!bdrv_is_inserted(bs)) +if (!bdrv_is_inserted(bs)) { return -ENOMEDIUM; - -if (bs-growable) -return 0; - -len = bdrv_getlength(bs); - -if (offset 0) -return -EIO; - -if ((offset len) || (len - offset size)) -return -EIO; +} return 0; } @@ -3045,10 +3031,10 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs, } /* Forward the request to the BlockDriver */ -if (!(bs-zero_beyond_eof bs-growable)) { +if (!bs-zero_beyond_eof) { ret = drv-bdrv_co_readv(bs, sector_num, nb_sectors, qiov); } else { -/* Read zeros after EOF of growable BDSes */ +/* Read zeros after EOF */ int64_t total_sectors, max_nb_sectors; total_sectors = bdrv_nb_sectors(bs); @@ -3328,7 +3314,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, block_acct_highest_sector(bs-stats, sector_num, nb_sectors); -if (bs-growable ret = 0) { +if (ret = 0) { bs-total_sectors = MAX(bs-total_sectors, sector_num + nb_sectors); } diff --git a/block/qcow2.c b/block/qcow2.c index dbaf016..2b31dac 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2521,15 +2521,12 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, { BDRVQcowState *s = bs-opaque; int64_t total_sectors = bs-total_sectors; -int growable = bs-growable; bool zero_beyond_eof = bs-zero_beyond_eof; int ret; BLKDBG_EVENT(bs-file, BLKDBG_VMSTATE_SAVE); -bs-growable = 1; bs-zero_beyond_eof = false; ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov); -bs-growable = growable; bs-zero_beyond_eof = zero_beyond_eof; /* bdrv_co_do_writev will have increased the total_sectors value to include @@ -2544,15 +2541,12 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size) { BDRVQcowState *s = bs-opaque; -int growable = bs-growable; bool zero_beyond_eof = bs-zero_beyond_eof; int ret; BLKDBG_EVENT(bs-file, BLKDBG_VMSTATE_LOAD); -bs-growable = 1; bs-zero_beyond_eof = false; ret = bdrv_pread(bs, qcow2_vm_state_offset(s) + pos, buf, size); -bs-growable = growable; bs-zero_beyond_eof = zero_beyond_eof; return ret; diff --git a/block/raw-posix.c b/block/raw-posix.c index e51293a..5debc72 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -984,7 +984,7 @@ static int aio_worker(void *arg) switch (aiocb-aio_type QEMU_AIO_TYPE_MASK) { case QEMU_AIO_READ: ret = handle_aiocb_rw(aiocb); -if (ret = 0 ret aiocb-aio_nbytes aiocb-bs-growable) { +if (ret = 0 ret aiocb-aio_nbytes) { iov_memset(aiocb-aio_iov, aiocb-aio_niov, ret, 0, aiocb-aio_nbytes - ret); diff --git a/block/raw-win32.c b/block/raw-win32.c index 06243d7..dae5d2f 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -101,7 +101,7 @@ static int aio_worker(void *arg) switch (aiocb-aio_type QEMU_AIO_TYPE_MASK) { case QEMU_AIO_READ: count = handle_aiocb_rw(aiocb); -if (count aiocb-aio_nbytes aiocb-bs-growable) { +if (count aiocb-aio_nbytes) { /* A short read means that we have reached EOF. Pad the buffer * with zeros for bytes after EOF. */ iov_memset(aiocb-aio_iov, aiocb-aio_niov,
[Qemu-devel] [PATCH v3 02/14] block: Add blk_new_open()
blk_new_with_bs() creates a BlockBackend with an empty BlockDriverState attached to it. Empty BDSs are not nice, therefore add an alternative function which combines blk_new_with_bs() with bdrv_open(). Note: In contrast to bdrv_open() which takes a BlockDriver parameter, blk_new_open() does not take such a parameter. This is because bdrv_open() opens a BlockDriverState, therefore it is naturally to be able to set the BlockDriver for that BDS. The fact that bdrv_open() can open more than a single BDS is merely some form of a byproduct. blk_new_open() on the other hand is intended to be used to create a whole tree of BlockDriverStates. Therefore, setting a single BlockDriver does not make much sense. Instead, the drivers to be used for each of the nodes must be configured through the options QDict; including the driver of the root BDS. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 34 ++ include/sysemu/block-backend.h | 3 +++ 2 files changed, 37 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index b359545..543edaa 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -91,6 +91,40 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp) return blk; } +/* + * Calls blk_new_with_bs() and then calls bdrv_open() on the BlockDriverState. + * + * Just as with bdrv_open(), after having called this function the reference to + * @options belongs to the block layer (even on failure). + * + * TODO: Remove @filename and @flags; it should be possible to specify a whole + * BDS tree just by specifying the @options QDict (or @reference, + * alternatively). At the time of adding this function, this is not possible, + * though, so callers of this function have to be able to specify @filename and + * @flags. + */ +BlockBackend *blk_new_open(const char *name, const char *filename, + const char *reference, QDict *options, int flags, + Error **errp) +{ +BlockBackend *blk; +int ret; + +blk = blk_new_with_bs(name, errp); +if (!blk) { +QDECREF(options); +return NULL; +} + +ret = bdrv_open(blk-bs, filename, reference, options, flags, NULL, errp); +if (ret 0) { +blk_unref(blk); +return NULL; +} + +return blk; +} + static void blk_delete(BlockBackend *blk) { assert(!blk-refcnt); diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 38afa79..f39bb5c 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -62,6 +62,9 @@ typedef struct BlockDevOps { BlockBackend *blk_new(const char *name, Error **errp); BlockBackend *blk_new_with_bs(const char *name, Error **errp); +BlockBackend *blk_new_open(const char *name, const char *filename, + const char *reference, QDict *options, int flags, + Error **errp); void blk_ref(BlockBackend *blk); void blk_unref(BlockBackend *blk); const char *blk_name(BlockBackend *blk); -- 2.1.0
[Qemu-devel] [PATCH 09/50] block: Move guest_block_size into BlockBackend
guest_block_size is a guest device property so it should be moved into the interface between block layer and guest devices, which is the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 7 --- block/block-backend.c | 7 +-- include/block/block.h | 1 - include/block/block_int.h | 3 --- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/block.c b/block.c index aff7682..eff92ca 100644 --- a/block.c +++ b/block.c @@ -965,7 +965,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, } bs-open_flags = flags; -bs-guest_block_size = 512; bs-request_alignment = 512; bs-zero_beyond_eof = true; open_flags = bdrv_open_flags(bs, flags); @@ -2039,7 +2038,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, /* move some fields that need to stay attached to the device */ /* dev info */ -bs_dest-guest_block_size = bs_src-guest_block_size; bs_dest-copy_on_read = bs_src-copy_on_read; bs_dest-enable_write_cache = bs_src-enable_write_cache; @@ -5286,11 +5284,6 @@ BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, return NULL; } -void bdrv_set_guest_block_size(BlockDriverState *bs, int align) -{ -bs-guest_block_size = align; -} - void *qemu_blockalign(BlockDriverState *bs, size_t size) { return qemu_memalign(bdrv_opt_mem_align(bs), size); diff --git a/block/block-backend.c b/block/block-backend.c index 4a2428e..bf0fcc9 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -31,6 +31,9 @@ struct BlockBackend { /* TODO change to DeviceState when all users are qdevified */ const BlockDevOps *dev_ops; void *dev_opaque; + +/* the block size for which the guest device expects atomicity */ +int guest_block_size; }; typedef struct BlockBackendAIOCB { @@ -334,7 +337,7 @@ void blk_detach_dev(BlockBackend *blk, void *dev) blk-dev = NULL; blk-dev_ops = NULL; blk-dev_opaque = NULL; -bdrv_set_guest_block_size(blk-bs, 512); +blk-guest_block_size = 512; blk_unref(blk); } @@ -763,7 +766,7 @@ int blk_get_flags(BlockBackend *blk) void blk_set_guest_block_size(BlockBackend *blk, int align) { -bdrv_set_guest_block_size(blk-bs, align); +blk-guest_block_size = align; } void *blk_blockalign(BlockBackend *blk, size_t size) diff --git a/include/block/block.h b/include/block/block.h index 3082d2b..df656db 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -425,7 +425,6 @@ void bdrv_img_create(const char *filename, const char *fmt, /* Returns the alignment in bytes that is required so that no bounce buffer * is required throughout the stack */ size_t bdrv_opt_mem_align(BlockDriverState *bs); -void bdrv_set_guest_block_size(BlockDriverState *bs, int align); void *qemu_blockalign(BlockDriverState *bs, size_t size); void *qemu_blockalign0(BlockDriverState *bs, size_t size); void *qemu_try_blockalign(BlockDriverState *bs, size_t size); diff --git a/include/block/block_int.h b/include/block/block_int.h index b340e7e..c6ab73a 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -375,9 +375,6 @@ struct BlockDriverState { /* Alignment requirement for offset/length of I/O requests */ unsigned int request_alignment; -/* the block size for which the guest device expects atomicity */ -int guest_block_size; - /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; -- 2.1.0
[Qemu-devel] [PATCH 20/50] blockdev: Check blk_is_available() in sn-del-int-sync
Check whether the BlockBackend is actually available at the start of snapshot-delete-internal-sync. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 18 +- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index ae1137f..858d181 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1096,18 +1096,23 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, const char *name, Error **errp) { -BlockDriverState *bs = bdrv_find(device); +BlockBackend *blk; +BlockDriverState *bs; AioContext *aio_context; QEMUSnapshotInfo sn; Error *local_err = NULL; SnapshotInfo *info = NULL; int ret; -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return NULL; } +aio_context = blk_get_aio_context(blk); +aio_context_acquire(aio_context); + if (!has_id) { id = NULL; } @@ -1118,11 +1123,14 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, if (!id !name) { error_setg(errp, Name or id must be provided); -return NULL; +goto out_aio_context; } -aio_context = bdrv_get_aio_context(bs); -aio_context_acquire(aio_context); +if (!blk_is_available(blk)) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); +goto out_aio_context; +} +bs = blk_bs(blk); if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) { goto out_aio_context; -- 2.1.0
[Qemu-devel] [PATCH 36/50] blockdev: Allow more options for BB-less BDS tree
Most of the options which blockdev_init() parses for both the BlockBackend and the root BDS are valid for just the root BDS as well (e.g. read-only). This patch allows specifying these options even if not creating a BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 156 ++--- 1 file changed, 150 insertions(+), 6 deletions(-) diff --git a/blockdev.c b/blockdev.c index d573c5c..2f3ccb5 100644 --- a/blockdev.c +++ b/blockdev.c @@ -591,6 +591,61 @@ err_no_opts: return NULL; } +static QemuOptsList qemu_root_bds_opts; + +/* Takes the ownership of bs_opts */ +static BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp) +{ +BlockDriverState *bs; +QemuOpts *opts; +Error *local_error = NULL; +ThrottleConfig cfg; +BlockdevDetectZeroesOptions detect_zeroes; +int ret; +int bdrv_flags = 0; + +opts = qemu_opts_create(qemu_root_bds_opts, NULL, 1, errp); +if (!opts) { +goto fail; +} + +qemu_opts_absorb_qdict(opts, bs_opts, local_error); +if (local_error) { +error_propagate(errp, local_error); +goto fail; +} + +extract_common_blockdev_options(opts, bdrv_flags, cfg, detect_zeroes, +local_error); +if (local_error) { +error_propagate(errp, local_error); +goto fail; +} + +bs = NULL; +ret = bdrv_open(bs, NULL, NULL, bs_opts, bdrv_flags, NULL, errp); +if (ret 0) { +goto fail_no_bs_opts; +} + +bs-detect_zeroes = detect_zeroes; + +/* disk I/O throttling */ +if (throttle_enabled(cfg)) { +bdrv_io_limits_enable(bs); +bdrv_set_io_limits(bs, cfg); +} + +fail_no_bs_opts: +qemu_opts_del(opts); +return bs; + +fail: +qemu_opts_del(opts); +QDECREF(bs_opts); +return NULL; +} + static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to, Error **errp) { @@ -2994,12 +3049,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) bs = blk_bs(blk); } else { -int ret; - -bs = NULL; -ret = bdrv_open(bs, NULL, NULL, qdict, BDRV_O_RDWR | BDRV_O_CACHE_WB, -NULL, errp); -if (ret 0) { +bs = bds_tree_init(qdict, errp); +if (!bs) { goto fail; } } @@ -3150,6 +3201,99 @@ QemuOptsList qemu_common_drive_opts = { }, }; +static QemuOptsList qemu_root_bds_opts = { +.name = root-bds, +.head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head), +.desc = { +{ +.name = discard, +.type = QEMU_OPT_STRING, +.help = discard operation (ignore/off, unmap/on), +},{ +.name = cache.writeback, +.type = QEMU_OPT_BOOL, +.help = enables writeback mode for any caches, +},{ +.name = cache.direct, +.type = QEMU_OPT_BOOL, +.help = enables use of O_DIRECT (bypass the host page cache), +},{ +.name = cache.no-flush, +.type = QEMU_OPT_BOOL, +.help = ignore any flush requests for the device, +},{ +.name = aio, +.type = QEMU_OPT_STRING, +.help = host AIO implementation (threads, native), +},{ +.name = read-only, +.type = QEMU_OPT_BOOL, +.help = open drive file as read-only, +},{ +.name = throttling.iops-total, +.type = QEMU_OPT_NUMBER, +.help = limit total I/O operations per second, +},{ +.name = throttling.iops-read, +.type = QEMU_OPT_NUMBER, +.help = limit read operations per second, +},{ +.name = throttling.iops-write, +.type = QEMU_OPT_NUMBER, +.help = limit write operations per second, +},{ +.name = throttling.bps-total, +.type = QEMU_OPT_NUMBER, +.help = limit total bytes per second, +},{ +.name = throttling.bps-read, +.type = QEMU_OPT_NUMBER, +.help = limit read bytes per second, +},{ +.name = throttling.bps-write, +.type = QEMU_OPT_NUMBER, +.help = limit write bytes per second, +},{ +.name = throttling.iops-total-max, +.type = QEMU_OPT_NUMBER, +.help = I/O operations burst, +},{ +.name = throttling.iops-read-max, +.type = QEMU_OPT_NUMBER, +.help = I/O operations read burst, +},{ +.name = throttling.iops-write-max, +.type = QEMU_OPT_NUMBER, +.help = I/O operations write burst, +},{ +.name = throttling.bps-total-max, +.type = QEMU_OPT_NUMBER, +.help = total bytes burst, +},{ +
[Qemu-devel] [PATCH 15/50] block: Fail requests to empty BlockBackend
If there is no BlockDriverState in a BlockBackend or if the tray of the guest device is open, fail all requests (where that is possible) with -ENOMEDIUM. The reason the status of the guest device is taken into account is because once the guest device's tray is opened, any request on the same BlockBackend as the guest uses should fail. If the BDS tree is supposed to be usable even after ejecting it from the guest, a different BlockBackend must be used. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 43 ++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/block/block-backend.c b/block/block-backend.c index 62be370..4f3122a 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -507,7 +507,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset, return -EIO; } -if (!blk_is_inserted(blk)) { +if (!blk_is_available(blk)) { return -ENOMEDIUM; } @@ -635,6 +635,10 @@ int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count) int64_t blk_getlength(BlockBackend *blk) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_getlength(blk-bs); } @@ -670,6 +674,10 @@ BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num, BlockAIOCB *blk_aio_flush(BlockBackend *blk, BlockCompletionFunc *cb, void *opaque) { +if (!blk_is_available(blk)) { +return abort_aio_request(blk, cb, opaque, -ENOMEDIUM); +} + return bdrv_aio_flush(blk-bs, cb, opaque); } @@ -711,12 +719,20 @@ int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs) int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_ioctl(blk-bs, req, buf); } BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, BlockCompletionFunc *cb, void *opaque) { +if (!blk_is_available(blk)) { +return abort_aio_request(blk, cb, opaque, -ENOMEDIUM); +} + return bdrv_aio_ioctl(blk-bs, req, buf, cb, opaque); } @@ -732,11 +748,19 @@ int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors) int blk_co_flush(BlockBackend *blk) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_co_flush(blk-bs); } int blk_flush(BlockBackend *blk) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_flush(blk-bs); } @@ -853,6 +877,11 @@ void blk_set_enable_write_cache(BlockBackend *blk, bool wce) void blk_invalidate_cache(BlockBackend *blk, Error **errp) { +if (!blk-bs) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, blk-name); +return; +} + bdrv_invalidate_cache(blk-bs, errp); } @@ -1003,6 +1032,10 @@ int blk_write_compressed(BlockBackend *blk, int64_t sector_num, int blk_truncate(BlockBackend *blk, int64_t offset) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_truncate(blk-bs, offset); } @@ -1019,11 +1052,19 @@ int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors) int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, int64_t pos, int size) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_save_vmstate(blk-bs, buf, pos, size); } int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size) { +if (!blk_is_available(blk)) { +return -ENOMEDIUM; +} + return bdrv_load_vmstate(blk-bs, buf, pos, size); } -- 2.1.0
[Qemu-devel] [PATCH 45/50] qmp: Introduce blockdev-change-medium
Introduce a new QMP command 'blockdev-change-medium' which is intended to replace the 'change' command for block devices. The existing function qmp_change_blockdev() is accordingly renamed to qmp_blockdev_change_medium(). Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c| 7 --- include/sysemu/blockdev.h | 2 -- qapi-schema.json | 3 ++- qapi/block-core.json | 23 +++ qmp-commands.hx | 31 +++ qmp.c | 2 +- 6 files changed, 61 insertions(+), 7 deletions(-) diff --git a/blockdev.c b/blockdev.c index 6e440b8..2ada2b1 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2012,8 +2012,9 @@ void qmp_blockdev_insert_medium(const char *device, const char *node_name, qmp_blockdev_insert_anon_medium(device, bs, errp); } -void qmp_change_blockdev(const char *device, const char *filename, - const char *format, Error **errp) +void qmp_blockdev_change_medium(const char *device, const char *filename, +bool has_format, const char *format, +Error **errp) { BlockBackend *blk; BlockBackendRootState *blk_rs; @@ -2036,7 +2037,7 @@ void qmp_change_blockdev(const char *device, const char *filename, bdrv_flags = blk_rs-read_only ? 0 : BDRV_O_RDWR; bdrv_flags |= blk_rs-open_flags ~BDRV_O_RDWR; -if (format) { +if (has_format) { drv = bdrv_find_whitelisted_format(format, bdrv_flags BDRV_O_RDWR); if (!drv) { error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 09d1e30..2a34332 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -65,8 +65,6 @@ DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type); DriveInfo *add_init_drive(const char *opts); -void qmp_change_blockdev(const char *device, const char *filename, - const char *format, Error **errp); void do_commit(Monitor *mon, const QDict *qdict); int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); #endif diff --git a/qapi-schema.json b/qapi-schema.json index e16f8eb..61867e1 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1649,7 +1649,8 @@ # device between when these calls are executed is undefined. # # Notes: It is strongly recommended that this interface is not used especially -# for changing block devices. +# for changing block devices. Please use blockdev-change-medium +# instead (for VNC, please use change-vnc-password). # # Since: 0.14.0 ## diff --git a/qapi/block-core.json b/qapi/block-core.json index ba41015..d3c3ca7 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1785,6 +1785,29 @@ ## +# @blockdev-change-medium: +# +# Changes the medium inserted into a block device by ejecting the current medium +# and loading a new image file which is inserted as the new medium (this command +# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium +# and blockdev-close-tray). +# +# @device: block device name +# +# @filename:filename of the new image to be loaded +# +# @format: #optional, format to open the new image with (defaults to the +# probed format) +# +# Since: 2.3 +## +{ 'command': 'blockdev-change-medium', + 'data': { 'device': 'str', +'filename': 'str', +'*format': 'str' } } + + +## # @BlockErrorAction # # An enumeration of action that has been taken when a DISK I/O occurs diff --git a/qmp-commands.hx b/qmp-commands.hx index 604d638..1987a09 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3854,6 +3854,37 @@ Example: EQMP { +.name = blockdev-change-medium, +.args_type = device:B,filename:F,format:s?, +.mhandler.cmd_new = qmp_marshal_input_blockdev_change_medium, +}, + +SQMP +blockdev-change-medium +-- + +Changes the medium inserted into a block device by ejecting the current medium +and loading a new image file which is inserted as the new medium. + +Arguments: + +- device: device name (json-string) +- filename: filename of the new image (json-string) +- format: format of the new image (json-string, optional) + +Examples: + +1. Change a removable medium + +- { execute: blockdev-change-medium, + arguments: { device: ide1-cd0, +filename: /srv/images/Fedora-12-x86_64-DVD.iso, +format: raw } } +- { return: {} } + +EQMP + +{ .name = query-memdev, .args_type = , .mhandler.cmd_new = qmp_marshal_input_query_memdev, diff --git a/qmp.c b/qmp.c index 635d001..1cfdb74 100644 --- a/qmp.c +++ b/qmp.c @@ -417,7 +417,7 @@ void qmp_change(const char *device, const char *target, if (strcmp(device, vnc) == 0) {
[Qemu-devel] [PATCH 28/50] blockdev: Check BB validity in drive-mirror
Call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index e335d06..4e12061 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2516,6 +2516,7 @@ void qmp_drive_mirror(const char *device, const char *target, bool has_on_target_error, BlockdevOnError on_target_error, Error **errp) { +BlockBackend *blk; BlockDriverState *bs; BlockDriverState *source, *target_bs; AioContext *aio_context; @@ -2555,19 +2556,20 @@ void qmp_drive_mirror(const char *device, const char *target, return; } -bs = bdrv_find(device); -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } -aio_context = bdrv_get_aio_context(bs); +aio_context = blk_get_aio_context(blk); aio_context_acquire(aio_context); -if (!bdrv_is_inserted(bs)) { +if (!blk_is_available(blk)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); goto out; } +bs = blk_bs(blk); if (!has_format) { format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs-drv-format_name; -- 2.1.0
[Qemu-devel] [PATCH 43/50] blockdev: Implement change with basic operations
Implement 'change' on block devices by calling blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium (a variation of that which does not need a node-name) and blockdev-close-tray. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 191 +++-- 1 file changed, 72 insertions(+), 119 deletions(-) diff --git a/blockdev.c b/blockdev.c index 0b204eb..6e440b8 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1828,41 +1828,6 @@ exit: } } - -static void eject_device(BlockBackend *blk, int force, Error **errp) -{ -BlockDriverState *bs = blk_bs(blk); -AioContext *aio_context; - -aio_context = blk_get_aio_context(blk); -aio_context_acquire(aio_context); - -if (bs bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { -goto out; -} -if (!blk_dev_has_removable_media(blk)) { -error_setg(errp, Device '%s' is not removable, - bdrv_get_device_name(bs)); -goto out; -} - -if (blk_dev_is_medium_locked(blk) !blk_dev_is_tray_open(blk)) { -blk_dev_eject_request(blk, force); -if (!force) { -error_setg(errp, Device '%s' is locked, - bdrv_get_device_name(bs)); -goto out; -} -} - -if (bs) { -bdrv_close(bs); -} - -out: -aio_context_release(aio_context); -} - void qmp_eject(const char *device, bool has_force, bool force, Error **errp) { Error *local_err = NULL; @@ -1909,90 +1874,6 @@ out: aio_context_release(aio_context); } -/* Assumes AioContext is held */ -static void qmp_bdrv_open_encrypted(BlockDriverState **pbs, -const char *filename, -int bdrv_flags, BlockDriver *drv, -const char *password, Error **errp) -{ -BlockDriverState *bs; -Error *local_err = NULL; -int ret; - -ret = bdrv_open(pbs, filename, NULL, NULL, bdrv_flags, drv, local_err); -if (ret 0) { -error_propagate(errp, local_err); -return; -} -bs = *pbs; - -if (bdrv_key_required(bs)) { -if (password) { -if (bdrv_set_key(bs, password) 0) { -error_set(errp, QERR_INVALID_PASSWORD); -} -} else { -error_set(errp, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs), - bdrv_get_encrypted_filename(bs)); -} -} else if (password) { -error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); -} -} - -void qmp_change_blockdev(const char *device, const char *filename, - const char *format, Error **errp) -{ -BlockBackend *blk; -BlockDriverState *bs; -AioContext *aio_context; -BlockDriver *drv = NULL; -int bdrv_flags; -bool new_bs; -Error *err = NULL; - -blk = blk_by_name(device); -if (!blk) { -error_set(errp, QERR_DEVICE_NOT_FOUND, device); -return; -} -bs = blk_bs(blk); -new_bs = !bs; - -aio_context = blk_get_aio_context(blk); -aio_context_acquire(aio_context); - -if (format) { -drv = bdrv_find_whitelisted_format(format, blk_is_read_only(blk)); -if (!drv) { -error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); -goto out; -} -} - -eject_device(blk, 0, err); -if (err) { -error_propagate(errp, err); -goto out; -} - -bdrv_flags = blk_is_read_only(blk) ? 0 : BDRV_O_RDWR; -bdrv_flags |= blk_get_root_state(blk)-open_flags ~BDRV_O_RDWR; - -qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, err); -if (err) { -error_propagate(errp, err); -} else if (new_bs) { -blk_insert_bs(blk, bs); -/* Has been sent automatically by bdrv_open() if blk_bs(blk) was not - * NULL */ -blk_dev_change_media_cb(blk, true); -} - -out: -aio_context_release(aio_context); -} - void qmp_blockdev_open_tray(const char *device, bool has_force, bool force, Error **errp) { @@ -2131,6 +2012,78 @@ void qmp_blockdev_insert_medium(const char *device, const char *node_name, qmp_blockdev_insert_anon_medium(device, bs, errp); } +void qmp_change_blockdev(const char *device, const char *filename, + const char *format, Error **errp) +{ +BlockBackend *blk; +BlockBackendRootState *blk_rs; +BlockDriverState *medium_bs; +BlockDriver *drv = NULL; +int bdrv_flags, ret; +Error *err = NULL; + +blk = blk_by_name(device); +if (!blk) { +error_set(errp, QERR_DEVICE_NOT_FOUND, device); +return; +} + +if (blk_bs(blk)) { +blk_update_root_state(blk); +} + +blk_rs = blk_get_root_state(blk); +bdrv_flags = blk_rs-read_only ? 0 : BDRV_O_RDWR; +bdrv_flags |= blk_rs-open_flags ~BDRV_O_RDWR; + +if (format) { +drv =
[Qemu-devel] [PATCH 38/50] blockdev: Add blockdev-open-tray
Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 48 qapi/block-core.json | 21 + qmp-commands.hx | 37 + 3 files changed, 106 insertions(+) diff --git a/blockdev.c b/blockdev.c index 2f3ccb5..a0b9f17 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1993,6 +1993,54 @@ out: aio_context_release(aio_context); } +void qmp_blockdev_open_tray(const char *device, bool has_force, bool force, +Error **errp) +{ +BlockBackend *blk; +BlockDriverState *bs; +AioContext *aio_context = NULL; + +if (!has_force) { +force = false; +} + +blk = blk_by_name(device); +if (!blk) { +error_set(errp, QERR_DEVICE_NOT_FOUND, device); +return; +} + +if (!blk_dev_has_removable_media(blk)) { +error_setg(errp, Device '%s' is not removable, device); +return; +} + +if (blk_dev_is_tray_open(blk)) { +return; +} + +bs = blk_bs(blk); +if (bs) { +aio_context = bdrv_get_aio_context(bs); +aio_context_acquire(aio_context); + +if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { +goto out; +} +} + +if (blk_dev_is_medium_locked(blk)) { +blk_dev_eject_request(blk, force); +} else { +blk_dev_change_media_cb(blk, false); +} + +out: +if (aio_context) { +aio_context_release(aio_context); +} +} + /* throttling disk I/O limits */ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, int64_t bps_wr, diff --git a/qapi/block-core.json b/qapi/block-core.json index ca9bc32..029f08b 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1718,6 +1718,27 @@ ## { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } } +## +# @blockdev-open-tray: +# +# Opens a block device's tray. If there is a block driver state tree inserted as +# a medium, it will become inaccessible to the guest (but it will remain +# associated to the block device, so closing the tray will make it accessible +# again). +# +# @device: block device name +# +# @force: #optional if false (the default), an eject request will be sent to +# the guest if it has locked the tray (and the tray will not be opened +# immediately); if true, the tray will be opened regardless of whether +# it is locked +# +# Since: 2.3 +## +{ 'command': 'blockdev-open-tray', + 'data': { 'device': 'str', +'*force': 'bool' } } + ## # @BlockErrorAction diff --git a/qmp-commands.hx b/qmp-commands.hx index 7576c18..cfa1b98 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3641,6 +3641,43 @@ Example (2): EQMP { +.name = blockdev-open-tray, +.args_type = device:s,force:b?, +.mhandler.cmd_new = qmp_marshal_input_blockdev_open_tray, +}, + +SQMP +blockdev-open-tray +-- + +Opens a block device's tray. If there is a block driver state tree inserted as a +medium, it will become inaccessible to the guest (but it will remain associated +to the block device, so closing the tray will make it accessible again). + +Arguments: + +- device: block device name (json-string) +- force: if false (the default), an eject request will be sent to the guest if + it has locked the tray (and the tray will not be opened immediately); + if true, the tray will be opened regardless of whether it is locked + (json-bool, optional) + +Example (1): + +- { execute: blockdev-open-tray, + arguments: { device: ide1-cd0 } } + +- { timestamp: { seconds: 1418751016, +microseconds: 716996 }, + event: DEVICE_TRAY_MOVED, + data: { device: ide1-cd0, + tray-open: true } } + +- { return: {} } + +EQMP + +{ .name = query-named-block-nodes, .args_type = , .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes, -- 2.1.0
[Qemu-devel] [PATCH v2 1/2] target-s390x: Mark check_privileged() as !CONFIG_USER_ONLY
The function check_privileged() is only used in the softmmu configs; wrap it in an #ifndef CONFIG_USER_ONLY to avoid clang warnings on the linux-user builds. Signed-off-by: Peter Maydell peter.mayd...@linaro.org Reviewed-by: Stefan Weil s...@weilnetz.de Message-id: 1419373100-17690-2-git-send-email-peter.mayd...@linaro.org --- target-s390x/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index ab01bc0..1c3a8e8 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -317,12 +317,14 @@ static inline void gen_illegal_opcode(DisasContext *s) gen_program_exception(s, PGM_SPECIFICATION); } +#ifndef CONFIG_USER_ONLY static inline void check_privileged(DisasContext *s) { if (s-tb-flags (PSW_MASK_PSTATE 32)) { gen_program_exception(s, PGM_PRIVILEGED); } } +#endif static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2) { -- 1.9.1
[Qemu-devel] [PATCH] target-mips: use CP0EnLo_XI instead of magic number
Signed-off-by: Leon Alrae leon.al...@imgtec.com --- target-mips/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 635192c..77d89be 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4947,7 +4947,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) #if defined(TARGET_MIPS64) if (ctx-rxi) { TCGv tmp = tcg_temp_new(); -tcg_gen_andi_tl(tmp, arg, (3ull 62)); +tcg_gen_andi_tl(tmp, arg, (3ull CP0EnLo_XI)); tcg_gen_shri_tl(tmp, tmp, 32); tcg_gen_or_tl(arg, arg, tmp); tcg_temp_free(tmp); @@ -5002,7 +5002,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) #if defined(TARGET_MIPS64) if (ctx-rxi) { TCGv tmp = tcg_temp_new(); -tcg_gen_andi_tl(tmp, arg, (3ull 62)); +tcg_gen_andi_tl(tmp, arg, (3ull CP0EnLo_XI)); tcg_gen_shri_tl(tmp, tmp, 32); tcg_gen_or_tl(arg, arg, tmp); tcg_temp_free(tmp); -- 2.1.0
[Qemu-devel] [PATCH v3 07/14] qemu-img: Use BlockBackend as far as possible
Although qemu-img already creates BlockBackends, it does not do accesses to the images through them. This patch converts all of the bdrv_* calls for which this is currently possible to blk_* calls. Most of the remaining calls will probably stay bdrv_* calls because they really do operate on the BDS level instead of the BB level. Signed-off-by: Max Reitz mre...@redhat.com --- qemu-img.c | 98 ++ 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 0b23c87..8b4139e 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1008,19 +1008,19 @@ static int64_t sectors_to_process(int64_t total, int64_t from) * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero * data and negative value on error. * - * @param bs: Driver used for accessing file + * @param blk: BlockBackend for the image * @param sect_num: Number of first sector to check * @param sect_count: Number of sectors to check * @param filename: Name of disk file we are checking (logging purpose) * @param buffer: Allocated buffer for storing read data * @param quiet: Flag for quiet mode */ -static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num, +static int check_empty_sectors(BlockBackend *blk, int64_t sect_num, int sect_count, const char *filename, uint8_t *buffer, bool quiet) { int pnum, ret = 0; -ret = bdrv_read(bs, sect_num, buffer, sect_count); +ret = blk_read(blk, sect_num, buffer, sect_count); if (ret 0) { error_report(Error while reading offset % PRId64 of %s: %s, sectors_to_bytes(sect_num), filename, strerror(-ret)); @@ -1130,22 +1130,26 @@ static int img_compare(int argc, char **argv) } bs2 = blk_bs(blk2); -buf1 = qemu_blockalign(bs1, IO_BUF_SIZE); -buf2 = qemu_blockalign(bs2, IO_BUF_SIZE); -total_sectors1 = bdrv_nb_sectors(bs1); +buf1 = blk_blockalign(blk1, IO_BUF_SIZE); +buf2 = blk_blockalign(blk2, IO_BUF_SIZE); +total_sectors1 = blk_getlength(blk1); if (total_sectors1 0) { error_report(Can't get size of %s: %s, filename1, strerror(-total_sectors1)); ret = 4; goto out; } -total_sectors2 = bdrv_nb_sectors(bs2); +total_sectors2 = blk_getlength(blk2); if (total_sectors2 0) { error_report(Can't get size of %s: %s, filename2, strerror(-total_sectors2)); ret = 4; goto out; } + +total_sectors1 /= BDRV_SECTOR_SIZE; +total_sectors2 /= BDRV_SECTOR_SIZE; + total_sectors = MIN(total_sectors1, total_sectors2); progress_base = MAX(total_sectors1, total_sectors2); @@ -1181,7 +1185,7 @@ static int img_compare(int argc, char **argv) if (allocated1 == allocated2) { if (allocated1) { -ret = bdrv_read(bs1, sector_num, buf1, nb_sectors); +ret = blk_read(blk1, sector_num, buf1, nb_sectors); if (ret 0) { error_report(Error while reading offset % PRId64 of %s: %s, sectors_to_bytes(sector_num), filename1, @@ -1189,7 +1193,7 @@ static int img_compare(int argc, char **argv) ret = 4; goto out; } -ret = bdrv_read(bs2, sector_num, buf2, nb_sectors); +ret = blk_read(blk2, sector_num, buf2, nb_sectors); if (ret 0) { error_report(Error while reading offset % PRId64 of %s: %s, sectors_to_bytes(sector_num), @@ -1216,10 +1220,10 @@ static int img_compare(int argc, char **argv) } if (allocated1) { -ret = check_empty_sectors(bs1, sector_num, nb_sectors, +ret = check_empty_sectors(blk1, sector_num, nb_sectors, filename1, buf1, quiet); } else { -ret = check_empty_sectors(bs2, sector_num, nb_sectors, +ret = check_empty_sectors(blk2, sector_num, nb_sectors, filename2, buf1, quiet); } if (ret) { @@ -1236,18 +1240,18 @@ static int img_compare(int argc, char **argv) } if (total_sectors1 != total_sectors2) { -BlockDriverState *bs_over; +BlockBackend *blk_over; int64_t total_sectors_over; const char *filename_over; qprintf(quiet, Warning: Image size mismatch!\n); if (total_sectors1 total_sectors2) { total_sectors_over = total_sectors1; -bs_over = bs1; +blk_over = blk1; filename_over = filename1; } else { total_sectors_over = total_sectors2; -bs_over = bs2; +blk_over = blk2;
Re: [Qemu-devel] [PATCH] linux-user/syscall.c: Let all lock_user_struct() and unlock_user_struct() paired with each other
On 26 January 2015 at 14:59, Chen Gang S gang.c...@sunrus.com.cn wrote: On 1/26/15 06:10, Peter Maydell wrote: I would just like the commit message to be clear about the scope of the work the patch covers. If the patch is just Fix mismatched lock/unlock calls in IPC struct conversion functions then that's fine, but the commit message should say that. At the moment the commit message is very vague. OK, thanks. I am not quite familiar with this file, so I describe the modification by function name, e.g. lock_user_struct() and unlick_user_struct() in the patch subject. In a big file I think it's often more useful to describe the functions which are being changed. My suggested subject would be: Fix mismatched lock/unlock calls in IPC struct conversion functions Riku can decide if he wants a v2 or will just fix it up as he applies it to his linux-user tree. -- PMM
[Qemu-devel] [PATCH v3 01/14] block: Lift some BDS functions to the BlockBackend
Create the blk_* counterparts for the following bdrv_* functions (which make sense to call on the BlockBackend level): - bdrv_co_write_zeroes() - bdrv_write_compressed() - bdrv_truncate() - bdrv_discard() - bdrv_load_vmstate() - bdrv_save_vmstate() Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 33 + include/sysemu/block-backend.h | 9 + 2 files changed, 42 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index d00c129..b359545 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -663,3 +663,36 @@ void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, { return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque); } + +int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t sector_num, + int nb_sectors, BdrvRequestFlags flags) +{ +return bdrv_co_write_zeroes(blk-bs, sector_num, nb_sectors, flags); +} + +int blk_write_compressed(BlockBackend *blk, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ +return bdrv_write_compressed(blk-bs, sector_num, buf, nb_sectors); +} + +int blk_truncate(BlockBackend *blk, int64_t offset) +{ +return bdrv_truncate(blk-bs, offset); +} + +int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors) +{ +return bdrv_discard(blk-bs, sector_num, nb_sectors); +} + +int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, + int64_t pos, int size) +{ +return bdrv_save_vmstate(blk-bs, buf, pos, size); +} + +int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size) +{ +return bdrv_load_vmstate(blk-bs, buf, pos, size); +} diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 8871a02..38afa79 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -150,5 +150,14 @@ BlockAcctStats *blk_get_stats(BlockBackend *blk); void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, BlockCompletionFunc *cb, void *opaque); +int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t sector_num, + int nb_sectors, BdrvRequestFlags flags); +int blk_write_compressed(BlockBackend *blk, int64_t sector_num, + const uint8_t *buf, int nb_sectors); +int blk_truncate(BlockBackend *blk, int64_t offset); +int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors); +int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf, + int64_t pos, int size); +int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size); #endif -- 2.1.0
[Qemu-devel] [PATCH v2 1/4] target-tricore: target-tricore: Add instructions of RR1 opcode format, that have 0x93 as first opcode
Signed-off-by: Bastian Koppelmann kbast...@mail.uni-paderborn.de --- v1 - v2: - now uses 3 helper functions (gen_mul_q, gen_mul_q_16, gen_mulr_q) to remove repetition. - now uses 64 arithmetic instead of emulating it. - now uses arithmetic shift, instead of normal shift + sign extend for arg extraction. target-tricore/translate.c | 182 + 1 file changed, 182 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index def7f4a..804d181 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -987,6 +987,119 @@ static inline void gen_maddsui_32(TCGv ret, TCGv r1, TCGv r2, int32_t con) tcg_temp_free(temp); } +static void +gen_mul_q(TCGv rl, TCGv rh, TCGv arg1, TCGv arg2, uint32_t n, uint32_t up_shift) +{ +TCGv temp = tcg_temp_new(); +TCGv_i64 temp_64 = tcg_temp_new_i64(); +TCGv_i64 temp2_64 = tcg_temp_new_i64(); + +if (n == 0) { +if ((up_shift == 32)) { +tcg_gen_muls2_tl(rh, rl, arg1, arg2); +} else if (up_shift == 16) { +tcg_gen_ext_i32_i64(temp_64, arg1); +tcg_gen_ext_i32_i64(temp2_64, arg2); + +tcg_gen_mul_i64(temp_64, temp_64, temp2_64); +tcg_gen_shri_i64(temp_64, temp_64, up_shift); +tcg_gen_extr_i64_i32(rl, rh, temp_64); +} else { +tcg_gen_muls2_tl(rl, rh, arg1, arg2); +} +/* reset v bit */ +tcg_gen_movi_tl(cpu_PSW_V, 0); +} else { /* n is exspected to be 1 */ +tcg_gen_ext_i32_i64(temp_64, arg1); +tcg_gen_ext_i32_i64(temp2_64, arg2); + +tcg_gen_mul_i64(temp_64, temp_64, temp2_64); + +if (up_shift == 0) { +tcg_gen_shli_i64(temp_64, temp_64, 1); +} else { +tcg_gen_shri_i64(temp_64, temp_64, up_shift - 1); +} +tcg_gen_extr_i64_i32(rl, rh, temp_64); +/* overflow only occours if r1 = r2 = 0x8000 */ +if (up_shift == 0) {/* result is 64 bit */ +tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, rh, +0x8000); +} else { /* result is 32 bit */ +tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, rl, +0x8000); +} +tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31); +/* calc sv overflow bit */ +tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V); +} +/* calc av overflow bit */ +if (up_shift == 0) { +tcg_gen_add_tl(cpu_PSW_AV, rh, rh); +tcg_gen_xor_tl(cpu_PSW_AV, rh, cpu_PSW_AV); +} else { +tcg_gen_add_tl(cpu_PSW_AV, rl, rl); +tcg_gen_xor_tl(cpu_PSW_AV, rl, cpu_PSW_AV); +} +/* calc sav overflow bit */ +tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); +tcg_temp_free(temp); +tcg_temp_free_i64(temp_64); +tcg_temp_free_i64(temp2_64); +} + +static void +gen_mul_q_16(TCGv ret, TCGv arg1, TCGv arg2, uint32_t n) +{ +TCGv temp = tcg_temp_new(); +if (n == 0) { +tcg_gen_mul_tl(ret, arg1, arg2); +} else { /* n is exspected to be 1 */ +tcg_gen_mul_tl(ret, arg1, arg2); +tcg_gen_shli_tl(ret, ret, 1); +/* catch special case r1 = r2 = 0x8000 */ +tcg_gen_setcondi_tl(TCG_COND_EQ, temp, ret, 0x8000); +tcg_gen_sub_tl(ret, ret, temp); +} +/* reset v bit */ +tcg_gen_movi_tl(cpu_PSW_V, 0); +/* calc av overflow bit */ +tcg_gen_add_tl(cpu_PSW_AV, ret, ret); +tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); +/* calc sav overflow bit */ +tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); + +tcg_temp_free(temp); +} + +static void gen_mulr_q(TCGv ret, TCGv arg1, TCGv arg2, uint32_t n) +{ +TCGv temp = tcg_temp_new(); +if (n == 0) { +tcg_gen_mul_tl(ret, arg1, arg2); +tcg_gen_addi_tl(ret, ret, 0x8000); +} else { +tcg_gen_mul_tl(ret, arg1, arg2); +tcg_gen_shli_tl(ret, ret, 1); +tcg_gen_addi_tl(ret, ret, 0x8000); +/* catch special case r1 = r2 = 0x8000 */ +tcg_gen_setcondi_tl(TCG_COND_EQ, temp, ret, 0x80008000); +tcg_gen_muli_tl(temp, temp, 0x8001); +tcg_gen_sub_tl(ret, ret, temp); +} +/* reset v bit */ +tcg_gen_movi_tl(cpu_PSW_V, 0); +/* calc av overflow bit */ +tcg_gen_add_tl(cpu_PSW_AV, ret, ret); +tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV); +/* calc sav overflow bit */ +tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV); +/* cut halfword off */ +tcg_gen_andi_tl(ret, ret, 0x); + +tcg_temp_free(temp); +} + static inline void gen_maddsi_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high, int32_t con) @@ -4778,6 +4891,72 @@ static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx) tcg_temp_free(n); } +static void decode_rr1_mulq(CPUTriCoreState *env, DisasContext *ctx) +{ +uint32_t op2; +int r1, r2, r3; +
[Qemu-devel] [PATCH v2 3/4] target-tricore: Add instructions of RRPW opcode format
Signed-off-by: Bastian Koppelmann kbast...@mail.uni-paderborn.de --- v1 - v2: - optimize OPC2_32_RRPW_EXTR by using only two shifts, instead of four. - OPC1_32_RRPW_DEXTR now has r1 == r2 as a special case. target-tricore/translate.c | 70 ++ 1 file changed, 70 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 8f9679e..aa70f61 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -4990,6 +4990,57 @@ static void decode_rr2_mul(CPUTriCoreState *env, DisasContext *ctx) } } +/* RRPW format */ +static void decode_rrpw_extract_insert(CPUTriCoreState *env, DisasContext *ctx) +{ +uint32_t op2; +int r1, r2, r3; +int32_t pos, width; + +op2 = MASK_OP_RRPW_OP2(ctx-opcode); +r1 = MASK_OP_RRPW_S1(ctx-opcode); +r2 = MASK_OP_RRPW_S2(ctx-opcode); +r3 = MASK_OP_RRPW_D(ctx-opcode); +pos = MASK_OP_RRPW_POS(ctx-opcode); +width = MASK_OP_RRPW_WIDTH(ctx-opcode); + +switch (op2) { +case OPC2_32_RRPW_EXTR: +if (pos + width = 31) { +/* optimize special cases */ +if ((pos == 0) (width == 8)){ +tcg_gen_ext8s_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); +} else if ((pos == 0) (width == 16)) { +tcg_gen_ext16s_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]); +} else { +tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 32 - pos - width); +tcg_gen_sari_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], 32 - width); +} +} +break; +case OPC2_32_RRPW_EXTR_U: +if (width == 0) { +tcg_gen_movi_tl(cpu_gpr_d[r3], 0); +} else { +tcg_gen_shri_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], pos); +tcg_gen_andi_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], ~0u (32-width)); +} +break; +case OPC2_32_RRPW_IMASK: +if (pos + width = 31) { +tcg_gen_movi_tl(cpu_gpr_d[r3+1], ((1u width) - 1) pos); +tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r2], pos); +} +break; +case OPC2_32_RRPW_INSERT: +if (pos + width = 31) { +tcg_gen_deposit_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], + width, pos); +} +break; +} +} + static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) { int op1; @@ -5254,6 +5305,25 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPCM_32_RR2_MUL: decode_rr2_mul(env, ctx); break; +/* RRPW format */ +case OPCM_32_RRPW_EXTRACT_INSERT: +decode_rrpw_extract_insert(env, ctx); +break; +case OPC1_32_RRPW_DEXTR: +r1 = MASK_OP_RRPW_S1(ctx-opcode); +r2 = MASK_OP_RRPW_S2(ctx-opcode); +r3 = MASK_OP_RRPW_D(ctx-opcode); +const16 = MASK_OP_RRPW_POS(ctx-opcode); +if (r1 == r2) { +tcg_gen_rotli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], const16); +} else { +temp = tcg_temp_new(); +tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r2], const16); +tcg_gen_shri_tl(temp, cpu_gpr_d[r1], 32 - const16); +tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r3], temp); +tcg_temp_free(temp); +} +break; } } -- 2.2.2
[Qemu-devel] [PATCH v2 0/4] TriCore add instructions of RR1, RR2, RRPW and RRR opcode format
Hi, this is a rather short patchset, that only implements instructions of four formats. There will be another patchset, which has a few bugfixes. Cheers, Bastian v1 - v2: - Add 3 helper functions (gen_mul_q, gen_mul_q_16, gen_mulr_q) to remove repetition. - gen_mul_q now uses 64 arithmetic instead of emulating it. - MUL_Q now uses arithmetic shift, instead of normal shift + sign extend for arg extraction. - optimize OPC2_32_RRPW_EXTR by using only two shifts, instead of four. - OPC1_32_RRPW_DEXTR now has r1 == r2 as a special case. Bastian Koppelmann (4): target-tricore: target-tricore: Add instructions of RR1 opcode format, that have 0x93 as first opcode target-tricore: Add instructions of RR2 opcode format target-tricore: Add instructions of RRPW opcode format target-tricore: Add instructions of RRR opcode format target-tricore/helper.h | 8 + target-tricore/op_helper.c | 160 ++ target-tricore/translate.c | 439 +++ target-tricore/tricore-opcodes.h | 2 +- 4 files changed, 608 insertions(+), 1 deletion(-) -- 2.2.2
Re: [Qemu-devel] [PATCH 2/2] hw/ppc/spapr Add qemu_register_boot_set for SPAPR
On 01/26/2015 11:49 AM, Dinar Valeev wrote: On 01/24/2015 12:04 AM, Alexander Graf wrote: On 23.01.15 23:51, dval...@suse.de wrote: From: Dinar Valeev dval...@suse.com In order to have -boot once=d functioning, it is required to have qemu_register_boot_set qemu-system-ppc64 -enable-kvm -boot once=d Ready! 0 dev /chosen ok 0 .properties ... qemu,boot-device d ... 0 reset-all Ready! 0 dev /chosen ok 0 .properties ... qemu,boot-device cdn ... Signed-off-by: Dinar Valeev dval...@suse.com --- hw/ppc/spapr.c | 12 1 file changed, 12 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3d2cfa3..38b03fc 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -314,6 +314,16 @@ static void add_str(GString *s, const gchar *s1) g_string_append_len(s, s1, strlen(s1) + 1); } +static void spapr_boot_set(void *opaque, const char *boot_device, + Error **errp) +{ +int offset; +offset = fdt_path_offset(opaque, /chosen); +fdt_setprop_string(opaque, offset, qemu,boot-device, boot_device); + +} + + static void *spapr_create_fdt_skel(hwaddr initrd_base, hwaddr initrd_size, hwaddr kernel_size, @@ -414,6 +424,8 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, if (boot_device) { _FDT((fdt_property_string(fdt, qemu,boot-device, boot_device))); } +qemu_register_boot_set(spapr_boot_set, fdt); If you simply move the code above (the _FDT() one) from create_fdt_skel to spapr_finalize_fdt() you should have the same net effect and much cleaner code :). I've tried your proposal, on reset boot-device property stays d Ugh, the machine field doesn't change on reset. I think it'd be a lot more intuitive if it did. Can you try with the patch below applied as well? diff --git a/bootdevice.c b/bootdevice.c index 5914417..3b750ff 100644 --- a/bootdevice.c +++ b/bootdevice.c @@ -50,6 +50,7 @@ void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) void qemu_boot_set(const char *boot_order, Error **errp) { Error *local_err = NULL; +MachineState *machine = MACHINE(qdev_get_machine()); if (!boot_set_handler) { error_setg(errp, no function defined to set boot device list for @@ -63,6 +64,7 @@ void qemu_boot_set(const char *boot_order, Error **errp) return; } +machine-boot_order = boot_order; boot_set_handler(boot_set_opaque, boot_order, errp); } Thanks, Alex
Re: [Qemu-devel] [PATCH v3 00/14] block: Remove growable, add blk_new_open()
On Mon, 26 Jan 2015, Max Reitz wrote: This series removes the growable field from the BlockDriverState object. Its use was to clamp guest requests against the limits of the BDS; however, this can now be done more easily by moving those checks into the BlockBackend functions. In a future series, growable may be reintroduced (maybe with a different name); it will then signify whether a BDS is able to grow (in contrast to the current growable, which signifies whether it is allowed to). Maybe I will add it to the BlockDriver instead of the BDS, though. To be able to remove that field, qemu-io needs to be converted to BlockBackend, which is done by this series as well. While working on that I decided to convert blk_new_with_bs()+bdrv_open() to blk_new_open(). I was skeptical about that decision at first, but it seems good now that I was able to replace nearly every blk_new_with_bs() call by blk_new_open(). In a future series I may try to convert some remaining bdrv_open() calls to blk_new_open() as well. (And, in fact, in a future series I *will* replace the last remaining blk_new_with_bs() outside of blk_new_open() by blk_new_open().) Finally, the question needs to be asked: If, after this series, every BDS is allowed to grow, are there any users which do not use BB, but should still be disallowed from reading/writing beyond a BDS's limits? The only users I could see were the block jobs. Some of them should indeed be converted to BB; but none of them takes a user-supplied offset or size, all work on the full BDS (or only on parts which have been modified, etc.). Therefore, it is by design impossible for them to exceed the BDS's limits, which makes making all BDS's growable safe. v3: - Rebased (onto Stefan's branch rebased onto master) - Fixed patch 4 [Stefano] Thanks! It builds correctly and seems to work OK. v2: - Rebased [Kevin] - Patch 2: Added a TODO comment about removing @filename and @flags from blk_new_open() when possible [Kevin] git-backport-diff against v2: Key: [] : patches are identical [] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/14:[] [--] 'block: Lift some BDS functions to the BlockBackend' 002/14:[] [--] 'block: Add blk_new_open()' 003/14:[] [--] 'blockdev: Use blk_new_open() in blockdev_init()' 004/14:[0004] [FC] 'block/xen: Use blk_new_open() in blk_connect()' 005/14:[] [--] 'qemu-img: Use blk_new_open() in img_open()' 006/14:[] [-C] 'qemu-img: Use blk_new_open() in img_rebase()' 007/14:[] [-C] 'qemu-img: Use BlockBackend as far as possible' 008/14:[] [--] 'qemu-nbd: Use blk_new_open() in main()' 009/14:[] [--] 'qemu-io: Use blk_new_open() in openfile()' 010/14:[] [--] 'qemu-io: Remove growable option' 011/14:[] [--] 'qemu-io: Use BlockBackend' 012/14:[] [--] 'block: Clamp BlockBackend requests' 013/14:[] [--] 'block: Remove growable from BDS' 014/14:[] [--] 'block: Keep bdrv_check*_request()'s return value' git-backport-diff against v1: Key: [] : patches are identical [] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/14:[] [--] 'block: Lift some BDS functions to the BlockBackend' 002/14:[0006] [FC] 'block: Add blk_new_open()' 003/14:[] [-C] 'blockdev: Use blk_new_open() in blockdev_init()' 004/14:[0004] [FC] 'block/xen: Use blk_new_open() in blk_connect()' 005/14:[] [--] 'qemu-img: Use blk_new_open() in img_open()' 006/14:[] [-C] 'qemu-img: Use blk_new_open() in img_rebase()' 007/14:[] [-C] 'qemu-img: Use BlockBackend as far as possible' 008/14:[] [--] 'qemu-nbd: Use blk_new_open() in main()' 009/14:[] [--] 'qemu-io: Use blk_new_open() in openfile()' 010/14:[0002] [FC] 'qemu-io: Remove growable option' 011/14:[] [--] 'qemu-io: Use BlockBackend' 012/14:[] [--] 'block: Clamp BlockBackend requests' 013/14:[] [--] 'block: Remove growable from BDS' 014/14:[] [--] 'block: Keep bdrv_check*_request()'s return value' Max Reitz (14): block: Lift some BDS functions to the BlockBackend block: Add blk_new_open() blockdev: Use blk_new_open() in blockdev_init() block/xen: Use blk_new_open() in blk_connect() qemu-img: Use blk_new_open() in img_open() qemu-img: Use blk_new_open() in img_rebase() qemu-img: Use BlockBackend as far as possible qemu-nbd: Use blk_new_open() in main() qemu-io: Use blk_new_open() in openfile() qemu-io: Remove growable option qemu-io: Use BlockBackend block: Clamp BlockBackend requests block: Remove growable from BDS block: Keep bdrv_check*_request()'s return value block.c| 59 +- block/block-backend.c
[Qemu-devel] [PATCH 00/50] blockdev: BlockBackend and media
This series reworks a lot regarding BlockBackend and media. It is essentially a v3 to the blockdev: Add blockdev-change-medium with read-only option series (which is in fact a part of this series), but of course does a lot more. Basically, this series allows empty BlockBackends, that is BBs without a BDS tree. Before this series, empty drives are represented by a BlockBackend with an empty BDS attached to it (a BDS with a NULL driver). However, now we have BlockBackends, thus an empty drive should be represented by a BlockBackend without any BDS tree attached to it. This is what this series does. I am CC'ing a lot of people (basically everyone who is working on the block layer) due to the fact that this series touches a lot of places in the block layer. Please pick out patches that seem to be relevant to your area of expertise (e.g. there is an FDC tray patch for John; there are some block job patches for Jeff; etc. pp.). I want to explicitly encourage you to review only parts of this series! (Of course, reviewing everything is fine, too :-)) Also, brace for a follow-up regarding bdrv_close_all() (there is a nice bug in there which I found while working on this series). This series depends on v3 (or any later version) of my series 'block: Remove growable, add blk_new_open()'. - Patches 1 and 2 make it possible to use blockdev-add without creating a BlockBackend. This is necessary because the QMP command introduced in patch 42 (blockdev-insert-medium) will insert a BDS tree (a medium) into a BlockBackend (a drive). Creating a BlockBackend for such a BDS tree would both be a hassle and a waste, so this makes it possible to omit creating a BB. Patches 35 and 36 are kind of a follow-up to these; but patch 35 depends on patch 34 which is the reason why there is a large gap between patch 2 and 35. - Patch 3 implements a tray status for floppy disk drives. See the commit message for more information on what this means. - Patches 3 to 33 basically all prepare the block layer for having BBs without BDS trees. I will only list the most notable ones (patch 3, for instance, is not notable). They do so by moving some information into the BlockBackend, and primarily by intercepting accesses to empty BBs in the BB layer and resorting to default actions there. Furthermore, hopefully all non-BB calls to bdrv_*() functions are guarded by checking whether that BDS actually exists. - Patch 6 makes blk_is_inserted() return true only if there is a BDS tree; furthermore, blk_is_available() is added which additionally checks whether the guest device tray is closed. - Patches 7 and 8 are some kind of follow-up to patch 6; they make bdrv_is_inserted() actually useful (unless I'm not mistaken; maybe I am and they make bdrv_is_inserted() actually useless). - Patches 9, 11 and 12 move some (root!) BDS fields into the BB, because that is where they belong. This way they survive a medium (BDS tree) change. - Patch 10 is necessary because the structure moved in patch 11 (BlockAcctStats) contains one field which does belong into the BDS (wr_highest_offset). Thus, this field is moved out of that structure into the BDS here. - Patch 13 adds a structure to the BB which can save some options from the root BDS so they survive a medium change. In theory, those options should probably not survive a medium change (they are not really drive- but medium-related), but this is how the 'change' command always handled it so this structure (the BlockBackendRootState, BBRS) is required for compatibility. One of these options is the read-only status, for example. - Patches 17 to 30 and patches 32 and 33 prepare functions in the block layer which directly access a BDS to cope with a non-existing BDS tree. Patch 31 is a prerequisite for patch 32. - Patch 34 gets down to business: Empty drives no longer have a BDS tree. - Patches 35 and 36 are, as described above, a follow-up to patch 1. - Patch 37 is the counterpart to patch 31, obviously. - Patches 38 to 41 implement the basic QMP operations for tray and medium operation: blockdev-open-tray, blockdev-close-tray, blockdev-remove-medium and blockdev-insert-medium. - Patches 42 and 43 reimplement 'eject' and 'change' using these new medium operations. - With me now knowing exactly what 'change' does (because I reimplemented it), patch 44 became possible. - Patches 45 to 48 are from v2 of series (slightly modified) blockdev: Add blockdev-change-medium with read-only option One modification are notes in patch 45 that blockdev-change-medium is preferred over simply 'change' [Eric] and what atomic operations blockdev-change-medium itself performs. - Patch 50 adds a test for 'change' and all associated QMP commands, patch 49 makes small amendments to VM.add_drive() in iotests.py to make the new test work. git-backport-diff output against v2 of blockdev: Add blockdev-change-medium with read-only
[Qemu-devel] [PATCH 02/50] iotests: Only create BB if necessary
Tests 071 and 081 test giving references in blockdev-add. It is not necessary to create a BlockBackend here, so omit it. Signed-off-by: Max Reitz mre...@redhat.com --- tests/qemu-iotests/071 | 50 ++ tests/qemu-iotests/071.out | 12 +++ tests/qemu-iotests/081 | 14 - tests/qemu-iotests/081.out | 5 +++-- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071 index 9eaa49b..68bedd4 100755 --- a/tests/qemu-iotests/071 +++ b/tests/qemu-iotests/071 @@ -104,11 +104,20 @@ echo echo === Testing blkdebug on existing block device === echo -run_qemu -drive file=$TEST_IMG,format=raw,if=none,id=drive0 EOF +run_qemu EOF { execute: qmp_capabilities } { execute: blockdev-add, arguments: { options: { +node-name: drive0, +driver: file, +filename: $TEST_IMG +} +} +} +{ execute: blockdev-add, +arguments: { +options: { driver: $IMGFMT, id: drive0-debug, file: { @@ -133,11 +142,23 @@ echo echo === Testing blkverify on existing block device === echo -run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=drive0 EOF +run_qemu EOF { execute: qmp_capabilities } { execute: blockdev-add, arguments: { options: { +node-name: drive0, +driver: $IMGFMT, +file: { +driver: file, +filename: $TEST_IMG +} +} +} +} +{ execute: blockdev-add, +arguments: { +options: { driver: blkverify, id: drive0-verify, test: drive0, @@ -163,11 +184,23 @@ echo echo === Testing blkverify on existing raw block device === echo -run_qemu -drive file=$TEST_IMG.base,format=raw,if=none,id=drive0 EOF +run_qemu EOF { execute: qmp_capabilities } { execute: blockdev-add, arguments: { options: { +node-name: drive0, +driver: raw, +file: { +driver: file, +filename: $TEST_IMG.base +} +} +} +} +{ execute: blockdev-add, +arguments: { +options: { driver: blkverify, id: drive0-verify, test: { @@ -193,11 +226,20 @@ echo echo === Testing blkdebug's set-state through QMP === echo -run_qemu -drive file=$TEST_IMG,format=raw,if=none,id=drive0 EOF +run_qemu EOF { execute: qmp_capabilities } { execute: blockdev-add, arguments: { options: { +node-name: drive0, +driver: file, +filename: $TEST_IMG +} +} +} +{ execute: blockdev-add, +arguments: { +options: { driver: $IMGFMT, id: drive0-debug, file: { diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out index 9205ce2..c8ecfaf 100644 --- a/tests/qemu-iotests/071.out +++ b/tests/qemu-iotests/071.out @@ -42,10 +42,11 @@ read failed: Input/output error === Testing blkdebug on existing block device === -Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0 +Testing: QMP_VERSION {return: {}} {return: {}} +{return: {}} read failed: Input/output error {return: } {return: {}} @@ -58,28 +59,31 @@ QEMU_PROG: Failed to flush the refcount block cache: Input/output error === Testing blkverify on existing block device === -Testing: -drive file=TEST_DIR/t.IMGFMT,format=IMGFMT,if=none,id=drive0 +Testing: QMP_VERSION {return: {}} {return: {}} +{return: {}} blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 === Testing blkverify on existing raw block device === -Testing: -drive file=TEST_DIR/t.IMGFMT.base,format=raw,if=none,id=drive0 +Testing: QMP_VERSION {return: {}} {return: {}} +{return: {}} blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0 === Testing blkdebug's set-state through QMP === -Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0 +Testing: QMP_VERSION {return: {}} {return: {}} +{return: {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {return: } diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081 index d9b042c..5c8a8fa 100755 --- a/tests/qemu-iotests/081 +++ b/tests/qemu-iotests/081 @@ -101,11 +101,23 @@ $QEMU_IO -c open -o $quorum -c read -P 0x32 0 $size | _filter_qemu_io echo echo == checking mixed reference/option specification == -run_qemu -drive file=$TEST_DIR/2.raw,format=$IMGFMT,if=none,id=drive2 EOF +run_qemu EOF { execute: qmp_capabilities } { execute: blockdev-add, arguments: { options: { +node-name: drive2, +driver: raw, +file: { +driver: file, +filename: $TEST_DIR/2.raw +} +} +} +} +{ execute: blockdev-add, +arguments: { +options: {
[Qemu-devel] [PATCH 08/50] block/quorum: Implement bdrv_is_inserted()
bdrv_is_inserted() should be invoked recursively on the children of quorum. Signed-off-by: Max Reitz mre...@redhat.com --- block/quorum.c | 16 1 file changed, 16 insertions(+) diff --git a/block/quorum.c b/block/quorum.c index 437b122..7811c4a 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1064,6 +1064,20 @@ static void quorum_refresh_filename(BlockDriverState *bs) bs-full_open_options = opts; } +static int quorum_is_inserted(BlockDriverState *bs) +{ +BDRVQuorumState *s = bs-opaque; +int i; + +for (i = 0; i s-num_children; i++) { +if (!bdrv_is_inserted(s-bs[i])) { +return 0; +} +} + +return 1; +} + static BlockDriver bdrv_quorum = { .format_name= quorum, .protocol_name = quorum, @@ -1087,6 +1101,8 @@ static BlockDriver bdrv_quorum = { .is_filter = true, .bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter, + +.bdrv_is_inserted = quorum_is_inserted, }; static void bdrv_quorum_init(void) -- 2.1.0
[Qemu-devel] [PATCH 11/50] block: Move BlockAcctStats into BlockBackend
As the comment above bdrv_get_stats() says, BlockAcctStats is something which belongs to the device instead of each BlockDriverState. This patch therefore moves it into the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 11 --- block/block-backend.c | 5 - block/qapi.c | 20 include/block/block.h | 2 -- include/block/block_int.h | 3 --- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/block.c b/block.c index 5db71c6..17e4ee3 100644 --- a/block.c +++ b/block.c @@ -6119,14 +6119,3 @@ void bdrv_refresh_filename(BlockDriverState *bs) QDECREF(json); } } - -/* This accessor function purpose is to allow the device models to access the - * BlockAcctStats structure embedded inside a BlockDriverState without being - * aware of the BlockDriverState structure layout. - * It will go away when the BlockAcctStats structure will be moved inside - * the device models. - */ -BlockAcctStats *bdrv_get_stats(BlockDriverState *bs) -{ -return bs-stats; -} diff --git a/block/block-backend.c b/block/block-backend.c index bf0fcc9..3d565d8 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -34,6 +34,9 @@ struct BlockBackend { /* the block size for which the guest device expects atomicity */ int guest_block_size; + +/* I/O stats (display with info blockstats). */ +BlockAcctStats stats; }; typedef struct BlockBackendAIOCB { @@ -849,7 +852,7 @@ void blk_io_unplug(BlockBackend *blk) BlockAcctStats *blk_get_stats(BlockBackend *blk) { -return bdrv_get_stats(blk-bs); +return blk-stats; } void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk, diff --git a/block/qapi.c b/block/qapi.c index 4e97574..7840c81 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -334,14 +334,18 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs, } s-stats = g_malloc0(sizeof(*s-stats)); -s-stats-rd_bytes = bs-stats.nr_bytes[BLOCK_ACCT_READ]; -s-stats-wr_bytes = bs-stats.nr_bytes[BLOCK_ACCT_WRITE]; -s-stats-rd_operations = bs-stats.nr_ops[BLOCK_ACCT_READ]; -s-stats-wr_operations = bs-stats.nr_ops[BLOCK_ACCT_WRITE]; -s-stats-flush_operations = bs-stats.nr_ops[BLOCK_ACCT_FLUSH]; -s-stats-wr_total_time_ns = bs-stats.total_time_ns[BLOCK_ACCT_WRITE]; -s-stats-rd_total_time_ns = bs-stats.total_time_ns[BLOCK_ACCT_READ]; -s-stats-flush_total_time_ns = bs-stats.total_time_ns[BLOCK_ACCT_FLUSH]; +if (bs-blk) { +BlockAcctStats *stats = blk_get_stats(bs-blk); + +s-stats-rd_bytes = stats-nr_bytes[BLOCK_ACCT_READ]; +s-stats-wr_bytes = stats-nr_bytes[BLOCK_ACCT_WRITE]; +s-stats-rd_operations = stats-nr_ops[BLOCK_ACCT_READ]; +s-stats-wr_operations = stats-nr_ops[BLOCK_ACCT_WRITE]; +s-stats-flush_operations = stats-nr_ops[BLOCK_ACCT_FLUSH]; +s-stats-wr_total_time_ns = stats-total_time_ns[BLOCK_ACCT_WRITE]; +s-stats-rd_total_time_ns = stats-total_time_ns[BLOCK_ACCT_READ]; +s-stats-flush_total_time_ns = stats-total_time_ns[BLOCK_ACCT_FLUSH]; +} s-stats-wr_highest_offset = bs-wr_highest_sector * BDRV_SECTOR_SIZE; diff --git a/include/block/block.h b/include/block/block.h index df656db..8cd6b31 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -550,6 +550,4 @@ void bdrv_io_plug(BlockDriverState *bs); void bdrv_io_unplug(BlockDriverState *bs); void bdrv_flush_io_queue(BlockDriverState *bs); -BlockAcctStats *bdrv_get_stats(BlockDriverState *bs); - #endif diff --git a/include/block/block_int.h b/include/block/block_int.h index e309d8a..d023913 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -363,9 +363,6 @@ struct BlockDriverState { CoQueue throttled_reqs[2]; bool io_limits_enabled; -/* I/O stats (display with info blockstats). */ -BlockAcctStats stats; - /* Highest sector index written to */ uint64_t wr_highest_sector; -- 2.1.0
[Qemu-devel] [PATCH 21/50] blockdev: Check BB validity in internal snapshot TA
Call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 858d181..012c603 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1217,6 +1217,7 @@ static void internal_snapshot_prepare(BlkTransactionState *common, Error *local_err = NULL; const char *device; const char *name; +BlockBackend *blk; BlockDriverState *bs; QEMUSnapshotInfo old_sn, *sn; bool ret; @@ -1235,20 +1236,21 @@ static void internal_snapshot_prepare(BlkTransactionState *common, name = internal-name; /* 2. check for validation */ -bs = bdrv_find(device); -if (!bs) { +blk = blk_by_name(device); +if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } /* AioContext is released in .clean() */ -state-aio_context = bdrv_get_aio_context(bs); +state-aio_context = blk_get_aio_context(blk); aio_context_acquire(state-aio_context); -if (!bdrv_is_inserted(bs)) { +if (!blk_is_available(blk)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; } +bs = blk_bs(blk); if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) { return; -- 2.1.0
[Qemu-devel] [PATCH 16/50] block: Prepare remaining BB functions for NULL BDS
There are several BlockBackend functions which, in theory, cannot fail. This patch makes them cope with the BlockDriverState pointer being NULL by making them fall back to some default action like ignoring the value in setters and returning the default in getters. Signed-off-by: Max Reitz mre...@redhat.com --- block/block-backend.c | 70 --- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 4f3122a..760558f 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -644,7 +644,11 @@ int64_t blk_getlength(BlockBackend *blk) void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr) { -bdrv_get_geometry(blk-bs, nb_sectors_ptr); +if (!blk-bs) { +*nb_sectors_ptr = 0; +} else { +bdrv_get_geometry(blk-bs, nb_sectors_ptr); +} } BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num, @@ -862,17 +866,27 @@ int blk_is_read_only(BlockBackend *blk) int blk_is_sg(BlockBackend *blk) { +if (!blk-bs) { +return 0; +} + return bdrv_is_sg(blk-bs); } int blk_enable_write_cache(BlockBackend *blk) { +if (!blk-bs) { +return 0; +} + return bdrv_enable_write_cache(blk-bs); } void blk_set_enable_write_cache(BlockBackend *blk, bool wce) { -bdrv_set_enable_write_cache(blk-bs, wce); +if (blk-bs) { +bdrv_set_enable_write_cache(blk-bs, wce); +} } void blk_invalidate_cache(BlockBackend *blk, Error **errp) @@ -897,12 +911,16 @@ bool blk_is_available(BlockBackend *blk) void blk_lock_medium(BlockBackend *blk, bool locked) { -bdrv_lock_medium(blk-bs, locked); +if (blk-bs) { +bdrv_lock_medium(blk-bs, locked); +} } void blk_eject(BlockBackend *blk, bool eject_flag) { -bdrv_eject(blk-bs, eject_flag); +if (blk-bs) { +bdrv_eject(blk-bs, eject_flag); +} } int blk_get_flags(BlockBackend *blk) @@ -926,22 +944,32 @@ void *blk_blockalign(BlockBackend *blk, size_t size) bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp) { +if (!blk-bs) { +return false; +} + return bdrv_op_is_blocked(blk-bs, op, errp); } void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason) { -bdrv_op_unblock(blk-bs, op, reason); +if (blk-bs) { +bdrv_op_unblock(blk-bs, op, reason); +} } void blk_op_block_all(BlockBackend *blk, Error *reason) { -bdrv_op_block_all(blk-bs, reason); +if (blk-bs) { +bdrv_op_block_all(blk-bs, reason); +} } void blk_op_unblock_all(BlockBackend *blk, Error *reason) { -bdrv_op_unblock_all(blk-bs, reason); +if (blk-bs) { +bdrv_op_unblock_all(blk-bs, reason); +} } AioContext *blk_get_aio_context(BlockBackend *blk) @@ -961,15 +989,19 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb) void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) { -bdrv_set_aio_context(blk-bs, new_context); +if (blk-bs) { +bdrv_set_aio_context(blk-bs, new_context); +} } void blk_add_aio_context_notifier(BlockBackend *blk, void (*attached_aio_context)(AioContext *new_context, void *opaque), void (*detach_aio_context)(void *opaque), void *opaque) { -bdrv_add_aio_context_notifier(blk-bs, attached_aio_context, - detach_aio_context, opaque); +if (blk-bs) { +bdrv_add_aio_context_notifier(blk-bs, attached_aio_context, + detach_aio_context, opaque); +} } void blk_remove_aio_context_notifier(BlockBackend *blk, @@ -978,23 +1010,31 @@ void blk_remove_aio_context_notifier(BlockBackend *blk, void (*detach_aio_context)(void *), void *opaque) { -bdrv_remove_aio_context_notifier(blk-bs, attached_aio_context, - detach_aio_context, opaque); +if (blk-bs) { +bdrv_remove_aio_context_notifier(blk-bs, attached_aio_context, + detach_aio_context, opaque); +} } void blk_add_close_notifier(BlockBackend *blk, Notifier *notify) { -bdrv_add_close_notifier(blk-bs, notify); +if (blk-bs) { +bdrv_add_close_notifier(blk-bs, notify); +} } void blk_io_plug(BlockBackend *blk) { -bdrv_io_plug(blk-bs); +if (blk-bs) { +bdrv_io_plug(blk-bs); +} } void blk_io_unplug(BlockBackend *blk) { -bdrv_io_unplug(blk-bs); +if (blk-bs) { +bdrv_io_unplug(blk-bs); +} } BlockAcctStats *blk_get_stats(BlockBackend *blk) -- 2.1.0
[Qemu-devel] [PATCH 17/50] block: Respect empty BB in bdrv_lookup_bs()
blk_by_name() may return a BlockBackend for which blk_bs() returns NULL. In this case, an error should be returned (instead of just returning NULL without modifying *errp). Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 5 + 1 file changed, 5 insertions(+) diff --git a/block.c b/block.c index 9a0a510..b7e631c 100644 --- a/block.c +++ b/block.c @@ -3718,6 +3718,11 @@ BlockDriverState *bdrv_lookup_bs(const char *device, blk = blk_by_name(device); if (blk) { +if (!blk_bs(blk)) { +error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); +return NULL; +} + return blk_bs(blk); } } -- 2.1.0
[Qemu-devel] [PATCH 35/50] blockdev: Pull out blockdev option extraction
Extract some of the blockdev option extraction code from blockdev_init() into an own function. This simplifies blockdev_init() and will allow reusing the code in a different function added in a follow-up patch. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 201 + 1 file changed, 108 insertions(+), 93 deletions(-) diff --git a/blockdev.c b/blockdev.c index d99edbb..d573c5c 100644 --- a/blockdev.c +++ b/blockdev.c @@ -341,24 +341,123 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp) typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; +static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags, +ThrottleConfig *throttle_cfg, BlockdevDetectZeroesOptions *detect_zeroes, +Error **errp) +{ +const char *discard, *aio; +Error *local_error = NULL; + +if (!qemu_opt_get_bool(opts, read-only, false)) { +*bdrv_flags |= BDRV_O_RDWR; +} +if (qemu_opt_get_bool(opts, copy-on-read, false)) { +*bdrv_flags |= BDRV_O_COPY_ON_READ; +} + +if ((discard = qemu_opt_get(opts, discard)) != NULL) { +if (bdrv_parse_discard_flags(discard, bdrv_flags) != 0) { +error_setg(errp, Invalid discard option); +return; +} +} + +if (qemu_opt_get_bool(opts, cache.writeback, true)) { +*bdrv_flags |= BDRV_O_CACHE_WB; +} +if (qemu_opt_get_bool(opts, cache.direct, false)) { +*bdrv_flags |= BDRV_O_NOCACHE; +} +if (qemu_opt_get_bool(opts, cache.no-flush, false)) { +*bdrv_flags |= BDRV_O_NO_FLUSH; +} + +#ifdef CONFIG_LINUX_AIO +if ((aio = qemu_opt_get(opts, aio)) != NULL) { +if (!strcmp(aio, native)) { +*bdrv_flags |= BDRV_O_NATIVE_AIO; +} else if (!strcmp(aio, threads)) { +/* this is the default */ +} else { + error_setg(errp, invalid aio option); + return; +} +} +#endif + +/* disk I/O throttling */ +memset(throttle_cfg, 0, sizeof(*throttle_cfg)); +throttle_cfg-buckets[THROTTLE_BPS_TOTAL].avg = +qemu_opt_get_number(opts, throttling.bps-total, 0); +throttle_cfg-buckets[THROTTLE_BPS_READ].avg = +qemu_opt_get_number(opts, throttling.bps-read, 0); +throttle_cfg-buckets[THROTTLE_BPS_WRITE].avg = +qemu_opt_get_number(opts, throttling.bps-write, 0); +throttle_cfg-buckets[THROTTLE_OPS_TOTAL].avg = +qemu_opt_get_number(opts, throttling.iops-total, 0); +throttle_cfg-buckets[THROTTLE_OPS_READ].avg = +qemu_opt_get_number(opts, throttling.iops-read, 0); +throttle_cfg-buckets[THROTTLE_OPS_WRITE].avg = +qemu_opt_get_number(opts, throttling.iops-write, 0); + +throttle_cfg-buckets[THROTTLE_BPS_TOTAL].max = +qemu_opt_get_number(opts, throttling.bps-total-max, 0); +throttle_cfg-buckets[THROTTLE_BPS_READ].max = +qemu_opt_get_number(opts, throttling.bps-read-max, 0); +throttle_cfg-buckets[THROTTLE_BPS_WRITE].max = +qemu_opt_get_number(opts, throttling.bps-write-max, 0); +throttle_cfg-buckets[THROTTLE_OPS_TOTAL].max = +qemu_opt_get_number(opts, throttling.iops-total-max, 0); +throttle_cfg-buckets[THROTTLE_OPS_READ].max = +qemu_opt_get_number(opts, throttling.iops-read-max, 0); +throttle_cfg-buckets[THROTTLE_OPS_WRITE].max = +qemu_opt_get_number(opts, throttling.iops-write-max, 0); + +throttle_cfg-op_size = +qemu_opt_get_number(opts, throttling.iops-size, 0); + +if (!check_throttle_config(throttle_cfg, errp)) { +return; +} + +*detect_zeroes = +qapi_enum_parse(BlockdevDetectZeroesOptions_lookup, +qemu_opt_get(opts, detect-zeroes), +BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX, +BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, +local_error); +if (local_error) { +error_propagate(errp, local_error); +return; +} + +if (*detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP +!(*bdrv_flags BDRV_O_UNMAP)) +{ +error_setg(errp, setting detect-zeroes to unmap is not allowed + without setting discard operation to unmap); +return; +} + +} + /* Takes the ownership of bs_opts */ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, Error **errp) { const char *buf; -int ro = 0; int bdrv_flags = 0; int on_read_error, on_write_error; BlockBackend *blk; BlockDriverState *bs; ThrottleConfig cfg; int snapshot = 0; -bool copy_on_read; Error *error = NULL; QemuOpts *opts; const char *id; bool has_driver_specific_opts; -BlockdevDetectZeroesOptions detect_zeroes; +BlockdevDetectZeroesOptions detect_zeroes = +BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; /* Check common options
[Qemu-devel] [PATCH v3 14/14] block: Keep bdrv_check*_request()'s return value
Do not throw away the value returned by bdrv_check_request() and bdrv_check_byte_request(). Fix up some coding style issues in the proximity of the affected hunks. Signed-off-by: Max Reitz mre...@redhat.com --- block.c | 35 --- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/block.c b/block.c index 356a857..4a5f8fc 100644 --- a/block.c +++ b/block.c @@ -3096,8 +3096,10 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs, if (!drv) { return -ENOMEDIUM; } -if (bdrv_check_byte_request(bs, offset, bytes)) { -return -EIO; + +ret = bdrv_check_byte_request(bs, offset, bytes); +if (ret 0) { +return ret; } if (bs-copy_on_read) { @@ -3343,8 +3345,10 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, if (bs-read_only) { return -EACCES; } -if (bdrv_check_byte_request(bs, offset, bytes)) { -return -EIO; + +ret = bdrv_check_byte_request(bs, offset, bytes); +if (ret 0) { +return ret; } /* throttling disk I/O */ @@ -4168,12 +4172,18 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { BlockDriver *drv = bs-drv; -if (!drv) +int ret; + +if (!drv) { return -ENOMEDIUM; -if (!drv-bdrv_write_compressed) +} +if (!drv-bdrv_write_compressed) { return -ENOTSUP; -if (bdrv_check_request(bs, sector_num, nb_sectors)) -return -EIO; +} +ret = bdrv_check_request(bs, sector_num, nb_sectors); +if (ret 0) { +return ret; +} assert(QLIST_EMPTY(bs-dirty_bitmaps)); @@ -5091,12 +5101,15 @@ static void coroutine_fn bdrv_discard_co_entry(void *opaque) int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { -int max_discard; +int max_discard, ret; if (!bs-drv) { return -ENOMEDIUM; -} else if (bdrv_check_request(bs, sector_num, nb_sectors)) { -return -EIO; +} + +ret = bdrv_check_request(bs, sector_num, nb_sectors); +if (ret 0) { +return ret; } else if (bs-read_only) { return -EROFS; } -- 2.1.0
Re: [Qemu-devel] [PATCH v2 01/47] acpi: introduce AML composer aml_append()
On Mon, 26 Jan 2015 10:57:21 +0100 Igor Mammedov imamm...@redhat.com wrote: On Sat, 24 Jan 2015 18:33:50 +0200 Michael S. Tsirkin m...@redhat.com wrote: On Fri, Jan 23, 2015 at 06:56:20PM +0100, Igor Mammedov wrote: On Fri, 23 Jan 2015 15:55:11 +0200 Michael S. Tsirkin m...@redhat.com wrote: [...] I refuse to give up on cleaner and simpler API yet :) Your patches are almost there, they are pretty clean, the only issue I think is this passing of AcpiAml by value, sometimes freeing buffer in the process, sometimes not. Currently buffer is allocated by API and is always freed whenever it's passed to another API function. That's why it makes user not to care about memory mgmt. The only limitation of it is if you store AcpiAml return value into some variable you are responsible to use it only once for passing to another API function. Reusing this variable's value (pass it to API function second time) would cause cause use-after-free and freeing-freed bugs. Like this: AcpiAml table = acpi_definition_block(SSDT,...); AcpiAml scope = acpi_scope(PCI0); aml_append(table, scope); // - here scope becomes invalid // a bug aml_append(table, scope); // use-after-free + freeing-freed bugs There are several approaches to look for resolving above issues: 1. Adopt and use memory mgmt model used by GTK+ in nutshell: http://www.cs.hunter.cuny.edu/~sweiss/course_materials/csci493.70/lecture_notes/GTK_memory_mngmt.pdf In particular adopt behavior of GInitiallyUnowned usage model that will allow to keep convenient chained call style and if necessary reuse objects returned by API by explicitly referencing/dereferencing them if needed. Hmm, it's still easy to misuse. I think I prefer option 2 below. That's basically what we have/use in QOM with object_new(FOO) + object_unref() I have no idea why we invented our own Object infrastructure when we could just use GObject one from already used glib. 2. It's possible to drop freeing inside API completely and record(store in list) every new object inside a table context. When table is constructed, list of created objects could be safely freed. With that it would be safe to reuse every AcpiAml object and avoid free-after-use issues with limitation that created AcpiAml objects shouldn't be used after table was closed. It should cover all practical use of API, i.e. no cross table AcpiAml objects. So each aml_alloc function gets pointer to this list, and adds the new element there. Eventually we do free_all to free all elements, so there isn't even an aml_free to mis-use. I'm thinking a little bit different about implementation though. I still don't like the use of explicit alloc/free being called by API user since it doesn't allow chained API calls and I think it's unnecessary complication see below why. Here is what's true about current API and a I'd like to with it: 1. Every API call (except aml_append) makes aml_alloc(), it's just like a wrapper about object_new(FOO). (current + new impl.) 2 Every API call that takes AML type as input argument 2.1 consumes (frees) it (current impl.) (it's easy to fix use after free concern too, just pass AML by pointer and zero-out memory before it's freed and assert whenever one of input arguments is not correct, i.e. it was reused second time) There is no need for following steps after this one. 2.2 takes ownership of GInitiallyUnowned and adds it to its list of its children. 3. Free children when AML object is destroyed (i.e. ref count zero) That way when toplevel table object (definition block in 42/47) is added to ACPI blob we can unref it, which will cause its whole children tree freed, except for AML objects where API user explicitly took extra reference (i.e. wanted them to reuse in another table) I'd prefer: * 2.1 way to address your current concern of use-after-free as the most simplest one (no reuse is possible however) or * follow already used by QEMU QOM/GObject pattern of implicit alloc/free since they allow to construct AML in a more simple/manageable way i.e. aml_append(method, aml_store(aml_string(foo), aml_local(0))) ); v.s. explicit headache of alloc/free, which doesn't fix use-after-free anyway and just adds more boiler plate plus makes code har to read read str = aml_alloc(); aml_string(str, foo); loc0 = aml_alloc(); aml_local(loc0, 0); store = aml_alloc(); aml_store(store, str, loc0); aml_append(method, store); aml_free(store); aml_free(loc0); aml_free(str); Here is a compromise what I and Michael came to on a phone call: Externally API usage would look like: AmlAllocList *p = some_list_alloc(); Aml *ssdt = aml_def_block(p,
[Qemu-devel] [PATCH] target-mips: fix detection of the end of the page during translation
The test is supposed to terminate TB if the end of the page is reached. However, with current implementation it may never succeed for microMIPS or mips16. Reported-by: Richard Henderson r...@twiddle.net Signed-off-by: Leon Alrae leon.al...@imgtec.com --- target-mips/translate.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index e9d86b2..f33c10c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -19091,6 +19091,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, CPUMIPSState *env = cpu-env; DisasContext ctx; target_ulong pc_start; +target_ulong next_page_start; uint16_t *gen_opc_end; CPUBreakpoint *bp; int j, lj = -1; @@ -19103,6 +19104,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, qemu_log(search pc %d\n, search_pc); pc_start = tb-pc; +next_page_start = (pc_start TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; ctx.pc = pc_start; ctx.saved_pc = -1; @@ -19202,8 +19204,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, break; } -if ((ctx.pc (TARGET_PAGE_SIZE - 1)) == 0) +if (ctx.pc = next_page_start) { break; +} if (tcg_ctx.gen_opc_ptr = gen_opc_end) { break; -- 2.1.0
[Qemu-devel] [PATCH 29/50] blockdev: Check BB validity in find_block_job()
Call blk_is_available() before using blk_bs() to obtain the root BlockDriverState behind the BlockBackend. Signed-off-by: Max Reitz mre...@redhat.com --- blockdev.c | 20 +++- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/blockdev.c b/blockdev.c index 4e12061..4bd52b8 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2698,25 +2698,35 @@ out: /* Get the block job for a given device name and acquire its AioContext */ static BlockJob *find_block_job(const char *device, AioContext **aio_context) { +BlockBackend *blk; BlockDriverState *bs; -bs = bdrv_find(device); -if (!bs) { +*aio_context = NULL; + +blk = blk_by_name(device); +if (!blk) { goto notfound; } -*aio_context = bdrv_get_aio_context(bs); +*aio_context = blk_get_aio_context(blk); aio_context_acquire(*aio_context); +if (!blk_is_available(blk)) { +goto notfound; +} +bs = blk_bs(blk); + if (!bs-job) { -aio_context_release(*aio_context); goto notfound; } return bs-job; notfound: -*aio_context = NULL; +if (*aio_context) { +aio_context_release(*aio_context); +*aio_context = NULL; +} return NULL; } -- 2.1.0