dataplane: do not free VirtQueueElement in vring_push()
VirtQueueElement is allocated in vring_pop() so it seems to make sense that vring_push() should free it. Alas, virtio-blk frees VirtQueueElement itself in virtio_blk_free_request(). This patch solves a double-free assertion in glib's g_slice_free(). Rename vring_free_element() to vring_unmap_element() since it no longer frees the VirtQueueElement. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Tested-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
		
							parent
							
								
									0a21ea3289
								
							
						
					
					
						commit
						abd764250f
					
				| 
						 | 
					@ -272,7 +272,7 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem,
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void vring_free_element(VirtQueueElement *elem)
 | 
					static void vring_unmap_element(VirtQueueElement *elem)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -287,8 +287,6 @@ void vring_free_element(VirtQueueElement *elem)
 | 
				
			||||||
    for (i = 0; i < elem->in_num; i++) {
 | 
					    for (i = 0; i < elem->in_num; i++) {
 | 
				
			||||||
        vring_unmap(elem->in_sg[i].iov_base, true);
 | 
					        vring_unmap(elem->in_sg[i].iov_base, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_slice_free(VirtQueueElement, elem);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This looks in the virtqueue and for the first available buffer, and converts
 | 
					/* This looks in the virtqueue and for the first available buffer, and converts
 | 
				
			||||||
| 
						 | 
					@ -402,7 +400,8 @@ out:
 | 
				
			||||||
        vring->broken = true;
 | 
					        vring->broken = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (elem) {
 | 
					    if (elem) {
 | 
				
			||||||
        vring_free_element(elem);
 | 
					        vring_unmap_element(elem);
 | 
				
			||||||
 | 
					        g_slice_free(VirtQueueElement, elem);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    *p_elem = NULL;
 | 
					    *p_elem = NULL;
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
| 
						 | 
					@ -418,7 +417,7 @@ void vring_push(Vring *vring, VirtQueueElement *elem, int len)
 | 
				
			||||||
    unsigned int head = elem->index;
 | 
					    unsigned int head = elem->index;
 | 
				
			||||||
    uint16_t new;
 | 
					    uint16_t new;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vring_free_element(elem);
 | 
					    vring_unmap_element(elem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Don't touch vring if a fatal error occurred */
 | 
					    /* Don't touch vring if a fatal error occurred */
 | 
				
			||||||
    if (vring->broken) {
 | 
					    if (vring->broken) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,5 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
 | 
				
			||||||
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
 | 
					bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
 | 
				
			||||||
int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement **elem);
 | 
					int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement **elem);
 | 
				
			||||||
void vring_push(Vring *vring, VirtQueueElement *elem, int len);
 | 
					void vring_push(Vring *vring, VirtQueueElement *elem, int len);
 | 
				
			||||||
void vring_free_element(VirtQueueElement *elem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* VRING_H */
 | 
					#endif /* VRING_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue