On Wed, Dec 02, 2009 at 08:03:22PM +0100, Juan Quintela wrote: > "Michael S. Tsirkin" <m...@redhat.com> wrote: > > > I don't understand. > > container_of is just more generic than DO_UPCAST. > > So why *ever* use DO_UPCAST? Let's get rid of it. > > functions that use a PCIDevice and you pass FooState "require" that > PCIDevice to be the 1st element in the struct.
If these used container_of consistently, maybe we won't get this limitation. > > Notice that it is "required", not "would be nice" or similar. If that > is not the way, things dont' work. > > In this particular case, it is also > required that VirtIODevice to be the 1st element: > > VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, > size_t config_size, size_t struct_size) > { > VirtIODevice *vdev; > > vdev = qemu_mallocz(struct_size); > > vdev->device_id = device_id; > vdev->status = 0; > vdev->isr = 0; > vdev->queue_sel = 0; > vdev->config_vector = VIRTIO_NO_VECTOR; > vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX); > > vdev->name = name; > vdev->config_len = config_size; > if (vdev->config_len) > vdev->config = qemu_mallocz(config_size); > else > vdev->config = NULL; > > return vdev; > } > > See how you create a device of size struct_size, but then you access it > with vdev. If vdev is _not_ the 1st element of the struct, you have got > corruption. A cleaner solution IMO would be to have callers allocate the memory and pass VirtIODevice * to virtio_common_init. > DO_UPCAST() prevent you for having that error. If we want to assert specific structure layout, this should be a compile-time check. There's no reason to do this check every time at a random place where DO_UPCAST is called. > container_of() would have leave you go around, and have a memory > corruption not easy to fix. > > DO_UPCAST() macro was created just to avoid this kind of errors. > > Later, Juan.