[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: [PATCH 0/9] Virtio cleanups
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] Re: [PATCH 0/9] Virtio cleanups |
Date: |
Thu, 18 Mar 2010 15:47:29 +0200 |
User-agent: |
Mutt/1.5.19 (2009-01-05) |
On Thu, Mar 18, 2010 at 02:43:04PM +0100, Juan Quintela wrote:
> "Michael S. Tsirkin" <address@hidden> wrote:
> > On Thu, Mar 18, 2010 at 12:53:06PM +0100, Juan Quintela wrote:
> >>
> >> You cant. Your trick of creating of mallocking in the caller the struct
> >> don't work for qdev. qdev is the one that creates it. Again, any other
> >> implementation is going to be more complex for no gain.
> >
> > I can prove that allocation in the caller is better: just looking at
> > that code made it obvious that no one frees the structure now. That's
> > right, the pretty wrappers hide the fact that common_init leaks memory,
> > my refactoring made this obvious.
>
> Fully disagree. A bug is a bug independently of how you find it.
>
> >> >> For me is a clear case of
> >> >> coherence. Virtio* can live with container_of() instead of DO_UPCAST()
> >> >> because they are not exposed (directly) through qdev. Then mark it as
> >> >> different that everything else, indeed if it don't bring us anything,
> >> >> just to confuse new users. This is one of the features that I hate
> >> >> more, searching for how to use a qemu api because from only the
> >> >> prototypes it is not clear, and just pick an example, and that one uses
> >> >> it in a non-conventional way.
> >> >>
> >> >> Later, Juan.
> >> >
> >> > I think we should just fix qdev. All we need to do is replace
> >> >
> >> > .qdev.size = sizeof(VirtIOPCIProxy),
> >> >
> >> > with
> >> >
> >> > DEFINE_QDEV(VirtIOPCIProxy, qdev),
> >>
> >> No, because you don't necesarily know that at that point.
> >> To add insult to injury, now you can free a device in common code.
> >>
> >> qemu_free() needs to take the beginning of the malloced space.
> >>
> >> In resume:
> >>
> >> type safety:
> >> - DO_UPCAST() && container_of -> identical (DO_UPCAST uses container_of)
> >> - wins of using container_of: zero (hypotetical gains when in the future
> >> we could use it for .... are that, hypotetical)
> >> - wins of using DO_UPCAST(): we use the same structure that qdev/pci,
> >> not yet a different idiom.
> >
> > It's best not to do any casts. this is what my patch does:
> > It removes an upcast during initialization.
>
> #ifdef __GNUC__
> #define DO_UPCAST(type, field, dev) ( __extension__ ( { \
> char __attribute__((unused)) offset_must_be_zero[ \
> -offsetof(type, field)]; \
> container_of(dev, type, field);}))
> #else
> #define DO_UPCAST(type, field, dev) container_of(dev, type, field)
> #endif
>
>
> DO_UPCAST don't do any cast. As already say, from type safety
> perspective, there are no differences. DO_UPCAST is _yours_ patch &
> making sure that field is the 1st one.
Yes but my patch does not do any casting at all, not even
container_of. That is better.
> >> You/me can discuss all day long about point one. really they have
> >> exactly the same safety.
> >
> > The issue is that as long as our design relies on specific
> > layout in memory, people will abuse this assumption,
> > with straight casts or punning through void *.
> > Not relying on struct layout is a simple rule that
> > makes you think *what kind of object are you passing here*.
>
> void * leaves you abuse whatever you want.
Right, but at least, we can try to be consistent about which type
you cast it to.
> >>
> >> - For you, it is more important to be "future" proof if anybody, anywhere
> >> finds a way where it could be used in a different position.
> >>
> >> - For me, it is easier to understand having the same idiom that
> >> qdev/pci. One less idiom in qemu for doing the same -> better.
> >> Furthermore, it fits clearly with my model of sub/super class.
> >>
> >
> > As I said, we'll remove the assumption in qdev too, eventually.
>
> I doubt it. It is a "feature" :)
>
> > And I don't think pci has this problem, except where it uses qdev :)
>
> /* Unlink device from bus and free the structure. */
> void qdev_free(DeviceState *dev)
> {
> BusState *bus;
>
> if (dev->state == DEV_STATE_INITIALIZED) {
> while (dev->num_child_bus) {
> bus = QLIST_FIRST(&dev->child_bus);
> qbus_free(bus);
> }
> if (dev->info->vmsd)
> vmstate_unregister(dev->info->vmsd, dev);
> if (dev->info->exit)
> dev->info->exit(dev);
> if (dev->opts)
> qemu_opts_del(dev->opts);
> }
> qemu_unregister_reset(qdev_reset, dev);
> QLIST_REMOVE(dev, sibling);
> qemu_free(dev);
> }
>
> How are you going to make this work with your design? if your
> suggestion is to use an offset inside qdev, that is the same that
> forcing it in position zero, just made it uglier.
If it's the same, can we just do it and close the issue :) ?
> >> Obviously your/my priorities here are different. None of the solutions
> >> are better. Mine is more consistent, that is why I preffer it. But
> >> clearly, this discussion is not going anywhere :(
> >>
> >> If you have any other reason that I haven't put here _why_ you want to
> >> use container_of() instead of DO_UPCAST(), I am open to suggestions.
> >
> > Ability to put qdev and vdev in the same structure, without
> > resolving to complex tricks like two structures pointing to each other.
> >
> > Also look virtio-pci: so VirtIOPCIProxy must
> > have PCIDevice as first member. Why? Because down there
> > PCIDevice has qdev inside it, and qdev must be first member.
> See my example of qdev_free(). That is the biggest example when you
> want it to be the 1st elemement. But there are other with that assumptions.
>
> > This is leaking implementation in a very inelegant way.
>
> Your view varies. For me, it is fixing a problem in a very elegant way :)
So you want to use a structure, instead of just embedding it
you need to carefully look at implementation to figure out
whether there are offset assumptions ... where is the elegance?
> >> If the argument is to continue to discuss between the two
> >> alternatives that I have exposesd, then I think that we have to agree
> >> to disagree.
> >>
> >> Later, Juan.
> >
> > I was thinking about removing the limitation of zero offset
> > for a while now, and I saw the "no clean way to do this in C"
> > as a challenge, which made me go ahead and handle this finally:
> > what I posted, I think, shows a pretty clean way to do this.
>
> No. You have to do the allocation outside for no good reason, it should
> be done in generic code.
Very good reasons:
- lifetime becomes clearer
- it is clear that memory is zero initialized
> The same for deallocation. Your suggestion
> makes that each device has to handle lifecycle, what is wrong.
It is trivially simple to understand. So why is it wrong?
> > I guess before we agree to disagree I'd like to understand the reasons
> > that you object. Do you generally object to uses of container_of
> > as opposed to UP_CAST, because you find cast to non-first member
> > confusing?
>
> No. I like container_of() when it is used for good reason. Notice that
> DO_UPCAST() uses container_of + other thigs to be sure that it is the
> 1st member.
>
> What I object is:
> - I have a problem that is easily implementable with OOP
> - I can do a simple OOP implementation
>
> I like to stop here. Your point is:
> - If I made it more complex, I can simulate multiple inheritance, we
> still don't need it, but "perhaps" we could need it in the future.
My patch removes lines of code. It is actually simpler than
what we had: no casts, no assumptions.
> (Yes, that is paraphrasing yourself in a funny way, pardon for the
> license )
>
> about vdev & pcidev. I still think that a lot of things would be easier
> if a vdev device is a pci_device _always_, not just some times. And
> VirtIOPCIProxy shows it.
>
> Later, Juan.
Yes. But we don't always have pci. So the world we model does
not match single inheritance: a cow is both a mammal and a quadruped,
even if java programmers prefer it to be a mammal first of all :)
--
MST
- [Qemu-devel] Re: [PATCH 8/9] virtio-blk: change rq type to VirtIOBlockReq, (continued)
- [Qemu-devel] [PATCH 9/9] virtio-blk: use QLIST for the list of requests, Juan Quintela, 2010/03/16
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Juan Quintela, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Juan Quintela, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Juan Quintela, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Juan Quintela, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups,
Michael S. Tsirkin <=
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Juan Quintela, 2010/03/18
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/18
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Jamie Lokier, 2010/03/18
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/21
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Jamie Lokier, 2010/03/21
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Michael S. Tsirkin, 2010/03/21
- [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Juan Quintela, 2010/03/21
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Anthony Liguori, 2010/03/21
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Paul Brook, 2010/03/22
- Re: [Qemu-devel] Re: [PATCH 0/9] Virtio cleanups, Anthony Liguori, 2010/03/22