qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qapi: Smooth visitor error checking in generated code

Use visitor functions' return values to check for failure. Eliminate
error_propagate() that are now unnecessary. Delete @err that are now
unused.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-41-armbru@redhat.com>

+55 -84
+23 -37
docs/devel/qapi-code-gen.txt
··· 1420 1420 1421 1421 bool visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp) 1422 1422 { 1423 - Error *err = NULL; 1424 - 1425 1423 if (!visit_type_int(v, "integer", &obj->integer, errp)) { 1426 1424 return false; 1427 1425 } ··· 1430 1428 return false; 1431 1429 } 1432 1430 } 1433 - error_propagate(errp, err); 1434 - return !err; 1431 + return true; 1435 1432 } 1436 1433 1437 1434 bool visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp) 1438 1435 { 1439 - Error *err = NULL; 1436 + bool ok = false; 1440 1437 1441 1438 if (!visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), errp)) { 1442 1439 return false; ··· 1446 1443 assert(visit_is_dealloc(v)); 1447 1444 goto out_obj; 1448 1445 } 1449 - visit_type_UserDefOne_members(v, *obj, &err); 1450 - if (err) { 1446 + if (!visit_type_UserDefOne_members(v, *obj, errp)) { 1451 1447 goto out_obj; 1452 1448 } 1453 - visit_check_struct(v, &err); 1449 + ok = visit_check_struct(v, errp); 1454 1450 out_obj: 1455 1451 visit_end_struct(v, (void **)obj); 1456 - if (err && visit_is_input(v)) { 1452 + if (!ok && visit_is_input(v)) { 1457 1453 qapi_free_UserDefOne(*obj); 1458 1454 *obj = NULL; 1459 1455 } 1460 - error_propagate(errp, err); 1461 - return !err; 1456 + return ok; 1462 1457 } 1463 1458 1464 1459 bool visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp) 1465 1460 { 1466 - Error *err = NULL; 1461 + bool ok = false; 1467 1462 UserDefOneList *tail; 1468 1463 size_t size = sizeof(**obj); 1469 1464 ··· 1473 1468 1474 1469 for (tail = *obj; tail; 1475 1470 tail = (UserDefOneList *)visit_next_list(v, (GenericList *)tail, size)) { 1476 - visit_type_UserDefOne(v, NULL, &tail->value, &err); 1477 - if (err) { 1478 - break; 1471 + if (!visit_type_UserDefOne(v, NULL, &tail->value, errp)) { 1472 + goto out_obj; 1479 1473 } 1480 1474 } 1481 1475 1482 - if (!err) { 1483 - visit_check_list(v, &err); 1484 - } 1476 + ok = visit_check_list(v, errp); 1477 + out_obj: 1485 1478 visit_end_list(v, (void **)obj); 1486 - if (err && visit_is_input(v)) { 1479 + if (!ok && visit_is_input(v)) { 1487 1480 qapi_free_UserDefOneList(*obj); 1488 1481 *obj = NULL; 1489 1482 } 1490 - error_propagate(errp, err); 1491 - return !err; 1483 + return ok; 1492 1484 } 1493 1485 1494 1486 bool visit_type_q_obj_my_command_arg_members(Visitor *v, q_obj_my_command_arg *obj, Error **errp) 1495 1487 { 1496 - Error *err = NULL; 1497 - 1498 1488 if (!visit_type_UserDefOneList(v, "arg1", &obj->arg1, errp)) { 1499 1489 return false; 1500 1490 } 1501 - error_propagate(errp, err); 1502 - return !err; 1491 + return true; 1503 1492 } 1504 1493 1505 1494 [Uninteresting stuff omitted...] ··· 1554 1543 1555 1544 static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp) 1556 1545 { 1557 - Error *err = NULL; 1558 1546 Visitor *v; 1559 1547 1560 1548 v = qobject_output_visitor_new(ret_out); 1561 - visit_type_UserDefOne(v, "unused", &ret_in, &err); 1562 - if (!err) { 1549 + if (visit_type_UserDefOne(v, "unused", &ret_in, errp)) { 1563 1550 visit_complete(v, ret_out); 1564 1551 } 1565 - error_propagate(errp, err); 1566 1552 visit_free(v); 1567 1553 v = qapi_dealloc_visitor_new(); 1568 1554 visit_type_UserDefOne(v, "unused", &ret_in, NULL); ··· 1572 1558 void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp) 1573 1559 { 1574 1560 Error *err = NULL; 1561 + bool ok = false; 1575 1562 Visitor *v; 1576 1563 UserDefOne *retval; 1577 1564 q_obj_my_command_arg arg = {0}; 1578 1565 1579 1566 v = qobject_input_visitor_new(QOBJECT(args)); 1580 - visit_start_struct(v, NULL, NULL, 0, &err); 1581 - if (err) { 1567 + if (!visit_start_struct(v, NULL, NULL, 0, errp)) { 1582 1568 goto out; 1583 1569 } 1584 - visit_type_q_obj_my_command_arg_members(v, &arg, &err); 1585 - if (!err) { 1586 - visit_check_struct(v, &err); 1570 + if (visit_type_q_obj_my_command_arg_members(v, &arg, errp)) { 1571 + ok = visit_check_struct(v, errp); 1587 1572 } 1588 1573 visit_end_struct(v, NULL); 1589 - if (err) { 1574 + if (!ok) { 1590 1575 goto out; 1591 1576 } 1592 1577 1593 1578 retval = qmp_my_command(arg.arg1, &err); 1579 + error_propagate(errp, err); 1594 1580 if (err) { 1595 1581 goto out; 1596 1582 } 1597 1583 1598 - qmp_marshal_output_UserDefOne(retval, ret, &err); 1584 + qmp_marshal_output_UserDefOne(retval, ret, errp); 1599 1585 1600 1586 out: 1601 - error_propagate(errp, err); 1602 1587 visit_free(v); 1603 1588 v = qapi_dealloc_visitor_new(); 1604 1589 visit_start_struct(v, NULL, NULL, 0, NULL); ··· 1606 1591 visit_end_struct(v, NULL); 1607 1592 visit_free(v); 1608 1593 } 1594 + 1609 1595 [Uninteresting stuff omitted...] 1610 1596 $ cat qapi-generated/example-qapi-init-commands.h 1611 1597 [Uninteresting stuff omitted...]
+9 -13
scripts/qapi/commands.py
··· 47 47 ret = mcgen(''' 48 48 49 49 %(lhs)sqmp_%(c_name)s(%(args)s&err); 50 + error_propagate(errp, err); 50 51 ''', 51 52 c_name=c_name(name), args=argstr, lhs=lhs) 52 53 if ret_type: ··· 55 56 goto out; 56 57 } 57 58 58 - qmp_marshal_output_%(c_name)s(retval, ret, &err); 59 + qmp_marshal_output_%(c_name)s(retval, ret, errp); 59 60 ''', 60 61 c_name=ret_type.c_name()) 61 62 return ret ··· 66 67 67 68 static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp) 68 69 { 69 - Error *err = NULL; 70 70 Visitor *v; 71 71 72 72 v = qobject_output_visitor_new(ret_out); 73 - visit_type_%(c_name)s(v, "unused", &ret_in, &err); 74 - if (!err) { 73 + if (visit_type_%(c_name)s(v, "unused", &ret_in, errp)) { 75 74 visit_complete(v, ret_out); 76 75 } 77 - error_propagate(errp, err); 78 76 visit_free(v); 79 77 v = qapi_dealloc_visitor_new(); 80 78 visit_type_%(c_name)s(v, "unused", &ret_in, NULL); ··· 104 102 %(proto)s 105 103 { 106 104 Error *err = NULL; 105 + bool ok = false; 107 106 Visitor *v; 108 107 ''', 109 108 proto=build_marshal_proto(name)) ··· 123 122 ret += mcgen(''' 124 123 125 124 v = qobject_input_visitor_new(QOBJECT(args)); 126 - visit_start_struct(v, NULL, NULL, 0, &err); 127 - if (err) { 125 + if (!visit_start_struct(v, NULL, NULL, 0, errp)) { 128 126 goto out; 129 127 } 130 128 ''') 131 129 132 130 if have_args: 133 131 ret += mcgen(''' 134 - visit_type_%(c_arg_type)s_members(v, &arg, &err); 135 - if (!err) { 136 - visit_check_struct(v, &err); 132 + if (visit_type_%(c_arg_type)s_members(v, &arg, errp)) { 133 + ok = visit_check_struct(v, errp); 137 134 } 138 135 ''', 139 136 c_arg_type=arg_type.c_name()) 140 137 else: 141 138 ret += mcgen(''' 142 - visit_check_struct(v, &err); 139 + ok = visit_check_struct(v, errp); 143 140 ''') 144 141 145 142 ret += mcgen(''' 146 143 visit_end_struct(v, NULL); 147 - if (err) { 144 + if (!ok) { 148 145 goto out; 149 146 } 150 147 ''') ··· 154 151 ret += mcgen(''' 155 152 156 153 out: 157 - error_propagate(errp, err); 158 154 visit_free(v); 159 155 ''') 160 156
+23 -34
scripts/qapi/visit.py
··· 41 41 42 42 bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp) 43 43 { 44 - Error *err = NULL; 45 - 46 44 ''', 47 45 c_name=c_name(name)) 48 46 ··· 97 95 else: 98 96 ret += mcgen(''' 99 97 case %(case)s: 100 - visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err); 101 - break; 98 + return visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, errp); 102 99 ''', 103 100 case=case_str, 104 101 c_type=var.type.c_name(), c_name=c_name(var.name)) ··· 111 108 ''') 112 109 113 110 ret += mcgen(''' 114 - error_propagate(errp, err); 115 - return !err; 111 + return true; 116 112 } 117 113 ''') 118 114 return ret ··· 123 119 124 120 bool visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp) 125 121 { 126 - Error *err = NULL; 122 + bool ok = false; 127 123 %(c_name)s *tail; 128 124 size_t size = sizeof(**obj); 129 125 ··· 133 129 134 130 for (tail = *obj; tail; 135 131 tail = (%(c_name)s *)visit_next_list(v, (GenericList *)tail, size)) { 136 - visit_type_%(c_elt_type)s(v, NULL, &tail->value, &err); 137 - if (err) { 138 - break; 132 + if (!visit_type_%(c_elt_type)s(v, NULL, &tail->value, errp)) { 133 + goto out_obj; 139 134 } 140 135 } 141 136 142 - if (!err) { 143 - visit_check_list(v, &err); 144 - } 137 + ok = visit_check_list(v, errp); 138 + out_obj: 145 139 visit_end_list(v, (void **)obj); 146 - if (err && visit_is_input(v)) { 140 + if (!ok && visit_is_input(v)) { 147 141 qapi_free_%(c_name)s(*obj); 148 142 *obj = NULL; 149 143 } 150 - error_propagate(errp, err); 151 - return !err; 144 + return ok; 152 145 } 153 146 ''', 154 147 c_name=c_name(name), c_elt_type=element_type.c_name()) ··· 173 166 174 167 bool visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp) 175 168 { 176 - Error *err = NULL; 169 + bool ok = false; 177 170 178 171 if (!visit_start_alternate(v, name, (GenericAlternate **)obj, 179 172 sizeof(**obj), errp)) { ··· 182 175 if (!*obj) { 183 176 /* incomplete */ 184 177 assert(visit_is_dealloc(v)); 178 + ok = true; 185 179 goto out_obj; 186 180 } 187 181 switch ((*obj)->type) { ··· 196 190 case=var.type.alternate_qtype()) 197 191 if isinstance(var.type, QAPISchemaObjectType): 198 192 ret += mcgen(''' 199 - visit_start_struct(v, name, NULL, 0, &err); 200 - if (err) { 193 + if (!visit_start_struct(v, name, NULL, 0, errp)) { 201 194 break; 202 195 } 203 - visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, &err); 204 - if (!err) { 205 - visit_check_struct(v, &err); 196 + if (visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, errp)) { 197 + ok = visit_check_struct(v, errp); 206 198 } 207 199 visit_end_struct(v, NULL); 208 200 ''', ··· 210 202 c_name=c_name(var.name)) 211 203 else: 212 204 ret += mcgen(''' 213 - visit_type_%(c_type)s(v, name, &(*obj)->u.%(c_name)s, &err); 205 + ok = visit_type_%(c_type)s(v, name, &(*obj)->u.%(c_name)s, errp); 214 206 ''', 215 207 c_type=var.type.c_name(), 216 208 c_name=c_name(var.name)) ··· 224 216 abort(); 225 217 default: 226 218 assert(visit_is_input(v)); 227 - error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", 219 + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", 228 220 "%(name)s"); 229 221 /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */ 230 222 g_free(*obj); ··· 232 224 } 233 225 out_obj: 234 226 visit_end_alternate(v, (void **)obj); 235 - if (err && visit_is_input(v)) { 227 + if (!ok && visit_is_input(v)) { 236 228 qapi_free_%(c_name)s(*obj); 237 229 *obj = NULL; 238 230 } 239 - error_propagate(errp, err); 240 - return !err; 231 + return ok; 241 232 } 242 233 ''', 243 234 name=name, c_name=c_name(name)) ··· 250 241 251 242 bool visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp) 252 243 { 253 - Error *err = NULL; 244 + bool ok = false; 254 245 255 246 if (!visit_start_struct(v, name, (void **)obj, sizeof(%(c_name)s), errp)) { 256 247 return false; ··· 260 251 assert(visit_is_dealloc(v)); 261 252 goto out_obj; 262 253 } 263 - visit_type_%(c_name)s_members(v, *obj, &err); 264 - if (err) { 254 + if (!visit_type_%(c_name)s_members(v, *obj, errp)) { 265 255 goto out_obj; 266 256 } 267 - visit_check_struct(v, &err); 257 + ok = visit_check_struct(v, errp); 268 258 out_obj: 269 259 visit_end_struct(v, (void **)obj); 270 - if (err && visit_is_input(v)) { 260 + if (!ok && visit_is_input(v)) { 271 261 qapi_free_%(c_name)s(*obj); 272 262 *obj = NULL; 273 263 } 274 - error_propagate(errp, err); 275 - return !err; 264 + return ok; 276 265 } 277 266 ''', 278 267 c_name=c_name(name))