Re: [PATCH 6/6] Rename "QEMU global mutex" to "BQL" in comments and docs
Stefan Hajnoczi writes: > The term "QEMU global mutex" is identical to the more widely used Big > QEMU Lock ("BQL"). Update the code comments and documentation to use > "BQL" instead of "QEMU global mutex". > > Signed-off-by: Stefan Hajnoczi For QAPI Acked-by: Markus Armbruster
Re: [PATCH v3 0/7] Steps towards enabling -Wshadow=local
Markus Armbruster writes: > Local variables shadowing other local variables or parameters make the > code needlessly hard to understand. Bugs love to hide in such code. > Evidence: PATCH 1. > > Enabling -Wshadow would prevent bugs like this one. But we'd have to > clean up all the offenders first. We got a lot of them. > > Enabling -Wshadow=local should be less work for almost as much gain. > I took a stab at it. There's a small, exciting part, and a large, > boring part. > > The exciting part is dark preprocessor sorcery to let us nest macro > calls without shadowing: PATCH 7. [...] Queued.
[PATCH v3 4/7] block/dirty-bitmap: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: rename both the pair of parameters and the pair of local variables. While there, move the local variables to function scope. Suggested-by: Kevin Wolf Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf --- block/monitor/bitmap-qmp-cmds.c | 19 ++- block/qcow2-bitmap.c| 3 +-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c index 55f778f5af..70d01a3776 100644 --- a/block/monitor/bitmap-qmp-cmds.c +++ b/block/monitor/bitmap-qmp-cmds.c @@ -258,37 +258,38 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name, bdrv_disable_dirty_bitmap(bitmap); } -BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, +BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node, + const char *dst_bitmap, BlockDirtyBitmapOrStrList *bms, HBitmap **backup, Error **errp) { BlockDriverState *bs; BdrvDirtyBitmap *dst, *src; BlockDirtyBitmapOrStrList *lst; +const char *src_node, *src_bitmap; HBitmap *local_backup = NULL; GLOBAL_STATE_CODE(); -dst = block_dirty_bitmap_lookup(node, target, &bs, errp); +dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp); if (!dst) { return NULL; } for (lst = bms; lst; lst = lst->next) { switch (lst->value->type) { -const char *name, *node; case QTYPE_QSTRING: -name = lst->value->u.local; -src = bdrv_find_dirty_bitmap(bs, name); +src_bitmap = lst->value->u.local; +src = bdrv_find_dirty_bitmap(bs, src_bitmap); if (!src) { -error_setg(errp, "Dirty bitmap '%s' not found", name); +error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap); goto fail; } break; case QTYPE_QDICT: -node = lst->value->u.external.node; -name = lst->value->u.external.name; -src = block_dirty_bitmap_lookup(node, name, NULL, errp); +src_node = lst->value->u.external.node; +src_bitmap = lst->value->u.external.name; +src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp); if (!src) { goto fail; } diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 037fa2d435..ffd5cd3b23 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1555,7 +1555,6 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, FOR_EACH_DIRTY_BITMAP(bs, bitmap) { const char *name = bdrv_dirty_bitmap_name(bitmap); uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap); -Qcow2Bitmap *bm; if (!bdrv_dirty_bitmap_get_persistence(bitmap) || bdrv_dirty_bitmap_inconsistent(bitmap)) { @@ -1625,7 +1624,7 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, /* allocate clusters and store bitmaps */ QSIMPLEQ_FOREACH(bm, bm_list, entry) { -BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; +bitmap = bm->dirty_bitmap; if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) { continue; -- 2.41.0
[PATCH v3 7/7] qobject atomics osdep: Make a few macros more hygienic
Variables declared in macros can shadow other variables. Much of the time, this is harmless, e.g.: #define _FDT(exp) \ do { \ int ret = (exp); \ if (ret < 0) { \ error_report("error creating device tree: %s: %s", \ #exp, fdt_strerror(ret)); \ exit(1); \ } \ } while (0) Harmless shadowing in h_client_architecture_support(): target_ulong ret; [...] ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize); if (ret == H_SUCCESS) { _FDT((fdt_pack(spapr->fdt_blob))); [...] } return ret; However, we can get in trouble when the shadowed variable is used in a macro argument: #define QOBJECT(obj) ({ \ typeof(obj) o = (obj); \ o ? container_of(&(o)->base, QObject, base) : NULL; \ }) QOBJECT(o) expands into ({ --->typeof(o) o = (o); o ? container_of(&(o)->base, QObject, base) : NULL; }) Unintended variable name capture at --->. We'd be saved by -Winit-self. But I could certainly construct more elaborate death traps that don't trigger it. To reduce the risk of trapping ourselves, we use variable names in macros that no sane person would use elsewhere. Here's our actual definition of QOBJECT(): #define QOBJECT(obj) ({ \ typeof(obj) _obj = (obj); \ _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ }) Works well enough until we nest macro calls. For instance, with #define qobject_ref(obj) ({ \ typeof(obj) _obj = (obj); \ qobject_ref_impl(QOBJECT(_obj));\ _obj; \ }) the expression qobject_ref(obj) expands into ({ typeof(obj) _obj = (obj); qobject_ref_impl( ({ --->typeof(_obj) _obj = (_obj); _obj ? container_of(&(_obj)->base, QObject, base) : NULL; })); _obj; }) Unintended variable name capture at --->. The only reliable way to prevent unintended variable name capture is -Wshadow. One blocker for enabling it is shadowing hiding in function-like macros like qdict_put(dict, "name", qobject_ref(...)) qdict_put() wraps its last argument in QOBJECT(), and the last argument here contains another QOBJECT(). Use dark preprocessor sorcery to make the macros that give us this problem use different variable names on every call. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/qmp/qobject.h | 10 -- include/qemu/atomic.h | 17 - include/qemu/compiler.h| 3 +++ include/qemu/osdep.h | 27 --- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 9003b71fd3..89b97d88bc 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -45,10 +45,16 @@ struct QObject { struct QObjectBase_ base; }; -#define QOBJECT(obj) ({ \ +/* + * Preprocessor sorcery ahead: use a different identifier for the + * local variable in each expansion, so we can nest macro calls + * without shadowing variables. + */ +#define QOBJECT_INTERNAL(obj, _obj) ({ \ typeof(obj) _obj = (obj); \ -_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ +_obj ? container_of(&_obj->base, QObject, base) : NULL; \ }) +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), MAKE_IDENTFIER(_obj)) /* Required for qobject_to() */ #define QTYPE_CAST_TO_QNull QTYPE_QNULL diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index d95612f7a0..f1d3d1702a 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -157,13 +157,20 @@ smp_read_barrier_depends(); #endif -#define qatomic_rcu_read(ptr) \ -({ \ +/* + * Preprocessor sorcery ahead: use a different identifier for the + * local variable in each expansion, so we can nest macro calls + * without shadowing variables. + */ +#define qatomic_rcu_read_internal(ptr, _val)\ +({ \ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZ
[PATCH v3 0/7] Steps towards enabling -Wshadow=local
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: PATCH 1. Enabling -Wshadow would prevent bugs like this one. But we'd have to clean up all the offenders first. We got a lot of them. Enabling -Wshadow=local should be less work for almost as much gain. I took a stab at it. There's a small, exciting part, and a large, boring part. The exciting part is dark preprocessor sorcery to let us nest macro calls without shadowing: PATCH 7. The boring part is cleaning up all the other warnings. I did some [PATCH 2-6], but ran out of steam long before finishing the job. Some 160 unique warnings remain. To see them, enable -Wshadow=local like so: diff --git a/meson.build b/meson.build index 98e68ef0b1..9fc4c7ac9d 100644 --- a/meson.build +++ b/meson.build @@ -466,6 +466,9 @@ warn_flags = [ '-Wno-tautological-type-limit-compare', '-Wno-psabi', '-Wno-gnu-variable-sized-type-not-at-end', + '-Wshadow=local', + '-Wno-error=shadow=local', + '-Wno-error=shadow=compatible-local', ] if targetos != 'darwin' You may want to drop the -Wno-error lines. v3: * PATCH 7: Comment typo [Eric], peel off a pair of parenthesis [Eric], revert accidental line breaks [Kevin] v2: * PATCH 3+6: Mollify checkpatch * PATCH 4: Redo for clearer code, R-bys dropped [Kevin] * PATCH 5: Rename tweaked [Kevin] * PATCH 6: Rename local @tran instead of the parameter [Kevin] * PATCH 7: Drop PASTE(), use glue() instead [Richard]; pass identifiers instead of __COUNTER__ for readability [Eric]; add comments Markus Armbruster (7): migration/rdma: Fix save_page method to fail on polling error migration: Clean up local variable shadowing ui: Clean up local variable shadowing block/dirty-bitmap: Clean up local variable shadowing block/vdi: Clean up local variable shadowing block: Clean up local variable shadowing qobject atomics osdep: Make a few macros more hygienic include/qapi/qmp/qobject.h | 10 -- include/qemu/atomic.h | 17 +++- include/qemu/compiler.h | 3 +++ include/qemu/osdep.h| 27 ++--- block.c | 9 + block/monitor/bitmap-qmp-cmds.c | 19 +- block/qcow2-bitmap.c| 3 +-- block/rbd.c | 2 +- block/stream.c | 1 - block/vdi.c | 7 +++ block/vvfat.c | 35 + hw/block/xen-block.c| 6 +++--- migration/block.c | 4 ++-- migration/ram.c | 8 +++- migration/rdma.c| 14 - migration/vmstate.c | 2 +- ui/gtk.c| 14 ++--- ui/spice-display.c | 9 + ui/vnc-palette.c| 2 -- ui/vnc.c| 12 +-- ui/vnc-enc-zrle.c.inc | 9 - 21 files changed, 121 insertions(+), 92 deletions(-) -- 2.41.0
[PATCH v3 1/7] migration/rdma: Fix save_page method to fail on polling error
qemu_rdma_save_page() reports polling error with error_report(), then succeeds anyway. This is because the variable holding the polling status *shadows* the variable the function returns. The latter remains zero. Broken since day one, and duplicated more recently. Fixes: 2da776db4846 (rdma: core logic) Fixes: b390afd8c50b (migration/rdma: Fix out of order wrid) Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Peter Xu Reviewed-by: Li Zhijian --- migration/rdma.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/migration/rdma.c b/migration/rdma.c index a2a3db35b1..3915d1d7c9 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -3282,7 +3282,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, */ while (1) { uint64_t wr_id, wr_id_in; -int ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); +ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; @@ -3297,7 +3298,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, while (1) { uint64_t wr_id, wr_id_in; -int ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); +ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; -- 2.41.0
[PATCH v3 2/7] migration: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Peter Xu Reviewed-by: Li Zhijian --- migration/block.c | 4 ++-- migration/ram.c | 8 +++- migration/rdma.c| 8 +--- migration/vmstate.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/migration/block.c b/migration/block.c index 86c2256a2b..eb6aafeb9e 100644 --- a/migration/block.c +++ b/migration/block.c @@ -440,8 +440,8 @@ static int init_blk_migration(QEMUFile *f) /* Can only insert new BDSes now because doing so while iterating block * devices may end up in a deadlock (iterating the new BDSes, too). */ for (i = 0; i < num_bs; i++) { -BlkMigDevState *bmds = bmds_bs[i].bmds; -BlockDriverState *bs = bmds_bs[i].bs; +bmds = bmds_bs[i].bmds; +bs = bmds_bs[i].bs; if (bmds) { ret = blk_insert_bs(bmds->blk, bs, &local_err); diff --git a/migration/ram.c b/migration/ram.c index 9040d66e61..0c202f8109 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3517,8 +3517,6 @@ int colo_init_ram_cache(void) * we use the same name 'ram_bitmap' as for migration. */ if (ram_bytes_total()) { -RAMBlock *block; - RAMBLOCK_FOREACH_NOT_IGNORED(block) { unsigned long pages = block->max_length >> TARGET_PAGE_BITS; block->bmap = bitmap_new(pages); @@ -3998,12 +3996,12 @@ static int ram_load_precopy(QEMUFile *f) } } if (migrate_ignore_shared()) { -hwaddr addr = qemu_get_be64(f); +hwaddr addr2 = qemu_get_be64(f); if (migrate_ram_is_ignored(block) && -block->mr->addr != addr) { +block->mr->addr != addr2) { error_report("Mismatched GPAs for block %s " "%" PRId64 "!= %" PRId64, - id, (uint64_t)addr, + id, (uint64_t)addr2, (uint64_t)block->mr->addr); ret = -EINVAL; } diff --git a/migration/rdma.c b/migration/rdma.c index 3915d1d7c9..c78ddfcb74 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -1902,9 +1902,11 @@ static int qemu_rdma_exchange_send(RDMAContext *rdma, RDMAControlHeader *head, * by waiting for a READY message. */ if (rdma->control_ready_expected) { -RDMAControlHeader resp; -ret = qemu_rdma_exchange_get_response(rdma, -&resp, RDMA_CONTROL_READY, RDMA_WRID_READY); +RDMAControlHeader resp_ignored; + +ret = qemu_rdma_exchange_get_response(rdma, &resp_ignored, + RDMA_CONTROL_READY, + RDMA_WRID_READY); if (ret < 0) { return ret; } diff --git a/migration/vmstate.c b/migration/vmstate.c index 31842c3afb..438ea77cfa 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -97,7 +97,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, return -EINVAL; } if (vmsd->pre_load) { -int ret = vmsd->pre_load(opaque); +ret = vmsd->pre_load(opaque); if (ret) { return ret; } -- 2.41.0
[PATCH v3 3/7] ui: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Peter Maydell --- ui/gtk.c | 14 +++--- ui/spice-display.c| 9 + ui/vnc-palette.c | 2 -- ui/vnc.c | 12 ++-- ui/vnc-enc-zrle.c.inc | 9 - 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index e09f97a86b..3373427c9b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -930,8 +930,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); GdkRectangle geometry; -int x = (int)motion->x_root; -int y = (int)motion->y_root; +int xr = (int)motion->x_root; +int yr = (int)motion->y_root; gdk_monitor_get_geometry(monitor, &geometry); @@ -942,13 +942,13 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, * may still be only half way across the screen. Without * this warp, the server pointer would thus appear to hit * an invisible wall */ -if (x <= geometry.x || x - geometry.x >= geometry.width - 1 || -y <= geometry.y || y - geometry.y >= geometry.height - 1) { +if (xr <= geometry.x || xr - geometry.x >= geometry.width - 1 || +yr <= geometry.y || yr - geometry.y >= geometry.height - 1) { GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion); -x = geometry.x + geometry.width / 2; -y = geometry.y + geometry.height / 2; +xr = geometry.x + geometry.width / 2; +yr = geometry.y + geometry.height / 2; -gdk_device_warp(dev, screen, x, y); +gdk_device_warp(dev, screen, xr, yr); s->last_set = FALSE; return FALSE; } diff --git a/ui/spice-display.c b/ui/spice-display.c index 5cc47bd668..6eb98a5a5c 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1081,15 +1081,16 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, } if (render_cursor) { -int x, y; +int ptr_x, ptr_y; + qemu_mutex_lock(&ssd->lock); -x = ssd->ptr_x; -y = ssd->ptr_y; +ptr_x = ssd->ptr_x; +ptr_y = ssd->ptr_y; qemu_mutex_unlock(&ssd->lock); egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb, !y_0_top); egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb, - !y_0_top, x, y, 1.0, 1.0); + !y_0_top, ptr_x, ptr_y, 1.0, 1.0); glFlush(); } diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c index dc7c0ba997..4e88c412f0 100644 --- a/ui/vnc-palette.c +++ b/ui/vnc-palette.c @@ -86,8 +86,6 @@ int palette_put(VncPalette *palette, uint32_t color) return 0; } if (!entry) { -VncPaletteEntry *entry; - entry = &palette->pool[palette->size]; entry->color = color; entry->idx = idx; diff --git a/ui/vnc.c b/ui/vnc.c index 6fd86996a5..ecb75ff8c8 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1584,15 +1584,15 @@ static void vnc_jobs_bh(void *opaque) */ static int vnc_client_read(VncState *vs) { -size_t ret; +size_t sz; #ifdef CONFIG_VNC_SASL if (vs->sasl.conn && vs->sasl.runSSF) -ret = vnc_client_read_sasl(vs); +sz = vnc_client_read_sasl(vs); else #endif /* CONFIG_VNC_SASL */ -ret = vnc_client_read_plain(vs); -if (!ret) { +sz = vnc_client_read_plain(vs); +if (!sz) { if (vs->disconnecting) { vnc_disconnect_finish(vs); return -1; @@ -3118,8 +3118,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd) cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES, server_stride); if (vd->guest.format != VNC_SERVER_FB_FORMAT) { -int width = pixman_image_get_width(vd->server); -tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); +int w = pixman_image_get_width(vd->server); +tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, w); } else { int guest_bpp = PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb)); diff --git a/ui/vnc-enc-zrle.c.inc b/ui/vnc-enc-zrle.c.inc index a8ca37d05e..2ef7501d52 100644 --- a/ui/vnc-enc-zrle.c.inc +++ b/ui/vnc-enc-zrle.c.inc @@ -153,11 +153,12 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, } if (use_rle) { -ZRLE_PIXEL *ptr = data; -ZRLE_PI
[PATCH v3 6/7] block: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Acked-by: Anthony PERARD Acked-by: Ilya Dryomov Reviewed-by: Kevin Wolf --- block.c | 9 + block/rbd.c | 2 +- block/stream.c | 1 - block/vvfat.c| 35 ++- hw/block/xen-block.c | 6 +++--- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/block.c b/block.c index 8da89aaa62..bb5dd17e9c 100644 --- a/block.c +++ b/block.c @@ -3035,18 +3035,19 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs, &local_err); if (ret < 0 && child_class->change_aio_ctx) { -Transaction *tran = tran_new(); +Transaction *aio_ctx_tran = tran_new(); GHashTable *visited = g_hash_table_new(NULL, NULL); bool ret_child; g_hash_table_add(visited, new_child); ret_child = child_class->change_aio_ctx(new_child, child_ctx, -visited, tran, NULL); +visited, aio_ctx_tran, +NULL); if (ret_child == true) { error_free(local_err); ret = 0; } -tran_finalize(tran, ret_child == true ? 0 : -1); +tran_finalize(aio_ctx_tran, ret_child == true ? 0 : -1); g_hash_table_destroy(visited); } @@ -6077,12 +6078,12 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), QLIST_FOREACH(drv, &bdrv_drivers, list) { if (drv->format_name) { bool found = false; -int i = count; if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, read_only)) { continue; } +i = count; while (formats && i && !found) { found = !strcmp(formats[--i], drv->format_name); } diff --git a/block/rbd.c b/block/rbd.c index 978671411e..472ca05cba 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1290,7 +1290,7 @@ static int coroutine_fn qemu_rbd_start_co(BlockDriverState *bs, * operations that exceed the current size. */ if (offset + bytes > s->image_size) { -int r = qemu_rbd_resize(bs, offset + bytes); +r = qemu_rbd_resize(bs, offset + bytes); if (r < 0) { return r; } diff --git a/block/stream.c b/block/stream.c index e522bbdec5..007253880b 100644 --- a/block/stream.c +++ b/block/stream.c @@ -282,7 +282,6 @@ void stream_start(const char *job_id, BlockDriverState *bs, /* Make sure that the image is opened in read-write mode */ bs_read_only = bdrv_is_read_only(bs); if (bs_read_only) { -int ret; /* Hold the chain during reopen */ if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) { return; diff --git a/block/vvfat.c b/block/vvfat.c index 0ddc91fc09..856b479c91 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -777,7 +777,6 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) while((entry=readdir(dir))) { unsigned int length=strlen(dirname)+2+strlen(entry->d_name); char* buffer; -direntry_t* direntry; struct stat st; int is_dot=!strcmp(entry->d_name,"."); int is_dotdot=!strcmp(entry->d_name,".."); @@ -857,7 +856,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) /* fill with zeroes up to the end of the cluster */ while(s->directory.next%(0x10*s->sectors_per_cluster)) { -direntry_t* direntry=array_get_next(&(s->directory)); +direntry = array_get_next(&(s->directory)); memset(direntry,0,sizeof(direntry_t)); } @@ -1962,24 +1961,24 @@ get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const ch * This is horribly inefficient, but that is okay, since * it is rarely executed, if at all. */ -int64_t offset = cluster2sector(s, cluster_num); +int64_t offs = cluster2sector(s, cluster_num); vvfat_close_current_file(s); for (i = 0; i < s->sectors_per_cluster; i++) { int res; res = bdrv_is_allocated(s->qcow->bs, -(offset + i) * BDRV_SECTOR_SIZE, +(offs
[PATCH v3 5/7] block/vdi: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf --- block/vdi.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 6c35309e04..934e1b849b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -634,7 +634,6 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, bmap_entry = le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Allocate new block and write to it. */ -uint64_t data_offset; qemu_co_rwlock_upgrade(&s->bmap_lock); bmap_entry = le32_to_cpu(s->bmap[block_index]); if (VDI_IS_ALLOCATED(bmap_entry)) { @@ -700,7 +699,7 @@ nonallocating_write: /* One or more new blocks were allocated. */ VdiHeader *header; uint8_t *base; -uint64_t offset; +uint64_t bmap_offset; uint32_t n_sectors; g_free(block); @@ -723,11 +722,11 @@ nonallocating_write: bmap_first /= (SECTOR_SIZE / sizeof(uint32_t)); bmap_last /= (SECTOR_SIZE / sizeof(uint32_t)); n_sectors = bmap_last - bmap_first + 1; -offset = s->bmap_sector + bmap_first; +bmap_offset = s->bmap_sector + bmap_first; base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE; logout("will write %u block map sectors starting from entry %u\n", n_sectors, bmap_first); -ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE, +ret = bdrv_co_pwrite(bs->file, bmap_offset * SECTOR_SIZE, n_sectors * SECTOR_SIZE, base, 0); } -- 2.41.0
Re: [PATCH v2 7/7] qobject atomics osdep: Make a few macros more hygienic
Kevin Wolf writes: > Am 20.09.2023 um 20:31 hat Markus Armbruster geschrieben: [...] >> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h >> index 9003b71fd3..d36cc97805 100644 >> --- a/include/qapi/qmp/qobject.h >> +++ b/include/qapi/qmp/qobject.h >> @@ -45,10 +45,17 @@ struct QObject { >> struct QObjectBase_ base; >> }; >> >> -#define QOBJECT(obj) ({ \ >> +/* >> + * Preprocessory sorcery ahead: use a different identifier for the >> + * local variable in each expansion, so we can nest macro calls >> + * without shadowing variables. >> + */ >> +#define QOBJECT_INTERNAL(obj, _obj) ({ \ >> typeof(obj) _obj = (obj); \ >> -_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ >> +_obj\ >> +? container_of(&(_obj)->base, QObject, base) : NULL;\ > > What happened here? The code in this line (or now two lines) seems to be > unchanged apart from a strange looking newline. Accident, will fix, thanks! >> }) >> +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), MAKE_IDENTFIER(_obj)) > > Kevin
Re: [PATCH v2 7/7] qobject atomics osdep: Make a few macros more hygienic
Eric Blake writes: > On Wed, Sep 20, 2023 at 08:31:49PM +0200, Markus Armbruster wrote: > ... >> The only reliable way to prevent unintended variable name capture is >> -Wshadow. >> >> One blocker for enabling it is shadowing hiding in function-like >> macros like >> >> qdict_put(dict, "name", qobject_ref(...)) >> >> qdict_put() wraps its last argument in QOBJECT(), and the last >> argument here contains another QOBJECT(). >> >> Use dark preprocessor sorcery to make the macros that give us this >> problem use different variable names on every call. >> >> Signed-off-by: Markus Armbruster >> Reviewed-by: Eric Blake > > It's changed (for the better) since v1, so I'm re-reviewing. > >> --- >> include/qapi/qmp/qobject.h | 11 +-- >> include/qemu/atomic.h | 17 - >> include/qemu/compiler.h| 3 +++ >> include/qemu/osdep.h | 31 +++ >> 4 files changed, 47 insertions(+), 15 deletions(-) >> >> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h >> index 9003b71fd3..d36cc97805 100644 >> --- a/include/qapi/qmp/qobject.h >> +++ b/include/qapi/qmp/qobject.h >> @@ -45,10 +45,17 @@ struct QObject { >> struct QObjectBase_ base; >> }; >> >> -#define QOBJECT(obj) ({ \ >> +/* >> + * Preprocessory sorcery ahead: use a different identifier for the > > s/Preprocessory/Preprocessor/ (multiple times in the patch) Dang! Will fix. >> + * local variable in each expansion, so we can nest macro calls >> + * without shadowing variables. >> + */ >> +#define QOBJECT_INTERNAL(obj, _obj) ({ \ >> typeof(obj) _obj = (obj); \ >> -_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ >> +_obj\ >> +? container_of(&(_obj)->base, QObject, base) : NULL;\ > > As pointed out before, you can write &_obj->base instead of > &(_obj)->base, now that we know _obj is a single identifier rather > than an arbitrary expression. Not strictly necessary since the extra > () doesn't change semantics... Makes sense, I just forgot here. >> }) >> +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), MAKE_IDENTFIER(_obj)) >> >> /* Required for qobject_to() */ >> #define QTYPE_CAST_TO_QNull QTYPE_QNULL >> diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h >> index d95612f7a0..d4cbd01909 100644 >> --- a/include/qemu/atomic.h >> +++ b/include/qemu/atomic.h >> @@ -157,13 +157,20 @@ >> smp_read_barrier_depends(); >> #endif >> >> -#define qatomic_rcu_read(ptr) \ >> -({ \ >> +/* >> + * Preprocessory sorcery ahead: use a different identifier for the >> + * local variable in each expansion, so we can nest macro calls >> + * without shadowing variables. >> + */ >> +#define qatomic_rcu_read_internal(ptr, _val)\ >> +({ \ >> qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \ >> -typeof_strip_qual(*ptr) _val; \ >> -qatomic_rcu_read__nocheck(ptr, &_val); \ >> -_val; \ >> +typeof_strip_qual(*ptr) _val; \ >> +qatomic_rcu_read__nocheck(ptr, &_val); \ > > ...but it looks odd for the patch to not be consistent on that front. > >> +_val; \ >> }) >> +#define qatomic_rcu_read(ptr) \ >> +qatomic_rcu_read_internal((ptr), MAKE_IDENTFIER(_val)) >> >> #define qatomic_rcu_set(ptr, i) do { \ >> qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \ >> diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h >> index a309f90c76..03236d830c 100644 >> --- a/include/qemu/compiler.h >> +++ b/include/qemu/compiler.h >> @@ -37,6 +37,9 @@ >> #define tostring(s) #s >> #endif >> >> +/* Expands into an identifier stemN, where N is another number each time */ >> +#define MAKE_IDENTFIER(stem) glue(stem, __COUNTER__) > > I like how this turned out. > > With the spelling fix, and optionally with the redundant () dropped, > you can keep my R-b. Thanks!
[PATCH v2 3/7] ui: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Peter Maydell --- ui/gtk.c | 14 +++--- ui/spice-display.c| 9 + ui/vnc-palette.c | 2 -- ui/vnc.c | 12 ++-- ui/vnc-enc-zrle.c.inc | 9 - 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index e09f97a86b..3373427c9b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -930,8 +930,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); GdkRectangle geometry; -int x = (int)motion->x_root; -int y = (int)motion->y_root; +int xr = (int)motion->x_root; +int yr = (int)motion->y_root; gdk_monitor_get_geometry(monitor, &geometry); @@ -942,13 +942,13 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, * may still be only half way across the screen. Without * this warp, the server pointer would thus appear to hit * an invisible wall */ -if (x <= geometry.x || x - geometry.x >= geometry.width - 1 || -y <= geometry.y || y - geometry.y >= geometry.height - 1) { +if (xr <= geometry.x || xr - geometry.x >= geometry.width - 1 || +yr <= geometry.y || yr - geometry.y >= geometry.height - 1) { GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion); -x = geometry.x + geometry.width / 2; -y = geometry.y + geometry.height / 2; +xr = geometry.x + geometry.width / 2; +yr = geometry.y + geometry.height / 2; -gdk_device_warp(dev, screen, x, y); +gdk_device_warp(dev, screen, xr, yr); s->last_set = FALSE; return FALSE; } diff --git a/ui/spice-display.c b/ui/spice-display.c index 5cc47bd668..6eb98a5a5c 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1081,15 +1081,16 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, } if (render_cursor) { -int x, y; +int ptr_x, ptr_y; + qemu_mutex_lock(&ssd->lock); -x = ssd->ptr_x; -y = ssd->ptr_y; +ptr_x = ssd->ptr_x; +ptr_y = ssd->ptr_y; qemu_mutex_unlock(&ssd->lock); egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb, !y_0_top); egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb, - !y_0_top, x, y, 1.0, 1.0); + !y_0_top, ptr_x, ptr_y, 1.0, 1.0); glFlush(); } diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c index dc7c0ba997..4e88c412f0 100644 --- a/ui/vnc-palette.c +++ b/ui/vnc-palette.c @@ -86,8 +86,6 @@ int palette_put(VncPalette *palette, uint32_t color) return 0; } if (!entry) { -VncPaletteEntry *entry; - entry = &palette->pool[palette->size]; entry->color = color; entry->idx = idx; diff --git a/ui/vnc.c b/ui/vnc.c index 6fd86996a5..ecb75ff8c8 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1584,15 +1584,15 @@ static void vnc_jobs_bh(void *opaque) */ static int vnc_client_read(VncState *vs) { -size_t ret; +size_t sz; #ifdef CONFIG_VNC_SASL if (vs->sasl.conn && vs->sasl.runSSF) -ret = vnc_client_read_sasl(vs); +sz = vnc_client_read_sasl(vs); else #endif /* CONFIG_VNC_SASL */ -ret = vnc_client_read_plain(vs); -if (!ret) { +sz = vnc_client_read_plain(vs); +if (!sz) { if (vs->disconnecting) { vnc_disconnect_finish(vs); return -1; @@ -3118,8 +3118,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd) cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES, server_stride); if (vd->guest.format != VNC_SERVER_FB_FORMAT) { -int width = pixman_image_get_width(vd->server); -tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); +int w = pixman_image_get_width(vd->server); +tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, w); } else { int guest_bpp = PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb)); diff --git a/ui/vnc-enc-zrle.c.inc b/ui/vnc-enc-zrle.c.inc index a8ca37d05e..2ef7501d52 100644 --- a/ui/vnc-enc-zrle.c.inc +++ b/ui/vnc-enc-zrle.c.inc @@ -153,11 +153,12 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, } if (use_rle) { -ZRLE_PIXEL *ptr = data; -ZRLE_PI
[PATCH v2 0/7] Steps towards enabling -Wshadow=local
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: PATCH 1. Enabling -Wshadow would prevent bugs like this one. But we'd have to clean up all the offenders first. We got a lot of them. Enabling -Wshadow=local should be less work for almost as much gain. I took a stab at it. There's a small, exciting part, and a large, boring part. The exciting part is dark preprocessor sorcery to let us nest macro calls without shadowing: PATCH 7. The boring part is cleaning up all the other warnings. I did some [PATCH 2-6], but ran out of steam long before finishing the job. Some 160 unique warnings remain. To see them, enable -Wshadow=local like so: diff --git a/meson.build b/meson.build index 98e68ef0b1..9fc4c7ac9d 100644 --- a/meson.build +++ b/meson.build @@ -466,6 +466,9 @@ warn_flags = [ '-Wno-tautological-type-limit-compare', '-Wno-psabi', '-Wno-gnu-variable-sized-type-not-at-end', + '-Wshadow=local', + '-Wno-error=shadow=local', + '-Wno-error=shadow=compatible-local', ] if targetos != 'darwin' You may want to drop the -Wno-error lines. v2: * PATCH 3+6: Mollify checkpatch * PATCH 4: Redo for clearer code, R-bys dropped [Kevin] * PATCH 5: Rename tweaked [Kevin] * PATCH 6: Rename local @tran instead of the parameter [Kevin] * PATCH 7: Drop PASTE(), use glue() instead [Richard]; pass identifiers instead of __COUNTER__ for readability [Eric]; add comments Markus Armbruster (7): migration/rdma: Fix save_page method to fail on polling error migration: Clean up local variable shadowing ui: Clean up local variable shadowing block/dirty-bitmap: Clean up local variable shadowing block/vdi: Clean up local variable shadowing block: Clean up local variable shadowing qobject atomics osdep: Make a few macros more hygienic include/qapi/qmp/qobject.h | 11 +-- include/qemu/atomic.h | 17 +++- include/qemu/compiler.h | 3 +++ include/qemu/osdep.h| 31 + block.c | 9 + block/monitor/bitmap-qmp-cmds.c | 19 +- block/qcow2-bitmap.c| 3 +-- block/rbd.c | 2 +- block/stream.c | 1 - block/vdi.c | 7 +++ block/vvfat.c | 35 + hw/block/xen-block.c| 6 +++--- migration/block.c | 4 ++-- migration/ram.c | 8 +++- migration/rdma.c| 14 - migration/vmstate.c | 2 +- ui/gtk.c| 14 ++--- ui/spice-display.c | 9 + ui/vnc-palette.c| 2 -- ui/vnc.c| 12 +-- ui/vnc-enc-zrle.c.inc | 9 - 21 files changed, 125 insertions(+), 93 deletions(-) -- 2.41.0
[PATCH v2 4/7] block/dirty-bitmap: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: rename both the pair of parameters and the pair of local variables. While there, move the local variables to function scope. Suggested-by: Kevin Wolf Signed-off-by: Markus Armbruster --- block/monitor/bitmap-qmp-cmds.c | 19 ++- block/qcow2-bitmap.c| 3 +-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c index 55f778f5af..70d01a3776 100644 --- a/block/monitor/bitmap-qmp-cmds.c +++ b/block/monitor/bitmap-qmp-cmds.c @@ -258,37 +258,38 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name, bdrv_disable_dirty_bitmap(bitmap); } -BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, +BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *dst_node, + const char *dst_bitmap, BlockDirtyBitmapOrStrList *bms, HBitmap **backup, Error **errp) { BlockDriverState *bs; BdrvDirtyBitmap *dst, *src; BlockDirtyBitmapOrStrList *lst; +const char *src_node, *src_bitmap; HBitmap *local_backup = NULL; GLOBAL_STATE_CODE(); -dst = block_dirty_bitmap_lookup(node, target, &bs, errp); +dst = block_dirty_bitmap_lookup(dst_node, dst_bitmap, &bs, errp); if (!dst) { return NULL; } for (lst = bms; lst; lst = lst->next) { switch (lst->value->type) { -const char *name, *node; case QTYPE_QSTRING: -name = lst->value->u.local; -src = bdrv_find_dirty_bitmap(bs, name); +src_bitmap = lst->value->u.local; +src = bdrv_find_dirty_bitmap(bs, src_bitmap); if (!src) { -error_setg(errp, "Dirty bitmap '%s' not found", name); +error_setg(errp, "Dirty bitmap '%s' not found", src_bitmap); goto fail; } break; case QTYPE_QDICT: -node = lst->value->u.external.node; -name = lst->value->u.external.name; -src = block_dirty_bitmap_lookup(node, name, NULL, errp); +src_node = lst->value->u.external.node; +src_bitmap = lst->value->u.external.name; +src = block_dirty_bitmap_lookup(src_node, src_bitmap, NULL, errp); if (!src) { goto fail; } diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 037fa2d435..ffd5cd3b23 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1555,7 +1555,6 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, FOR_EACH_DIRTY_BITMAP(bs, bitmap) { const char *name = bdrv_dirty_bitmap_name(bitmap); uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap); -Qcow2Bitmap *bm; if (!bdrv_dirty_bitmap_get_persistence(bitmap) || bdrv_dirty_bitmap_inconsistent(bitmap)) { @@ -1625,7 +1624,7 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, /* allocate clusters and store bitmaps */ QSIMPLEQ_FOREACH(bm, bm_list, entry) { -BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; +bitmap = bm->dirty_bitmap; if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) { continue; -- 2.41.0
[PATCH v2 7/7] qobject atomics osdep: Make a few macros more hygienic
Variables declared in macros can shadow other variables. Much of the time, this is harmless, e.g.: #define _FDT(exp) \ do { \ int ret = (exp); \ if (ret < 0) { \ error_report("error creating device tree: %s: %s", \ #exp, fdt_strerror(ret)); \ exit(1); \ } \ } while (0) Harmless shadowing in h_client_architecture_support(): target_ulong ret; [...] ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize); if (ret == H_SUCCESS) { _FDT((fdt_pack(spapr->fdt_blob))); [...] } return ret; However, we can get in trouble when the shadowed variable is used in a macro argument: #define QOBJECT(obj) ({ \ typeof(obj) o = (obj); \ o ? container_of(&(o)->base, QObject, base) : NULL; \ }) QOBJECT(o) expands into ({ --->typeof(o) o = (o); o ? container_of(&(o)->base, QObject, base) : NULL; }) Unintended variable name capture at --->. We'd be saved by -Winit-self. But I could certainly construct more elaborate death traps that don't trigger it. To reduce the risk of trapping ourselves, we use variable names in macros that no sane person would use elsewhere. Here's our actual definition of QOBJECT(): #define QOBJECT(obj) ({ \ typeof(obj) _obj = (obj); \ _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ }) Works well enough until we nest macro calls. For instance, with #define qobject_ref(obj) ({ \ typeof(obj) _obj = (obj); \ qobject_ref_impl(QOBJECT(_obj));\ _obj; \ }) the expression qobject_ref(obj) expands into ({ typeof(obj) _obj = (obj); qobject_ref_impl( ({ --->typeof(_obj) _obj = (_obj); _obj ? container_of(&(_obj)->base, QObject, base) : NULL; })); _obj; }) Unintended variable name capture at --->. The only reliable way to prevent unintended variable name capture is -Wshadow. One blocker for enabling it is shadowing hiding in function-like macros like qdict_put(dict, "name", qobject_ref(...)) qdict_put() wraps its last argument in QOBJECT(), and the last argument here contains another QOBJECT(). Use dark preprocessor sorcery to make the macros that give us this problem use different variable names on every call. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- include/qapi/qmp/qobject.h | 11 +-- include/qemu/atomic.h | 17 - include/qemu/compiler.h| 3 +++ include/qemu/osdep.h | 31 +++ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 9003b71fd3..d36cc97805 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -45,10 +45,17 @@ struct QObject { struct QObjectBase_ base; }; -#define QOBJECT(obj) ({ \ +/* + * Preprocessory sorcery ahead: use a different identifier for the + * local variable in each expansion, so we can nest macro calls + * without shadowing variables. + */ +#define QOBJECT_INTERNAL(obj, _obj) ({ \ typeof(obj) _obj = (obj); \ -_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ +_obj\ +? container_of(&(_obj)->base, QObject, base) : NULL;\ }) +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), MAKE_IDENTFIER(_obj)) /* Required for qobject_to() */ #define QTYPE_CAST_TO_QNull QTYPE_QNULL diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index d95612f7a0..d4cbd01909 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -157,13 +157,20 @@ smp_read_barrier_depends(); #endif -#define qatomic_rcu_read(ptr) \ -({ \ +/* + * Preprocessory sorcery ahead: use a different identifier for the + * local variable in each expansion, so we can nest macro calls + * without shadowing variables. + */ +#define qatomic_rcu_read_internal(ptr, _val)\ +({
[PATCH v2 2/7] migration: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Peter Xu --- migration/block.c | 4 ++-- migration/ram.c | 8 +++- migration/rdma.c| 8 +--- migration/vmstate.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/migration/block.c b/migration/block.c index 86c2256a2b..eb6aafeb9e 100644 --- a/migration/block.c +++ b/migration/block.c @@ -440,8 +440,8 @@ static int init_blk_migration(QEMUFile *f) /* Can only insert new BDSes now because doing so while iterating block * devices may end up in a deadlock (iterating the new BDSes, too). */ for (i = 0; i < num_bs; i++) { -BlkMigDevState *bmds = bmds_bs[i].bmds; -BlockDriverState *bs = bmds_bs[i].bs; +bmds = bmds_bs[i].bmds; +bs = bmds_bs[i].bs; if (bmds) { ret = blk_insert_bs(bmds->blk, bs, &local_err); diff --git a/migration/ram.c b/migration/ram.c index 9040d66e61..0c202f8109 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3517,8 +3517,6 @@ int colo_init_ram_cache(void) * we use the same name 'ram_bitmap' as for migration. */ if (ram_bytes_total()) { -RAMBlock *block; - RAMBLOCK_FOREACH_NOT_IGNORED(block) { unsigned long pages = block->max_length >> TARGET_PAGE_BITS; block->bmap = bitmap_new(pages); @@ -3998,12 +3996,12 @@ static int ram_load_precopy(QEMUFile *f) } } if (migrate_ignore_shared()) { -hwaddr addr = qemu_get_be64(f); +hwaddr addr2 = qemu_get_be64(f); if (migrate_ram_is_ignored(block) && -block->mr->addr != addr) { +block->mr->addr != addr2) { error_report("Mismatched GPAs for block %s " "%" PRId64 "!= %" PRId64, - id, (uint64_t)addr, + id, (uint64_t)addr2, (uint64_t)block->mr->addr); ret = -EINVAL; } diff --git a/migration/rdma.c b/migration/rdma.c index 3915d1d7c9..c78ddfcb74 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -1902,9 +1902,11 @@ static int qemu_rdma_exchange_send(RDMAContext *rdma, RDMAControlHeader *head, * by waiting for a READY message. */ if (rdma->control_ready_expected) { -RDMAControlHeader resp; -ret = qemu_rdma_exchange_get_response(rdma, -&resp, RDMA_CONTROL_READY, RDMA_WRID_READY); +RDMAControlHeader resp_ignored; + +ret = qemu_rdma_exchange_get_response(rdma, &resp_ignored, + RDMA_CONTROL_READY, + RDMA_WRID_READY); if (ret < 0) { return ret; } diff --git a/migration/vmstate.c b/migration/vmstate.c index 31842c3afb..438ea77cfa 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -97,7 +97,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, return -EINVAL; } if (vmsd->pre_load) { -int ret = vmsd->pre_load(opaque); +ret = vmsd->pre_load(opaque); if (ret) { return ret; } -- 2.41.0
[PATCH v2 5/7] block/vdi: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi --- block/vdi.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 6c35309e04..934e1b849b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -634,7 +634,6 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, bmap_entry = le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Allocate new block and write to it. */ -uint64_t data_offset; qemu_co_rwlock_upgrade(&s->bmap_lock); bmap_entry = le32_to_cpu(s->bmap[block_index]); if (VDI_IS_ALLOCATED(bmap_entry)) { @@ -700,7 +699,7 @@ nonallocating_write: /* One or more new blocks were allocated. */ VdiHeader *header; uint8_t *base; -uint64_t offset; +uint64_t bmap_offset; uint32_t n_sectors; g_free(block); @@ -723,11 +722,11 @@ nonallocating_write: bmap_first /= (SECTOR_SIZE / sizeof(uint32_t)); bmap_last /= (SECTOR_SIZE / sizeof(uint32_t)); n_sectors = bmap_last - bmap_first + 1; -offset = s->bmap_sector + bmap_first; +bmap_offset = s->bmap_sector + bmap_first; base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE; logout("will write %u block map sectors starting from entry %u\n", n_sectors, bmap_first); -ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE, +ret = bdrv_co_pwrite(bs->file, bmap_offset * SECTOR_SIZE, n_sectors * SECTOR_SIZE, base, 0); } -- 2.41.0
[PATCH v2 1/7] migration/rdma: Fix save_page method to fail on polling error
qemu_rdma_save_page() reports polling error with error_report(), then succeeds anyway. This is because the variable holding the polling status *shadows* the variable the function returns. The latter remains zero. Broken since day one, and duplicated more recently. Fixes: 2da776db4846 (rdma: core logic) Fixes: b390afd8c50b (migration/rdma: Fix out of order wrid) Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Peter Xu Reviewed-by: Li Zhijian --- migration/rdma.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/migration/rdma.c b/migration/rdma.c index a2a3db35b1..3915d1d7c9 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -3282,7 +3282,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, */ while (1) { uint64_t wr_id, wr_id_in; -int ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); +ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; @@ -3297,7 +3298,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, while (1) { uint64_t wr_id, wr_id_in; -int ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); +ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; -- 2.41.0
[PATCH v2 6/7] block: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Acked-by: Anthony PERARD Acked-by: Ilya Dryomov --- block.c | 9 + block/rbd.c | 2 +- block/stream.c | 1 - block/vvfat.c| 35 ++- hw/block/xen-block.c | 6 +++--- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/block.c b/block.c index 8da89aaa62..bb5dd17e9c 100644 --- a/block.c +++ b/block.c @@ -3035,18 +3035,19 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs, &local_err); if (ret < 0 && child_class->change_aio_ctx) { -Transaction *tran = tran_new(); +Transaction *aio_ctx_tran = tran_new(); GHashTable *visited = g_hash_table_new(NULL, NULL); bool ret_child; g_hash_table_add(visited, new_child); ret_child = child_class->change_aio_ctx(new_child, child_ctx, -visited, tran, NULL); +visited, aio_ctx_tran, +NULL); if (ret_child == true) { error_free(local_err); ret = 0; } -tran_finalize(tran, ret_child == true ? 0 : -1); +tran_finalize(aio_ctx_tran, ret_child == true ? 0 : -1); g_hash_table_destroy(visited); } @@ -6077,12 +6078,12 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), QLIST_FOREACH(drv, &bdrv_drivers, list) { if (drv->format_name) { bool found = false; -int i = count; if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, read_only)) { continue; } +i = count; while (formats && i && !found) { found = !strcmp(formats[--i], drv->format_name); } diff --git a/block/rbd.c b/block/rbd.c index 978671411e..472ca05cba 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1290,7 +1290,7 @@ static int coroutine_fn qemu_rbd_start_co(BlockDriverState *bs, * operations that exceed the current size. */ if (offset + bytes > s->image_size) { -int r = qemu_rbd_resize(bs, offset + bytes); +r = qemu_rbd_resize(bs, offset + bytes); if (r < 0) { return r; } diff --git a/block/stream.c b/block/stream.c index e522bbdec5..007253880b 100644 --- a/block/stream.c +++ b/block/stream.c @@ -282,7 +282,6 @@ void stream_start(const char *job_id, BlockDriverState *bs, /* Make sure that the image is opened in read-write mode */ bs_read_only = bdrv_is_read_only(bs); if (bs_read_only) { -int ret; /* Hold the chain during reopen */ if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) { return; diff --git a/block/vvfat.c b/block/vvfat.c index 0ddc91fc09..856b479c91 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -777,7 +777,6 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) while((entry=readdir(dir))) { unsigned int length=strlen(dirname)+2+strlen(entry->d_name); char* buffer; -direntry_t* direntry; struct stat st; int is_dot=!strcmp(entry->d_name,"."); int is_dotdot=!strcmp(entry->d_name,".."); @@ -857,7 +856,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) /* fill with zeroes up to the end of the cluster */ while(s->directory.next%(0x10*s->sectors_per_cluster)) { -direntry_t* direntry=array_get_next(&(s->directory)); +direntry = array_get_next(&(s->directory)); memset(direntry,0,sizeof(direntry_t)); } @@ -1962,24 +1961,24 @@ get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const ch * This is horribly inefficient, but that is okay, since * it is rarely executed, if at all. */ -int64_t offset = cluster2sector(s, cluster_num); +int64_t offs = cluster2sector(s, cluster_num); vvfat_close_current_file(s); for (i = 0; i < s->sectors_per_cluster; i++) { int res; res = bdrv_is_allocated(s->qcow->bs, -(offset + i) * BDRV_SECTOR_SIZE, +(offs + i) * BDRV_SECTOR_SIZE,
Re: [PATCH 4/7] block/dirty-bitmap: Clean up local variable shadowing
Kevin Wolf writes: > Am 19.09.2023 um 07:48 hat Markus Armbruster geschrieben: >> Kevin Wolf writes: >> >> > Am 31.08.2023 um 15:25 hat Markus Armbruster geschrieben: >> >> Local variables shadowing other local variables or parameters make the >> >> code needlessly hard to understand. Tracked down with -Wshadow=local. >> >> Clean up: delete inner declarations when they are actually redundant, >> >> else rename variables. >> >> >> >> Signed-off-by: Markus Armbruster >> >> --- >> >> block/monitor/bitmap-qmp-cmds.c | 2 +- >> >> block/qcow2-bitmap.c| 3 +-- >> >> 2 files changed, 2 insertions(+), 3 deletions(-) >> >> >> >> diff --git a/block/monitor/bitmap-qmp-cmds.c >> >> b/block/monitor/bitmap-qmp-cmds.c >> >> index 55f778f5af..4d018423d8 100644 >> >> --- a/block/monitor/bitmap-qmp-cmds.c >> >> +++ b/block/monitor/bitmap-qmp-cmds.c >> >> @@ -276,7 +276,7 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char >> >> *node, const char *target, >> >> >> >> for (lst = bms; lst; lst = lst->next) { >> >> switch (lst->value->type) { >> >> -const char *name, *node; >> >> +const char *name; >> >> case QTYPE_QSTRING: >> >> name = lst->value->u.local; >> >> src = bdrv_find_dirty_bitmap(bs, name); >> > >> > The names in this function are all over the place... A more ambitious >> > patch could rename the parameters to dst_node/dst_bitmap and these >> > variables to src_node/src_bitmap to get some more consistency (both with >> > each other and with the existing src/dst variables). >> >> What exactly would you like me to consider? Perhaps: >> >> * Rename parameter @node to @dst_node >> >> * Rename which parameter to @dst_bitmap? > > Parameter @target to @dst_bitmap (it's the name of a bitmap in > @node/@dst_node) > >> * Rename nested local @node to @src_node >> >> * Rename which local variable to @src_bitmap? > > @name to @src_bitmap (it's the name of a bitmap in the local > @node/@src_node) > >> * Move nested locals to function scope > > I don't really mind either way, but yes, maybe that would be more > conventional. Done for v2. > That you couldn't tell for two of the variables what they actually are > probably supports the argument that they should be renamed. :-) Fair point!
Re: [PATCH 7/7] qobject atomics osdep: Make a few macros more hygienic
Eric Blake writes: > On Fri, Sep 01, 2023 at 10:48:26AM +0200, Markus Armbruster wrote: >> > Indeed, not fully understanding the preprocessor makes for some >> > interesting death traps. >> >> We use ALL_CAPS for macros to signal "watch out for traps". >> > >> >> -#define QOBJECT(obj) ({ \ >> >> -typeof(obj) _obj = (obj); \ >> >> -_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ >> >> +#define QOBJECT_INTERNAL(obj, l) ({ \ >> >> +typeof(obj) PASTE(_obj, l) = (obj); \ >> >> +PASTE(_obj, l) \ >> >> +? container_of(&(PASTE(_obj, l))->base, QObject, base) : NULL; \ >> >> }) >> >> +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), __COUNTER__) >> > >> > Slick! Every call to QOBJECT() defines a unique temporary variable >> > name. But as written, QOBJECT(o) expands to this (when __COUNTER__ is >> > 1): >> > >> > ({ >> > typeof((o)) _obj1 = ((o)); >> > _obj1 ? container_of(&(_obj1)->base, QObject, base) : NULL; >> > }) >> > >> > which has three sets of redundant parens that could be elided. Why do >> > you need to add () around obj when forwarding to QOBJECT_INTERNAL()? >> >> Habit: enclose macro arguments in parenthesis unless there's a specific >> need not to. >> >> > The only way the expansion of the text passed through the 'obj' >> > parameter can contain a comma is if the user has already parenthesized >> > it on their end (not that I expect a comma expression to be a frequent >> > argument to QOBJECT(), but who knows). Arguing that it is to silence >> > a syntax checker is weak; since we must NOT add parens around the >> > parameters to QOBJECT_INTERNAL (calling PASTE((_obj), (l)) is >> > obviously wrong). >> > >> > Meanwhile, the repetition of three calls to PASTE() is annoying. How >> > about: >> > >> > #define QOBJECT_INTERNAL_2(_obj, _tmp) ({ \ >> > typeof _obj _tmp = _obj; \ >> > _tmp ? container_of(&_tmp->base, QObject, base) : NULL; \ >> > )} >> > #define QOBJECT_INTERNAL_1(_arg, _tmp) QOBJECT_INTERNAL_2(_arg, _tmp) >> > #define QOBJECT_INTERNAL(_arg, _ctr) \ >> > QOBJECT_INTERNAL_1(_arg, PASTE(_obj, _ctr)) >> > #define QOBJECT(obj) QOBJECT_INTERNAL((obj), __COUNTER__) >> > >> > or: >> > >> > #define QOBJECT_INTERNAL_2(_obj, _tmp) ({ \ >> > typeof(_obj) _tmp = (_obj); \ >> > _tmp ? container_of(&_tmp->base, QObject, base) : NULL; \ >> > )} >> > #define QOBJECT_INTERNAL_1(_arg, _tmp) QOBJECT_INTERNAL_2(_arg, _tmp) >> > #define QOBJECT_INTERNAL(_arg, _ctr) \ >> > QOBJECT_INTERNAL_1(_arg, PASTE(_obj, _ctr)) >> > #define QOBJECT(obj) QOBJECT_INTERNAL(obj, __COUNTER__) >> > >> > where, in either case, QOBJECT(o) should then expand to >> > >> > ({ >> > typeof (o) _obj1 = (o); >> > _obj1 ? container_of(&_obj1->base, QObject, base) : NULL; >> > }) >> >> The idea is to have the innermost macro take the variable name instead >> of the counter. "PASTE(_obj, l)" then becomes "_tmp" there, which is >> more legible. However, we pay for it by going through two more macros. >> >> Can you explain why you need two more? > > Likewise habit, on my part (and laziness - I wrote the previous email > without testing anything). I've learned over the years that pasting is > hard (you can't mix ## with a macro that you want expanded without 2 > layers of indirection), so I started out by adding two layers of > QOBJECT_INTERNAL, then wrote QOBJECT to forward to QOBJECT_INTERNAL. > But now that you asked, I actually spent the time to test with the > preprocessor, and your hunch is indeed correct: I over-compensated > becaues of my habit. > > $cat foo.c > #define PASTE(_a, _b) _a##_b > > #define QOBJECT_INTERNAL_2(_obj, _tmp) ({ \ > typeof _obj _tmp = _obj; \ > _tmp ? container_of(&_tmp->base, QObject, base) : NULL; \ > )} > #define QOBJECT_INTERNAL_1(_arg, _tmp) QOBJECT_INTERNAL_2(_arg, _tmp) > #define QOBJECT_INTERNAL(_arg, _ctr) \ > QOBJECT_INTERNAL_1(_arg, PASTE(_obj, _ctr)) > #define QOBJECT(obj) QOBJECT_INTERNAL((obj), __COUNTER__) > >
Re: [PATCH 4/7] block/dirty-bitmap: Clean up local variable shadowing
Kevin Wolf writes: > Am 31.08.2023 um 15:25 hat Markus Armbruster geschrieben: >> Local variables shadowing other local variables or parameters make the >> code needlessly hard to understand. Tracked down with -Wshadow=local. >> Clean up: delete inner declarations when they are actually redundant, >> else rename variables. >> >> Signed-off-by: Markus Armbruster >> --- >> block/monitor/bitmap-qmp-cmds.c | 2 +- >> block/qcow2-bitmap.c| 3 +-- >> 2 files changed, 2 insertions(+), 3 deletions(-) >> >> diff --git a/block/monitor/bitmap-qmp-cmds.c >> b/block/monitor/bitmap-qmp-cmds.c >> index 55f778f5af..4d018423d8 100644 >> --- a/block/monitor/bitmap-qmp-cmds.c >> +++ b/block/monitor/bitmap-qmp-cmds.c >> @@ -276,7 +276,7 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char >> *node, const char *target, >> >> for (lst = bms; lst; lst = lst->next) { >> switch (lst->value->type) { >> -const char *name, *node; >> +const char *name; >> case QTYPE_QSTRING: >> name = lst->value->u.local; >> src = bdrv_find_dirty_bitmap(bs, name); > > The names in this function are all over the place... A more ambitious > patch could rename the parameters to dst_node/dst_bitmap and these > variables to src_node/src_bitmap to get some more consistency (both with > each other and with the existing src/dst variables). What exactly would you like me to consider? Perhaps: * Rename parameter @node to @dst_node * Rename which parameter to @dst_bitmap? * Rename nested local @node to @src_node * Rename which local variable to @src_bitmap? * Move nested locals to function scope > Preexisting, so I'm not insisting that you should do this. > >> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c >> index 037fa2d435..ffd5cd3b23 100644 >> --- a/block/qcow2-bitmap.c >> +++ b/block/qcow2-bitmap.c >> @@ -1555,7 +1555,6 @@ bool >> qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, >> FOR_EACH_DIRTY_BITMAP(bs, bitmap) { >> const char *name = bdrv_dirty_bitmap_name(bitmap); >> uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap); >> -Qcow2Bitmap *bm; >> >> if (!bdrv_dirty_bitmap_get_persistence(bitmap) || >> bdrv_dirty_bitmap_inconsistent(bitmap)) { >> @@ -1625,7 +1624,7 @@ bool >> qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, >> >> /* allocate clusters and store bitmaps */ >> QSIMPLEQ_FOREACH(bm, bm_list, entry) { >> -BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; >> +bitmap = bm->dirty_bitmap; >> >> if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) { >> continue; > > Reviewed-by: Kevin Wolf Thanks!
Re: [PATCH 1/7] migration/rdma: Fix save_page method to fail on polling error
Eric Blake writes: > On Thu, Aug 31, 2023 at 03:25:40PM +0200, Markus Armbruster wrote: >> qemu_rdma_save_page() reports polling error with error_report(), then >> succeeds anyway. This is because the variable holding the polling >> status *shadows* the variable the function returns. The latter >> remains zero. >> >> Broken since day one, and duplicated more recently. >> >> Fixes: 2da776db4846 (rdma: core logic) >> Fixes: b390afd8c50b (migration/rdma: Fix out of order wrid) > > Alas, the curse of immutable git history preserving typos in commit > subjects ;) "wrid" is short for "work request ID", actually. > The alternative of rewriting history and breaking SHA > references is worse. Rewriting master is a big no-no. git-note can be used to correct the record, but it has its usability issues. >> Signed-off-by: Markus Armbruster >> --- >> migration/rdma.c | 6 -- >> 1 file changed, 4 insertions(+), 2 deletions(-) > > Reviewed-by: Eric Blake Thanks!
Re: [PATCH 6/7] block: Clean up local variable shadowing
Kevin Wolf writes: > Am 31.08.2023 um 15:25 hat Markus Armbruster geschrieben: >> Local variables shadowing other local variables or parameters make the >> code needlessly hard to understand. Tracked down with -Wshadow=local. >> Clean up: delete inner declarations when they are actually redundant, >> else rename variables. >> >> Signed-off-by: Markus Armbruster >> --- >> block.c | 7 --- >> block/rbd.c | 2 +- >> block/stream.c | 1 - >> block/vvfat.c| 34 +- >> hw/block/xen-block.c | 6 +++--- >> 5 files changed, 25 insertions(+), 25 deletions(-) > > I wonder why you made vdi a separate patch, but not vvfat, even though > that has more changes. (Of course, my selfish motivation for asking this > is that I could have given a R-b for it and wouldn't have to look at it > again in a v2 :-)) I split by maintainer. The files changed by this patch are only covered by "Block layer core". >> diff --git a/block.c b/block.c >> index a307c151a8..7f0003d8ac 100644 >> --- a/block.c >> +++ b/block.c >> @@ -3001,7 +3001,8 @@ static BdrvChild >> *bdrv_attach_child_common(BlockDriverState *child_bs, >> BdrvChildRole child_role, >> uint64_t perm, uint64_t >> shared_perm, >> void *opaque, >> - Transaction *tran, Error **errp) >> + Transaction *transaction, >> + Error **errp) >> { >> BdrvChild *new_child; >> AioContext *parent_ctx, *new_child_ctx; >> @@ -3088,7 +3089,7 @@ static BdrvChild >> *bdrv_attach_child_common(BlockDriverState *child_bs, >> .old_parent_ctx = parent_ctx, >> .old_child_ctx = child_ctx, >> }; >> -tran_add(tran, &bdrv_attach_child_common_drv, s); >> +tran_add(transaction, &bdrv_attach_child_common_drv, s); >> >> if (new_child_ctx != child_ctx) { >> aio_context_release(new_child_ctx); > > I think I would resolve this one the other way around. 'tran' is the > typical name for the parameter and it is the transaction that this > function should add things to. > > The other one that shadows it is a local transaction that is completed > within the function. I think it's better if that one has a different > name. > > As usual, being more specific than just 'tran' vs. 'transaction' would > be nice. Maybe 'aio_ctx_tran' for the nested one? Can do. > The rest looks okay. Thanks!
Re: [PATCH 5/7] block/vdi: Clean up local variable shadowing
Kevin Wolf writes: > Am 31.08.2023 um 15:25 hat Markus Armbruster geschrieben: >> Local variables shadowing other local variables or parameters make the >> code needlessly hard to understand. Tracked down with -Wshadow=local. >> Clean up: delete inner declarations when they are actually redundant, >> else rename variables. >> >> Signed-off-by: Markus Armbruster > >> @@ -700,7 +699,7 @@ nonallocating_write: >> /* One or more new blocks were allocated. */ >> VdiHeader *header; >> uint8_t *base; >> -uint64_t offset; >> +uint64_t offs; >> uint32_t n_sectors; >> >> g_free(block); >> @@ -723,11 +722,11 @@ nonallocating_write: >> bmap_first /= (SECTOR_SIZE / sizeof(uint32_t)); >> bmap_last /= (SECTOR_SIZE / sizeof(uint32_t)); >> n_sectors = bmap_last - bmap_first + 1; >> -offset = s->bmap_sector + bmap_first; >> +offs = s->bmap_sector + bmap_first; >> base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE; >> logout("will write %u block map sectors starting from entry %u\n", >> n_sectors, bmap_first); >> -ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE, >> +ret = bdrv_co_pwrite(bs->file, offs * SECTOR_SIZE, >> n_sectors * SECTOR_SIZE, base, 0); >> } > > Having two variables 'offset' and 'offs' doesn't really help with > clarity either. Can we be more specific and use something like > 'bmap_offset' here? Sure!
Re: [PATCH 7/7] qobject atomics osdep: Make a few macros more hygienic
Cédric Le Goater writes: > On 8/31/23 16:30, Eric Blake wrote: >> On Thu, Aug 31, 2023 at 03:25:46PM +0200, Markus Armbruster wrote: >> [This paragraph written last: Bear with my stream of consciousness >> review below, where I end up duplicating some of the conslusions you >> reached before the point where I saw where the patch was headed] >> >>> Variables declared in macros can shadow other variables. Much of the >>> time, this is harmless, e.g.: >>> >>> #define _FDT(exp) \ >>> do { \ >>> int ret = (exp); \ >>> if (ret < 0) { \ >>> error_report("error creating device tree: %s: %s", \ >>> #exp, fdt_strerror(ret)); \ >>> exit(1); \ >>> } \ >>> } while (0) >> Which is why I've seen some projects require a strict namespace >> separation: if all macro parameters and any identifiers declared in >> macros use either a leading or a trailing _ (I prefer a trailing one, >> to avoid risking conflicts with libc reserved namespace; but leading >> is usually okay), and all other identifiers avoid that namespace, then >> you will never have shadowing by calling a macro from normal code. > > I started fixing the _FDT() macro since it is quite noisy at compile. > Same for qemu_fdt_setprop_cells(). So are we ok with names like 'ret_' > and 'i_' ? I used a 'local_' prefix for now but I can change. I believe identifiers with a '_' suffix are just fine in macros. We have quite a few of them already. > I also have a bunch of fixes for ppc. Appreciated!
Re: [PATCH 7/7] qobject atomics osdep: Make a few macros more hygienic
Eric Blake writes: > On Thu, Aug 31, 2023 at 03:25:46PM +0200, Markus Armbruster wrote: > > [This paragraph written last: Bear with my stream of consciousness > review below, where I end up duplicating some of the conslusions you > reached before the point where I saw where the patch was headed] > >> Variables declared in macros can shadow other variables. Much of the >> time, this is harmless, e.g.: >> >> #define _FDT(exp) \ >> do { \ >> int ret = (exp); \ >> if (ret < 0) { \ >> error_report("error creating device tree: %s: %s", \ >> #exp, fdt_strerror(ret)); \ >> exit(1); \ >> } \ >> } while (0) > > Which is why I've seen some projects require a strict namespace > separation: if all macro parameters and any identifiers declared in > macros use either a leading or a trailing _ (I prefer a trailing one, > to avoid risking conflicts with libc reserved namespace; but leading > is usually okay), and all other identifiers avoid that namespace, then > you will never have shadowing by calling a macro from normal code. > >> >> Harmless shadowing in h_client_architecture_support(): >> >> target_ulong ret; >> >> [...] >> >> ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize); >> if (ret == H_SUCCESS) { >> _FDT((fdt_pack(spapr->fdt_blob))); >> [...] >> } >> >> return ret; >> >> However, we can get in trouble when the shadowed variable is used in a >> macro argument: >> >> #define QOBJECT(obj) ({ \ >> typeof(obj) o = (obj); \ >> o ? container_of(&(o)->base, QObject, base) : NULL; \ >> }) >> >> QOBJECT(o) expands into >> >> ({ >> --->typeof(o) o = (o); >> o ? container_of(&(o)->base, QObject, base) : NULL; >> }) >> >> Unintended variable name capture at --->. We'd be saved by >> -Winit-self. But I could certainly construct more elaborate death >> traps that don't trigger it. > > Indeed, not fully understanding the preprocessor makes for some > interesting death traps. We use ALL_CAPS for macros to signal "watch out for traps". >> To reduce the risk of trapping ourselves, we use variable names in >> macros that no sane person would use elsewhere. Here's our actual >> definition of QOBJECT(): >> >> #define QOBJECT(obj) ({ \ >> typeof(obj) _obj = (obj); \ >> _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ >> }) > > Yep, goes back to the policy I've seen of enforcing naming conventions > that ensure macros can't shadow normal code. > >> >> Works well enough until we nest macro calls. For instance, with >> >> #define qobject_ref(obj) ({ \ >> typeof(obj) _obj = (obj); \ >> qobject_ref_impl(QOBJECT(_obj));\ >> _obj; \ >> }) >> >> the expression qobject_ref(obj) expands into >> >> ({ >> typeof(obj) _obj = (obj); >> qobject_ref_impl( >> ({ >> --->typeof(_obj) _obj = (_obj); >> _obj ? container_of(&(_obj)->base, QObject, base) : NULL; >> })); >> _obj; >> }) >> >> Unintended variable name capture at --->. > > Yep, you've just proven how macros calling macros requires care, as we > no longer have the namespace protections. If macro calls can only > form a DAG, it is possible to choose unique intermediate declarations > for every macro (although remembering to do that, and still keeping > the macro definition legible, may not be easy). But if you can have > macros that form any sort of nesting loop (and we WANT to allow things > like MIN(MIN(a, b), c) - which is such a loop), dynamic naming becomes > the only solution. > >> >> The
Re: [PATCH 7/7] qobject atomics osdep: Make a few macros more hygienic
Richard Henderson writes: > On 8/31/23 06:25, Markus Armbruster wrote: >> +#define PASTE(a, b) a##b > > We already have glue() in qemu/compiler.h. Missed it, will fix. > The rest of it looks quite sensible. Thanks!
Re: [PATCH 3/7] ui: Clean up local variable shadowing
Peter Maydell writes: > On Thu, 31 Aug 2023 at 14:25, Markus Armbruster wrote: >> >> Local variables shadowing other local variables or parameters make the >> code needlessly hard to understand. Tracked down with -Wshadow=local. >> Clean up: delete inner declarations when they are actually redundant, >> else rename variables. >> >> Signed-off-by: Markus Armbruster > > >> diff --git a/ui/vnc-enc-zrle.c.inc b/ui/vnc-enc-zrle.c.inc >> index c107d8affc..edf42d4a6a 100644 >> --- a/ui/vnc-enc-zrle.c.inc >> +++ b/ui/vnc-enc-zrle.c.inc >> @@ -153,11 +153,12 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL >> *data, int w, int h, >> } >> >> if (use_rle) { >> -ZRLE_PIXEL *ptr = data; >> -ZRLE_PIXEL *end = ptr + w * h; >> ZRLE_PIXEL *run_start; >> ZRLE_PIXEL pix; >> >> +ptr = data; >> +end = ptr + w * h; >> + >> while (ptr < end) { >> int len; >> int index = 0; >> @@ -198,7 +199,7 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL >> *data, int w, int h, >> } >> } else if (use_palette) { /* no RLE */ >> int bppp; >> -ZRLE_PIXEL *ptr = data; >> +ptr = data; >> >> /* packed pixels */ >> >> @@ -241,8 +242,6 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL >> *data, int w, int h, >> #endif >> { >> #ifdef ZRLE_COMPACT_PIXEL >> -ZRLE_PIXEL *ptr; >> - >> for (ptr = data; ptr < data + w * h; ptr++) { >> ZRLE_WRITE_PIXEL(vs, *ptr); >> } > > For this one I'm tempted to suggest instead moving the > pix and end currently at whole-function scope into their > own block, so it's clear these are actually four > completely independent uses of ptr/end. But either way You have a point. However, we'd need to splice in a block just for that, which involved some reindenting. Can do if the assigned maintainers (Gerd and Marc-André) prefer it. Else, I'll stay with minimally invasive. > Reviewed-by: Peter Maydell Thanks!
Re: [PATCH 0/7] Steps towards enabling -Wshadow=local
Markus Armbruster writes: > Local variables shadowing other local variables or parameters make the > code needlessly hard to understand. Bugs love to hide in such code. > Evidence: PATCH 1. > > Enabling -Wshadow would prevent bugs like this one. But we'd have to > clean up all the offenders first. We got a lot of them. > > Enabling -Wshadow=local should be less work for almost as much gain. > I took a stab at it. There's a small, exciting part, and a large, > boring part. > > The exciting part is dark preprocessor sorcery to let us nest macro > calls without shadowing: PATCH 7. > > The boring part is cleaning up all the other warnings. I did some > [PATCH 2-6], but ran out of steam long before finishing the job. Some > 160 unique warnings remain. > > To see them, enable -Wshadow=local like so: > > diff --git a/meson.build b/meson.build > index 98e68ef0b1..9fc4c7ac9d 100644 > --- a/meson.build > +++ b/meson.build > @@ -466,6 +466,9 @@ warn_flags = [ >'-Wno-tautological-type-limit-compare', >'-Wno-psabi', >'-Wno-gnu-variable-sized-type-not-at-end', > + '-Wshadow=local', > + '-Wno-error=shadow=local', > + '-Wno-error=shadow=compatible-local', > ] > > if targetos != 'darwin' > > You may want to drop the -Wno-error lines. > > Subsystems with -Wshadow=local warnings: > > virtio-gpu > virtio > Device Tree > Overall TCG CPUs Philippe's "[PATCH 00/11] (few more) Steps towards enabling -Wshadow" takes care of this one. > Overall Audio backends > Open Sound System (OSS) Audio backend > vhost > vhost-user-gpu > Cryptography > M68K TCG CPUs > Dump > ACPI/SMBIOS > Allwinner-a10 Likewise. > ARM TCG CPUs > MPS2 > ASPEED BMCs > ARM SMMU > Virt > Machine core > PC Chipset > X86 TCG CPUs > PC > VT-d Emulation > IDE Likewise. > ARM cores > OpenPIC interrupt controller > q800 Likewise. > petalogix_ml605 > MicroBlaze TCG CPUs > Versatile PB > Network devices > NiosII TCG CPUs > nvme > PowerNV (Non-Virtualized) > sPAPR (pseries) > OpenTitan > RISC-V TCG CPUs > SCSI > USB > Linux user > Network packet abstractions Likewise. > Network device backends Likewise. > Network Block Device (NBD) > Semihosting > Memory API > Seccomp > Main loop > Hexagon TCG CPUs > X86 KVM CPUs > MIPS TCG CPUs Likewise. > PowerPC TCG CPUs > TriCore TCG CPUs > Common TCG code Likewise. > qtest > Throttling infrastructure > Vhost-user block device backend server > > Files with -Wshadow=local warnings: > > accel/tcg/tb-maint.c Likewise. > audio/audio.c > audio/ossaudio.c > contrib/vhost-user-gpu/vhost-user-gpu.c > contrib/vhost-user-gpu/vugpu.h > crypto/cipher-gnutls.c.inc > crypto/tls-cipher-suites.c > disas/m68k.c > dump/dump.c > hw/acpi/cpu_hotplug.c > hw/arm/allwinner-r40.c Likewise. > hw/arm/armsse.c > hw/arm/armv7m.c > hw/arm/aspeed_ast2600.c Likewise. > hw/arm/smmuv3-internal.h > hw/arm/smmuv3.c > hw/arm/virt.c Likewise. > hw/core/machine.c > hw/i2c/aspeed_i2c.c > hw/i2c/pm_smbus.c > hw/i386/acpi-build.c > hw/i386/acpi-microvm.c > hw/i386/intel_iommu.c > hw/i386/pc.c > hw/i386/x86.c > hw/ide/ahci.c Likewise. > hw/intc/arm_gicv3_its.c > hw/intc/openpic.c > hw/loongarch/virt.c > hw/m68k/bootinfo.h Likewise. > hw/microblaze/petalogix_ml605_mmu.c > hw/misc/arm_sysctl.c > hw/misc/aspeed_i3c.c > hw/net/vhost_net.c > hw/nios2/10m50_devboard.c > hw/nvme/ns.c > hw/ppc/pnv_psi.c > hw/ppc/spapr.c > hw/ppc/spapr_drc.c > hw/ppc/spapr_pci.c > hw/riscv/opentitan.c > hw/scsi/mptsas.c > hw/smbios/smbios.c > hw/usb/desc.c > hw/usb/dev-hub.c > hw/usb/dev-storage.c > hw/usb/hcd-xhci.c > hw/usb/host-libusb.c > hw/virtio/vhost.c > hw/virtio/virtio-pci.c > include/hw/cxl/cxl_device.h > include/hw/ppc/fdt.h > include/hw/virtio/virtio-gpu.h > include/sysemu/device_tree.h Likewise. > linux-user/flatload.c > linux-user/mmap.c > linux-user/strace.c > linux-user/syscall.c > net/eth.c Likewise. > qemu-nbd.c > semihosting/arm-compat-semi.c > softmmu/device_tree.c > softmmu/memory.c >
[PATCH 6/7] block: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster --- block.c | 7 --- block/rbd.c | 2 +- block/stream.c | 1 - block/vvfat.c| 34 +- hw/block/xen-block.c | 6 +++--- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/block.c b/block.c index a307c151a8..7f0003d8ac 100644 --- a/block.c +++ b/block.c @@ -3001,7 +3001,8 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs, BdrvChildRole child_role, uint64_t perm, uint64_t shared_perm, void *opaque, - Transaction *tran, Error **errp) + Transaction *transaction, + Error **errp) { BdrvChild *new_child; AioContext *parent_ctx, *new_child_ctx; @@ -3088,7 +3089,7 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs, .old_parent_ctx = parent_ctx, .old_child_ctx = child_ctx, }; -tran_add(tran, &bdrv_attach_child_common_drv, s); +tran_add(transaction, &bdrv_attach_child_common_drv, s); if (new_child_ctx != child_ctx) { aio_context_release(new_child_ctx); @@ -6073,12 +6074,12 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), QLIST_FOREACH(drv, &bdrv_drivers, list) { if (drv->format_name) { bool found = false; -int i = count; if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, read_only)) { continue; } +i = count; while (formats && i && !found) { found = !strcmp(formats[--i], drv->format_name); } diff --git a/block/rbd.c b/block/rbd.c index 978671411e..472ca05cba 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1290,7 +1290,7 @@ static int coroutine_fn qemu_rbd_start_co(BlockDriverState *bs, * operations that exceed the current size. */ if (offset + bytes > s->image_size) { -int r = qemu_rbd_resize(bs, offset + bytes); +r = qemu_rbd_resize(bs, offset + bytes); if (r < 0) { return r; } diff --git a/block/stream.c b/block/stream.c index e522bbdec5..007253880b 100644 --- a/block/stream.c +++ b/block/stream.c @@ -282,7 +282,6 @@ void stream_start(const char *job_id, BlockDriverState *bs, /* Make sure that the image is opened in read-write mode */ bs_read_only = bdrv_is_read_only(bs); if (bs_read_only) { -int ret; /* Hold the chain during reopen */ if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) { return; diff --git a/block/vvfat.c b/block/vvfat.c index 0ddc91fc09..d7425ee602 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -777,7 +777,6 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) while((entry=readdir(dir))) { unsigned int length=strlen(dirname)+2+strlen(entry->d_name); char* buffer; -direntry_t* direntry; struct stat st; int is_dot=!strcmp(entry->d_name,"."); int is_dotdot=!strcmp(entry->d_name,".."); @@ -857,7 +856,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) /* fill with zeroes up to the end of the cluster */ while(s->directory.next%(0x10*s->sectors_per_cluster)) { -direntry_t* direntry=array_get_next(&(s->directory)); +direntry = array_get_next(&(s->directory)); memset(direntry,0,sizeof(direntry_t)); } @@ -1962,24 +1961,24 @@ get_cluster_count_for_direntry(BDRVVVFATState* s, direntry_t* direntry, const ch * This is horribly inefficient, but that is okay, since * it is rarely executed, if at all. */ -int64_t offset = cluster2sector(s, cluster_num); +int64_t offs = cluster2sector(s, cluster_num); vvfat_close_current_file(s); for (i = 0; i < s->sectors_per_cluster; i++) { int res; res = bdrv_is_allocated(s->qcow->bs, -(offset + i) * BDRV_SECTOR_SIZE, +(offs + i) * BDRV_SECTOR_SIZE, BDRV_SECTOR_SIZE, NULL); if (res < 0) { return -1; } if (!res) { -
[PATCH 4/7] block/dirty-bitmap: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster --- block/monitor/bitmap-qmp-cmds.c | 2 +- block/qcow2-bitmap.c| 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c index 55f778f5af..4d018423d8 100644 --- a/block/monitor/bitmap-qmp-cmds.c +++ b/block/monitor/bitmap-qmp-cmds.c @@ -276,7 +276,7 @@ BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target, for (lst = bms; lst; lst = lst->next) { switch (lst->value->type) { -const char *name, *node; +const char *name; case QTYPE_QSTRING: name = lst->value->u.local; src = bdrv_find_dirty_bitmap(bs, name); diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 037fa2d435..ffd5cd3b23 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1555,7 +1555,6 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, FOR_EACH_DIRTY_BITMAP(bs, bitmap) { const char *name = bdrv_dirty_bitmap_name(bitmap); uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap); -Qcow2Bitmap *bm; if (!bdrv_dirty_bitmap_get_persistence(bitmap) || bdrv_dirty_bitmap_inconsistent(bitmap)) { @@ -1625,7 +1624,7 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, /* allocate clusters and store bitmaps */ QSIMPLEQ_FOREACH(bm, bm_list, entry) { -BdrvDirtyBitmap *bitmap = bm->dirty_bitmap; +bitmap = bm->dirty_bitmap; if (bitmap == NULL || bdrv_dirty_bitmap_readonly(bitmap)) { continue; -- 2.41.0
[PATCH 5/7] block/vdi: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster --- block/vdi.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index 6c35309e04..c084105b78 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -634,7 +634,6 @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, bmap_entry = le32_to_cpu(s->bmap[block_index]); if (!VDI_IS_ALLOCATED(bmap_entry)) { /* Allocate new block and write to it. */ -uint64_t data_offset; qemu_co_rwlock_upgrade(&s->bmap_lock); bmap_entry = le32_to_cpu(s->bmap[block_index]); if (VDI_IS_ALLOCATED(bmap_entry)) { @@ -700,7 +699,7 @@ nonallocating_write: /* One or more new blocks were allocated. */ VdiHeader *header; uint8_t *base; -uint64_t offset; +uint64_t offs; uint32_t n_sectors; g_free(block); @@ -723,11 +722,11 @@ nonallocating_write: bmap_first /= (SECTOR_SIZE / sizeof(uint32_t)); bmap_last /= (SECTOR_SIZE / sizeof(uint32_t)); n_sectors = bmap_last - bmap_first + 1; -offset = s->bmap_sector + bmap_first; +offs = s->bmap_sector + bmap_first; base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE; logout("will write %u block map sectors starting from entry %u\n", n_sectors, bmap_first); -ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE, +ret = bdrv_co_pwrite(bs->file, offs * SECTOR_SIZE, n_sectors * SECTOR_SIZE, base, 0); } -- 2.41.0
[PATCH 0/7] Steps towards enabling -Wshadow=local
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Bugs love to hide in such code. Evidence: PATCH 1. Enabling -Wshadow would prevent bugs like this one. But we'd have to clean up all the offenders first. We got a lot of them. Enabling -Wshadow=local should be less work for almost as much gain. I took a stab at it. There's a small, exciting part, and a large, boring part. The exciting part is dark preprocessor sorcery to let us nest macro calls without shadowing: PATCH 7. The boring part is cleaning up all the other warnings. I did some [PATCH 2-6], but ran out of steam long before finishing the job. Some 160 unique warnings remain. To see them, enable -Wshadow=local like so: diff --git a/meson.build b/meson.build index 98e68ef0b1..9fc4c7ac9d 100644 --- a/meson.build +++ b/meson.build @@ -466,6 +466,9 @@ warn_flags = [ '-Wno-tautological-type-limit-compare', '-Wno-psabi', '-Wno-gnu-variable-sized-type-not-at-end', + '-Wshadow=local', + '-Wno-error=shadow=local', + '-Wno-error=shadow=compatible-local', ] if targetos != 'darwin' You may want to drop the -Wno-error lines. Subsystems with -Wshadow=local warnings: virtio-gpu virtio Device Tree Overall TCG CPUs Overall Audio backends Open Sound System (OSS) Audio backend vhost vhost-user-gpu Cryptography M68K TCG CPUs Dump ACPI/SMBIOS Allwinner-a10 ARM TCG CPUs MPS2 ASPEED BMCs ARM SMMU Virt Machine core PC Chipset X86 TCG CPUs PC VT-d Emulation IDE ARM cores OpenPIC interrupt controller q800 petalogix_ml605 MicroBlaze TCG CPUs Versatile PB Network devices NiosII TCG CPUs nvme PowerNV (Non-Virtualized) sPAPR (pseries) OpenTitan RISC-V TCG CPUs SCSI USB Linux user Network packet abstractions Network device backends Network Block Device (NBD) Semihosting Memory API Seccomp Main loop Hexagon TCG CPUs X86 KVM CPUs MIPS TCG CPUs PowerPC TCG CPUs TriCore TCG CPUs Common TCG code qtest Throttling infrastructure Vhost-user block device backend server Files with -Wshadow=local warnings: accel/tcg/tb-maint.c audio/audio.c audio/ossaudio.c contrib/vhost-user-gpu/vhost-user-gpu.c contrib/vhost-user-gpu/vugpu.h crypto/cipher-gnutls.c.inc crypto/tls-cipher-suites.c disas/m68k.c dump/dump.c hw/acpi/cpu_hotplug.c hw/arm/allwinner-r40.c hw/arm/armsse.c hw/arm/armv7m.c hw/arm/aspeed_ast2600.c hw/arm/smmuv3-internal.h hw/arm/smmuv3.c hw/arm/virt.c hw/core/machine.c hw/i2c/aspeed_i2c.c hw/i2c/pm_smbus.c hw/i386/acpi-build.c hw/i386/acpi-microvm.c hw/i386/intel_iommu.c hw/i386/pc.c hw/i386/x86.c hw/ide/ahci.c hw/intc/arm_gicv3_its.c hw/intc/openpic.c hw/loongarch/virt.c hw/m68k/bootinfo.h hw/microblaze/petalogix_ml605_mmu.c hw/misc/arm_sysctl.c hw/misc/aspeed_i3c.c hw/net/vhost_net.c hw/nios2/10m50_devboard.c hw/nvme/ns.c hw/ppc/pnv_psi.c hw/ppc/spapr.c hw/ppc/spapr_drc.c hw/ppc/spapr_pci.c hw/riscv/opentitan.c hw/scsi/mptsas.c hw/smbios/smbios.c hw/usb/desc.c hw/usb/dev-hub.c hw/usb/dev-storage.c hw/usb/hcd-xhci.c hw/usb/host-libusb.c hw/virtio/vhost.c hw/virtio/virtio-pci.c include/hw/cxl/cxl_device.h include/hw/ppc/fdt.h include/hw/virtio/virtio-gpu.h include/sysemu/device_tree.h linux-user/flatload.c linux-user/mmap.c linux-user/strace.c linux-user/syscall.c net/eth.c qemu-nbd.c semihosting/arm-compat-semi.c softmmu/device_tree.c softmmu/memory.c softmmu/physmem.c softmmu/qemu-seccomp.c softmmu/vl.c target/arm/tcg/mve_helper.c target/arm/tcg/translate-m-nocp.c target/hexagon/helper_funcs_generated.c.inc target/hexagon/mmvec/macros.h target/hexagon/op_helper.c target/hexagon/translate.c target/i386/cpu.c target/i386/kvm/kvm.c target/i386/tcg/seg_helper.c target/i386/tcg/sysemu/svm_helper.c target/i386/tcg/translate.c target/m68k/translate.c target/mips/tcg/msa_helper.c target/mips/tcg/nanomips_translate.c.inc target/mips/tcg/translate.c target/ppc/int_helper.c target/riscv/cpu.c target/riscv/vector_helper.c target/tricore/translate.c tcg/tcg.c tests/qtest/m48t59-test.c tests/qtest/pflash-cfi02-test.c tests/unit/test-throttle.c util/vhost-user-server.c Markus Armbruster (7): migration/rdma: Fix save_page method to fail on polling error migration: Clean up local variable shadowing ui: Clean up local variable shadowing block/dirty-bitmap: Clean up local variable shadowing block/vdi: Clean up local variable shadowing block: C
[PATCH 1/7] migration/rdma: Fix save_page method to fail on polling error
qemu_rdma_save_page() reports polling error with error_report(), then succeeds anyway. This is because the variable holding the polling status *shadows* the variable the function returns. The latter remains zero. Broken since day one, and duplicated more recently. Fixes: 2da776db4846 (rdma: core logic) Fixes: b390afd8c50b (migration/rdma: Fix out of order wrid) Signed-off-by: Markus Armbruster --- migration/rdma.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/migration/rdma.c b/migration/rdma.c index ca430d319d..b2e869aced 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -3281,7 +3281,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, */ while (1) { uint64_t wr_id, wr_id_in; -int ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); +ret = qemu_rdma_poll(rdma, rdma->recv_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; @@ -3296,7 +3297,8 @@ static size_t qemu_rdma_save_page(QEMUFile *f, while (1) { uint64_t wr_id, wr_id_in; -int ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); +ret = qemu_rdma_poll(rdma, rdma->send_cq, &wr_id_in, NULL); + if (ret < 0) { error_report("rdma migration: polling error! %d", ret); goto err; -- 2.41.0
[PATCH 3/7] ui: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster --- ui/gtk.c | 14 +++--- ui/spice-display.c| 9 + ui/vnc-palette.c | 2 -- ui/vnc.c | 12 ++-- ui/vnc-enc-zrle.c.inc | 9 - 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 8ba41c8f13..24c78df79e 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -930,8 +930,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); GdkRectangle geometry; -int x = (int)motion->x_root; -int y = (int)motion->y_root; +int xr = (int)motion->x_root; +int yr = (int)motion->y_root; gdk_monitor_get_geometry(monitor, &geometry); @@ -942,13 +942,13 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, * may still be only half way across the screen. Without * this warp, the server pointer would thus appear to hit * an invisible wall */ -if (x <= geometry.x || x - geometry.x >= geometry.width - 1 || -y <= geometry.y || y - geometry.y >= geometry.height - 1) { +if (xr <= geometry.x || xr - geometry.x >= geometry.width - 1 || +yr <= geometry.y || yr - geometry.y >= geometry.height - 1) { GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion); -x = geometry.x + geometry.width / 2; -y = geometry.y + geometry.height / 2; +xr = geometry.x + geometry.width / 2; +yr = geometry.y + geometry.height / 2; -gdk_device_warp(dev, screen, x, y); +gdk_device_warp(dev, screen, xr, yr); s->last_set = FALSE; return FALSE; } diff --git a/ui/spice-display.c b/ui/spice-display.c index 3f3f8013d8..cbaba3bbad 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1080,15 +1080,16 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, } if (render_cursor) { -int x, y; +int ptr_x, ptr_y; + qemu_mutex_lock(&ssd->lock); -x = ssd->ptr_x; -y = ssd->ptr_y; +ptr_x = ssd->ptr_x; +ptr_y = ssd->ptr_y; qemu_mutex_unlock(&ssd->lock); egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb, !y_0_top); egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb, - !y_0_top, x, y, 1.0, 1.0); + !y_0_top, ptr_x, ptr_y, 1.0, 1.0); glFlush(); } diff --git a/ui/vnc-palette.c b/ui/vnc-palette.c index dc7c0ba997..4e88c412f0 100644 --- a/ui/vnc-palette.c +++ b/ui/vnc-palette.c @@ -86,8 +86,6 @@ int palette_put(VncPalette *palette, uint32_t color) return 0; } if (!entry) { -VncPaletteEntry *entry; - entry = &palette->pool[palette->size]; entry->color = color; entry->idx = idx; diff --git a/ui/vnc.c b/ui/vnc.c index 92964dcc0c..3e1fccffa3 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1584,15 +1584,15 @@ static void vnc_jobs_bh(void *opaque) */ static int vnc_client_read(VncState *vs) { -size_t ret; +size_t sz; #ifdef CONFIG_VNC_SASL if (vs->sasl.conn && vs->sasl.runSSF) -ret = vnc_client_read_sasl(vs); +sz = vnc_client_read_sasl(vs); else #endif /* CONFIG_VNC_SASL */ -ret = vnc_client_read_plain(vs); -if (!ret) { +sz = vnc_client_read_plain(vs); +if (!sz) { if (vs->disconnecting) { vnc_disconnect_finish(vs); return -1; @@ -3118,8 +3118,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd) cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES, server_stride); if (vd->guest.format != VNC_SERVER_FB_FORMAT) { -int width = pixman_image_get_width(vd->server); -tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width); +int w = pixman_image_get_width(vd->server); +tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, w); } else { int guest_bpp = PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb)); diff --git a/ui/vnc-enc-zrle.c.inc b/ui/vnc-enc-zrle.c.inc index c107d8affc..edf42d4a6a 100644 --- a/ui/vnc-enc-zrle.c.inc +++ b/ui/vnc-enc-zrle.c.inc @@ -153,11 +153,12 @@ static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, } if (use_rle) { -ZRLE_PIXEL *ptr = data; -ZRLE_PIXEL *end = ptr + w * h;
[PATCH 2/7] migration: Clean up local variable shadowing
Local variables shadowing other local variables or parameters make the code needlessly hard to understand. Tracked down with -Wshadow=local. Clean up: delete inner declarations when they are actually redundant, else rename variables. Signed-off-by: Markus Armbruster --- migration/block.c | 4 ++-- migration/ram.c | 8 +++- migration/rdma.c| 8 +--- migration/vmstate.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/migration/block.c b/migration/block.c index b9580a6c7e..33b3776198 100644 --- a/migration/block.c +++ b/migration/block.c @@ -438,8 +438,8 @@ static int init_blk_migration(QEMUFile *f) /* Can only insert new BDSes now because doing so while iterating block * devices may end up in a deadlock (iterating the new BDSes, too). */ for (i = 0; i < num_bs; i++) { -BlkMigDevState *bmds = bmds_bs[i].bmds; -BlockDriverState *bs = bmds_bs[i].bs; +bmds = bmds_bs[i].bmds; +bs = bmds_bs[i].bs; if (bmds) { ret = blk_insert_bs(bmds->blk, bs, &local_err); diff --git a/migration/ram.c b/migration/ram.c index 9040d66e61..0c202f8109 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3517,8 +3517,6 @@ int colo_init_ram_cache(void) * we use the same name 'ram_bitmap' as for migration. */ if (ram_bytes_total()) { -RAMBlock *block; - RAMBLOCK_FOREACH_NOT_IGNORED(block) { unsigned long pages = block->max_length >> TARGET_PAGE_BITS; block->bmap = bitmap_new(pages); @@ -3998,12 +3996,12 @@ static int ram_load_precopy(QEMUFile *f) } } if (migrate_ignore_shared()) { -hwaddr addr = qemu_get_be64(f); +hwaddr addr2 = qemu_get_be64(f); if (migrate_ram_is_ignored(block) && -block->mr->addr != addr) { +block->mr->addr != addr2) { error_report("Mismatched GPAs for block %s " "%" PRId64 "!= %" PRId64, - id, (uint64_t)addr, + id, (uint64_t)addr2, (uint64_t)block->mr->addr); ret = -EINVAL; } diff --git a/migration/rdma.c b/migration/rdma.c index b2e869aced..c6400cf641 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -1902,9 +1902,11 @@ static int qemu_rdma_exchange_send(RDMAContext *rdma, RDMAControlHeader *head, * by waiting for a READY message. */ if (rdma->control_ready_expected) { -RDMAControlHeader resp; -ret = qemu_rdma_exchange_get_response(rdma, -&resp, RDMA_CONTROL_READY, RDMA_WRID_READY); +RDMAControlHeader resp_ignored; + +ret = qemu_rdma_exchange_get_response(rdma, &resp_ignored, + RDMA_CONTROL_READY, + RDMA_WRID_READY); if (ret < 0) { return ret; } diff --git a/migration/vmstate.c b/migration/vmstate.c index 31842c3afb..438ea77cfa 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -97,7 +97,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, return -EINVAL; } if (vmsd->pre_load) { -int ret = vmsd->pre_load(opaque); +ret = vmsd->pre_load(opaque); if (ret) { return ret; } -- 2.41.0
[PATCH 7/7] qobject atomics osdep: Make a few macros more hygienic
Variables declared in macros can shadow other variables. Much of the time, this is harmless, e.g.: #define _FDT(exp) \ do { \ int ret = (exp); \ if (ret < 0) { \ error_report("error creating device tree: %s: %s", \ #exp, fdt_strerror(ret)); \ exit(1); \ } \ } while (0) Harmless shadowing in h_client_architecture_support(): target_ulong ret; [...] ret = do_client_architecture_support(cpu, spapr, vec, fdt_bufsize); if (ret == H_SUCCESS) { _FDT((fdt_pack(spapr->fdt_blob))); [...] } return ret; However, we can get in trouble when the shadowed variable is used in a macro argument: #define QOBJECT(obj) ({ \ typeof(obj) o = (obj); \ o ? container_of(&(o)->base, QObject, base) : NULL; \ }) QOBJECT(o) expands into ({ --->typeof(o) o = (o); o ? container_of(&(o)->base, QObject, base) : NULL; }) Unintended variable name capture at --->. We'd be saved by -Winit-self. But I could certainly construct more elaborate death traps that don't trigger it. To reduce the risk of trapping ourselves, we use variable names in macros that no sane person would use elsewhere. Here's our actual definition of QOBJECT(): #define QOBJECT(obj) ({ \ typeof(obj) _obj = (obj); \ _obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ }) Works well enough until we nest macro calls. For instance, with #define qobject_ref(obj) ({ \ typeof(obj) _obj = (obj); \ qobject_ref_impl(QOBJECT(_obj));\ _obj; \ }) the expression qobject_ref(obj) expands into ({ typeof(obj) _obj = (obj); qobject_ref_impl( ({ --->typeof(_obj) _obj = (_obj); _obj ? container_of(&(_obj)->base, QObject, base) : NULL; })); _obj; }) Unintended variable name capture at --->. The only reliable way to prevent unintended variable name capture is -Wshadow. One blocker for enabling it is shadowing hiding in function-like macros like qdict_put(dict, "name", qobject_ref(...)) qdict_put() wraps its last argument in QOBJECT(), and the last argument here contains another QOBJECT(). Use dark preprocessor sorcery to make the macros that give us this problem use different variable names on every call. Signed-off-by: Markus Armbruster --- include/qapi/qmp/qobject.h | 8 +--- include/qemu/atomic.h | 11 ++- include/qemu/osdep.h | 34 +++--- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 9003b71fd3..7b50fc905d 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -45,10 +45,12 @@ struct QObject { struct QObjectBase_ base; }; -#define QOBJECT(obj) ({ \ -typeof(obj) _obj = (obj); \ -_obj ? container_of(&(_obj)->base, QObject, base) : NULL; \ +#define QOBJECT_INTERNAL(obj, l) ({ \ +typeof(obj) PASTE(_obj, l) = (obj); \ +PASTE(_obj, l) \ +? container_of(&(PASTE(_obj, l))->base, QObject, base) : NULL; \ }) +#define QOBJECT(obj) QOBJECT_INTERNAL((obj), __COUNTER__) /* Required for qobject_to() */ #define QTYPE_CAST_TO_QNull QTYPE_QNULL diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index d95612f7a0..3f80ffac69 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -157,13 +157,14 @@ smp_read_barrier_depends(); #endif -#define qatomic_rcu_read(ptr) \ -({ \ +#define qatomic_rcu_read_internal(ptr, l) \ +({ \ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \ -typeof_strip_qual(*ptr) _val; \ -qatomic_rcu_read__nocheck(ptr, &_val); \ -_val; \ +typeof_strip_qual(*ptr) PASTE
Re: [PATCH 0/2] Deprecate support for 32-bit x86 and arm hosts
"Michael S. Tsirkin" writes: > On Tue, Feb 28, 2023 at 09:05:16PM +0100, Thomas Huth wrote: >> Well, without CI, I assume that the code will bitrot quite fast (considering >> that there are continuous improvements to TCG, for example). > > We have lots of hosts which we don't test with CI. They don't bitrot > because people do testing before release. This is what RCs are for. > We did releases before CI - it is a cost/benefit thing. Dropping 32-bit x86 from CI feels like a no-brainer in the current situation. As to deprecating 32-bit x86: the people by far most qualified to judge the "cost/benefit thing" are the regulars who are bearing the cost, i.e. the people who are actually maintaining it. Their opinion should overrule any "but somebody out there might still want to use it". Maintainers, please state your opinion, if any: aye or nay. Richard tells us "the maint overhead is large." Makes me think he's in favour of dropping 32-bit x86. Richard? Peter seems to be reluctant to drop 32-bit ARM at this point. Peter?
Re: [PATCH 1/2] docs/about: Deprecate 32-bit x86 hosts and qemu-system-i386
"Michael S. Tsirkin" writes: > On Tue, Feb 28, 2023 at 11:39:39AM +0100, Markus Armbruster wrote: >> The question to answer: Is 32 bit x86 worth its upkeep? Two >> sub-questions: 1. Is it worth the human attention? 2. Is it worth >> (scarce!) CI minutes? > > 3. Is it worth arguing about? If it's not worth arguing, then we merge Thomas's patch.
Re: [PATCH 1/2] docs/about: Deprecate 32-bit x86 hosts and qemu-system-i386
"Michael S. Tsirkin" writes: > On Tue, Feb 28, 2023 at 09:40:49AM +, Daniel P. Berrangé wrote: >> On Tue, Feb 28, 2023 at 10:14:52AM +0100, Thomas Huth wrote: >> > On 28/02/2023 10.03, Michael S. Tsirkin wrote: >> > > On Tue, Feb 28, 2023 at 08:59:52AM +, Daniel P. Berrangé wrote: >> > > > On Tue, Feb 28, 2023 at 03:19:20AM -0500, Michael S. Tsirkin wrote: >> > > > > On Tue, Feb 28, 2023 at 08:49:09AM +0100, Thomas Huth wrote: >> > > > > > On 27/02/2023 21.12, Michael S. Tsirkin wrote: >> > > > > > > On Mon, Feb 27, 2023 at 11:50:07AM +, Daniel P. Berrangé >> > > > > > > wrote: >> > > > > > > > I feel like we should have separate deprecation entries for the >> > > > > > > > i686 host support, and for qemu-system-i386 emulator binary, as >> > > > > > > > although they're related they are independant features with >> > > > > > > > differing impact. eg removing qemu-system-i386 affects all >> > > > > > > > host architectures, not merely 32-bit x86 host, so I think we >> > > > > > > > can explain the impact more clearly if we separate them. >> > > > > > > >> > > > > > > Removing qemu-system-i386 seems ok to me - I think >> > > > > > > qemu-system-x86_64 is >> > > > > > > a superset. >> > > > > > > >> > > > > > > Removing support for building on 32 bit systems seems like a >> > > > > > > pity - it's >> > > > > > > one of a small number of ways to run 64 bit binaries on 32 bit >> > > > > > > systems, >> > > > > > > and the maintainance overhead is quite small. >> > > > > > >> > > > > > Note: We're talking about 32-bit *x86* hosts here. Do you really >> > > > > > think that >> > > > > > someone is still using QEMU usermode emulation >> > > > > > to run 64-bit binaries on a 32-bit x86 host?? ... If so, I'd be >> > > > > > very surprised! >> > > > > >> > > > > I don't know - why x86 specifically? One can build a 32 bit binary >> > > > > on any host. >> > > > > I think 32 bit x86 environments are just more common in the cloud. >> > > > >> > > > Can you point to anything that backs up that assertion. Clouds I've >> > > > seen always give you a 64-bit environment, and many OS no longer >> > > > even ship 32-bit installable media. >> > > >> > > Sorry about being unclear. I meant that it seems easier to run CI in the >> > > cloud in a 32 bit x64 environment than get a 32 bit ARM environment. >> > >> > It's still doable ... but for how much longer? We're currently depending on >> > Fedora, but they also slowly drop more and more support for this >> > environment, see e.g.: >> >> FWIW, we should cull our fedora-i386-cross.docker dockerfile and >> replace it with a debian i686 dockerfile generated by lcitool. >> There's no compelling reason why i686 should be different from >> all our other cross builds which are based on Debian. The Debian >> lcitool generated container would have access to a wider range >> of deps than our hand written Fedora one. >> >> > https://www.theregister.com/2022/03/10/fedora_inches_closer_to_dropping/ >> >> With regards, >> Daniel > > ... and is closer to where 32 bit is likely to be deployed which is > systems like e.g. raspberry pi os which until recently was only > 32 bit. 32 bit ARM. How is that an argument for continued maintenance of 32 bit x86? If the argument goes like "32 bit x86 is easier to test in CI", then I don't buy it. Testing 64 bit ARM + 32 bit x86 does not magically replace testing 32 bit ARM. The question to answer: Is 32 bit x86 worth its upkeep? Two sub-questions: 1. Is it worth the human attention? 2. Is it worth (scarce!) CI minutes? I want to see an argument for benefits justifying the costs. A benefit like "somebody out there might still want to use it" I'd value at zero.
Re: [QEMU][PATCH v2 07/11] hw/xen/xen-hvm-common: Use g_new and error_setg_errno
Philippe Mathieu-Daudé writes: > On 2/12/22 03:59, Vikram Garhwal wrote: >> Replace g_malloc with g_new and perror with error_setg_errno. >> >> Signed-off-by: Vikram Garhwal >> --- >> hw/xen/xen-hvm-common.c | 15 --- >> 1 file changed, 8 insertions(+), 7 deletions(-) > > >> @@ -717,7 +717,7 @@ void destroy_hvm_domain(bool reboot) >> xc_interface *xc_handle; >> int sts; >> int rc; >> - >> +Error *errp = NULL; >> unsigned int reason = reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff; >> >> if (xen_dmod) { >> @@ -726,7 +726,7 @@ void destroy_hvm_domain(bool reboot) >> return; >> } >> if (errno != ENOTTY /* old Xen */) { >> -perror("xendevicemodel_shutdown failed"); >> +error_setg_errno(&errp, errno, "xendevicemodel_shutdown >> failed"); > > See "qapi/error.h": > > * = Passing errors around = > * > * Errors get passed to the caller through the conventional @errp > * parameter. > > Here you are not passing the error to the caller. Instead, you're leaking its memory. > Maybe you are looking for the "qemu/error-report.h" API? Plausible. Also, @errp is the conventional name for the Error ** parameter used to pass errors to the caller. Local Error * variables are usually called @err or @local_err (I prefer the former). [...]
Re: [PATCH v13 17/17] net: stream: add QAPI events to report connection state
Stefano Brivio writes: > On Mon, 24 Oct 2022 13:00:09 +0200 > Markus Armbruster wrote: > >> Markus Armbruster writes: >> >> > Cc: Stefano Brivio >> > >> > Laurent Vivier writes: >> > >> >> On 10/21/22 07:48, Markus Armbruster wrote: >> >>> Laurent Vivier writes: >> >>> >> >>>> The netdev reports NETDEV_STREAM_CONNECTED event when the backend >> >>>> is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. >> >>> >> >>> Use cases? >> >> >> >> This is asked by Stefano Brivio to allow libvirt to detect if connection >> >> to passt is lost and to restart passt. >> >> [...] >> >> >>> Could similar event signalling be useful for other kinds of netdev >> >>> backends? >> >> >> >> I was wondering, but it becomes more complicated to be generic. >> > >> > Making something complicated and generic where a simpler special >> > solution would do is the worst. >> > >> > Not quite as bad (but still plenty bad) is making a few special >> > solutions first, then replace them all with a generic solution. >> > >> > I believe we should have a good, hard think on possible applications of >> > a generic solution now. >> > >> > There is no need to hold back this series for that. >> > >> > If we conclude a generic solution is called for, we better replace this >> > special solution before it becomes ABI. Either by replacing it before >> > we release it, or by keeping it unstable until we replace it. >> >> Stefano, any thoughts on this? > > Actually, to me, it already looks as generic as it can be: stream > back-ends are the only ones connecting and disconnecting. > > I quickly tried to think about possible, similar events for other > back-ends: > > - user: handled by libslirp, there's no connection, and probably not > much we can or want to export from libslirp itself > > - tap, bridge: the closest equivalent would be interfaces changing > states, but that's something that's also externally observable with a > netlink socket, in case one needs to know. And in any case, it's > logically very different from a connection or disconnection. If we > want events for that, they should have different names > > - vhost-user, vde: we could implement something similar if the need > arises, but it should logically have a different name > > - l2tpv3: stateless, same as datagram-oriented socket. No states, no > events to report, I guess. > > All in all, to me, NETDEV_STREAM_{,DIS}CONNECTED events here don't look > very "special" or hackish. Thanks!
Re: [PATCH v14 17/17] net: stream: add QAPI events to report connection state
Laurent Vivier writes: > The netdev reports NETDEV_STREAM_CONNECTED event when the backend > is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. > > The NETDEV_STREAM_CONNECTED event includes the destination address. > > This allows a system manager like libvirt to detect when the server > fails. > > For instance with passt: > > { 'execute': 'qmp_capabilities' } > { "return": { } } > { "timestamp": { "seconds": 1666341395, "microseconds": 505347 }, > "event": "NETDEV_STREAM_CONNECTED", > "data": { "netdev-id": "netdev0", > "addr": { "path": "/tmp/passt_1.socket", "type": "unix" } } } > > [killing passt here] > > { "timestamp": { "seconds": 1666341430, "microseconds": 968694 }, > "event": "NETDEV_STREAM_DISCONNECTED", > "data": { "netdev-id": "netdev0" } } > > Signed-off-by: Laurent Vivier > Acked-by: Michael S. Tsirkin QAPI schema Acked-by: Markus Armbruster
Re: [PATCH v13 17/17] net: stream: add QAPI events to report connection state
Markus Armbruster writes: > Cc: Stefano Brivio > > Laurent Vivier writes: > >> On 10/21/22 07:48, Markus Armbruster wrote: >>> Laurent Vivier writes: >>> >>>> The netdev reports NETDEV_STREAM_CONNECTED event when the backend >>>> is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. >>> >>> Use cases? >> >> This is asked by Stefano Brivio to allow libvirt to detect if connection to >> passt is lost and to restart passt. [...] >>> Could similar event signalling be useful for other kinds of netdev >>> backends? >> >> I was wondering, but it becomes more complicated to be generic. > > Making something complicated and generic where a simpler special > solution would do is the worst. > > Not quite as bad (but still plenty bad) is making a few special > solutions first, then replace them all with a generic solution. > > I believe we should have a good, hard think on possible applications of > a generic solution now. > > There is no need to hold back this series for that. > > If we conclude a generic solution is called for, we better replace this > special solution before it becomes ABI. Either by replacing it before > we release it, or by keeping it unstable until we replace it. Stefano, any thoughts on this?
Re: [PATCH v14 15/17] net: stream: move to QIO to enable additional parameters
Laurent Vivier writes: > On 10/21/22 12:35, Markus Armbruster wrote: >> Philippe Mathieu-Daudé writes: >> >>> On 21/10/22 11:09, Laurent Vivier wrote: >>>> Use QIOChannel, QIOChannelSocket and QIONetListener. >>>> This allows net/stream to use all the available parameters provided by >>>> SocketAddress. >>>> Signed-off-by: Laurent Vivier >>>> Acked-by: Michael S. Tsirkin >>>> --- >>>>net/stream.c| 492 +--- >>>>qemu-options.hx | 4 +- >>>>2 files changed, 178 insertions(+), 318 deletions(-) >>> >>>> -static void net_stream_accept(void *opaque) >>>> +static void net_stream_server_listening(QIOTask *task, gpointer opaque) >>>>{ >>>>NetStreamState *s = opaque; >>>> -struct sockaddr_storage saddr; >>>> -socklen_t len; >>>> -int fd; >>>> - >>>> -for (;;) { >>>> -len = sizeof(saddr); >>>> -fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len); >>>> -if (fd < 0 && errno != EINTR) { >>>> -return; >>>> -} else if (fd >= 0) { >>>> -qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); >>>> -break; >>>> -} >>>> -} >>>> +QIOChannelSocket *listen_sioc = QIO_CHANNEL_SOCKET(s->listen_ioc); >>>> +SocketAddress *addr; >>>> +int ret; >>>> -s->fd = fd; >>>> -s->nc.link_down = false; >>>> -net_stream_connect(s); >>>> -switch (saddr.ss_family) { >>>> -case AF_INET: { >>>> -struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr; >>>> - >>>> -qemu_set_info_str(&s->nc, "connection from %s:%d", >>>> - inet_ntoa(saddr_in->sin_addr), >>>> - ntohs(saddr_in->sin_port)); >>>> -break; >>>> +if (listen_sioc->fd < 0) { >>>> +qemu_set_info_str(&s->nc, "connection error"); >>>> +return; >>>>} >>>> -case AF_UNIX: { >>>> -struct sockaddr_un saddr_un; >>>> -len = sizeof(saddr_un); >>>> -getsockname(s->listen_fd, (struct sockaddr *)&saddr_un, &len); >>>> -qemu_set_info_str(&s->nc, "connect from %s", saddr_un.sun_path); >>>> -break; >>>> -} >>>> -default: >>>> -g_assert_not_reached(); >>>> +addr = qio_channel_socket_get_local_address(listen_sioc, NULL); >>>> +g_assert(addr != NULL); >>> >>> Missing propagating Error* (observed in v12). >> >> *If* this is really a programming error: what about &error_abort? > > assert() informs the compiler that following code will not use addr with a > NULL value, I > don't think &error_abort does that. This could avoid an error report in code > static analyzer. I'd expect Coverity to see right through it. Static analyzers with a less global view won't, of course. For what it's worth, there are about a thousand uses of &error_abort outside tests/. I'm not aware of them confusing static analyzers we care about. I like &error_abort, because it makes the program crash when we try to put the error into &error_abort, with an informative message. This is often right where things go wrong[*]. I personally don't care much about the better message, but others do. The better stack backtrace has been quite useful to me. Let's use &error_abort, and throw in the assert when a static analyzer we care about needs it. [*] error_propagate() messes this up. That's why the comments in error.h ask you to do without when practical.
Re: [PATCH v13 17/17] net: stream: add QAPI events to report connection state
Stefano Brivio writes: > [Cc: Laine, full quote] > > On Fri, 21 Oct 2022 11:12:20 +0200 > Markus Armbruster wrote: > >> Cc: Stefano Brivio >> >> Laurent Vivier writes: >> >> > On 10/21/22 07:48, Markus Armbruster wrote: >> >> Laurent Vivier writes: >> >> >> >>> The netdev reports NETDEV_STREAM_CONNECTED event when the backend >> >>> is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. >> >> >> >> Use cases? >> > >> > This is asked by Stefano Brivio to allow libvirt to detect if connection >> > to passt is lost and to restart passt. >> >> Let's add something like this to the commit message: >> >> This lets libvirt notice when the connection is lost somehow, and >> restart the peer (such as passt). >> >> Who's working on the libvirt part? > > Laine Stump and myself. Nothing to show yet, though. Good enough for me :) [...]
Re: [PATCH v14 15/17] net: stream: move to QIO to enable additional parameters
Philippe Mathieu-Daudé writes: > On 21/10/22 11:09, Laurent Vivier wrote: >> Use QIOChannel, QIOChannelSocket and QIONetListener. >> This allows net/stream to use all the available parameters provided by >> SocketAddress. >> Signed-off-by: Laurent Vivier >> Acked-by: Michael S. Tsirkin >> --- >> net/stream.c| 492 +--- >> qemu-options.hx | 4 +- >> 2 files changed, 178 insertions(+), 318 deletions(-) > >> -static void net_stream_accept(void *opaque) >> +static void net_stream_server_listening(QIOTask *task, gpointer opaque) >> { >> NetStreamState *s = opaque; >> -struct sockaddr_storage saddr; >> -socklen_t len; >> -int fd; >> - >> -for (;;) { >> -len = sizeof(saddr); >> -fd = qemu_accept(s->listen_fd, (struct sockaddr *)&saddr, &len); >> -if (fd < 0 && errno != EINTR) { >> -return; >> -} else if (fd >= 0) { >> -qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); >> -break; >> -} >> -} >> +QIOChannelSocket *listen_sioc = QIO_CHANNEL_SOCKET(s->listen_ioc); >> +SocketAddress *addr; >> +int ret; >> -s->fd = fd; >> -s->nc.link_down = false; >> -net_stream_connect(s); >> -switch (saddr.ss_family) { >> -case AF_INET: { >> -struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr; >> - >> -qemu_set_info_str(&s->nc, "connection from %s:%d", >> - inet_ntoa(saddr_in->sin_addr), >> - ntohs(saddr_in->sin_port)); >> -break; >> +if (listen_sioc->fd < 0) { >> +qemu_set_info_str(&s->nc, "connection error"); >> +return; >> } >> -case AF_UNIX: { >> -struct sockaddr_un saddr_un; >> -len = sizeof(saddr_un); >> -getsockname(s->listen_fd, (struct sockaddr *)&saddr_un, &len); >> -qemu_set_info_str(&s->nc, "connect from %s", saddr_un.sun_path); >> -break; >> -} >> -default: >> -g_assert_not_reached(); >> +addr = qio_channel_socket_get_local_address(listen_sioc, NULL); >> +g_assert(addr != NULL); > > Missing propagating Error* (observed in v12). *If* this is really a programming error: what about &error_abort? [...]
Re: [PATCH v13 17/17] net: stream: add QAPI events to report connection state
Laurent Vivier writes: > On 10/21/22 11:12, Markus Armbruster wrote: >> Cc: Stefano Brivio >> >> Laurent Vivier writes: >> >>> On 10/21/22 07:48, Markus Armbruster wrote: >>>> Laurent Vivier writes: >>>> >>>>> The netdev reports NETDEV_STREAM_CONNECTED event when the backend >>>>> is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. >>>> >>>> Use cases? >>> >>> This is asked by Stefano Brivio to allow libvirt to detect if connection to >>> passt is lost and to restart passt. >> >> Let's add something like this to the commit message: >> >> This lets libvirt notice when the connection is lost somehow, and >> restart the peer (such as passt). >> >> Who's working on the libvirt part? >> >>> I have also a patch to add a "reconnect=seconds" option, but I didn't want >>> to add it to this series. >> >> It's okay to mention future work in commit messages, but not required. >> >>>> Could similar event signalling be useful for other kinds of netdev >>>> backends? >>> >>> I was wondering, but it becomes more complicated to be generic. >> >> Making something complicated and generic where a simpler special >> solution would do is the worst. >> >> Not quite as bad (but still plenty bad) is making a few special >> solutions first, then replace them all with a generic solution. >> >> I believe we should have a good, hard think on possible applications of >> a generic solution now. >> >> There is no need to hold back this series for that. >> >> If we conclude a generic solution is called for, we better replace this >> special solution before it becomes ABI. Either by replacing it before >> we release it, or by keeping it unstable until we replace it. >> > > I sent the v14 few minutes before this email. > > Jason, perhaps we can remove PATCH 17 from the series and only merge PATCH 1 > to 16? > > I will resend PATCH 17 in a new series with the reconnect option patch once > this series is > merged. Certainly works for me. Thanks for your patience!
Re: [PATCH v13 17/17] net: stream: add QAPI events to report connection state
Cc: Stefano Brivio Laurent Vivier writes: > On 10/21/22 07:48, Markus Armbruster wrote: >> Laurent Vivier writes: >> >>> The netdev reports NETDEV_STREAM_CONNECTED event when the backend >>> is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. >> >> Use cases? > > This is asked by Stefano Brivio to allow libvirt to detect if connection to > passt is lost and to restart passt. Let's add something like this to the commit message: This lets libvirt notice when the connection is lost somehow, and restart the peer (such as passt). Who's working on the libvirt part? > I have also a patch to add a "reconnect=seconds" option, but I didn't want to > add it to this series. It's okay to mention future work in commit messages, but not required. >> Could similar event signalling be useful for other kinds of netdev >> backends? > > I was wondering, but it becomes more complicated to be generic. Making something complicated and generic where a simpler special solution would do is the worst. Not quite as bad (but still plenty bad) is making a few special solutions first, then replace them all with a generic solution. I believe we should have a good, hard think on possible applications of a generic solution now. There is no need to hold back this series for that. If we conclude a generic solution is called for, we better replace this special solution before it becomes ABI. Either by replacing it before we release it, or by keeping it unstable until we replace it.
Re: [PATCH v13 00/17] qapi: net: add unix socket type support to netdev backend
Jason Wang writes: > I've queued this version and will send pull requests shortly. > > Any future comment we can do patches on top. Please give Laurent and me a few hours to try to improve PATCH 17's commit message. Which you could then integrate without a respin.
Re: [PATCH v13 17/17] net: stream: add QAPI events to report connection state
Laurent Vivier writes: > The netdev reports NETDEV_STREAM_CONNECTED event when the backend > is connected, and NETDEV_STREAM_DISCONNECTED when it is disconnected. Use cases? Could similar event signalling be useful for other kinds of netdev backends? > The NETDEV_STREAM_CONNECTED event includes the URI of the destination > address. No more. Easy fix: scratch "the URI of". > Signed-off-by: Laurent Vivier > Acked-by: Michael S. Tsirkin > --- > net/stream.c | 9 +++-- > qapi/net.json | 49 + > 2 files changed, 56 insertions(+), 2 deletions(-) > > diff --git a/net/stream.c b/net/stream.c > index 95d6b910407d..cac01d4d792a 100644 > --- a/net/stream.c > +++ b/net/stream.c > @@ -38,6 +38,7 @@ > #include "io/channel.h" > #include "io/channel-socket.h" > #include "io/net-listener.h" > +#include "qapi/qapi-events-net.h" > > typedef struct NetStreamState { > NetClientState nc; > @@ -168,6 +169,8 @@ static gboolean net_stream_send(QIOChannel *ioc, > s->nc.link_down = true; > qemu_set_info_str(&s->nc, ""); > > +qapi_event_send_netdev_stream_disconnected(s->nc.name); > + > return G_SOURCE_REMOVE; > } > buf = buf1; > @@ -244,8 +247,8 @@ static void net_stream_listen(QIONetListener *listener, > uri = socket_uri(addr); > qemu_set_info_str(&s->nc, uri); > g_free(uri); > +qapi_event_send_netdev_stream_connected(s->nc.name, addr); > qapi_free_SocketAddress(addr); > - Don't add this blank line in PATCH 15, please. > } > > static void net_stream_server_listening(QIOTask *task, gpointer opaque) > @@ -327,7 +330,6 @@ static void net_stream_client_connected(QIOTask *task, > gpointer opaque) > goto error; > } > g_assert(ret == 0); > -qapi_free_SocketAddress(addr); > > net_socket_rs_init(&s->rs, net_stream_rs_finalize, false); > > @@ -338,6 +340,9 @@ static void net_stream_client_connected(QIOTask *task, > gpointer opaque) > s, NULL); > s->nc.link_down = false; > > +qapi_event_send_netdev_stream_connected(s->nc.name, addr); > +qapi_free_SocketAddress(addr); > + > return; > error: > object_unref(OBJECT(s->ioc)); Could put the qapi_free_SocketAddress() in its final place in PATCH 15 already to reduce churn. Up to you. > diff --git a/qapi/net.json b/qapi/net.json > index 39388b1b6c41..c37b24717382 100644 > --- a/qapi/net.json > +++ b/qapi/net.json > @@ -895,3 +895,52 @@ > ## > { 'event': 'FAILOVER_NEGOTIATED', >'data': {'device-id': 'str'} } > + > +## > +# @NETDEV_STREAM_CONNECTED: > +# > +# Emitted when the netdev stream backend is connected > +# > +# @netdev-id: QEMU netdev id that is connected > +# @addr: The destination address > +# > +# Since: 7.2 > +# > +# Example: > +# > +# <- { "event": "NETDEV_STREAM_CONNECTED", > +# "data": { "netdev-id": "netdev0", > +#"addr": { "port": "47666", "ipv6": true, > +# "host": "::1", "type": "inet" } }, > +# "timestamp": { "seconds": 1666269863, "microseconds": 311222 } } > +# > +# or > +# > +# <- { "event": "NETDEV_STREAM_CONNECTED", > +# "data": { "netdev-id": "netdev0", > +#"addr": { "path": "/tmp/qemu0", "type": "unix" } }, > +# "timestamp": { "seconds": 1666269706, "microseconds": 413651 } } > +# > +## > +{ 'event': 'NETDEV_STREAM_CONNECTED', > + 'data': { 'netdev-id': 'str', > +'addr': 'SocketAddress' } } > + > +## > +# @NETDEV_STREAM_DISCONNECTED: > +# > +# Emitted when the netdev stream backend is disconnected > +# > +# @netdev-id: QEMU netdev id that is disconnected > +# > +# Since: 7.2 > +# > +# Example: > +# > +# <- { 'event': 'NETDEV_STREAM_DISCONNECTED', > +# 'data': {'netdev-id': 'netdev0'}, > +# 'timestamp': {'seconds': 1663330937, 'microseconds': 526695} } > +# > +## > +{ 'event': 'NETDEV_STREAM_DISCONNECTED', > + 'data': { 'netdev-id': 'str' } } Schema looks good to me.
Re: [PATCH v11 17/17] net: stream: add QAPI events to report connection state
Sorry for the slow replay, too many distractions... Laurent Vivier writes: > On 10/17/22 15:23, Markus Armbruster wrote: >> Laurent Vivier writes: >> >>> The netdev reports NETDEV_STREAM_CONNECTED event when the backend >>> is connected, and NETDEV_STREAM_EOC when it is disconnected. >>> >>> The NETDEV_STREAM_CONNECTED event includes the URI of the destination >>> address. >>> >>> Signed-off-by: Laurent Vivier >>> Acked-by: Michael S. Tsirkin [...] >>> diff --git a/qapi/net.json b/qapi/net.json >>> index 6a1a49749294..69f83bceff3f 100644 >>> --- a/qapi/net.json >>> +++ b/qapi/net.json >>> @@ -895,3 +895,49 @@ >>> ## >>> { 'event': 'FAILOVER_NEGOTIATED', >>> 'data': {'device-id': 'str'} } >>> + >>> +## >>> +# @NETDEV_STREAM_CONNECTED: >>> +# >>> +# Emitted when the netdev stream backend is connected >>> +# >>> +# @netdev-id: QEMU netdev id that is connected >>> +# @uri: The Uniform Resource Identifier identifying the destination address >> >> Is an URI the appropriate representation here? It's not how we specify >> such addresses elsewhere in QAPI/QMP... > > I put in the event the same information we have in info_str and displayed by > the HMP command 'info network'. What would be a more appropriate reprensation? SocketAddress? >>> +# >>> +# Since: 7.2 >>> +# >>> +# Example: >>> +# >>> +# <- { 'event': 'NETDEV_STREAM_CONNECTED', >>> +# 'data': {'uri': 'tcp:::1:1234', 'netdev-id': 'netdev0'}, >>> +# 'timestamp': {'seconds': 1663330564, 'microseconds': 804317} } >>> +# >>> +# or >>> +# >>> +# <- { 'event': 'NETDEV_STREAM_CONNECTED', >>> +# 'data': {'uri': ''unix:/tmp/qemu0', 'netdev-id': 'netdev0'}, >>> +# 'timestamp': {'seconds': 1663330564, 'microseconds': 804317} } >>> +# >>> +## >>> +{ 'event': 'NETDEV_STREAM_CONNECTED', >>> + 'data': { 'netdev-id': 'str', >>> +'uri': 'str' } } >>> + >>> +## >>> +# @NETDEV_STREAM_EOC: >> >> What does "EOC" mean? > > End-Of-Connection, this is the nomenclature used in the code when the socket > is disconnected. > >> Could this be named NETDEV_STREAM_DISCONNECTED, for symmetry with >> NETDEV_STREAM_CONNECTED? > > Yes, it can. EOC is shorter, it's why I used it, but if you prefer > "disconnected"... For better or worse, we've always preferred longhand to abbreviations in QAPI schema names. Exceptions have crept in, of course. [...]
Re: [PATCH v11 17/17] net: stream: add QAPI events to report connection state
Laurent Vivier writes: > The netdev reports NETDEV_STREAM_CONNECTED event when the backend > is connected, and NETDEV_STREAM_EOC when it is disconnected. > > The NETDEV_STREAM_CONNECTED event includes the URI of the destination > address. > > Signed-off-by: Laurent Vivier > Acked-by: Michael S. Tsirkin > --- > net/stream.c | 11 +-- > qapi/net.json | 46 ++ > 2 files changed, 55 insertions(+), 2 deletions(-) > > diff --git a/net/stream.c b/net/stream.c > index 0293e38e5b57..821ae3265356 100644 > --- a/net/stream.c > +++ b/net/stream.c > @@ -38,6 +38,7 @@ > #include "io/channel.h" > #include "io/channel-socket.h" > #include "io/net-listener.h" > +#include "qapi/qapi-events-net.h" > > typedef struct NetStreamState { > NetClientState nc; > @@ -168,6 +169,8 @@ static gboolean net_stream_send(QIOChannel *ioc, > s->nc.link_down = true; > qemu_set_info_str(&s->nc, ""); > > +qapi_event_send_netdev_stream_eoc(s->nc.name); > + > return G_SOURCE_REMOVE; > } > buf = buf1; > @@ -243,9 +246,10 @@ static void net_stream_listen(QIONetListener *listener, > g_assert(addr != NULL); > uri = socket_uri(addr); > qemu_set_info_str(&s->nc, uri); > -g_free(uri); > qapi_free_SocketAddress(addr); > > +qapi_event_send_netdev_stream_connected(s->nc.name, uri); > +g_free(uri); > } > > static void net_stream_server_listening(QIOTask *task, gpointer opaque) > @@ -317,12 +321,12 @@ static void net_stream_client_connected(QIOTask *task, > gpointer opaque) > g_assert(addr != NULL); > uri = socket_uri(addr); > qemu_set_info_str(&s->nc, uri); > -g_free(uri); > > ret = qemu_socket_try_set_nonblock(sioc->fd); > if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) { > qemu_set_info_str(&s->nc, "can't use file descriptor %s (errno %d)", >addr->u.fd.str, -ret); > +g_free(uri); > qapi_free_SocketAddress(addr); > goto error; > } > @@ -338,6 +342,9 @@ static void net_stream_client_connected(QIOTask *task, > gpointer opaque) > s, NULL); > s->nc.link_down = false; > > +qapi_event_send_netdev_stream_connected(s->nc.name, uri); > +g_free(uri); > + > return; > error: > object_unref(OBJECT(s->ioc)); > diff --git a/qapi/net.json b/qapi/net.json > index 6a1a49749294..69f83bceff3f 100644 > --- a/qapi/net.json > +++ b/qapi/net.json > @@ -895,3 +895,49 @@ > ## > { 'event': 'FAILOVER_NEGOTIATED', >'data': {'device-id': 'str'} } > + > +## > +# @NETDEV_STREAM_CONNECTED: > +# > +# Emitted when the netdev stream backend is connected > +# > +# @netdev-id: QEMU netdev id that is connected > +# @uri: The Uniform Resource Identifier identifying the destination address Is an URI the appropriate representation here? It's not how we specify such addresses elsewhere in QAPI/QMP... > +# > +# Since: 7.2 > +# > +# Example: > +# > +# <- { 'event': 'NETDEV_STREAM_CONNECTED', > +# 'data': {'uri': 'tcp:::1:1234', 'netdev-id': 'netdev0'}, > +# 'timestamp': {'seconds': 1663330564, 'microseconds': 804317} } > +# > +# or > +# > +# <- { 'event': 'NETDEV_STREAM_CONNECTED', > +# 'data': {'uri': ''unix:/tmp/qemu0', 'netdev-id': 'netdev0'}, > +# 'timestamp': {'seconds': 1663330564, 'microseconds': 804317} } > +# > +## > +{ 'event': 'NETDEV_STREAM_CONNECTED', > + 'data': { 'netdev-id': 'str', > +'uri': 'str' } } > + > +## > +# @NETDEV_STREAM_EOC: What does "EOC" mean? Could this be named NETDEV_STREAM_DISCONNECTED, for symmetry with NETDEV_STREAM_CONNECTED? > +# > +# Emitted when the netdev stream backend is disconnected > +# > +# @netdev-id: QEMU netdev id that is disconnected > +# > +# Since: 7.2 > +# > +# Example: > +# > +# <- { 'event': 'NETDEV_STREAM_EOC', > +# 'data': {'netdev-id': 'netdev0'}, > +# 'timestamp': {'seconds': 1663330937, 'microseconds': 526695} } > +# > +## > +{ 'event': 'NETDEV_STREAM_EOC', > + 'data': { 'netdev-id': 'str' } }
Re: [PATCH v11 12/17] net: dgram: add unix socket
Laurent Vivier writes: > Signed-off-by: Laurent Vivier > Reviewed-by: Stefano Brivio > Reviewed-by: David Gibson > Acked-by: Michael S. Tsirkin QAPI schema Acked-by: Markus Armbruster
Re: [PATCH v11 09/17] net: stream: add unix socket
Laurent Vivier writes: > Signed-off-by: Laurent Vivier > Reviewed-by: Stefano Brivio > Acked-by: Michael S. Tsirkin QAPI schema Acked-by: Markus Armbruster
Re: [PATCH 1/9] hw/riscv/sifive_e: Fix inheritance of SiFiveEState
Bernhard Beschow writes: > Am 20. September 2022 11:36:47 UTC schrieb Markus Armbruster > : >>Alistair Francis writes: >> >>> On Tue, Sep 20, 2022 at 9:18 AM Bernhard Beschow wrote: >>>> >>>> SiFiveEState inherits from SysBusDevice while it's TypeInfo claims it to >>>> inherit from TYPE_MACHINE. This is an inconsistency which can cause >>>> undefined behavior such as memory corruption. >>>> >>>> Change SiFiveEState to inherit from MachineState since it is registered >>>> as a machine. >>>> >>>> Signed-off-by: Bernhard Beschow >>> >>> Reviewed-by: Alistair Francis >> >>To the SiFive maintainers: since this is a bug fix, let's merge it right >>away. > > I could repost this particular patch with the three new tags (incl. Fixes) if > desired. Can't hurt, and could help the maintainers.
Re: [PATCH 1/9] hw/riscv/sifive_e: Fix inheritance of SiFiveEState
Alistair Francis writes: > On Tue, Sep 20, 2022 at 9:18 AM Bernhard Beschow wrote: >> >> SiFiveEState inherits from SysBusDevice while it's TypeInfo claims it to >> inherit from TYPE_MACHINE. This is an inconsistency which can cause >> undefined behavior such as memory corruption. >> >> Change SiFiveEState to inherit from MachineState since it is registered >> as a machine. >> >> Signed-off-by: Bernhard Beschow > > Reviewed-by: Alistair Francis To the SiFive maintainers: since this is a bug fix, let's merge it right away.
Re: [PATCH 3/3] Use g_new() & friends where that makes obvious sense
Philippe Mathieu-Daudé writes: > On 15/3/22 14:59, Markus Armbruster wrote: >> Alex Bennée writes: >> >>> Markus Armbruster writes: >>> >>>> g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, >>>> for two reasons. One, it catches multiplication overflowing size_t. >>>> Two, it returns T * rather than void *, which lets the compiler catch >>>> more type errors. >>>> >>> >>>> diff --git a/semihosting/config.c b/semihosting/config.c >>>> index 137171b717..6d48ec9566 100644 >>>> --- a/semihosting/config.c >>>> +++ b/semihosting/config.c >>>> @@ -98,7 +98,7 @@ static int add_semihosting_arg(void *opaque, >>>> if (strcmp(name, "arg") == 0) { >>>> s->argc++; >>>> /* one extra element as g_strjoinv() expects NULL-terminated >>>> array */ >>>> -s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *)); >>>> +s->argv = g_renew(void *, s->argv, s->argc + 1); >>> >>> This did indeed break CI because s->argv is an array of *char: >>> >>> ../semihosting/config.c:101:17: error: assignment to ‘const char **’ from >>> incompatible pointer type ‘void **’ [-Werror=incompatible-pointer-types] >>>101 | s->argv = g_renew(void *, s->argv, s->argc + 1); >>>| ^ >>> cc1: all warnings being treated as errors >>> >>> So it did the job of type checking but failed to build ;-) >> >> You found a hole in my compile testing, thanks! >> >> I got confused about the configuration of my build trees. Catching such >> mistakes is what CI is for :) > > FYI Alex fixed this here: > https://lore.kernel.org/qemu-devel/20220315121251.2280317-8-alex.ben...@linaro.org/ > > So your series could go on top (modulo the Coverity change). I dropped this hunk in v2. Whether my v2 or Alex's series goes in first doesn't matter.
[PATCH v2 3/3] Use g_new() & friends where that makes obvious sense
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This commit only touches allocations with size arguments of the form sizeof(T). Patch created mechanically with: $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ --macro-file scripts/cocci-macro-file.h FILES... Signed-off-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Reviewed-by: Alex Bennée Acked-by: Dr. David Alan Gilbert --- include/qemu/timer.h | 2 +- accel/kvm/kvm-all.c | 6 ++-- accel/tcg/tcg-accel-ops-mttcg.c | 2 +- accel/tcg/tcg-accel-ops-rr.c | 4 +-- audio/audio.c| 4 +-- audio/audio_legacy.c | 6 ++-- audio/dsoundaudio.c | 2 +- audio/jackaudio.c| 6 ++-- audio/paaudio.c | 4 +-- backends/cryptodev.c | 2 +- contrib/vhost-user-gpu/vhost-user-gpu.c | 2 +- cpus-common.c| 4 +-- dump/dump.c | 2 +- hw/acpi/hmat.c | 2 +- hw/audio/intel-hda.c | 2 +- hw/char/parallel.c | 2 +- hw/char/riscv_htif.c | 2 +- hw/char/virtio-serial-bus.c | 6 ++-- hw/core/irq.c| 2 +- hw/core/reset.c | 2 +- hw/display/pxa2xx_lcd.c | 2 +- hw/display/tc6393xb.c| 2 +- hw/display/virtio-gpu.c | 4 +-- hw/display/xenfb.c | 4 +-- hw/dma/rc4030.c | 4 +-- hw/i2c/core.c| 4 +-- hw/i2c/i2c_mux_pca954x.c | 2 +- hw/i386/amd_iommu.c | 4 +-- hw/i386/intel_iommu.c| 2 +- hw/i386/xen/xen-hvm.c| 10 +++--- hw/i386/xen/xen-mapcache.c | 14 hw/input/lasips2.c | 2 +- hw/input/pckbd.c | 2 +- hw/input/ps2.c | 4 +-- hw/input/pxa2xx_keypad.c | 2 +- hw/input/tsc2005.c | 3 +- hw/intc/riscv_aclint.c | 6 ++-- hw/intc/xics.c | 2 +- hw/m68k/virt.c | 2 +- hw/mips/mipssim.c| 2 +- hw/misc/applesmc.c | 2 +- hw/misc/imx6_src.c | 2 +- hw/misc/ivshmem.c| 4 +-- hw/net/virtio-net.c | 4 +-- hw/nvme/ns.c | 2 +- hw/pci-host/pnv_phb3.c | 2 +- hw/pci-host/pnv_phb4.c | 2 +- hw/pci/pcie_sriov.c | 2 +- hw/ppc/e500.c| 2 +- hw/ppc/ppc.c | 8 ++--- hw/ppc/ppc405_boards.c | 4 +-- hw/ppc/ppc405_uc.c | 18 +- hw/ppc/ppc4xx_devs.c | 2 +- hw/ppc/ppc_booke.c | 4 +-- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_events.c| 2 +- hw/ppc/spapr_hcall.c | 2 +- hw/ppc/spapr_numa.c | 3 +- hw/rdma/vmw/pvrdma_dev_ring.c| 2 +- hw/rdma/vmw/pvrdma_qp_ops.c | 6 ++-- hw/sh4/r2d.c | 4 +-- hw/sh4/sh7750.c | 2 +- hw/sparc/leon3.c | 2 +- hw/sparc64/sparc64.c | 4 +-- hw/timer/arm_timer.c | 2 +- hw/timer/slavio_timer.c | 2 +- hw/vfio/pci.c| 4 +-- hw/vfio/platform.c | 4 +-- hw/virtio/virtio-crypto.c| 2 +- hw/virtio/virtio-iommu.c | 2 +- hw/virtio/virtio.c | 5 ++- hw/xtensa/xtfpga.c | 2 +- linux-user/syscall.c | 2 +- migration/dirtyrate.c| 4 +-- migration/multifd-zlib.c | 4 +-- migration/ram.c | 2 +- monitor/misc.c | 2 +- monitor/qmp-cmds.c | 2 +- qga/commands-win32.c | 8 ++--- qga/commands.c | 2 +- qom/qom-qmp-cmds.c | 2 +- replay/replay-char.c | 4 +-- replay/replay-events.c | 10 +++--- softmmu/bootdevice.c | 4 +-- softmmu/dma-helpers.c| 4 +-- softmmu/memory_mapp
[PATCH v2 0/3] Use g_new() & friends where that makes obvious sense
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This series only touches allocations with size arguments of the form sizeof(T). It's mechanical, except for a tiny fix in PATCH 2. PATCH 1 adds the Coccinelle script. PATCH 2 cleans up the virtio-9p subsystem, and fixes a harmless typing error uncovered by the cleanup. PATCH 3 cleans up everything else. I started to split it up, but splitting is a lot of decisions, and I just can't see the value. For instance, MAINTAINERS tells me to split for subsystem "virtio", patching hw/char/virtio-serial-bus.c hw/display/virtio-gpu.c hw/net/virtio-net.c hw/virtio/virtio-crypto.c hw/virtio/virtio-iommu.c hw/virtio/virtio.c But it also tells me to split for subsystem "Character devices", patching hw/char/parallel.c | 2 +- hw/char/riscv_htif.c | 2 +- hw/char/virtio-serial-bus.c | 6 +- and for subsystem "Network devices", patching hw/net/virtio-net.c and for subsystem "virtio-gpu", patching hw/display/virtio-gpu.c I guess I'd go with "virtio". Six files down, 103 to go. Thanks, but no thanks. Since the transformation is local to a function call, dropping is completely safe. We can deal with conflicts by dropping conflicting hunks, with "git-pull -s recursive -X ours". Or drop entire files with conflicts. If you want me to split off certain parts, please tell me exactly what you want split off, and I'll gladly do the splitting. I don't mind the splitting part, I do mind the *thinking* part. I backed out two changes made by the Coccinelle script: scripts/coverity-scan/model.c, because that's special, and semihosting/config.c, because it has a typing error similar to the one fixed in PATCH 2, and Alex already posted a patch for it. v2: * PATCH 3: Change to scripts/coverity-scan/model.c dropped [Eric] * PATCH 3: Change to semihosting/config.c dropped [Alex] * Commit messages tweaked Markus Armbruster (3): scripts/coccinelle: New use-g_new-etc.cocci 9pfs: Use g_new() & friends where that makes obvious sense Use g_new() & friends where that makes obvious sense scripts/coccinelle/use-g_new-etc.cocci | 75 include/qemu/timer.h | 2 +- accel/kvm/kvm-all.c | 6 +- accel/tcg/tcg-accel-ops-mttcg.c | 2 +- accel/tcg/tcg-accel-ops-rr.c | 4 +- audio/audio.c| 4 +- audio/audio_legacy.c | 6 +- audio/dsoundaudio.c | 2 +- audio/jackaudio.c| 6 +- audio/paaudio.c | 4 +- backends/cryptodev.c | 2 +- contrib/vhost-user-gpu/vhost-user-gpu.c | 2 +- cpus-common.c| 4 +- dump/dump.c | 2 +- hw/9pfs/9p-proxy.c | 2 +- hw/9pfs/9p-synth.c | 4 +- hw/9pfs/9p.c | 8 +-- hw/9pfs/codir.c | 6 +- hw/acpi/hmat.c | 2 +- hw/audio/intel-hda.c | 2 +- hw/char/parallel.c | 2 +- hw/char/riscv_htif.c | 2 +- hw/char/virtio-serial-bus.c | 6 +- hw/core/irq.c| 2 +- hw/core/reset.c | 2 +- hw/display/pxa2xx_lcd.c | 2 +- hw/display/tc6393xb.c| 2 +- hw/display/virtio-gpu.c | 4 +- hw/display/xenfb.c | 4 +- hw/dma/rc4030.c | 4 +- hw/i2c/core.c| 4 +- hw/i2c/i2c_mux_pca954x.c | 2 +- hw/i386/amd_iommu.c | 4 +- hw/i386/intel_iommu.c| 2 +- hw/i386/xen/xen-hvm.c| 10 ++-- hw/i386/xen/xen-mapcache.c | 14 ++--- hw/input/lasips2.c | 2 +- hw/input/pckbd.c | 2 +- hw/input/ps2.c | 4 +- hw/input/pxa2xx_keypad.c | 2 +- hw/input/tsc2005.c | 3 +- hw/intc/riscv_aclint.c | 6 +- hw/intc/xics.c | 2 +- hw/m68k/virt.c | 2 +- hw/mips/mipssim.c| 2 +- hw/misc/applesmc.c | 2 +- hw/misc/imx6_src.c | 2 +- hw/misc/ivshmem.c| 4 +- hw/net/virtio-net.c | 4 +- hw/nvme/ns.c | 2 +- hw/pci-host/pnv_
[PATCH v2 2/3] 9pfs: Use g_new() & friends where that makes obvious sense
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This commit only touches allocations with size arguments of the form sizeof(T). Initial patch created mechanically with: $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ --macro-file scripts/cocci-macro-file.h FILES... This uncovers a typing error: ../hw/9pfs/9p.c: In function ‘qid_path_fullmap’: ../hw/9pfs/9p.c:855:13: error: assignment to ‘QpfEntry *’ from incompatible pointer type ‘QppEntry *’ [-Werror=incompatible-pointer-types] 855 | val = g_new0(QppEntry, 1); | ^ Harmless, because QppEntry is larger than QpfEntry. Manually fixed to allocate a QpfEntry instead. Cc: Greg Kurz Cc: Christian Schoenebeck Signed-off-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Christian Schoenebeck Reviewed-by: Alex Bennée Reviewed-by: Greg Kurz --- hw/9pfs/9p-proxy.c | 2 +- hw/9pfs/9p-synth.c | 4 ++-- hw/9pfs/9p.c | 8 hw/9pfs/codir.c | 6 +++--- tests/qtest/virtio-9p-test.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c index 8b4b5cf7dc..4c5e0fc217 100644 --- a/hw/9pfs/9p-proxy.c +++ b/hw/9pfs/9p-proxy.c @@ -1187,7 +1187,7 @@ static int proxy_parse_opts(QemuOpts *opts, FsDriverEntry *fs, Error **errp) static int proxy_init(FsContext *ctx, Error **errp) { -V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy)); +V9fsProxy *proxy = g_new(V9fsProxy, 1); int sock_id; if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) { diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index b3080e415b..d99d263985 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -49,7 +49,7 @@ static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode, /* Add directory type and remove write bits */ mode = ((mode & 0777) | S_IFDIR) & ~(S_IWUSR | S_IWGRP | S_IWOTH); -node = g_malloc0(sizeof(V9fsSynthNode)); +node = g_new0(V9fsSynthNode, 1); if (attr) { /* We are adding .. or . entries */ node->attr = attr; @@ -128,7 +128,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, } /* Add file type and remove write bits */ mode = ((mode & 0777) | S_IFREG); -node = g_malloc0(sizeof(V9fsSynthNode)); +node = g_new0(V9fsSynthNode, 1); node->attr = &node->actual_attr; node->attr->inode = synth_node_count++; node->attr->nlink = 1; diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index a6d6b3f835..8e9d4aea73 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -324,7 +324,7 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) return NULL; } } -f = g_malloc0(sizeof(V9fsFidState)); +f = g_new0(V9fsFidState, 1); f->fid = fid; f->fid_type = P9_FID_NONE; f->ref = 1; @@ -804,7 +804,7 @@ static int qid_inode_prefix_hash_bits(V9fsPDU *pdu, dev_t dev) val = qht_lookup(&pdu->s->qpd_table, &lookup, hash); if (!val) { -val = g_malloc0(sizeof(QpdEntry)); +val = g_new0(QpdEntry, 1); *val = lookup; affix = affixForIndex(pdu->s->qp_affix_next); val->prefix_bits = affix.bits; @@ -852,7 +852,7 @@ static int qid_path_fullmap(V9fsPDU *pdu, const struct stat *stbuf, return -ENFILE; } -val = g_malloc0(sizeof(QppEntry)); +val = g_new0(QpfEntry, 1); *val = lookup; /* new unique inode and device combo */ @@ -928,7 +928,7 @@ static int qid_path_suffixmap(V9fsPDU *pdu, const struct stat *stbuf, return -ENFILE; } -val = g_malloc0(sizeof(QppEntry)); +val = g_new0(QppEntry, 1); *val = lookup; /* new unique inode affix and device combo */ diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 75148bc985..93ba44fb75 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -141,9 +141,9 @@ static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, /* append next node to result chain */ if (!e) { -*entries = e = g_malloc0(sizeof(V9fsDirEnt)); +*entries = e = g_new0(V9fsDirEnt, 1); } else { -e = e->next = g_malloc0(sizeof(V9fsDirEnt)); +e = e->next = g_new0(V9fsDirEnt, 1); } e->dent = qemu_dirent_dup(dent); @@ -163,7 +163,7 @@ static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, break; } -e->st = g_malloc0(sizeof(struct stat)); +e->st = g_new0(struct stat, 1); memcpy(e->st, &stbuf, sizeof(struct stat));
[PATCH v2 1/3] scripts/coccinelle: New use-g_new-etc.cocci
This is the semantic patch from commit b45c03f585 "arm: Use g_new() & friends where that makes obvious sense". Signed-off-by: Markus Armbruster Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée --- scripts/coccinelle/use-g_new-etc.cocci | 75 ++ 1 file changed, 75 insertions(+) create mode 100644 scripts/coccinelle/use-g_new-etc.cocci diff --git a/scripts/coccinelle/use-g_new-etc.cocci b/scripts/coccinelle/use-g_new-etc.cocci new file mode 100644 index 00..e2280e93b3 --- /dev/null +++ b/scripts/coccinelle/use-g_new-etc.cocci @@ -0,0 +1,75 @@ +// Use g_new() & friends where that makes obvious sense +@@ +type T; +@@ +-g_malloc(sizeof(T)) ++g_new(T, 1) +@@ +type T; +@@ +-g_try_malloc(sizeof(T)) ++g_try_new(T, 1) +@@ +type T; +@@ +-g_malloc0(sizeof(T)) ++g_new0(T, 1) +@@ +type T; +@@ +-g_try_malloc0(sizeof(T)) ++g_try_new0(T, 1) +@@ +type T; +expression n; +@@ +-g_malloc(sizeof(T) * (n)) ++g_new(T, n) +@@ +type T; +expression n; +@@ +-g_try_malloc(sizeof(T) * (n)) ++g_try_new(T, n) +@@ +type T; +expression n; +@@ +-g_malloc0(sizeof(T) * (n)) ++g_new0(T, n) +@@ +type T; +expression n; +@@ +-g_try_malloc0(sizeof(T) * (n)) ++g_try_new0(T, n) +@@ +type T; +expression p, n; +@@ +-g_realloc(p, sizeof(T) * (n)) ++g_renew(T, p, n) +@@ +type T; +expression p, n; +@@ +-g_try_realloc(p, sizeof(T) * (n)) ++g_try_renew(T, p, n) +@@ +type T; +expression n; +@@ +-(T *)g_new(T, n) ++g_new(T, n) +@@ +type T; +expression n; +@@ +-(T *)g_new0(T, n) ++g_new0(T, n) +@@ +type T; +expression p, n; +@@ +-(T *)g_renew(T, p, n) ++g_renew(T, p, n) -- 2.35.1
Re: [PATCH 3/3] Use g_new() & friends where that makes obvious sense
Eric Blake writes: > On Mon, Mar 14, 2022 at 05:01:08PM +0100, Markus Armbruster wrote: >> g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, >> for two reasons. One, it catches multiplication overflowing size_t. >> Two, it returns T * rather than void *, which lets the compiler catch >> more type errors. >> >> This commit only touches allocations with size arguments of the form >> sizeof(T). >> >> Patch created mechanically with: >> >> $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ >> --macro-file scripts/cocci-macro-file.h FILES... >> >> Signed-off-by: Markus Armbruster >> --- > > I agree that this is mechanical, but... > > >> qga/commands-win32.c | 8 ++--- >> qga/commands.c | 2 +- >> qom/qom-qmp-cmds.c | 2 +- >> replay/replay-char.c | 4 +-- >> replay/replay-events.c | 10 +++--- >> scripts/coverity-scan/model.c| 2 +- > > ...are we sure we want to touch this particular file? Good catch! >> diff --git a/scripts/coverity-scan/model.c b/scripts/coverity-scan/model.c >> index 9d4fba53d9..30bea672e1 100644 >> --- a/scripts/coverity-scan/model.c >> +++ b/scripts/coverity-scan/model.c >> @@ -356,7 +356,7 @@ int g_poll (GPollFD *fds, unsigned nfds, int timeout) >> typedef struct _GIOChannel GIOChannel; >> GIOChannel *g_io_channel_unix_new(int fd) >> { >> -GIOChannel *c = g_malloc0(sizeof(GIOChannel)); >> +GIOChannel *c = g_new0(GIOChannel, 1); >> __coverity_escape__(fd); >> return c; >> } > > Our model has a definition of g_malloc0(), but I'm not sure whether > Coverity picks up the macro g_new0() in the same manner. I believe it does, by parsing the macro definition from the header. Regardless, I'd prefer to keep model.c self-contained. I'll drop this hunk. Thanks!
Re: [PATCH 3/3] Use g_new() & friends where that makes obvious sense
Alex Bennée writes: > Markus Armbruster writes: > >> g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, >> for two reasons. One, it catches multiplication overflowing size_t. >> Two, it returns T * rather than void *, which lets the compiler catch >> more type errors. >> > >> diff --git a/semihosting/config.c b/semihosting/config.c >> index 137171b717..6d48ec9566 100644 >> --- a/semihosting/config.c >> +++ b/semihosting/config.c >> @@ -98,7 +98,7 @@ static int add_semihosting_arg(void *opaque, >> if (strcmp(name, "arg") == 0) { >> s->argc++; >> /* one extra element as g_strjoinv() expects NULL-terminated array >> */ >> -s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *)); >> +s->argv = g_renew(void *, s->argv, s->argc + 1); > > This did indeed break CI because s->argv is an array of *char: > > ../semihosting/config.c:101:17: error: assignment to ‘const char **’ from > incompatible pointer type ‘void **’ [-Werror=incompatible-pointer-types] > 101 | s->argv = g_renew(void *, s->argv, s->argc + 1); > | ^ > cc1: all warnings being treated as errors > > So it did the job of type checking but failed to build ;-) You found a hole in my compile testing, thanks! I got confused about the configuration of my build trees. Catching such mistakes is what CI is for :)
Re: [PATCH 3/3] Use g_new() & friends where that makes obvious sense
Alex Bennée writes: > Markus Armbruster writes: > >> g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, >> for two reasons. One, it catches multiplication overflowing size_t. >> Two, it returns T * rather than void *, which lets the compiler catch >> more type errors. >> >> This commit only touches allocations with size arguments of the form >> sizeof(T). >> >> Patch created mechanically with: >> >> $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ >> --macro-file scripts/cocci-macro-file.h FILES... >> >> Signed-off-by: Markus Armbruster [...] >> --- a/hw/pci/pcie_sriov.c >> +++ b/hw/pci/pcie_sriov.c >> @@ -177,7 +177,7 @@ static void register_vfs(PCIDevice *dev) >> assert(sriov_cap > 0); >> num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); >> >> -dev->exp.sriov_pf.vf = g_malloc(sizeof(PCIDevice *) * num_vfs); >> +dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs); >> assert(dev->exp.sriov_pf.vf); > > So what I find confusing about the conversion of sizeof(foo *) is that > while the internal sizeof in g_new is unaffected I think the casting > ends up as > > foo ** Yes. g_malloc(...) returns void *. g_new(T, ...) returns T *. > but I guess the compiler would have complained so maybe I don't > understand the magic enough. It doesn't complain here because dev->exp.sriov_pf.vf is of type PCIDevice **: struct PCIESriovPF { uint16_t num_vfs; /* Number of virtual functions created */ uint8_t vf_bar_type[PCI_NUM_REGIONS]; /* Store type for each VF bar */ const char *vfname; /* Reference to the device type used for the VFs */ PCIDevice **vf; /* Pointer to an array of num_vfs VF devices */ }; It does complain when the types don't match, as shown in PATCH 2. > >> index 42130667a7..598e6adc5e 100644 >> --- a/hw/rdma/vmw/pvrdma_dev_ring.c >> +++ b/hw/rdma/vmw/pvrdma_dev_ring.c >> @@ -41,7 +41,7 @@ int pvrdma_ring_init(PvrdmaRing *ring, const char *name, >> PCIDevice *dev, >> qatomic_set(&ring->ring_state->cons_head, 0); >> */ >> ring->npages = npages; >> -ring->pages = g_malloc0(npages * sizeof(void *)); >> +ring->pages = g_new0(void *, npages); > > At least here ring->pages agrees about void ** being the result. > > > > So other than my queries about the sizeof(foo *) which I'd like someone > to assuage me of my concerns it looks like the script has done a > thorough mechanical job as all good scripts should ;-) > > Reviewed-by: Alex Bennée Thanks!
Re: [PATCH 3/3] Use g_new() & friends where that makes obvious sense
Peter Maydell writes: > On Mon, 14 Mar 2022 at 16:01, Markus Armbruster wrote: >> >> g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, >> for two reasons. One, it catches multiplication overflowing size_t. >> Two, it returns T * rather than void *, which lets the compiler catch >> more type errors. >> >> This commit only touches allocations with size arguments of the form >> sizeof(T). >> >> Patch created mechanically with: >> >> $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ >> --macro-file scripts/cocci-macro-file.h FILES... >> >> Signed-off-by: Markus Armbruster >> --- > >> 104 files changed, 197 insertions(+), 202 deletions(-) > > I'm not going to say you must split this patch up. I'm just going to > say that I personally am not looking at it, because it's too big > for me to deal with. As with all big but trivial Coccinelle patches, reviewing the Coccinelle script and a reasonably representative sample of its output is almost certainly a better use of reviewer time than attempting to get all the patches reviewed. They are mind-numbingly dull! For what it's worth, we've used this script several times before. Last in commit bdd81addf4.
[PATCH 1/3] scripts/coccinelle: New use-g_new-etc.cocci
This is the semantic patch from commit b45c03f585 "arm: Use g_new() & friends where that makes obvious sense". Signed-off-by: Markus Armbruster --- scripts/coccinelle/use-g_new-etc.cocci | 75 ++ 1 file changed, 75 insertions(+) create mode 100644 scripts/coccinelle/use-g_new-etc.cocci diff --git a/scripts/coccinelle/use-g_new-etc.cocci b/scripts/coccinelle/use-g_new-etc.cocci new file mode 100644 index 00..e2280e93b3 --- /dev/null +++ b/scripts/coccinelle/use-g_new-etc.cocci @@ -0,0 +1,75 @@ +// Use g_new() & friends where that makes obvious sense +@@ +type T; +@@ +-g_malloc(sizeof(T)) ++g_new(T, 1) +@@ +type T; +@@ +-g_try_malloc(sizeof(T)) ++g_try_new(T, 1) +@@ +type T; +@@ +-g_malloc0(sizeof(T)) ++g_new0(T, 1) +@@ +type T; +@@ +-g_try_malloc0(sizeof(T)) ++g_try_new0(T, 1) +@@ +type T; +expression n; +@@ +-g_malloc(sizeof(T) * (n)) ++g_new(T, n) +@@ +type T; +expression n; +@@ +-g_try_malloc(sizeof(T) * (n)) ++g_try_new(T, n) +@@ +type T; +expression n; +@@ +-g_malloc0(sizeof(T) * (n)) ++g_new0(T, n) +@@ +type T; +expression n; +@@ +-g_try_malloc0(sizeof(T) * (n)) ++g_try_new0(T, n) +@@ +type T; +expression p, n; +@@ +-g_realloc(p, sizeof(T) * (n)) ++g_renew(T, p, n) +@@ +type T; +expression p, n; +@@ +-g_try_realloc(p, sizeof(T) * (n)) ++g_try_renew(T, p, n) +@@ +type T; +expression n; +@@ +-(T *)g_new(T, n) ++g_new(T, n) +@@ +type T; +expression n; +@@ +-(T *)g_new0(T, n) ++g_new0(T, n) +@@ +type T; +expression p, n; +@@ +-(T *)g_renew(T, p, n) ++g_renew(T, p, n) -- 2.35.1
[PATCH 2/3] 9pfs: Use g_new() & friends where that makes obvious sense
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This commit only touches allocations with size arguments of the form sizeof(T). Patch created mechanically with: $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ --macro-file scripts/cocci-macro-file.h FILES... Except this uncovers a typing error: ../hw/9pfs/9p.c:855:13: warning: incompatible pointer types assigning to 'QpfEntry *' from 'QppEntry *' [-Wincompatible-pointer-types] val = g_new0(QppEntry, 1); ^ ~~~ 1 warning generated. Harmless, because QppEntry is larger than QpfEntry. Fix to allocate a QpfEntry instead. Cc: Greg Kurz Cc: Christian Schoenebeck Signed-off-by: Markus Armbruster --- hw/9pfs/9p-proxy.c | 2 +- hw/9pfs/9p-synth.c | 4 ++-- hw/9pfs/9p.c | 8 hw/9pfs/codir.c | 6 +++--- tests/qtest/virtio-9p-test.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c index 8b4b5cf7dc..4c5e0fc217 100644 --- a/hw/9pfs/9p-proxy.c +++ b/hw/9pfs/9p-proxy.c @@ -1187,7 +1187,7 @@ static int proxy_parse_opts(QemuOpts *opts, FsDriverEntry *fs, Error **errp) static int proxy_init(FsContext *ctx, Error **errp) { -V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy)); +V9fsProxy *proxy = g_new(V9fsProxy, 1); int sock_id; if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) { diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index b3080e415b..d99d263985 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -49,7 +49,7 @@ static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode, /* Add directory type and remove write bits */ mode = ((mode & 0777) | S_IFDIR) & ~(S_IWUSR | S_IWGRP | S_IWOTH); -node = g_malloc0(sizeof(V9fsSynthNode)); +node = g_new0(V9fsSynthNode, 1); if (attr) { /* We are adding .. or . entries */ node->attr = attr; @@ -128,7 +128,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, } /* Add file type and remove write bits */ mode = ((mode & 0777) | S_IFREG); -node = g_malloc0(sizeof(V9fsSynthNode)); +node = g_new0(V9fsSynthNode, 1); node->attr = &node->actual_attr; node->attr->inode = synth_node_count++; node->attr->nlink = 1; diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index a6d6b3f835..8e9d4aea73 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -324,7 +324,7 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) return NULL; } } -f = g_malloc0(sizeof(V9fsFidState)); +f = g_new0(V9fsFidState, 1); f->fid = fid; f->fid_type = P9_FID_NONE; f->ref = 1; @@ -804,7 +804,7 @@ static int qid_inode_prefix_hash_bits(V9fsPDU *pdu, dev_t dev) val = qht_lookup(&pdu->s->qpd_table, &lookup, hash); if (!val) { -val = g_malloc0(sizeof(QpdEntry)); +val = g_new0(QpdEntry, 1); *val = lookup; affix = affixForIndex(pdu->s->qp_affix_next); val->prefix_bits = affix.bits; @@ -852,7 +852,7 @@ static int qid_path_fullmap(V9fsPDU *pdu, const struct stat *stbuf, return -ENFILE; } -val = g_malloc0(sizeof(QppEntry)); +val = g_new0(QpfEntry, 1); *val = lookup; /* new unique inode and device combo */ @@ -928,7 +928,7 @@ static int qid_path_suffixmap(V9fsPDU *pdu, const struct stat *stbuf, return -ENFILE; } -val = g_malloc0(sizeof(QppEntry)); +val = g_new0(QppEntry, 1); *val = lookup; /* new unique inode affix and device combo */ diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 75148bc985..93ba44fb75 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -141,9 +141,9 @@ static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, /* append next node to result chain */ if (!e) { -*entries = e = g_malloc0(sizeof(V9fsDirEnt)); +*entries = e = g_new0(V9fsDirEnt, 1); } else { -e = e->next = g_malloc0(sizeof(V9fsDirEnt)); +e = e->next = g_new0(V9fsDirEnt, 1); } e->dent = qemu_dirent_dup(dent); @@ -163,7 +163,7 @@ static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp, break; } -e->st = g_malloc0(sizeof(struct stat)); +e->st = g_new0(struct stat, 1); memcpy(e->st, &stbuf, sizeof(struct stat)); } diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c index 01ca076afe..e28c71bd8f 100644 --- a/tests/qtest/virt
[PATCH 3/3] Use g_new() & friends where that makes obvious sense
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This commit only touches allocations with size arguments of the form sizeof(T). Patch created mechanically with: $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ --macro-file scripts/cocci-macro-file.h FILES... Signed-off-by: Markus Armbruster --- include/qemu/timer.h | 2 +- accel/kvm/kvm-all.c | 6 ++-- accel/tcg/tcg-accel-ops-mttcg.c | 2 +- accel/tcg/tcg-accel-ops-rr.c | 4 +-- audio/audio.c| 4 +-- audio/audio_legacy.c | 6 ++-- audio/dsoundaudio.c | 2 +- audio/jackaudio.c| 6 ++-- audio/paaudio.c | 4 +-- backends/cryptodev.c | 2 +- contrib/vhost-user-gpu/vhost-user-gpu.c | 2 +- cpus-common.c| 4 +-- dump/dump.c | 2 +- hw/acpi/hmat.c | 2 +- hw/audio/intel-hda.c | 2 +- hw/char/parallel.c | 2 +- hw/char/riscv_htif.c | 2 +- hw/char/virtio-serial-bus.c | 6 ++-- hw/core/irq.c| 2 +- hw/core/reset.c | 2 +- hw/display/pxa2xx_lcd.c | 2 +- hw/display/tc6393xb.c| 2 +- hw/display/virtio-gpu.c | 4 +-- hw/display/xenfb.c | 4 +-- hw/dma/rc4030.c | 4 +-- hw/i2c/core.c| 4 +-- hw/i2c/i2c_mux_pca954x.c | 2 +- hw/i386/amd_iommu.c | 4 +-- hw/i386/intel_iommu.c| 2 +- hw/i386/xen/xen-hvm.c| 10 +++--- hw/i386/xen/xen-mapcache.c | 14 hw/input/lasips2.c | 2 +- hw/input/pckbd.c | 2 +- hw/input/ps2.c | 4 +-- hw/input/pxa2xx_keypad.c | 2 +- hw/input/tsc2005.c | 3 +- hw/intc/riscv_aclint.c | 6 ++-- hw/intc/xics.c | 2 +- hw/m68k/virt.c | 2 +- hw/mips/mipssim.c| 2 +- hw/misc/applesmc.c | 2 +- hw/misc/imx6_src.c | 2 +- hw/misc/ivshmem.c| 4 +-- hw/net/virtio-net.c | 4 +-- hw/nvme/ns.c | 2 +- hw/pci-host/pnv_phb3.c | 2 +- hw/pci-host/pnv_phb4.c | 2 +- hw/pci/pcie_sriov.c | 2 +- hw/ppc/e500.c| 2 +- hw/ppc/ppc.c | 8 ++--- hw/ppc/ppc405_boards.c | 4 +-- hw/ppc/ppc405_uc.c | 18 +- hw/ppc/ppc4xx_devs.c | 2 +- hw/ppc/ppc_booke.c | 4 +-- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_events.c| 2 +- hw/ppc/spapr_hcall.c | 2 +- hw/ppc/spapr_numa.c | 3 +- hw/rdma/vmw/pvrdma_dev_ring.c| 2 +- hw/rdma/vmw/pvrdma_qp_ops.c | 6 ++-- hw/sh4/r2d.c | 4 +-- hw/sh4/sh7750.c | 2 +- hw/sparc/leon3.c | 2 +- hw/sparc64/sparc64.c | 4 +-- hw/timer/arm_timer.c | 2 +- hw/timer/slavio_timer.c | 2 +- hw/vfio/pci.c| 4 +-- hw/vfio/platform.c | 4 +-- hw/virtio/virtio-crypto.c| 2 +- hw/virtio/virtio-iommu.c | 2 +- hw/virtio/virtio.c | 5 ++- hw/xtensa/xtfpga.c | 2 +- linux-user/syscall.c | 2 +- migration/dirtyrate.c| 4 +-- migration/multifd-zlib.c | 4 +-- migration/ram.c | 2 +- monitor/misc.c | 2 +- monitor/qmp-cmds.c | 2 +- qga/commands-win32.c | 8 ++--- qga/commands.c | 2 +- qom/qom-qmp-cmds.c | 2 +- replay/replay-char.c | 4 +-- replay/replay-events.c | 10 +++--- scripts/coverity-scan/model.c| 2 +- semihosting/config.c | 2 +- softmmu/bootdevice.c | 4 +-- softmmu/dma-helpers.c| 4 +-- softmmu/memory_mapping.c | 2 +- target
[PATCH 0/3] Use g_new() & friends where that makes obvious
g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This series only touches allocations with size arguments of the form sizeof(T). It's mechanical, except for a tiny fix in PATCH 2. PATCH 1 adds the Coccinelle script. PATCH 2 cleans up the virtio-9p subsystem, and fixes a harmless typing error uncovered by the cleanup. PATCH 3 cleans up everything else. I started to split it up, but splitting is a lot of decisions, and I just can't see the value. For instance, MAINTAINERS tells me to split for subsystem "virtio", patching hw/char/virtio-serial-bus.c hw/display/virtio-gpu.c hw/net/virtio-net.c hw/virtio/virtio-crypto.c hw/virtio/virtio-iommu.c hw/virtio/virtio.c But it also tells me to split for subsystem "Character devices", patching hw/char/parallel.c | 2 +- hw/char/riscv_htif.c | 2 +- hw/char/virtio-serial-bus.c | 6 +- and for subsystem "Network devices", patching hw/net/virtio-net.c and for subsystem "virtio-gpu", patching hw/display/virtio-gpu.c I guess I'd go with "virtio". Six files down, 103 to go. Thanks, but no thanks. Since the transformation is local to a function call, dropping is completely safe. We can deal with conflicts by dropping conflicting hunks, with "git-pull -s recursive -X ours". Or drop entire files with conflicts. If you want me to split off certain parts, please tell me exactly what you want split off, and I'll gladly do the splitting. I don't mind the splitting part, I do mind the *thinking* part. Markus Armbruster (3): scripts/coccinelle: New use-g_new-etc.cocci 9pfs: Use g_new() & friends where that makes obvious sense Use g_new() & friends where that makes obvious sense scripts/coccinelle/use-g_new-etc.cocci | 75 include/qemu/timer.h | 2 +- accel/kvm/kvm-all.c | 6 +- accel/tcg/tcg-accel-ops-mttcg.c | 2 +- accel/tcg/tcg-accel-ops-rr.c | 4 +- audio/audio.c| 4 +- audio/audio_legacy.c | 6 +- audio/dsoundaudio.c | 2 +- audio/jackaudio.c| 6 +- audio/paaudio.c | 4 +- backends/cryptodev.c | 2 +- contrib/vhost-user-gpu/vhost-user-gpu.c | 2 +- cpus-common.c| 4 +- dump/dump.c | 2 +- hw/9pfs/9p-proxy.c | 2 +- hw/9pfs/9p-synth.c | 4 +- hw/9pfs/9p.c | 8 +-- hw/9pfs/codir.c | 6 +- hw/acpi/hmat.c | 2 +- hw/audio/intel-hda.c | 2 +- hw/char/parallel.c | 2 +- hw/char/riscv_htif.c | 2 +- hw/char/virtio-serial-bus.c | 6 +- hw/core/irq.c| 2 +- hw/core/reset.c | 2 +- hw/display/pxa2xx_lcd.c | 2 +- hw/display/tc6393xb.c| 2 +- hw/display/virtio-gpu.c | 4 +- hw/display/xenfb.c | 4 +- hw/dma/rc4030.c | 4 +- hw/i2c/core.c| 4 +- hw/i2c/i2c_mux_pca954x.c | 2 +- hw/i386/amd_iommu.c | 4 +- hw/i386/intel_iommu.c| 2 +- hw/i386/xen/xen-hvm.c| 10 ++-- hw/i386/xen/xen-mapcache.c | 14 ++--- hw/input/lasips2.c | 2 +- hw/input/pckbd.c | 2 +- hw/input/ps2.c | 4 +- hw/input/pxa2xx_keypad.c | 2 +- hw/input/tsc2005.c | 3 +- hw/intc/riscv_aclint.c | 6 +- hw/intc/xics.c | 2 +- hw/m68k/virt.c | 2 +- hw/mips/mipssim.c| 2 +- hw/misc/applesmc.c | 2 +- hw/misc/imx6_src.c | 2 +- hw/misc/ivshmem.c| 4 +- hw/net/virtio-net.c | 4 +- hw/nvme/ns.c | 2 +- hw/pci-host/pnv_phb3.c | 2 +- hw/pci-host/pnv_phb4.c | 2 +- hw/pci/pcie_sriov.c | 2 +- hw/ppc/e500.c| 2 +- hw/ppc/ppc.c | 8 +-- hw/ppc/ppc405_boards.c | 4 +- hw/ppc/ppc405_uc.c | 18 +++--- hw/ppc/ppc4xx_devs.c | 2 +- hw/ppc/ppc_booke.c
Re: [RFC PATCH 02/10] accel: Use qemu_security_policy_taint(), mark KVM and Xen as safe
It's been a while... Daniel P. Berrangé writes: > On Thu, Sep 09, 2021 at 01:20:16AM +0200, Philippe Mathieu-Daudé wrote: >> Add the AccelClass::secure_policy_supported field to classify >> safe (within security boundary) vs unsafe accelerators. >> >> Signed-off-by: Philippe Mathieu-Daudé >> --- >> include/qemu/accel.h | 5 + >> accel/kvm/kvm-all.c | 1 + >> accel/xen/xen-all.c | 1 + >> softmmu/vl.c | 3 +++ >> 4 files changed, 10 insertions(+) >> >> diff --git a/include/qemu/accel.h b/include/qemu/accel.h >> index 4f4c283f6fc..895e30be0de 100644 >> --- a/include/qemu/accel.h >> +++ b/include/qemu/accel.h >> @@ -44,6 +44,11 @@ typedef struct AccelClass { >> hwaddr start_addr, hwaddr size); >> #endif >> bool *allowed; >> +/* >> + * Whether the accelerator is withing QEMU security policy boundary. >> + * See: https://www.qemu.org/contribute/security-process/ >> + */ >> +bool secure_policy_supported; > > The security handling policy is a high level concept that is > open to variation over time and also by downstream distro > vendors. Moreover, the concept of "tainting" isn't limited to "because security". > At a code level we should be dealing in a more fundamental > concept. At an accelerator level we should really jsut > declare whether or not the accelerator impl is considered > to be secure against malicious guest code. > > eg > > /* Whether this accelerator is secure against execution > * of malciious guest machine code */ > bool secure; What I'd like to see is a separation of "assertions", like "not meant to serve as security boundary", and policy. Yes, this is vague. Take it as food for thought. >> /* >> * Array of global properties that would be applied when specific >> * accelerator is chosen. It works like MachineClass.compat_props >> diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c >> index 0125c17edb8..eb6b9e44df2 100644 >> --- a/accel/kvm/kvm-all.c >> +++ b/accel/kvm/kvm-all.c >> @@ -3623,6 +3623,7 @@ static void kvm_accel_class_init(ObjectClass *oc, void >> *data) >> ac->init_machine = kvm_init; >> ac->has_memory = kvm_accel_has_memory; >> ac->allowed = &kvm_allowed; >> +ac->secure_policy_supported = true; >> >> object_class_property_add(oc, "kernel-irqchip", "on|off|split", >> NULL, kvm_set_kernel_irqchip, >> diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c >> index 69aa7d018b2..57867af5faf 100644 >> --- a/accel/xen/xen-all.c >> +++ b/accel/xen/xen-all.c >> @@ -198,6 +198,7 @@ static void xen_accel_class_init(ObjectClass *oc, void >> *data) >> ac->setup_post = xen_setup_post; >> ac->allowed = &xen_allowed; >> ac->compat_props = g_ptr_array_new(); >> +ac->secure_policy_supported = true; >> >> compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat)); >> >> diff --git a/softmmu/vl.c b/softmmu/vl.c >> index 92c05ac97ee..e4f94e159c3 100644 >> --- a/softmmu/vl.c >> +++ b/softmmu/vl.c >> @@ -2388,6 +2388,9 @@ static int do_configure_accelerator(void *opaque, >> QemuOpts *opts, Error **errp) >> return 0; >> } >> >> +qemu_security_policy_taint(!ac->secure_policy_supported, >> + "%s accelerator", acc); > > We need this information to be introspectable, becuase stuff printed > to stderr is essentially opaque to libvirt and mgmt apps above. > > We don't have a convenient "query-accel" command but I think this > could possibly fit into 'query-target'. ie the TargetInfo struct > gain a field: > > > ## > # @TargetInfo: > # > # Information describing the QEMU target. > # > # @arch: the target architecture > # @secure: Whether the currently active accelerator for this target > # is secure against execution of malicous guest code > # > # Since: 1.2 > ## > { 'struct': 'TargetInfo', > 'data': { 'arch': 'SysEmuTarget', > 'secure': 'bool'} } My preferred means of introspection is QAPI schema introspection. For QMP, that's query-qmp-schema. For CLI, it doesn't exist, yet. If it did, then it would tell us that (QAPIfied) -accel takes an argument @accel of a certain enumeration type. We could then tack suitable feature flags to the enumeration type's values. If we make the feature flags "special", i.e. known to QAPI, we can then tie them to policy, like special feature flag 'deprecated' is tied to policy configured with -compat deprecated-{input,output}=... Alternatively, leave policy to the management application. QAPI schema feature flags plus policy are is not a *complete* solution, just like feature flag 'deprecated' and -compat are not a complete solution for handling use of deprecated interfaces: we can and do deprecate usage that isn't tied to a syntactic element in the QAPI schema. Example: commit a9b305ba291 deprecated use of socket chardev option wait together with server=true. It is, however, a solution for
Re: [PATCH 0/5] qapi: Restrict machine (and migration) specific commands
Paolo Bonzini writes: > On 05/10/20 10:01, Markus Armbruster wrote: >> Philippe Mathieu-Daudé writes: >> >>> Reduce the machine code pulled into qemu-storage-daemon. >> I'm leaving review to Eduardo and Marcel for PATCH 1-4, and to David and >> Juan for PATCH 5. David already ACKed. >> >> Can do the pull request. >> > > If it counts, :) for patch 1-4: > > Acked-by: Paolo Bonzini > > Generally these patches to remove code from user-mode emulators > fall into the "if it builds it's fine" bucket, since I assume > we want the "misc" subschema to be as small as possible. Moving stuff out of qapi/misc.json is good as long as the new home makes sense. So, if it builds *and* the maintainers of the new home think it makes sense to have it there, it's fine. I don't think we should aim for eliminating every last bit of unused generated code from every program. We should aim for a sensible split into sub-modules. Unused generated code in a program can be a sign for a less than sensible split.
Re: [PATCH 0/5] qapi: Restrict machine (and migration) specific commands
Philippe Mathieu-Daudé writes: > Reduce the machine code pulled into qemu-storage-daemon. I'm leaving review to Eduardo and Marcel for PATCH 1-4, and to David and Juan for PATCH 5. David already ACKed. Can do the pull request.
Re: [PATCH 2/2] qdev: Let BusRealize() return a boolean value to indicate error
Philippe Mathieu-Daudé writes: > On 9/21/20 10:19 AM, Markus Armbruster wrote: >> Philippe Mathieu-Daudé writes: >> >>> Commit 9940b2cfbc0 introduced qdev_realize() and qbus_realize() >>> with the ability to return a boolean value if an error occured, >>> thus the caller does not need to check if the Error* pointer is >>> set. >>> Provide the same ability to the BusRealize type. >>> >>> Signed-off-by: Philippe Mathieu-Daudé >>> --- >>> include/hw/qdev-core.h | 14 +- >>> hw/hyperv/vmbus.c | 5 +++-- >>> hw/nubus/nubus-bus.c | 5 +++-- >>> hw/pci/pci.c | 12 +--- >>> hw/xen/xen-bus.c | 5 +++-- >>> 5 files changed, 31 insertions(+), 10 deletions(-) >>> >>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h >>> index 02ac1c50b7f..eecfe794a71 100644 >>> --- a/include/hw/qdev-core.h >>> +++ b/include/hw/qdev-core.h >>> @@ -32,7 +32,19 @@ typedef enum DeviceCategory { >>> typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); >>> typedef void (*DeviceUnrealize)(DeviceState *dev); >>> typedef void (*DeviceReset)(DeviceState *dev); >>> -typedef void (*BusRealize)(BusState *bus, Error **errp); >>> +/** >>> + * BusRealize: Realize @bus. >>> + * @bus: bus to realize >>> + * @errp: pointer to error object >>> + * >>> + * On success, return true. >>> + * On failure, store an error through @errp and return false. >>> + */ >>> +typedef bool (*BusRealize)(BusState *bus, Error **errp); >>> +/** >>> + * BusUnrealize: Unrealize @bus. >>> + * @bus: bus to unrealize >>> + */ >>> typedef void (*BusUnrealize)(BusState *bus); >>> >>> /** >>> diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c >>> index 6ef895bc352..8a0452b2464 100644 >>> --- a/hw/hyperv/vmbus.c >>> +++ b/hw/hyperv/vmbus.c >>> @@ -2487,7 +2487,7 @@ static const TypeInfo vmbus_dev_type_info = { >>> .instance_init = vmbus_dev_instance_init, >>> }; >>> >>> -static void vmbus_realize(BusState *bus, Error **errp) >>> +static bool vmbus_realize(BusState *bus, Error **errp) >>> { >>> int ret = 0; >>> Error *local_err = NULL; >>> @@ -2519,7 +2519,7 @@ static void vmbus_realize(BusState *bus, Error **errp) >>> goto clear_event_notifier; >>> } >>> >>> -return; >>> +return true; >>> >>> clear_event_notifier: >>> event_notifier_cleanup(&vmbus->notifier); >>> @@ -2528,6 +2528,7 @@ remove_msg_handler: >>> error_out: >>> qemu_mutex_destroy(&vmbus->rx_queue_lock); >>> error_propagate(errp, local_err); >>> +return false; >>> } >>> >>> static void vmbus_unrealize(BusState *bus) >>> diff --git a/hw/nubus/nubus-bus.c b/hw/nubus/nubus-bus.c >>> index 942a6d5342d..d20d9c0f72c 100644 >>> --- a/hw/nubus/nubus-bus.c >>> +++ b/hw/nubus/nubus-bus.c >>> @@ -65,12 +65,13 @@ static const MemoryRegionOps nubus_super_slot_ops = { >>> }, >>> }; >>> >>> -static void nubus_realize(BusState *bus, Error **errp) >>> +static bool nubus_realize(BusState *bus, Error **errp) >>> { >>> if (!nubus_find()) { >>> error_setg(errp, "at most one %s device is permitted", >>> TYPE_NUBUS_BUS); >>> -return; >>> +return false; >>> } >>> +return true; >>> } >>> >>> static void nubus_init(Object *obj) >>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c >>> index de0fae10ab9..f535ebac847 100644 >>> --- a/hw/pci/pci.c >>> +++ b/hw/pci/pci.c >>> @@ -115,7 +115,7 @@ static void pcibus_machine_done(Notifier *notifier, >>> void *data) >>> } >>> } >>> >>> -static void pci_bus_realize(BusState *qbus, Error **errp) >>> +static bool pci_bus_realize(BusState *qbus, Error **errp) >>> { >>> PCIBus *bus = PCI_BUS(qbus); >>> >>> @@ -123,13 +123,17 @@ static void pci_bus_realize(BusState *qbus, Error >>> **errp) >>> qemu_add_machine_init_done_notifier(&bus->machine_done); >>> >>> vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_pcibus, bus); >>> + >>> +return true;
Re: [PATCH 2/2] qdev: Let BusRealize() return a boolean value to indicate error
Philippe Mathieu-Daudé writes: > Commit 9940b2cfbc0 introduced qdev_realize() and qbus_realize() > with the ability to return a boolean value if an error occured, > thus the caller does not need to check if the Error* pointer is > set. > Provide the same ability to the BusRealize type. > > Signed-off-by: Philippe Mathieu-Daudé > --- > include/hw/qdev-core.h | 14 +- > hw/hyperv/vmbus.c | 5 +++-- > hw/nubus/nubus-bus.c | 5 +++-- > hw/pci/pci.c | 12 +--- > hw/xen/xen-bus.c | 5 +++-- > 5 files changed, 31 insertions(+), 10 deletions(-) > > diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h > index 02ac1c50b7f..eecfe794a71 100644 > --- a/include/hw/qdev-core.h > +++ b/include/hw/qdev-core.h > @@ -32,7 +32,19 @@ typedef enum DeviceCategory { > typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); > typedef void (*DeviceUnrealize)(DeviceState *dev); > typedef void (*DeviceReset)(DeviceState *dev); > -typedef void (*BusRealize)(BusState *bus, Error **errp); > +/** > + * BusRealize: Realize @bus. > + * @bus: bus to realize > + * @errp: pointer to error object > + * > + * On success, return true. > + * On failure, store an error through @errp and return false. > + */ > +typedef bool (*BusRealize)(BusState *bus, Error **errp); > +/** > + * BusUnrealize: Unrealize @bus. > + * @bus: bus to unrealize > + */ > typedef void (*BusUnrealize)(BusState *bus); > > /** > diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c > index 6ef895bc352..8a0452b2464 100644 > --- a/hw/hyperv/vmbus.c > +++ b/hw/hyperv/vmbus.c > @@ -2487,7 +2487,7 @@ static const TypeInfo vmbus_dev_type_info = { > .instance_init = vmbus_dev_instance_init, > }; > > -static void vmbus_realize(BusState *bus, Error **errp) > +static bool vmbus_realize(BusState *bus, Error **errp) > { > int ret = 0; > Error *local_err = NULL; > @@ -2519,7 +2519,7 @@ static void vmbus_realize(BusState *bus, Error **errp) > goto clear_event_notifier; > } > > -return; > +return true; > > clear_event_notifier: > event_notifier_cleanup(&vmbus->notifier); > @@ -2528,6 +2528,7 @@ remove_msg_handler: > error_out: > qemu_mutex_destroy(&vmbus->rx_queue_lock); > error_propagate(errp, local_err); > +return false; > } > > static void vmbus_unrealize(BusState *bus) > diff --git a/hw/nubus/nubus-bus.c b/hw/nubus/nubus-bus.c > index 942a6d5342d..d20d9c0f72c 100644 > --- a/hw/nubus/nubus-bus.c > +++ b/hw/nubus/nubus-bus.c > @@ -65,12 +65,13 @@ static const MemoryRegionOps nubus_super_slot_ops = { > }, > }; > > -static void nubus_realize(BusState *bus, Error **errp) > +static bool nubus_realize(BusState *bus, Error **errp) > { > if (!nubus_find()) { > error_setg(errp, "at most one %s device is permitted", > TYPE_NUBUS_BUS); > -return; > +return false; > } > +return true; > } > > static void nubus_init(Object *obj) > diff --git a/hw/pci/pci.c b/hw/pci/pci.c > index de0fae10ab9..f535ebac847 100644 > --- a/hw/pci/pci.c > +++ b/hw/pci/pci.c > @@ -115,7 +115,7 @@ static void pcibus_machine_done(Notifier *notifier, void > *data) > } > } > > -static void pci_bus_realize(BusState *qbus, Error **errp) > +static bool pci_bus_realize(BusState *qbus, Error **errp) > { > PCIBus *bus = PCI_BUS(qbus); > > @@ -123,13 +123,17 @@ static void pci_bus_realize(BusState *qbus, Error > **errp) > qemu_add_machine_init_done_notifier(&bus->machine_done); > > vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_pcibus, bus); > + > +return true; > } > > -static void pcie_bus_realize(BusState *qbus, Error **errp) > +static bool pcie_bus_realize(BusState *qbus, Error **errp) > { > PCIBus *bus = PCI_BUS(qbus); > > -pci_bus_realize(qbus, errp); > +if (!pci_bus_realize(qbus, errp)) { > +return false; > +} We now update bus->flags only when pci_bus_realize() succeeds. Is this a bug fix? > > /* > * A PCI-E bus can support extended config space if it's the root > @@ -144,6 +148,8 @@ static void pcie_bus_realize(BusState *qbus, Error **errp) > bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; > } > } > + > +return true; > } > > static void pci_bus_unrealize(BusState *qbus) > diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c > index 9ce1c9540b9..d7ef5d05e37 100644 > --- a/hw/xen/xen-bus.c > +++ b/hw/xen/xen-bus.c > @@ -444,7 +444,7 @@ static void xen_bus_unrealize(BusState *bus) > } > } > > -static void xen_bus_realize(BusState *bus, Error **errp) > +static bool xen_bus_realize(BusState *bus, Error **errp) > { > XenBus *xenbus = XEN_BUS(bus); > unsigned int domid; > @@ -478,10 +478,11 @@ static void xen_bus_realize(BusState *bus, Error **errp) >"failed to set up enumeration watch: "); > } > > -return; > +return true; > > fail: > xen_bus_unrealize(bus); > +
Re: [RFC PATCH-for-5.2 v2 2/2] block/block-backend: Let blk_attach_dev() provide helpful error
Daniel P. Berrangé writes: > On Thu, Jul 16, 2020 at 02:37:04PM +0200, Philippe Mathieu-Daudé wrote: >> Let blk_attach_dev() take an Error* object to return helpful >> information. Adapt the callers. >> >> $ qemu-system-arm -M n800 >> qemu-system-arm: sd_init failed: cannot attach blk 'sd0' to device >> 'sd-card' >> blk 'sd0' is already attached by device 'omap2-mmc' >> Drive 'sd0' is already in use because it has been automatically connected >> to another device >> (do you need 'if=none' in the drive options?) >> >> Signed-off-by: Philippe Mathieu-Daudé >> --- >> v2: Rebased after 668f62ec62 ("error: Eliminate error_propagate()") >> --- >> include/sysemu/block-backend.h | 2 +- >> block/block-backend.c| 11 ++- >> hw/block/fdc.c | 4 +--- >> hw/block/swim.c | 4 +--- >> hw/block/xen-block.c | 5 +++-- >> hw/core/qdev-properties-system.c | 16 +--- >> hw/ide/qdev.c| 4 +--- >> hw/scsi/scsi-disk.c | 4 +--- >> 8 files changed, 27 insertions(+), 23 deletions(-) >> >> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h >> index 8203d7f6f9..118fbad0b4 100644 >> --- a/include/sysemu/block-backend.h >> +++ b/include/sysemu/block-backend.h >> @@ -113,7 +113,7 @@ BlockDeviceIoStatus blk_iostatus(const BlockBackend >> *blk); >> void blk_iostatus_disable(BlockBackend *blk); >> void blk_iostatus_reset(BlockBackend *blk); >> void blk_iostatus_set_err(BlockBackend *blk, int error); >> -int blk_attach_dev(BlockBackend *blk, DeviceState *dev); >> +int blk_attach_dev(BlockBackend *blk, DeviceState *dev, Error **errp); >> void blk_detach_dev(BlockBackend *blk, DeviceState *dev); >> DeviceState *blk_get_attached_dev(BlockBackend *blk); >> char *blk_get_attached_dev_id(BlockBackend *blk); >> diff --git a/block/block-backend.c b/block/block-backend.c >> index 63ff940ef9..b7be0a4619 100644 >> --- a/block/block-backend.c >> +++ b/block/block-backend.c >> @@ -884,12 +884,21 @@ void blk_get_perm(BlockBackend *blk, uint64_t *perm, >> uint64_t *shared_perm) >> >> /* >> * Attach device model @dev to @blk. >> + * >> + * @blk: Block backend >> + * @dev: Device to attach the block backend to >> + * @errp: pointer to NULL initialized error object >> + * >> * Return 0 on success, -EBUSY when a device model is attached already. >> */ >> -int blk_attach_dev(BlockBackend *blk, DeviceState *dev) >> +int blk_attach_dev(BlockBackend *blk, DeviceState *dev, Error **errp) >> { >> trace_blk_attach_dev(blk_name(blk), object_get_typename(OBJECT(dev))); >> if (blk->dev) { >> +error_setg(errp, "cannot attach blk '%s' to device '%s'", >> + blk_name(blk), object_get_typename(OBJECT(dev))); >> +error_append_hint(errp, "blk '%s' is already attached by device >> '%s'\n", >> + blk_name(blk), >> object_get_typename(OBJECT(blk->dev))); > > I would have a preference for expanding the main error message and not > using a hint. Any hint is completely thrown away when using QMP :-( Hints work best in cases like error message hint suggesting things to try to fix it, in CLI syntax error message rejecting a configuration value hint listing possible values, in CLI syntax Why "in CLI syntax"? Well, we need to use *some* syntax to be useful. Hints have always been phrased for the CLI, simply because the hint feature grew out of my disgust over the loss of lovingly written CLI hints in the conversion to Error. Hints in CLI syntax would be misleading QMP. We never extended QMP to transport hints. Hints may tempt you in a case like error message that is painfully long, because it really tries hard to explain, which is laudable in theory, but sadly illegible in practice; also, interminable sentences, meh, this is an error message, not a Joyce novel to get something like terse error message Explanation that is rather long, because it really tries hard to explain. It can be multiple sentences, and lines are wrapped at a reasonable length. Comes out okay in the CLI, but the explanation is lost in QMP. I don't have a good solution to offer for errors that genuinely need explaining.
Re: [PATCH] trivial: Remove trailing whitespaces
Daniel P. Berrangé writes: > On Mon, Jul 06, 2020 at 06:23:00PM +0200, Christophe de Dinechin wrote: >> There are a number of unnecessary trailing whitespaces that have >> accumulated over time in the source code. They cause stray changes >> in patches if you use tools that automatically remove them. >> >> Tested by doing a `git diff -w` after the change. >> >> This could probably be turned into a pre-commit hook. See .git/hooks/pre-commit.sample. Expected test output is prone to flunk the whitespace test. One solution is to strip trailing whitespace from test output. > scripts/checkpatch.pl ought to be made to check it. > >> >> Signed-off-by: Christophe de Dinechin >> --- [...] >> 78 files changed, 440 insertions(+), 440 deletions(-) > > The cleanup is a good idea, however, I think it is probably better to > split the patch approx into subsystems. That will make it much easier > to cherry-pick for people doing backports. I doubt that's worth the trouble. Acked-by: Markus Armbruster
Re: [PATCH v12 1/8] error: New macro ERRP_AUTO_PROPAGATE()
Vladimir Sementsov-Ogievskiy writes: > 07.07.2020 19:50, Markus Armbruster wrote: >> From: Vladimir Sementsov-Ogievskiy >> >> Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of >> functions with an errp OUT parameter. >> >> It has three goals: >> >> 1. Fix issue with error_fatal and error_prepend/error_append_hint: user >> can't see this additional information, because exit() happens in >> error_setg earlier than information is added. [Reported by Greg Kurz] >> >> 2. Fix issue with error_abort and error_propagate: when we wrap >> error_abort by local_err+error_propagate, the resulting coredump will >> refer to error_propagate and not to the place where error happened. >> (the macro itself doesn't fix the issue, but it allows us to [3.] drop >> the local_err+error_propagate pattern, which will definitely fix the >> issue) [Reported by Kevin Wolf] >> >> 3. Drop local_err+error_propagate pattern, which is used to workaround >> void functions with errp parameter, when caller wants to know resulting >> status. (Note: actually these functions could be merely updated to >> return int error code). >> >> To achieve these goals, later patches will add invocations >> of this macro at the start of functions with either use >> error_prepend/error_append_hint (solving 1) or which use >> local_err+error_propagate to check errors, switching those >> functions to use *errp instead (solving 2 and 3). >> >> Signed-off-by: Vladimir Sementsov-Ogievskiy >> Reviewed-by: Paul Durrant >> Reviewed-by: Greg Kurz >> Reviewed-by: Eric Blake >> [Comments merged properly with recent commit "error: Document Error >> API usage rules", and edited for clarity. Put ERRP_AUTO_PROPAGATE() >> before its helpers, and touch up style. Commit message tweaked.] >> Signed-off-by: Markus Armbruster > > Ok, I see you have mostly rewritten the big comment Guilty as charged... I was happy with the contents you provided (and grateful for it), but our parallel work caused some redundancy. I went beyond a minimal merge to get a something that reads as one coherent text. > and not only in this patch, so, I go and read the whole comment on top of > these series. > > = > >* Pass an existing error to the caller with the message modified: >* error_propagate_prepend(errp, err, >* "Could not frobnicate '%s': ", name); >* This is more concise than >* error_propagate(errp, err); // don't do this >* error_prepend(errp, "Could not frobnicate '%s': ", name); >* and works even when @errp is &error_fatal. > > - the latter doesn't consider ERRP_AUTO_PROPAGATE: as we know, that > ERRP_AUTO_PROPAGATE should be used when we use error_prepend, the latter > should look like > > > ERRP_AUTO_PROPAGATE(); > ... > error_propagate(errp, err); // don't do this > error_prepend(errp, "Could not frobnicate '%s': ", name); > > - and it works even when @errp is &error_fatal, so the > error_propagate_prepend now is just a shortcut, not the only correct way. I can duplicate the advice from the paragraph preceding it, like this: * This is rarely needed. When @err is a local variable, use of * ERRP_GUARD() commonly results in more readable code. * Where it is needed, it is more concise than * error_propagate(errp, err); // don't do this * error_prepend(errp, "Could not frobnicate '%s': ", name); * and works even when @errp is &error_fatal. > Still, the text is formally correct as is, and may be improved later. > > = > >* 2. Replace &err by errp, and err by *errp. Delete local variable >*@err. > > - hmm a bit not obvious,, It can be local_err. Yes, but I trust the reader can make that mental jump. > It can be (in some rare cases) still needed to handle the error locally, not > passing to the caller.. I didn't think of this. What about * To convert a function to use ERRP_GUARD(), assuming the local * variable it propagates to @errp is called @err: [...] * 2. Replace &err by errp, and err by *errp. Delete local variable *@err if it s now unused. Nope, still no good, if we replace like that, @err *will* be unused, and the locally handled error will leak to the caller. No time left for wordsmithing; let's improve on top. > may be just something like "Assume local Error *err variable is used to get > errors from called functio
Re: [PATCH v12 2/8] scripts: Coccinelle script to use ERRP_AUTO_PROPAGATE()
Eric Blake writes: > On 7/7/20 11:50 AM, Markus Armbruster wrote: >> From: Vladimir Sementsov-Ogievskiy >> >> Script adds ERRP_AUTO_PROPAGATE macro invocation where appropriate and >> does corresponding changes in code (look for details in >> include/qapi/error.h) >> >> Usage example: >> spatch --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ >> --macro-file scripts/cocci-macro-file.h --in-place --no-show-diff \ >> --max-width 80 FILES... >> >> Signed-off-by: Vladimir Sementsov-Ogievskiy >> Reviewed-by: Markus Armbruster >> Signed-off-by: Markus Armbruster >> --- >> scripts/coccinelle/auto-propagated-errp.cocci | 337 ++ >> include/qapi/error.h | 3 + >> MAINTAINERS | 1 + >> 3 files changed, 341 insertions(+) >> create mode 100644 scripts/coccinelle/auto-propagated-errp.cocci > > Needs a tweak if we go with ERRP_GUARD. But that's easy. > >> + >> +// Convert special case with goto separately. >> +// I tried merging this into the following rule the obvious way, but >> +// it made Coccinelle hang on block.c >> +// >> +// Note interesting thing: if we don't do it here, and try to fixup >> +// "out: }" things later after all transformations (the rule will be >> +// the same, just without error_propagate() call), coccinelle fails to >> +// match this "out: }". > > "out: }" is not valid C; would referring to "out: ; }" fare any better? We can try for the next batch. >> +@ disable optional_qualifier@ >> +identifier rule1.fn, rule1.local_err, out; >> +symbol errp; >> +@@ >> + >> + fn(..., Error ** , ...) >> + { >> + <... >> +-goto out; >> ++return; >> + ...> >> +- out: >> +-error_propagate(errp, local_err); >> + } >> + >> +// Convert most of local_err related stuff. >> +// >> +// Note, that we inherit rule1.fn and rule1.local_err names, not >> +// objects themselves. We may match something not related to the >> +// pattern matched by rule1. For example, local_err may be defined with >> +// the same name in different blocks inside one function, and in one >> +// block follow the propagation pattern and in other block doesn't. >> +// >> +// Note also that errp-cleaning functions >> +// error_free_errp >> +// error_report_errp >> +// error_reportf_errp >> +// warn_report_errp >> +// warn_reportf_errp >> +// are not yet implemented. They must call corresponding Error* - >> +// freeing function and then set *errp to NULL, to avoid further >> +// propagation to original errp (consider ERRP_AUTO_PROPAGATE in use). >> +// For example, error_free_errp may look like this: >> +// >> +//void error_free_errp(Error **errp) >> +//{ >> +//error_free(*errp); >> +//*errp = NULL; >> +//} > > I guess we can still decide later if we want these additional > functions, or if they will even help after the number of places we > have already improved after applying this script as-is and with > Markus' cleanups in place. Yes. > While I won't call myself a Coccinelle expert, it at least looks sane > enough that I'm comfortable if you add: > > Reviewed-by: Eric Blake Thanks!
Re: [PATCH v12 1/8] error: New macro ERRP_AUTO_PROPAGATE()
Eric Blake writes: > On 7/7/20 11:50 AM, Markus Armbruster wrote: >> From: Vladimir Sementsov-Ogievskiy >> >> Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of >> functions with an errp OUT parameter. >> >> It has three goals: >> >> 1. Fix issue with error_fatal and error_prepend/error_append_hint: user > > the user Yes. >> can't see this additional information, because exit() happens in >> error_setg earlier than information is added. [Reported by Greg Kurz] >> >> 2. Fix issue with error_abort and error_propagate: when we wrap >> error_abort by local_err+error_propagate, the resulting coredump will >> refer to error_propagate and not to the place where error happened. >> (the macro itself doesn't fix the issue, but it allows us to [3.] drop >> the local_err+error_propagate pattern, which will definitely fix the >> issue) [Reported by Kevin Wolf] >> >> 3. Drop local_err+error_propagate pattern, which is used to workaround >> void functions with errp parameter, when caller wants to know resulting >> status. (Note: actually these functions could be merely updated to >> return int error code). >> >> To achieve these goals, later patches will add invocations >> of this macro at the start of functions with either use >> error_prepend/error_append_hint (solving 1) or which use >> local_err+error_propagate to check errors, switching those >> functions to use *errp instead (solving 2 and 3). >> >> Signed-off-by: Vladimir Sementsov-Ogievskiy >> Reviewed-by: Paul Durrant >> Reviewed-by: Greg Kurz >> Reviewed-by: Eric Blake >> [Comments merged properly with recent commit "error: Document Error >> API usage rules", and edited for clarity. Put ERRP_AUTO_PROPAGATE() >> before its helpers, and touch up style. Commit message tweaked.] >> Signed-off-by: Markus Armbruster >> --- >> include/qapi/error.h | 160 ++- >> 1 file changed, 141 insertions(+), 19 deletions(-) >> >> diff --git a/include/qapi/error.h b/include/qapi/error.h >> index 3fed49747d..c865a7d2f1 100644 >> --- a/include/qapi/error.h >> +++ b/include/qapi/error.h > >> @@ -128,18 +122,26 @@ >>* handle the error... >>* } >>* when it doesn't, say a void function: >> + * ERRP_AUTO_PROPAGATE(); >> + * foo(arg, errp); >> + * if (*errp) { >> + * handle the error... >> + * } >> + * More on ERRP_AUTO_PROPAGATE() below. >> + * >> + * Code predating ERRP_AUTO_PROPAGATE() still exits, and looks like this: > > exists Fixing... >>* Error *err = NULL; >>* foo(arg, &err); >>* if (err) { >>* handle the error... >> - * error_propagate(errp, err); >> + * error_propagate(errp, err); // deprecated >>* } >> - * Do *not* "optimize" this to >> + * Avoid in new code. Do *not* "optimize" it to >>* foo(arg, errp); >>* if (*errp) { // WRONG! >>* handle the error... >>* } >> - * because errp may be NULL! >> + * because errp may be NULL! Guard with ERRP_AUTO_PROPAGATE(). > > maybe: > > because errp may be NULL without the ERRP_AUTO_PROPAGATE() guard. Sold. >>* >>* But when all you do with the error is pass it on, please use >>* foo(arg, errp); >> @@ -158,6 +160,19 @@ >>* handle the error... >>* } >>* >> + * Pass an existing error to the caller: > >> + * = Converting to ERRP_AUTO_PROPAGATE() = >> + * >> + * To convert a function to use ERRP_AUTO_PROPAGATE(): >> + * >> + * 0. If the Error ** parameter is not named @errp, rename it to >> + *@errp. >> + * >> + * 1. Add an ERRP_AUTO_PROPAGATE() invocation, by convention right at >> + *the beginning of the function. This makes @errp safe to use. >> + * >> + * 2. Replace &err by errp, and err by *errp. Delete local variable >> + *@err. >> + * >> + * 3. Delete error_propagate(errp, *errp), replace >> + *error_propagate_prepend(errp, *errp, ...) by error_prepend(errp, ...), >> + * > > Why a comma here? Editing accident. >> + * 4. Ensure @errp is valid at return: when you destroy *errp, set >> + *errp = NULL. >> + * >> + * Example: >> + * >> + * bool fn(..., Error **errp) >> + * { >> + * Error *err = NULL; >> + * >> + * foo(arg, &am
[PATCH v12 7/8] nbd: Use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy If we want to add some info to errp (by error_prepend() or error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. Otherwise, this info will not be added when errp == &error_fatal (the program will exit prior to the error_append_hint() or error_prepend() call). Fix such cases. If we want to check error after errp-function call, we need to introduce local_err and then propagate it to errp. Instead, use ERRP_AUTO_PROPAGATE macro, benefits are: 1. No need of explicit error_propagate call 2. No need of explicit local_err variable: use errp directly 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or &error_fatal, this means that we don't break error_abort (we'll abort on error_set, not on error_propagate) This commit is generated by command sed -n '/^Network Block Device (NBD)$/,/^$/{s/^F: //p}' \ MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Reported-by: Kevin Wolf Reported-by: Greg Kurz Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Markus Armbruster [Commit message tweaked] Signed-off-by: Markus Armbruster --- include/block/nbd.h | 1 + block/nbd.c | 7 +++ nbd/client.c| 5 + nbd/server.c| 5 + 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 20363280ae..f7d87636d3 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -361,6 +361,7 @@ void nbd_server_start_options(NbdServerOptions *arg, Error **errp); static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size, const char *desc, Error **errp) { +ERRP_AUTO_PROPAGATE(); int ret = qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; if (ret < 0) { diff --git a/block/nbd.c b/block/nbd.c index 6876da04a7..b7cea0f650 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -1408,16 +1408,15 @@ static void nbd_client_close(BlockDriverState *bs) static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, Error **errp) { +ERRP_AUTO_PROPAGATE(); QIOChannelSocket *sioc; -Error *local_err = NULL; sioc = qio_channel_socket_new(); qio_channel_set_name(QIO_CHANNEL(sioc), "nbd-client"); -qio_channel_socket_connect_sync(sioc, saddr, &local_err); -if (local_err) { +qio_channel_socket_connect_sync(sioc, saddr, errp); +if (*errp) { object_unref(OBJECT(sioc)); -error_propagate(errp, local_err); return NULL; } diff --git a/nbd/client.c b/nbd/client.c index ba173108ba..e258ef3f7e 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -68,6 +68,7 @@ static int nbd_send_option_request(QIOChannel *ioc, uint32_t opt, uint32_t len, const char *data, Error **errp) { +ERRP_AUTO_PROPAGATE(); NBDOption req; QEMU_BUILD_BUG_ON(sizeof(req) != 16); @@ -153,6 +154,7 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt, static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply, bool strict, Error **errp) { +ERRP_AUTO_PROPAGATE(); g_autofree char *msg = NULL; if (!(reply->type & (1 << 31))) { @@ -337,6 +339,7 @@ static int nbd_receive_list(QIOChannel *ioc, char **name, char **description, static int nbd_opt_info_or_go(QIOChannel *ioc, uint32_t opt, NBDExportInfo *info, Error **errp) { +ERRP_AUTO_PROPAGATE(); NBDOptionReply reply; uint32_t len = strlen(info->name); uint16_t type; @@ -882,6 +885,7 @@ static int nbd_start_negotiate(AioContext *aio_context, QIOChannel *ioc, bool structured_reply, bool *zeroes, Error **errp) { +ERRP_AUTO_PROPAGATE(); uint64_t magic; trace_nbd_start_negotiate(tlscreds, hostname ? hostname : ""); @@ -1017,6 +1021,7 @@ int nbd_receive_negotiate(AioContext *aio_context, QIOChannel *ioc, const char *hostname, QIOChannel **outioc, NBDExportInfo *info, Error **errp) { +ERRP_AUTO_PROPAGATE(); int result; bool zeroes; bool base_allocation = info->base_allocation; diff --git a/nbd/server.c b/nbd/server.c index 20754e9ebc..8a12e586d7 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -211,6 +211,7 @@ static int GCC_FMT_ATTR(4, 0) nbd_negotiate_send_rep_verr(NBDClient *client, uint32_t type, Error **errp, const char *fmt, va_list va) { +ERRP_AUTO_PROPAGATE(); g_autofree char *msg = NULL; int re
[PATCH v12 4/8] pflash: Use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy If we want to add some info to errp (by error_prepend() or error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. Otherwise, this info will not be added when errp == &error_fatal (the program will exit prior to the error_append_hint() or error_prepend() call). Fix such cases. If we want to check error after errp-function call, we need to introduce local_err and then propagate it to errp. Instead, use ERRP_AUTO_PROPAGATE macro, benefits are: 1. No need of explicit error_propagate call 2. No need of explicit local_err variable: use errp directly 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or &error_fatal, this means that we don't break error_abort (we'll abort on error_set, not on error_propagate) This commit is generated by command sed -n '/^Parallel NOR Flash devices$/,/^$/{s/^F: //p}' \ MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Reported-by: Kevin Wolf Reported-by: Greg Kurz Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Philippe Mathieu-Daudé [Commit message tweaked] Signed-off-by: Markus Armbruster --- hw/block/pflash_cfi01.c | 7 +++ hw/block/pflash_cfi02.c | 7 +++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index cddc3a5a0c..859cfeae14 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -696,12 +696,12 @@ static const MemoryRegionOps pflash_cfi01_ops = { static void pflash_cfi01_realize(DeviceState *dev, Error **errp) { +ERRP_AUTO_PROPAGATE(); PFlashCFI01 *pfl = PFLASH_CFI01(dev); uint64_t total_len; int ret; uint64_t blocks_per_device, sector_len_per_device, device_len; int num_devices; -Error *local_err = NULL; if (pfl->sector_len == 0) { error_setg(errp, "attribute \"sector-length\" not specified or zero."); @@ -735,9 +735,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) &pfl->mem, OBJECT(dev), &pflash_cfi01_ops, pfl, -pfl->name, total_len, &local_err); -if (local_err) { -error_propagate(errp, local_err); +pfl->name, total_len, errp); +if (*errp) { return; } diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index b40ce2335a..15035ee5ef 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -724,9 +724,9 @@ static const MemoryRegionOps pflash_cfi02_ops = { static void pflash_cfi02_realize(DeviceState *dev, Error **errp) { +ERRP_AUTO_PROPAGATE(); PFlashCFI02 *pfl = PFLASH_CFI02(dev); int ret; -Error *local_err = NULL; if (pfl->uniform_sector_len == 0 && pfl->sector_len[0] == 0) { error_setg(errp, "attribute \"sector-length\" not specified or zero."); @@ -792,9 +792,8 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), &pflash_cfi02_ops, pfl, pfl->name, - pfl->chip_len, &local_err); -if (local_err) { -error_propagate(errp, local_err); + pfl->chip_len, errp); +if (*errp) { return; } -- 2.26.2
[PATCH v12 8/8] xen: Use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy If we want to add some info to errp (by error_prepend() or error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. Otherwise, this info will not be added when errp == &error_fatal (the program will exit prior to the error_append_hint() or error_prepend() call). Fix such cases. If we want to check error after errp-function call, we need to introduce local_err and then propagate it to errp. Instead, use ERRP_AUTO_PROPAGATE macro, benefits are: 1. No need of explicit error_propagate call 2. No need of explicit local_err variable: use errp directly 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or &error_fatal, this means that we don't break error_abort (we'll abort on error_set, not on error_propagate) This commit is generated by command sed -n '/^X86 Xen CPUs$/,/^$/{s/^F: //p}' MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Reported-by: Kevin Wolf Reported-by: Greg Kurz Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Philippe Mathieu-Daudé [Commit message tweaked] Signed-off-by: Markus Armbruster --- hw/block/dataplane/xen-block.c | 17 +++--- hw/block/xen-block.c | 102 ++--- hw/pci-host/xen_igd_pt.c | 7 +-- hw/xen/xen-backend.c | 7 +-- hw/xen/xen-bus.c | 92 + hw/xen/xen-host-pci-device.c | 27 + hw/xen/xen_pt.c| 25 hw/xen/xen_pt_config_init.c| 17 +++--- 8 files changed, 128 insertions(+), 166 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 5f8f15778b..1a077cc05f 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -723,8 +723,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, unsigned int protocol, Error **errp) { +ERRP_AUTO_PROPAGATE(); XenDevice *xendev = dataplane->xendev; -Error *local_err = NULL; unsigned int ring_size; unsigned int i; @@ -760,9 +760,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, } xen_device_set_max_grant_refs(xendev, dataplane->nr_ring_ref, - &local_err); -if (local_err) { -error_propagate(errp, local_err); + errp); +if (*errp) { goto stop; } @@ -770,9 +769,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, dataplane->ring_ref, dataplane->nr_ring_ref, PROT_READ | PROT_WRITE, - &local_err); -if (local_err) { -error_propagate(errp, local_err); + errp); +if (*errp) { goto stop; } @@ -805,9 +803,8 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, dataplane->event_channel = xen_device_bind_event_channel(xendev, event_channel, xen_block_dataplane_event, dataplane, - &local_err); -if (local_err) { -error_propagate(errp, local_err); + errp); +if (*errp) { goto stop; } diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index a775fba7c0..623ae5b8e0 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -195,6 +195,7 @@ static const BlockDevOps xen_block_dev_ops = { static void xen_block_realize(XenDevice *xendev, Error **errp) { +ERRP_AUTO_PROPAGATE(); XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev); XenBlockDeviceClass *blockdev_class = XEN_BLOCK_DEVICE_GET_CLASS(xendev); @@ -202,7 +203,6 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) XenBlockVdev *vdev = &blockdev->props.vdev; BlockConf *conf = &blockdev->props.conf; BlockBackend *blk = conf->blk; -Error *local_err = NULL; if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) { error_setg(errp, "vdev property not set"); @@ -212,9 +212,8 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) trace_xen_block_realize(type, vdev->disk, vdev->partition); if (blockdev_class->realize) { -blockdev_class->realize(blockdev, &local_err); -if (local_err) { -error_propagate(errp, local_err); +blockdev_class->realize(blockdev, errp); +if (*errp) { return; } } @@ -280,8 +279,8
[PATCH v12 2/8] scripts: Coccinelle script to use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy Script adds ERRP_AUTO_PROPAGATE macro invocation where appropriate and does corresponding changes in code (look for details in include/qapi/error.h) Usage example: spatch --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h --in-place --no-show-diff \ --max-width 80 FILES... Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- scripts/coccinelle/auto-propagated-errp.cocci | 337 ++ include/qapi/error.h | 3 + MAINTAINERS | 1 + 3 files changed, 341 insertions(+) create mode 100644 scripts/coccinelle/auto-propagated-errp.cocci diff --git a/scripts/coccinelle/auto-propagated-errp.cocci b/scripts/coccinelle/auto-propagated-errp.cocci new file mode 100644 index 00..c29f695adf --- /dev/null +++ b/scripts/coccinelle/auto-propagated-errp.cocci @@ -0,0 +1,337 @@ +// Use ERRP_AUTO_PROPAGATE (see include/qapi/error.h) +// +// Copyright (c) 2020 Virtuozzo International GmbH. +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// <http://www.gnu.org/licenses/>. +// +// Usage example: +// spatch --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ +// --macro-file scripts/cocci-macro-file.h --in-place \ +// --no-show-diff --max-width 80 FILES... +// +// Note: --max-width 80 is needed because coccinelle default is less +// than 80, and without this parameter coccinelle may reindent some +// lines which fit into 80 characters but not to coccinelle default, +// which in turn produces extra patch hunks for no reason. + +// Switch unusual Error ** parameter names to errp +// (this is necessary to use ERRP_AUTO_PROPAGATE). +// +// Disable optional_qualifier to skip functions with +// "Error *const *errp" parameter. +// +// Skip functions with "assert(_errp && *_errp)" statement, because +// that signals unusual semantics, and the parameter name may well +// serve a purpose. (like nbd_iter_channel_error()). +// +// Skip util/error.c to not touch, for example, error_propagate() and +// error_propagate_prepend(). +@ depends on !(file in "util/error.c") disable optional_qualifier@ +identifier fn; +identifier _errp != errp; +@@ + + fn(..., +- Error **_errp ++ Error **errp +,...) + { +( + ... when != assert(_errp && *_errp) +& + <... +-_errp ++errp + ...> +) + } + +// Add invocation of ERRP_AUTO_PROPAGATE to errp-functions where +// necessary +// +// Note, that without "when any" the final "..." does not mach +// something matched by previous pattern, i.e. the rule will not match +// double error_prepend in control flow like in +// vfio_set_irq_signaling(). +// +// Note, "exists" says that we want apply rule even if it does not +// match on all possible control flows (otherwise, it will not match +// standard pattern when error_propagate() call is in if branch). +@ disable optional_qualifier exists@ +identifier fn, local_err; +symbol errp; +@@ + + fn(..., Error **errp, ...) + { ++ ERRP_AUTO_PROPAGATE(); +... when != ERRP_AUTO_PROPAGATE(); +( +( +error_append_hint(errp, ...); +| +error_prepend(errp, ...); +| +error_vprepend(errp, ...); +) +... when any +| +Error *local_err = NULL; +... +( +error_propagate_prepend(errp, local_err, ...); +| +error_propagate(errp, local_err); +) +... +) + } + +// Warn when several Error * definitions are in the control flow. +// This rule is not chained to rule1 and less restrictive, to cover more +// functions to warn (even those we are not going to convert). +// +// Note, that even with one (or zero) Error * definition in the each +// control flow we may have several (in total) Error * definitions in +// the function. This case deserves attention too, but I don't see +// simple way to match with help of coccinelle. +@check1 disable optional_qualifier exists@ +identifier fn, _errp, local_err, local_err2; +position p1, p2; +@@ + + fn(..., Error **_errp, ...) + { + ... + Error *local_err = NULL;@p1 + ... when any + Error *local_err2 = NULL;@p2 + ... when any + } + +@ script:python @ +fn << check1.fn; +p1 << check1.p1; +p2 << check1.p2; +@@ + +print('Warning: function {} has several de
[PATCH v12 3/8] sd: Use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy If we want to add some info to errp (by error_prepend() or error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. Otherwise, this info will not be added when errp == &error_fatal (the program will exit prior to the error_append_hint() or error_prepend() call). Fix such cases. If we want to check error after errp-function call, we need to introduce local_err and then propagate it to errp. Instead, use ERRP_AUTO_PROPAGATE macro, benefits are: 1. No need of explicit error_propagate call 2. No need of explicit local_err variable: use errp directly 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or &error_fatal, this means that we don't break error_abort (we'll abort on error_set, not on error_propagate) This commit is generated by command sed -n '/^SD (Secure Card)$/,/^$/{s/^F: //p}' \ MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Reported-by: Kevin Wolf Reported-by: Greg Kurz Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Philippe Mathieu-Daudé [Commit message tweaked] Signed-off-by: Markus Armbruster --- hw/sd/sdhci-pci.c | 7 +++ hw/sd/sdhci.c | 21 + hw/sd/ssi-sd.c| 10 +- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/hw/sd/sdhci-pci.c b/hw/sd/sdhci-pci.c index 4f5977d487..38ec572fc6 100644 --- a/hw/sd/sdhci-pci.c +++ b/hw/sd/sdhci-pci.c @@ -29,13 +29,12 @@ static Property sdhci_pci_properties[] = { static void sdhci_pci_realize(PCIDevice *dev, Error **errp) { +ERRP_AUTO_PROPAGATE(); SDHCIState *s = PCI_SDHCI(dev); -Error *local_err = NULL; sdhci_initfn(s); -sdhci_common_realize(s, &local_err); -if (local_err) { -error_propagate(errp, local_err); +sdhci_common_realize(s, errp); +if (*errp) { return; } diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index eb2be6529e..be1928784d 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1288,7 +1288,7 @@ static const MemoryRegionOps sdhci_mmio_ops = { static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp) { -Error *local_err = NULL; +ERRP_AUTO_PROPAGATE(); switch (s->sd_spec_version) { case 2 ... 3: @@ -1299,9 +1299,8 @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp) } s->version = (SDHC_HCVER_VENDOR << 8) | (s->sd_spec_version - 1); -sdhci_check_capareg(s, &local_err); -if (local_err) { -error_propagate(errp, local_err); +sdhci_check_capareg(s, errp); +if (*errp) { return; } } @@ -1332,11 +1331,10 @@ void sdhci_uninitfn(SDHCIState *s) void sdhci_common_realize(SDHCIState *s, Error **errp) { -Error *local_err = NULL; +ERRP_AUTO_PROPAGATE(); -sdhci_init_readonly_registers(s, &local_err); -if (local_err) { -error_propagate(errp, local_err); +sdhci_init_readonly_registers(s, errp); +if (*errp) { return; } s->buf_maxsz = sdhci_get_fifolen(s); @@ -1456,13 +1454,12 @@ static void sdhci_sysbus_finalize(Object *obj) static void sdhci_sysbus_realize(DeviceState *dev, Error **errp) { +ERRP_AUTO_PROPAGATE(); SDHCIState *s = SYSBUS_SDHCI(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); -Error *local_err = NULL; -sdhci_common_realize(s, &local_err); -if (local_err) { -error_propagate(errp, local_err); +sdhci_common_realize(s, errp); +if (*errp) { return; } diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 3717b2e721..adb7fa9c24 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -241,10 +241,10 @@ static const VMStateDescription vmstate_ssi_sd = { static void ssi_sd_realize(SSISlave *d, Error **errp) { +ERRP_AUTO_PROPAGATE(); ssi_sd_state *s = SSI_SD(d); DeviceState *carddev; DriveInfo *dinfo; -Error *err = NULL; qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(d), "sd-bus"); @@ -255,23 +255,23 @@ static void ssi_sd_realize(SSISlave *d, Error **errp) carddev = qdev_new(TYPE_SD_CARD); if (dinfo) { if (!qdev_prop_set_drive_err(carddev, "drive", - blk_by_legacy_dinfo(dinfo), &err)) { + blk_by_legacy_dinfo(dinfo), errp)) { goto fail; } } -if (!object_property_set_bool(OBJECT(carddev), "spi", true, &err)) { +if (!object_property_set_bool(OBJECT(carddev), "spi", true, errp)) { goto fail; } -if (!qdev_realize_and_unref(carddev, BUS(&s->sdbus), &err)) { +if (!qdev_realize_and_unr
[PATCH v12 1/8] error: New macro ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of functions with an errp OUT parameter. It has three goals: 1. Fix issue with error_fatal and error_prepend/error_append_hint: user can't see this additional information, because exit() happens in error_setg earlier than information is added. [Reported by Greg Kurz] 2. Fix issue with error_abort and error_propagate: when we wrap error_abort by local_err+error_propagate, the resulting coredump will refer to error_propagate and not to the place where error happened. (the macro itself doesn't fix the issue, but it allows us to [3.] drop the local_err+error_propagate pattern, which will definitely fix the issue) [Reported by Kevin Wolf] 3. Drop local_err+error_propagate pattern, which is used to workaround void functions with errp parameter, when caller wants to know resulting status. (Note: actually these functions could be merely updated to return int error code). To achieve these goals, later patches will add invocations of this macro at the start of functions with either use error_prepend/error_append_hint (solving 1) or which use local_err+error_propagate to check errors, switching those functions to use *errp instead (solving 2 and 3). Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Paul Durrant Reviewed-by: Greg Kurz Reviewed-by: Eric Blake [Comments merged properly with recent commit "error: Document Error API usage rules", and edited for clarity. Put ERRP_AUTO_PROPAGATE() before its helpers, and touch up style. Commit message tweaked.] Signed-off-by: Markus Armbruster --- include/qapi/error.h | 160 ++- 1 file changed, 141 insertions(+), 19 deletions(-) diff --git a/include/qapi/error.h b/include/qapi/error.h index 3fed49747d..c865a7d2f1 100644 --- a/include/qapi/error.h +++ b/include/qapi/error.h @@ -30,6 +30,10 @@ * job. Since the value of @errp is about handling the error, the * function should not examine it. * + * - The function may pass @errp to functions it calls to pass on + * their errors to its caller. If it dereferences @errp to check + * for errors, it must use ERRP_AUTO_PROPAGATE(). + * * - On success, the function should not touch *errp. On failure, it * should set a new error, e.g. with error_setg(errp, ...), or * propagate an existing one, e.g. with error_propagate(errp, ...). @@ -45,15 +49,17 @@ * = Creating errors = * * Create an error: - * error_setg(&err, "situation normal, all fouled up"); + * error_setg(errp, "situation normal, all fouled up"); + * where @errp points to the location to receive the error. * * Create an error and add additional explanation: - * error_setg(&err, "invalid quark"); - * error_append_hint(&err, "Valid quarks are up, down, strange, " + * error_setg(errp, "invalid quark"); + * error_append_hint(errp, "Valid quarks are up, down, strange, " * "charm, top, bottom.\n"); + * This may require use of ERRP_AUTO_PROPAGATE(); more on that below. * * Do *not* contract this to - * error_setg(&err, "invalid quark\n" // WRONG! + * error_setg(errp, "invalid quark\n" // WRONG! *"Valid quarks are up, down, strange, charm, top, bottom."); * * = Reporting and destroying errors = @@ -107,18 +113,6 @@ * Errors get passed to the caller through the conventional @errp * parameter. * - * Pass an existing error to the caller: - * error_propagate(errp, err); - * where Error **errp is a parameter, by convention the last one. - * - * Pass an existing error to the caller with the message modified: - * error_propagate_prepend(errp, err, - * "Could not frobnicate '%s': ", name); - * This is more concise than - * error_propagate(errp, err); // don't do this - * error_prepend(errp, "Could not frobnicate '%s': ", name); - * and works even when @errp is &error_fatal. - * * Create a new error and pass it to the caller: * error_setg(errp, "situation normal, all fouled up"); * @@ -128,18 +122,26 @@ * handle the error... * } * when it doesn't, say a void function: + * ERRP_AUTO_PROPAGATE(); + * foo(arg, errp); + * if (*errp) { + * handle the error... + * } + * More on ERRP_AUTO_PROPAGATE() below. + * + * Code predating ERRP_AUTO_PROPAGATE() still exits, and looks like this: * Error *err = NULL; * foo(arg, &err); * if (err) { * handle the error... - * error_propagate(errp, err); + * error_propagate(errp, err); // deprecated * } - * Do *not* "optimize" this to + * Avoid in new code. Do *not* "optimize" it to * foo(arg, errp); * if (
[PATCH v12 6/8] virtio-9p: Use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy If we want to add some info to errp (by error_prepend() or error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. Otherwise, this info will not be added when errp == &error_fatal (the program will exit prior to the error_append_hint() or error_prepend() call). Fix such cases. If we want to check error after errp-function call, we need to introduce local_err and then propagate it to errp. Instead, use ERRP_AUTO_PROPAGATE macro, benefits are: 1. No need of explicit error_propagate call 2. No need of explicit local_err variable: use errp directly 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or &error_fatal, this means that we don't break error_abort (we'll abort on error_set, not on error_propagate) This commit is generated by command sed -n '/^virtio-9p$/,/^$/{s/^F: //p}' MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Reported-by: Kevin Wolf Reported-by: Greg Kurz Signed-off-by: Vladimir Sementsov-Ogievskiy Acked-by: Greg Kurz Reviewed-by: Christian Schoenebeck [Commit message tweaked] Signed-off-by: Markus Armbruster --- hw/9pfs/9p-local.c | 12 +--- hw/9pfs/9p.c | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index 54e012e5b4..0361e0c0b4 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -1479,10 +1479,10 @@ static void error_append_security_model_hint(Error *const *errp) static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) { +ERRP_AUTO_PROPAGATE(); const char *sec_model = qemu_opt_get(opts, "security_model"); const char *path = qemu_opt_get(opts, "path"); const char *multidevs = qemu_opt_get(opts, "multidevs"); -Error *local_err = NULL; if (!sec_model) { error_setg(errp, "security_model property not set"); @@ -1516,11 +1516,10 @@ static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) fse->export_flags &= ~V9FS_FORBID_MULTIDEVS; fse->export_flags &= ~V9FS_REMAP_INODES; } else { -error_setg(&local_err, "invalid multidevs property '%s'", +error_setg(errp, "invalid multidevs property '%s'", multidevs); -error_append_hint(&local_err, "Valid options are: multidevs=" +error_append_hint(errp, "Valid options are: multidevs=" "[remap|forbid|warn]\n"); -error_propagate(errp, local_err); return -1; } } @@ -1530,9 +1529,8 @@ static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) return -1; } -if (fsdev_throttle_parse_opts(opts, &fse->fst, &local_err)) { -error_propagate_prepend(errp, local_err, -"invalid throttle configuration: "); +if (fsdev_throttle_parse_opts(opts, &fse->fst, errp)) { +error_prepend(errp, "invalid throttle configuration: "); return -1; } diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 9755fba9a9..bdb1360482 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -4011,6 +4011,7 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr) int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, Error **errp) { +ERRP_AUTO_PROPAGATE(); int i, len; struct stat stat; FsDriverEntry *fse; -- 2.26.2
[PATCH v12 0/8] error: auto propagated local_err part I
To speed things up, I'm taking the liberty to respin Vladimir's series with my documentation amendments. After my documentation work, I'm very much inclined to rename ERRP_AUTO_PROPAGATE() to ERRP_GUARD(). The fact that it propagates below the hood is detail. What matters to its users is that it lets them use @errp more freely. Thoughts? Based-on: Message-Id: <20200707160613.848843-1-arm...@redhat.com> Available from my public repository https://repo.or.cz/qemu/armbru.git on branch error-auto. v12: (based on "[PATCH v4 00/45] Less clumsy error checking") 01: Comments merged properly with recent commit "error: Document Error API usage rules", and edited for clarity. Put ERRP_AUTO_PROPAGATE() before its helpers, and touch up style. 01-08: Commit messages tweaked Vladimir's cover letter for v11: v11: (based-on "[PATCH v2 00/44] Less clumsy error checking") 01: minor rebase of documentation, keep r-bs 02: - minor comment tweaks [Markus] - use explicit file name in MAINTAINERS instead of pattern - add Markus's r-b 03,07,08: rabase changes, drop r-bs v11 is available at https://src.openvz.org/scm/~vsementsov/qemu.git #tag up-auto-local-err-partI-v11 v10 is available at https://src.openvz.org/scm/~vsementsov/qemu.git #tag up-auto-local-err-partI-v10 In these series, there is no commit-per-subsystem script, each generated commit is generated in separate. Still, generating commands are very similar, and looks like sed -n '/^$/,/^$/{s/^F: //p}' MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Note, that in each generated commit, generation command is the only text, indented by 8 spaces in 'git log -1' output, so, to regenerate all commits (for example, after rebase, or change in coccinelle script), you may use the following command: git rebase -x "sh -c \"git show --pretty= --name-only | xargs git checkout HEAD^ -- ; git reset; git log -1 | grep '^' | sh\"" HEAD~6 Which will start automated interactive rebase for generated patches, which will stop if generated patch changed (you may do git commit --amend to apply updated generated changes). Note: git show --pretty= --name-only - lists files, changed in HEAD git log -1 | grep '^' | sh - rerun generation command of HEAD Check for compilation of changed .c files git rebase -x "sh -c \"git show --pretty= --name-only | sed -n 's/\.c$/.o/p' | xargs make -j9\"" HEAD~6 Vladimir Sementsov-Ogievskiy (8): error: New macro ERRP_AUTO_PROPAGATE() scripts: Coccinelle script to use ERRP_AUTO_PROPAGATE() sd: Use ERRP_AUTO_PROPAGATE() pflash: Use ERRP_AUTO_PROPAGATE() fw_cfg: Use ERRP_AUTO_PROPAGATE() virtio-9p: Use ERRP_AUTO_PROPAGATE() nbd: Use ERRP_AUTO_PROPAGATE() xen: Use ERRP_AUTO_PROPAGATE() scripts/coccinelle/auto-propagated-errp.cocci | 337 ++ include/block/nbd.h | 1 + include/qapi/error.h | 163 - block/nbd.c | 7 +- hw/9pfs/9p-local.c| 12 +- hw/9pfs/9p.c | 1 + hw/block/dataplane/xen-block.c| 17 +- hw/block/pflash_cfi01.c | 7 +- hw/block/pflash_cfi02.c | 7 +- hw/block/xen-block.c | 102 +++--- hw/nvram/fw_cfg.c | 14 +- hw/pci-host/xen_igd_pt.c | 7 +- hw/sd/sdhci-pci.c | 7 +- hw/sd/sdhci.c | 21 +- hw/sd/ssi-sd.c| 10 +- hw/xen/xen-backend.c | 7 +- hw/xen/xen-bus.c | 92 ++--- hw/xen/xen-host-pci-device.c | 27 +- hw/xen/xen_pt.c | 25 +- hw/xen/xen_pt_config_init.c | 17 +- nbd/client.c | 5 + nbd/server.c | 5 + MAINTAINERS | 1 + 23 files changed, 659 insertions(+), 233 deletions(-) create mode 100644 scripts/coccinelle/auto-propagated-errp.cocci -- 2.26.2
[PATCH v12 5/8] fw_cfg: Use ERRP_AUTO_PROPAGATE()
From: Vladimir Sementsov-Ogievskiy If we want to add some info to errp (by error_prepend() or error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. Otherwise, this info will not be added when errp == &error_fatal (the program will exit prior to the error_append_hint() or error_prepend() call). Fix such cases. If we want to check error after errp-function call, we need to introduce local_err and then propagate it to errp. Instead, use ERRP_AUTO_PROPAGATE macro, benefits are: 1. No need of explicit error_propagate call 2. No need of explicit local_err variable: use errp directly 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or &error_fatal, this means that we don't break error_abort (we'll abort on error_set, not on error_propagate) This commit is generated by command sed -n '/^Firmware configuration (fw_cfg)$/,/^$/{s/^F: //p}' \ MAINTAINERS | \ xargs git ls-files | grep '\.[hc]$' | \ xargs spatch \ --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ --macro-file scripts/cocci-macro-file.h \ --in-place --no-show-diff --max-width 80 Reported-by: Kevin Wolf Reported-by: Greg Kurz Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Philippe Mathieu-Daudé [Commit message tweaked] Signed-off-by: Markus Armbruster --- hw/nvram/fw_cfg.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 0408a31f8e..d5386c3235 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -1231,12 +1231,11 @@ static Property fw_cfg_io_properties[] = { static void fw_cfg_io_realize(DeviceState *dev, Error **errp) { +ERRP_AUTO_PROPAGATE(); FWCfgIoState *s = FW_CFG_IO(dev); -Error *local_err = NULL; -fw_cfg_file_slots_allocate(FW_CFG(s), &local_err); -if (local_err) { -error_propagate(errp, local_err); +fw_cfg_file_slots_allocate(FW_CFG(s), errp); +if (*errp) { return; } @@ -1282,14 +1281,13 @@ static Property fw_cfg_mem_properties[] = { static void fw_cfg_mem_realize(DeviceState *dev, Error **errp) { +ERRP_AUTO_PROPAGATE(); FWCfgMemState *s = FW_CFG_MEM(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops; -Error *local_err = NULL; -fw_cfg_file_slots_allocate(FW_CFG(s), &local_err); -if (local_err) { -error_propagate(errp, local_err); +fw_cfg_file_slots_allocate(FW_CFG(s), errp); +if (*errp) { return; } -- 2.26.2
Re: [PATCH v11 8/8] xen: introduce ERRP_AUTO_PROPAGATE
Philippe Mathieu-Daudé writes: > On 7/3/20 11:08 AM, Vladimir Sementsov-Ogievskiy wrote: >> If we want to add some info to errp (by error_prepend() or >> error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro. >> Otherwise, this info will not be added when errp == &error_fatal >> (the program will exit prior to the error_append_hint() or >> error_prepend() call). Fix such cases. >> >> If we want to check error after errp-function call, we need to >> introduce local_err and then propagate it to errp. Instead, use >> ERRP_AUTO_PROPAGATE macro, benefits are: >> 1. No need of explicit error_propagate call >> 2. No need of explicit local_err variable: use errp directly >> 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or >>&error_fatal, this means that we don't break error_abort >>(we'll abort on error_set, not on error_propagate) >> >> This commit is generated by command >> >> sed -n '/^X86 Xen CPUs$/,/^$/{s/^F: //p}' MAINTAINERS | \ >> xargs git ls-files | grep '\.[hc]$' | \ >> xargs spatch \ >> --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ >> --macro-file scripts/cocci-macro-file.h \ >> --in-place --no-show-diff --max-width 80 >> >> Reported-by: Kevin Wolf >> Reported-by: Greg Kurz >> Signed-off-by: Vladimir Sementsov-Ogievskiy >> --- >> hw/block/dataplane/xen-block.c | 17 +++--- >> hw/block/xen-block.c | 102 ++--- >> hw/pci-host/xen_igd_pt.c | 7 +-- >> hw/xen/xen-backend.c | 7 +-- >> hw/xen/xen-bus.c | 92 + >> hw/xen/xen-host-pci-device.c | 27 + >> hw/xen/xen_pt.c| 25 >> hw/xen/xen_pt_config_init.c| 17 +++--- >> 8 files changed, 128 insertions(+), 166 deletions(-) > > Without the description, this patch has 800 lines of diff... > It killed me, I don't have the energy to review patch #7 of this > series after that, sorry. > Consider splitting such mechanical patches next time. Here it > could have been hw/block, hw/pci-host, hw/xen. Probably my fault; I asked for less fine-grained splitting. Finding a split of a tree-wide transformation that pleases everyone is basically impossible. The conversion to ERRP_AUTO_PROPAGATE() could be one patch per function, but that would be excessive. Vladimir chose to split along maintenance boundaries, so he can cc: the right people on the right code. I agree with the idea. The difficulty is which boundaries. Our code is not partitioned into maintenance domains. Instead, we have overlapping sets. Makes sense, because it mirrors how we actually maintain it. Because of that, a blind split guided by MAINTAINERS won't work well. A split that makes sense needs a bit of human judgement, too. This part makes perfect sense to me from the cc: point of view: it's Xen, the whole of Xen, and nothing but Xen. I acknowledge that its size made it exhausting for you to review. I didn't expect that, probably because after having spent hours on reviewing and improving the macro and the Coccinelle script, I know exactly what to look for, and also consider the script trustworthy[*]. > Reviewed-by: Philippe Mathieu-Daudé Thank you, much appreciated! [*] I've learned not to trust Coccinelle 100%, ever.
Re: [PATCH v11 1/8] error: auto propagated local_err
Vladimir Sementsov-Ogievskiy writes: > Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of > functions with an errp OUT parameter. > > It has three goals: > > 1. Fix issue with error_fatal and error_prepend/error_append_hint: user > can't see this additional information, because exit() happens in > error_setg earlier than information is added. [Reported by Greg Kurz] > > 2. Fix issue with error_abort and error_propagate: when we wrap > error_abort by local_err+error_propagate, the resulting coredump will > refer to error_propagate and not to the place where error happened. > (the macro itself doesn't fix the issue, but it allows us to [3.] drop > the local_err+error_propagate pattern, which will definitely fix the > issue) [Reported by Kevin Wolf] > > 3. Drop local_err+error_propagate pattern, which is used to workaround > void functions with errp parameter, when caller wants to know resulting > status. (Note: actually these functions could be merely updated to > return int error code). > > To achieve these goals, later patches will add invocations > of this macro at the start of functions with either use > error_prepend/error_append_hint (solving 1) or which use > local_err+error_propagate to check errors, switching those > functions to use *errp instead (solving 2 and 3). > > Signed-off-by: Vladimir Sementsov-Ogievskiy > Reviewed-by: Paul Durrant > Reviewed-by: Greg Kurz > Reviewed-by: Eric Blake > --- > > Cc: Eric Blake > Cc: Kevin Wolf > Cc: Max Reitz > Cc: Greg Kurz > Cc: Christian Schoenebeck > Cc: Stefan Hajnoczi > Cc: Stefano Stabellini > Cc: Anthony Perard > Cc: Paul Durrant > Cc: "Philippe Mathieu-Daudé" > Cc: Laszlo Ersek > Cc: Gerd Hoffmann > Cc: Markus Armbruster > Cc: Michael Roth > Cc: qemu-de...@nongnu.org > Cc: qemu-bl...@nongnu.org > Cc: xen-devel@lists.xenproject.org > > include/qapi/error.h | 205 --- > 1 file changed, 172 insertions(+), 33 deletions(-) > > diff --git a/include/qapi/error.h b/include/qapi/error.h > index 5ceb3ace06..b54aedbfd7 100644 > --- a/include/qapi/error.h > +++ b/include/qapi/error.h > @@ -39,7 +39,7 @@ > * • pointer-valued functions return non-null / null pointer, and > * • integer-valued functions return non-negative / negative. > * > - * How to: > + * = Deal with Error object = > * > * Create an error: > * error_setg(errp, "situation normal, all fouled up"); > @@ -73,28 +73,91 @@ > * reporting it (primarily useful in testsuites): > * error_free_or_abort(&err); > * > - * Pass an existing error to the caller: > - * error_propagate(errp, err); > - * where Error **errp is a parameter, by convention the last one. > + * = Deal with Error ** function parameter = > * > - * Pass an existing error to the caller with the message modified: > - * error_propagate_prepend(errp, err); > + * A function may use the error system to return errors. In this case, the > + * function defines an Error **errp parameter, by convention the last one > (with > + * exceptions for functions using ... or va_list). > * > - * Avoid > - * error_propagate(errp, err); > - * error_prepend(errp, "Could not frobnicate '%s': ", name); > - * because this fails to prepend when @errp is &error_fatal. > + * The caller may then pass in the following errp values: > + * > + * 1. &error_abort > + *Any error will result in abort(). > + * 2. &error_fatal > + *Any error will result in exit() with a non-zero status. > + * 3. NULL > + *No error reporting through errp parameter. > + * 4. The address of a NULL-initialized Error *err > + *Any error will populate errp with an error object. The rebase onto my "error: Document Error API usage rules" rendered this this partly redundant. I'll try my hand at a proper merge, then ask you to check it. Should I fail to complete this in time for the soft freeze, we can merge the thing as is. Comment improvements are fair game until -rc1 or so. > * > - * Create a new error and pass it to the caller: > + * The following rules then implement the correct semantics desired by the > + * caller. > + * > + * Create a new error to pass to the caller: > * error_setg(errp, "situation normal, all fouled up"); > * > - * Call a function and receive an error from it: > + * Calling another errp-based function: > + * f(..., errp); > + * > + * == Checking success of subcall == > + * > + * If a function returns a value indicating an error in addition to setting > + * errp (which is recommended), then you don'
Re: [PATCH 2/2] xen: cleanup unrealized flash devices
Jason Andryuk writes: > On Wed, Jul 1, 2020 at 3:03 AM Paul Durrant wrote: >> >> > -Original Message- >> > From: Philippe Mathieu-Daudé >> > Sent: 30 June 2020 18:27 >> > To: p...@xen.org; xen-devel@lists.xenproject.org; qemu-de...@nongnu.org >> > Cc: 'Eduardo Habkost' ; 'Michael S. Tsirkin' >> > ; 'Paul Durrant' >> > ; 'Jason Andryuk' ; 'Paolo >> > Bonzini' ; >> > 'Richard Henderson' >> > Subject: Re: [PATCH 2/2] xen: cleanup unrealized flash devices >> > >> > On 6/30/20 5:44 PM, Paul Durrant wrote: >> > >> -Original Message- >> > >> From: Philippe Mathieu-Daudé >> > >> Sent: 30 June 2020 16:26 >> > >> To: Paul Durrant ; xen-devel@lists.xenproject.org; >> > >> qemu-de...@nongnu.org >> > >> Cc: Eduardo Habkost ; Michael S. Tsirkin >> > >> ; Paul Durrant >> > >> ; Jason Andryuk ; Paolo >> > >> Bonzini ; >> > >> Richard Henderson >> > >> Subject: Re: [PATCH 2/2] xen: cleanup unrealized flash devices >> > >> >> > >> On 6/24/20 2:18 PM, Paul Durrant wrote: >> > >>> From: Paul Durrant >> > >>> >> > >>> The generic pc_machine_initfn() calls pc_system_flash_create() which >> > >>> creates >> > >>> 'system.flash0' and 'system.flash1' devices. These devices are then >> > >>> realized >> > >>> by pc_system_flash_map() which is called from >> > >>> pc_system_firmware_init() which >> > >>> itself is called via pc_memory_init(). The latter however is not >> > >>> called when >> > >>> xen_enable() is true and hence the following assertion fails: >> > >>> >> > >>> qemu-system-i386: hw/core/qdev.c:439: qdev_assert_realized_properly: >> > >>> Assertion `dev->realized' failed >> > >>> >> > >>> These flash devices are unneeded when using Xen so this patch avoids >> > >>> the >> > >>> assertion by simply removing them using >> > >>> pc_system_flash_cleanup_unused(). >> > >>> >> > >>> Reported-by: Jason Andryuk >> > >>> Fixes: ebc29e1beab0 ("pc: Support firmware configuration with >> > >>> -blockdev") >> > >>> Signed-off-by: Paul Durrant >> > >>> Tested-by: Jason Andryuk >> > >>> --- >> > >>> Cc: Paolo Bonzini >> > >>> Cc: Richard Henderson >> > >>> Cc: Eduardo Habkost >> > >>> Cc: "Michael S. Tsirkin" >> > >>> Cc: Marcel Apfelbaum >> > >>> --- >> > >>> hw/i386/pc_piix.c| 9 ++--- >> > >>> hw/i386/pc_sysfw.c | 2 +- >> > >>> include/hw/i386/pc.h | 1 + >> > >>> 3 files changed, 8 insertions(+), 4 deletions(-) >> > >>> >> > >>> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c >> > >>> index 1497d0e4ae..977d40afb8 100644 >> > >>> --- a/hw/i386/pc_piix.c >> > >>> +++ b/hw/i386/pc_piix.c >> > >>> @@ -186,9 +186,12 @@ static void pc_init1(MachineState *machine, >> > >>> if (!xen_enabled()) { >> > >>> pc_memory_init(pcms, system_memory, >> > >>> rom_memory, &ram_memory); >> > >>> -} else if (machine->kernel_filename != NULL) { >> > >>> -/* For xen HVM direct kernel boot, load linux here */ >> > >>> -xen_load_linux(pcms); >> > >>> +} else { >> > >>> +pc_system_flash_cleanup_unused(pcms); >> > >> >> > >> TIL pc_system_flash_cleanup_unused(). >> > >> >> > >> What about restricting at the source? >> > >> >> > > >> > > And leave the devices in place? They are not relevant for Xen, so why >> > > not clean up? >> > >> > No, I meant to not create them in the first place, instead of >> > create+destroy. >> > >> > Anyway what you did works, so I don't have any problem. >> >> IIUC Jason originally tried restricting creation but encountered a problem >> because xen_enabled() would always return false at that point, because >> machine creation occurs before accelerators are initialized. > > Correct. Quoting my previous email: > """ > Removing the call to pc_system_flash_create() from pc_machine_initfn() > lets QEMU startup and run a Xen HVM again. xen_enabled() doesn't work > there since accelerators have not been initialized yes, I guess? > """ > > If you want to remove the creation in the first place, then I have two > questions. Why does pc_system_flash_create()/pc_pflash_create() get > called so early creating the pflash devices? Why aren't they just > created as needed in pc_system_flash_map()? commit ebc29e1beab02646702c8cb9a1d29b68f72ad503 pc: Support firmware configuration with -blockdev [...] Properties need to be created in .instance_init() methods. For PC machines, that's pc_machine_initfn(). To make alias properties work, we need to create the onboard flash devices there, too. [...] For context, read the entire commit message. If you have questions then, don't hesitate to ask them here.
Re: [PATCH 2/2] xen: cleanup unrealized flash devices
Philippe Mathieu-Daudé writes: > On 6/30/20 5:44 PM, Paul Durrant wrote: >>> -Original Message- >>> From: Philippe Mathieu-Daudé >>> Sent: 30 June 2020 16:26 >>> To: Paul Durrant ; xen-devel@lists.xenproject.org; >>> qemu-de...@nongnu.org >>> Cc: Eduardo Habkost ; Michael S. Tsirkin >>> ; Paul Durrant >>> ; Jason Andryuk ; Paolo Bonzini >>> ; >>> Richard Henderson >>> Subject: Re: [PATCH 2/2] xen: cleanup unrealized flash devices >>> >>> On 6/24/20 2:18 PM, Paul Durrant wrote: From: Paul Durrant The generic pc_machine_initfn() calls pc_system_flash_create() which creates 'system.flash0' and 'system.flash1' devices. These devices are then realized by pc_system_flash_map() which is called from pc_system_firmware_init() which itself is called via pc_memory_init(). The latter however is not called when xen_enable() is true and hence the following assertion fails: qemu-system-i386: hw/core/qdev.c:439: qdev_assert_realized_properly: Assertion `dev->realized' failed These flash devices are unneeded when using Xen so this patch avoids the assertion by simply removing them using pc_system_flash_cleanup_unused(). Reported-by: Jason Andryuk Fixes: ebc29e1beab0 ("pc: Support firmware configuration with -blockdev") Signed-off-by: Paul Durrant Tested-by: Jason Andryuk --- Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost Cc: "Michael S. Tsirkin" Cc: Marcel Apfelbaum --- hw/i386/pc_piix.c| 9 ++--- hw/i386/pc_sysfw.c | 2 +- include/hw/i386/pc.h | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 1497d0e4ae..977d40afb8 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -186,9 +186,12 @@ static void pc_init1(MachineState *machine, if (!xen_enabled()) { pc_memory_init(pcms, system_memory, rom_memory, &ram_memory); -} else if (machine->kernel_filename != NULL) { -/* For xen HVM direct kernel boot, load linux here */ -xen_load_linux(pcms); +} else { +pc_system_flash_cleanup_unused(pcms); >>> >>> TIL pc_system_flash_cleanup_unused(). >>> >>> What about restricting at the source? >>> >> >> And leave the devices in place? They are not relevant for Xen, so why not >> clean up? > > No, I meant to not create them in the first place, instead of > create+destroy. Better. Opinion, not demand :) [...]
Re: [PATCH 2/2] xen: cleanup unrealized flash devices
Anthony PERARD writes: > On Wed, Jun 24, 2020 at 01:18:41PM +0100, Paul Durrant wrote: >> From: Paul Durrant >> >> The generic pc_machine_initfn() calls pc_system_flash_create() which creates >> 'system.flash0' and 'system.flash1' devices. These devices are then realized >> by pc_system_flash_map() which is called from pc_system_firmware_init() which >> itself is called via pc_memory_init(). The latter however is not called when >> xen_enable() is true and hence the following assertion fails: >> >> qemu-system-i386: hw/core/qdev.c:439: qdev_assert_realized_properly: >> Assertion `dev->realized' failed >> >> These flash devices are unneeded when using Xen so this patch avoids the >> assertion by simply removing them using pc_system_flash_cleanup_unused(). >> >> Reported-by: Jason Andryuk >> Fixes: ebc29e1beab0 ("pc: Support firmware configuration with -blockdev") >> Signed-off-by: Paul Durrant >> Tested-by: Jason Andryuk > > Reviewed-by: Anthony PERARD > > I think I would add: > > Fixes: dfe8c79c4468 ("qdev: Assert onboard devices all get realized properly") > > as this is the first commit where the unrealized flash devices are an > issue. They were an issue before, but commit dfe8c79c4468 turned the minor issue into a crash bug. No objections.
Re: [PATCH v10 1/9] error: auto propagated local_err
Greg Kurz writes: > On Mon, 15 Jun 2020 07:21:03 +0200 > Markus Armbruster wrote: > >> Greg Kurz writes: >> >> > On Tue, 17 Mar 2020 18:16:17 +0300 >> > Vladimir Sementsov-Ogievskiy wrote: >> > >> >> Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of >> >> functions with an errp OUT parameter. >> >> >> >> It has three goals: >> >> >> >> 1. Fix issue with error_fatal and error_prepend/error_append_hint: user >> >> can't see this additional information, because exit() happens in >> >> error_setg earlier than information is added. [Reported by Greg Kurz] >> >> >> > >> > I have more of these coming and I'd really like to use ERRP_AUTO_PROPAGATE. >> > >> > It seems we have a consensus on the macro itself but this series is gated >> > by the conversion of the existing code base. >> > >> > What about merging this patch separately so that people can start using >> > it at least ? >> >> Please give me a few more days to finish the work I feel should go in >> before the conversion. With any luck, Vladimir can then rebase / >> recreate the conversion easily, and you can finally use the macro for >> your own work. >> > > Sure. Thanks. Just posted "[PATCH 00/46] Less clumsy error checking". The sheer size of the thing and the length of its dependency chain explains why it took me so long. I feel bad about delaying you all the same. Apologies! I hope we can converge quickly enough to get Vladimir's work on top ready in time for the soft freeze.
Re: sysbus failed assert for xen_sysdev
Jason Andryuk writes: > On Mon, Jun 22, 2020 at 5:17 PM Mark Cave-Ayland > wrote: >> >> On 22/06/2020 21:33, Jason Andryuk wrote: >> >> > Hi, >> > >> > Running qemu devel for a Xen VM is failing an assert after the recent >> > "qdev: Rework how we plug into the parent bus" sysbus changes. >> > >> > qemu-system-i386: hw/core/qdev.c:102: qdev_set_parent_bus: Assertion >> > `dc->bus_type && object_dynamic_cast(OBJECT(bus), dc->bus_type)' >> > failed. >> > >> > dc->bus_type is "xen-sysbus" and it's the >> > `object_dynamic_cast(OBJECT(bus), dc->bus_type)` portion that fails >> > the assert. bus seems to be "main-system-bus", I think: >> > (gdb) p *bus >> > $3 = {obj = {class = 0x5636d780, free = 0x77c40db0 , >> > properties = 0x563f7180, ref = 3, parent = 0x563fe980}, parent >> > = 0x0, name = 0x563fec60 "main-system-bus", ... >> > >> > The call comes from hw/xen/xen-legacy-backend.c:706 >> > sysbus_realize_and_unref(SYS_BUS_DEVICE(xen_sysdev), &error_fatal); >> > >> > Any pointers on what needs to be fixed? >> >> Hi Jason, >> >> My understanding is that the assert() is telling you that you're plugging a >> TYPE_SYS_BUS_DEVICE into a bus that isn't derived from TYPE_SYSTEM_BUS. >> TYPE_SYS_BUS_DEVICE into a bus that isn't derived from TYPE_SYSTEM_BUS. A >> quick look Correct. Let's review the assertion: assert(dc->bus_type && object_dynamic_cast(OBJECT(bus), dc->bus_type)); Context: we're supposted to plug @dev into @bus, and @dc is @dev's DeviceClass. The assertion checks that 1. @dev plugs into a bus: dc->bus_type 2. @bus is an instance of the type of bus @dev plugs into: object_dynamic_cast(OBJECT(bus), dc->bus_type) >> at the file in question suggests that you could try changing the parent >> class of >> TYPE_XENSYSBUS from TYPE_BUS to TYPE_SYSTEM_BUS to see if that helps? > > Hi, Mark. > > Thanks, but unfortunately changing xensysbus_info .parent does not > stop the assert. But it kinda pointed me in the right direction. > > xen-sysdev overrode the bus_type which was breaking sysbus_realize. > So drop that: > > --- a/hw/xen/xen-legacy-backend.c > +++ b/hw/xen/xen-legacy-backend.c > @@ -824,7 +825,7 @@ static void xen_sysdev_class_init(ObjectClass > *klass, void *data) > DeviceClass *dc = DEVICE_CLASS(klass); > > device_class_set_props(dc, xen_sysdev_properties); > -dc->bus_type = TYPE_XENSYSBUS; > +//dc->bus_type = TYPE_XENSYSBUS; > } Uff! Let me explain how things are supposed to work. Say we have FOO bus (QOM type TYPE_FOO_BUS), with FOO devices plugging into it (abstract QOM type TYPE_FOO_DEVICE). One of them is SOME_FOO (concrete QOM type TYPE_SOME_FOO). Code ties them together like this: static const TypeInfo pci_bus_info = { .name = TYPE_PCI_BUS, .parent = TYPE_BUS, ... }; static const TypeInfo foo_device_info = { .name = TYPE_FOO_DEVICE, .parent = TYPE_DEVICE, .abstract = true, .class_init = foo_device_class_init, ... }; static void foo_device_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); dc->bus_type = TYPE_FOO_BUS; ... } static const TypeInfo some_foo_info = { .name = TYPE_SOME_FOO, .parent = TYPE_FOO_DEVICE, ... }; When you plug an instance of TYPE_SOME_FOO into a bus, the assertion checks that the bus is an instance of TYPE_FOO_BUS. Note that subtypes of TYPE_FOO_DEVICE do not mess with dc->bus_type! TYPE_XENSYSDEV does mess with it: static void xen_sysdev_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); device_class_set_props(dc, xen_sysdev_properties); dc->bus_type = TYPE_XENSYSBUS; } static const TypeInfo xensysdev_info = { .name = TYPE_XENSYSDEV, .parent= TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SysBusDevice), .class_init= xen_sysdev_class_init, }; On the one hand, xensysdev_info.parent claims TYPE_XENSYSDEV is a TYPE_SYS_BUS_DEVICE (and therefore should plug into a TYPE_SYSTEM_BUS). On the other hand, its dc->bus_type is a TYPE_XENSYSBUS, which is *not* a subtype of TYPE_SYSTEM_BUS: static const TypeInfo xensysbus_info = { .name = TYPE_XENSYSBUS, --->.parent = TYPE_BUS, .class_init = xen_sysbus_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, { } } }; This is an inconsistent mess. Are TYPE_XENSYSDEV and TYPE_XENSYSBUS related to TYPE_SYS_BUS_DEVICE and TYPE_SYSTEM_BUS? If no, then xensysbus_info.parent should not be TYPE_SYS_BUS_DEVICE, and you must not pass instances of one kind to functions expecting the other kind. If yes, how? If the former are specializations of the latter, consider making the former subtypes of the latter. Both of them. Then a TYPE_XENSYSDEV device can plug into a TYPE_XENS
Re: [PATCH v10 1/9] error: auto propagated local_err
Greg Kurz writes: > On Tue, 17 Mar 2020 18:16:17 +0300 > Vladimir Sementsov-Ogievskiy wrote: > >> Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of >> functions with an errp OUT parameter. >> >> It has three goals: >> >> 1. Fix issue with error_fatal and error_prepend/error_append_hint: user >> can't see this additional information, because exit() happens in >> error_setg earlier than information is added. [Reported by Greg Kurz] >> > > I have more of these coming and I'd really like to use ERRP_AUTO_PROPAGATE. > > It seems we have a consensus on the macro itself but this series is gated > by the conversion of the existing code base. > > What about merging this patch separately so that people can start using > it at least ? Please give me a few more days to finish the work I feel should go in before the conversion. With any luck, Vladimir can then rebase / recreate the conversion easily, and you can finally use the macro for your own work.
Re: [PATCH v8 2/8] block: consolidate blocksize properties consistency checks
Roman Kagan writes: > Several block device properties related to blocksize configuration must > be in certain relationship WRT each other: physical block must be no > smaller than logical block; min_io_size, opt_io_size, and > discard_granularity must be a multiple of a logical block. > > To ensure these requirements are met, add corresponding consistency > checks to blkconf_blocksizes, adjusting its signature to communicate > possible error to the caller. Also remove the now redundant consistency > checks from the specific devices. > > Signed-off-by: Roman Kagan > Reviewed-by: Eric Blake > Reviewed-by: Paul Durrant > --- > include/hw/block/block.h | 2 +- > hw/block/block.c | 30 +- > hw/block/fdc.c | 5 - > hw/block/nvme.c| 5 - > hw/block/swim.c| 5 - > hw/block/virtio-blk.c | 7 +-- > hw/block/xen-block.c | 6 +- > hw/ide/qdev.c | 5 - > hw/scsi/scsi-disk.c| 12 +--- > hw/usb/dev-storage.c | 5 - > tests/qemu-iotests/172.out | 2 +- > 11 files changed, 58 insertions(+), 26 deletions(-) > > diff --git a/include/hw/block/block.h b/include/hw/block/block.h > index d7246f3862..784953a237 100644 > --- a/include/hw/block/block.h > +++ b/include/hw/block/block.h > @@ -87,7 +87,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void > *buf, hwaddr size, > bool blkconf_geometry(BlockConf *conf, int *trans, >unsigned cyls_max, unsigned heads_max, unsigned > secs_max, >Error **errp); > -void blkconf_blocksizes(BlockConf *conf); > +bool blkconf_blocksizes(BlockConf *conf, Error **errp); > bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, > bool resizable, Error **errp); > > diff --git a/hw/block/block.c b/hw/block/block.c > index bf56c7612b..b22207c921 100644 > --- a/hw/block/block.c > +++ b/hw/block/block.c > @@ -61,7 +61,7 @@ bool blk_check_size_and_read_all(BlockBackend *blk, void > *buf, hwaddr size, > return true; > } > > -void blkconf_blocksizes(BlockConf *conf) > +bool blkconf_blocksizes(BlockConf *conf, Error **errp) > { > BlockBackend *blk = conf->blk; > BlockSizes blocksizes; > @@ -83,6 +83,34 @@ void blkconf_blocksizes(BlockConf *conf) > conf->logical_block_size = BDRV_SECTOR_SIZE; > } > } > + > +if (conf->logical_block_size > conf->physical_block_size) { > +error_setg(errp, > + "logical_block_size > physical_block_size not supported"); > +return false; > +} Pardon me if this has been answered already for prior revisions: do we really support physical block sizes that are not a multiple of the logical block size? > + > +if (!QEMU_IS_ALIGNED(conf->min_io_size, conf->logical_block_size)) { > +error_setg(errp, > + "min_io_size must be a multiple of logical_block_size"); > +return false; > +} > + > +if (!QEMU_IS_ALIGNED(conf->opt_io_size, conf->logical_block_size)) { > +error_setg(errp, > + "opt_io_size must be a multiple of logical_block_size"); > +return false; > +} > + > +if (conf->discard_granularity != -1 && > +!QEMU_IS_ALIGNED(conf->discard_granularity, > + conf->logical_block_size)) { > +error_setg(errp, "discard_granularity must be " > + "a multiple of logical_block_size"); > +return false; > +} > + > +return true; > } > > bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, > diff --git a/hw/block/fdc.c b/hw/block/fdc.c > index c5fb9d6ece..8eda572ef4 100644 > --- a/hw/block/fdc.c > +++ b/hw/block/fdc.c > @@ -554,7 +554,10 @@ static void floppy_drive_realize(DeviceState *qdev, > Error **errp) > read_only = !blk_bs(dev->conf.blk) || > blk_is_read_only(dev->conf.blk); > } > > -blkconf_blocksizes(&dev->conf); > +if (!blkconf_blocksizes(&dev->conf, errp)) { > +return; > +} > + > if (dev->conf.logical_block_size != 512 || > dev->conf.physical_block_size != 512) > { > diff --git a/hw/block/nvme.c b/hw/block/nvme.c > index 2f3100e56c..672650e162 100644 > --- a/hw/block/nvme.c > +++ b/hw/block/nvme.c > @@ -1390,7 +1390,10 @@ static void nvme_realize(PCIDevice *pci_dev, Error > **errp) > host_memory_backend_set_mapped(n->pmrdev, true); > } > > -blkconf_blocksizes(&n->conf); > +if (!blkconf_blocksizes(&n->conf, errp)) { > +return; > +} > + > if (!blkconf_apply_backend_options(&n->conf, > blk_is_read_only(n->conf.blk), > false, errp)) { > return; > diff --git a/hw/block/swim.c b/hw/block/swim.c > index 8f124782f4..74f56e8f46 100644 > --- a/hw/block/swim.c > +++ b/hw/block/swim.c > @@ -189,7 +189,10 @@ static void swim_drive_