Zhao Liu <zhao1....@linux.intel.com> writes: > Hi Philippe, > > On Wed, Jan 31, 2024 at 05:48:24PM +0100, Philippe Mathieu-Daudé wrote: >> Date: Wed, 31 Jan 2024 17:48:24 +0100 >> From: Philippe Mathieu-Daudé <phi...@linaro.org> >> Subject: Re: [PATCH] hw/intc: Handle the error of >> IOAPICCommonClass.realize() >> >> Hi Zhao, >> >> On 31/1/24 15:29, Zhao Liu wrote: >> > From: Zhao Liu <zhao1....@intel.com> >> > >> > IOAPICCommonClass implements its own private realize(), and this private >> > realize() allows error. >> > >> > Therefore, return directly if IOAPICCommonClass.realize() meets error. >> > >> > Signed-off-by: Zhao Liu <zhao1....@intel.com> >> > --- >> > hw/intc/ioapic_common.c | 3 +++ >> > 1 file changed, 3 insertions(+) >> > >> > diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c >> > index cb9bf6214608..3772863377c2 100644 >> > --- a/hw/intc/ioapic_common.c >> > +++ b/hw/intc/ioapic_common.c >> > @@ -162,6 +162,9 @@ static void ioapic_common_realize(DeviceState *dev, >> > Error **errp) >> > info = IOAPIC_COMMON_GET_CLASS(s); >> > info->realize(dev, errp); >> > + if (*errp) { >> > + return; >> > + }
This is wrong, although it'll work in practice. It's wrong, because dereferencing @errp requires ERRP_GUARD(). qapi/error.h: * = Why, when and how to use ERRP_GUARD() = * * Without ERRP_GUARD(), use of the @errp parameter is restricted: * - It must not be dereferenced, because it may be null. * - It should not be passed to error_prepend() or * error_append_hint(), because that doesn't work with &error_fatal. * ERRP_GUARD() lifts these restrictions. * * To use ERRP_GUARD(), add it right at the beginning of the function. * @errp can then be used without worrying about the argument being * NULL or &error_fatal. * * Using it when it's not needed is safe, but please avoid cluttering * the source with useless code. It'll work anyway, because the caller never passes null. Obvious fix: diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c index cb9bf62146..280404cba5 100644 --- a/hw/intc/ioapic_common.c +++ b/hw/intc/ioapic_common.c @@ -152,6 +152,7 @@ static int ioapic_dispatch_post_load(void *opaque, int version_id) static void ioapic_common_realize(DeviceState *dev, Error **errp) { + ERRP_GUARD(); IOAPICCommonState *s = IOAPIC_COMMON(dev); IOAPICCommonClass *info; >> Could be clearer to deviate from DeviceRealize and let the >> handler return a boolean: >> >> -- >8 -- >> diff --git a/hw/intc/ioapic_internal.h b/hw/intc/ioapic_internal.h >> index 37b8565539..9664bb3e00 100644 >> --- a/hw/intc/ioapic_internal.h >> +++ b/hw/intc/ioapic_internal.h >> @@ -92,3 +92,3 @@ struct IOAPICCommonClass { >> >> - DeviceRealize realize; >> + bool (*realize)(DeviceState *dev, Error **errp); qapi.error.h advises: * - Whenever practical, also return a value that indicates success / * failure. This can make the error checking more concise, and can * avoid useless error object creation and destruction. Note that * we still have many functions returning void. We recommend * • bool-valued functions return true on success / false on failure, * • pointer-valued functions return non-null / null pointer, and * • integer-valued functions return non-negative / negative. The patch then becomes info = IOAPIC_COMMON_GET_CLASS(s); - info->realize(dev, errp); + if (!info->realize(dev, errp) { + return; + } DeviceClass and BusClass callbacks realize, unrealize ignore this advice: they return void. Why? Following the advice makes calls easier to read, but the callees have to do a tiny bit of extra work: return something. Good trade when we have at least as many callers as callees. But these callbacks have many more callees: many devices implement them, but only a few places call. Changing them to return something looked like more trouble than it's worth, so we didn't. > What about I change the name of this interface? > > Maybe ioapic_realize(), to distinguish it from DeviceClass.realize(). I wouldn't bother. >> DeviceUnrealize unrealize; > > Additionally, if I change the pattern of realize(), should I also avoid > the DeviceUnrealize macro for symmetry's sake and just declare a similar > function pointer as you said? > > Further, do you think it's necessary to introduce InternalRealize and > InternalUnrealize macros for qdev You mean typedefs? > for qdev to wrap these special realize/unrealize > to differentiate them from normal DeviceRealize/DeviceUnrealize? > > Because I found that this pattern of realize() (i.e. registering the > realize() of the child class in the parent class instead of DeviceClass, > and then calling the registered realize() in parent realize()) is also > widely used in many cases: > > * xen_block_realize() > * virtser_port_device_realize() > * x86_iommu_realize() > * virtio_input_device_realize() > * apic_common_realize() > * pc_dimm_realize() > * virtio_device_realize() > ... Yes. When a subtype overrides a supertype's method, it often makes sense to have the subtype's method call the supertype's method. > I'm not quite sure if this is a generic way to use it, although it looks > like it could easily be confused with DeviceClass.realize(). Did I answer your question? I'm not sure :) >> diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c >> index 409d0c8c76..96747ef2b8 100644 >> --- a/hw/i386/kvm/ioapic.c >> +++ b/hw/i386/kvm/ioapic.c >> @@ -121,3 +121,3 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, >> int level) >> >> -static void kvm_ioapic_realize(DeviceState *dev, Error **errp) >> +static bool kvm_ioapic_realize(DeviceState *dev, Error **errp) >> { >> @@ -133,2 +133,4 @@ static void kvm_ioapic_realize(DeviceState *dev, Error >> **errp) >> qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS); >> + >> + return true; >> } >> diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c >> index cb9bf62146..beab65be04 100644 >> --- a/hw/intc/ioapic_common.c >> +++ b/hw/intc/ioapic_common.c >> @@ -163,3 +163,5 @@ static void ioapic_common_realize(DeviceState *dev, >> Error **errp) >> info = IOAPIC_COMMON_GET_CLASS(s); >> - info->realize(dev, errp); >> + if (!info->realize(dev, errp)) { >> + return; >> + } >> >> --- >> >> What do you think? > > I'm OK with the change here, but not sure if the return of private > realize() should be changed elsewhere as well. I think I'd add the missing ERRP_GUARD() and call it a day.