"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. 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. DO_UPCAST() prevent you for having that error. 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.