> -----Original Message----- > From: Maxime Coquelin <maxime.coque...@redhat.com> > Sent: Friday, June 18, 2021 10:04 PM > To: dev@dpdk.org; david.march...@redhat.com; Xia, Chenbo > <chenbo....@intel.com> > Cc: Maxime Coquelin <maxime.coque...@redhat.com> > Subject: [PATCH v6 5/7] vhost: improve NUMA reallocation > > This patch improves the numa_realloc() function by making use > of rte_realloc_socket(), which takes care of the memory copy > and freeing of the old data. > > Suggested-by: David Marchand <david.march...@redhat.com> > Signed-off-by: Maxime Coquelin <maxime.coque...@redhat.com> > --- > lib/vhost/vhost_user.c | 186 ++++++++++++++++++----------------------- > 1 file changed, 81 insertions(+), 105 deletions(-) > > diff --git a/lib/vhost/vhost_user.c b/lib/vhost/vhost_user.c > index 51b96a0716..d6ec4000c3 100644 > --- a/lib/vhost/vhost_user.c > +++ b/lib/vhost/vhost_user.c > @@ -480,16 +480,17 @@ vhost_user_set_vring_num(struct virtio_net **pdev, > static struct virtio_net* > numa_realloc(struct virtio_net *dev, int index) > { > - int oldnode, newnode; > + int node, dev_node; > struct virtio_net *old_dev; > - struct vhost_virtqueue *old_vq, *vq; > - struct vring_used_elem *new_shadow_used_split; > - struct vring_used_elem_packed *new_shadow_used_packed; > - struct batch_copy_elem *new_batch_copy_elems; > + struct vhost_virtqueue *vq; > + struct batch_copy_elem *bce; > + struct guest_page *gp; > + struct rte_vhost_memory *mem; > + size_t mem_size; > int ret; > > old_dev = dev; > - vq = old_vq = dev->virtqueue[index]; > + vq = dev->virtqueue[index]; > > /* > * If VQ is ready, it is too late to reallocate, it certainly already > @@ -498,128 +499,103 @@ numa_realloc(struct virtio_net *dev, int index) > if (vq->ready) > return dev; > > - ret = get_mempolicy(&newnode, NULL, 0, old_vq->desc, > - MPOL_F_NODE | MPOL_F_ADDR); > - > - /* check if we need to reallocate vq */ > - ret |= get_mempolicy(&oldnode, NULL, 0, old_vq, > - MPOL_F_NODE | MPOL_F_ADDR); > + ret = get_mempolicy(&node, NULL, 0, vq->desc, MPOL_F_NODE | > MPOL_F_ADDR); > if (ret) { > - VHOST_LOG_CONFIG(ERR, > - "Unable to get vq numa information.\n"); > + VHOST_LOG_CONFIG(ERR, "Unable to get virtqueue %d numa > information.\n", index); > return dev; > } > - if (oldnode != newnode) { > - VHOST_LOG_CONFIG(INFO, > - "reallocate vq from %d to %d node\n", oldnode, newnode); > - vq = rte_malloc_socket(NULL, sizeof(*vq), 0, newnode); > - if (!vq) > - return dev; > > - memcpy(vq, old_vq, sizeof(*vq)); > + vq = rte_realloc_socket(vq, sizeof(*vq), 0, node); > + if (!vq) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc virtqueue %d on > node %d\n", > + index, node); > + return dev; > + } > > - if (vq_is_packed(dev)) { > - new_shadow_used_packed = rte_malloc_socket(NULL, > - vq->size * > - sizeof(struct vring_used_elem_packed), > - RTE_CACHE_LINE_SIZE, > - newnode); > - if (new_shadow_used_packed) { > - rte_free(vq->shadow_used_packed); > - vq->shadow_used_packed = new_shadow_used_packed; > - } > - } else { > - new_shadow_used_split = rte_malloc_socket(NULL, > - vq->size * > - sizeof(struct vring_used_elem), > - RTE_CACHE_LINE_SIZE, > - newnode); > - if (new_shadow_used_split) { > - rte_free(vq->shadow_used_split); > - vq->shadow_used_split = new_shadow_used_split; > - } > + if (vq != dev->virtqueue[index]) { > + VHOST_LOG_CONFIG(INFO, "reallocated virtqueue on node %d\n", > node); > + dev->virtqueue[index] = vq; > + vhost_user_iotlb_init(dev, index); > + } > + > + if (vq_is_packed(dev)) { > + struct vring_used_elem_packed *sup; > + > + sup = rte_realloc_socket(vq->shadow_used_packed, vq->size * > sizeof(*sup), > + RTE_CACHE_LINE_SIZE, node); > + if (!sup) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc shadow packed > on > node %d\n", node); > + return dev; > } > + vq->shadow_used_packed = sup; > + } else { > + struct vring_used_elem *sus; > > - new_batch_copy_elems = rte_malloc_socket(NULL, > - vq->size * sizeof(struct batch_copy_elem), > - RTE_CACHE_LINE_SIZE, > - newnode); > - if (new_batch_copy_elems) { > - rte_free(vq->batch_copy_elems); > - vq->batch_copy_elems = new_batch_copy_elems; > + sus = rte_realloc_socket(vq->shadow_used_split, vq->size * > sizeof(*sus), > + RTE_CACHE_LINE_SIZE, node); > + if (!sus) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc shadow split on > node %d\n", node); > + return dev; > } > + vq->shadow_used_split = sus; > + } > > - if (vq->log_cache) { > - struct log_cache_entry *log_cache; > + bce = rte_realloc_socket(vq->batch_copy_elems, vq->size * sizeof(*bce), > + RTE_CACHE_LINE_SIZE, node); > + if (!bce) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc batch copy elem on > node %d\n", node); > + return dev; > + } > + vq->batch_copy_elems = bce; > > - log_cache = rte_realloc_socket(vq->log_cache, > - sizeof(struct log_cache_entry) * > VHOST_LOG_CACHE_NR, > - 0, newnode); > - if (log_cache) > - vq->log_cache = log_cache; > - } > + if (vq->log_cache) { > + struct log_cache_entry *lc; > > - rte_free(old_vq); > + lc = rte_realloc_socket(vq->log_cache, sizeof(*lc) * > VHOST_LOG_CACHE_NR, 0, node); > + if (!lc) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc log cache on > node %d\n", node); > + return dev; > + } > + vq->log_cache = lc; > } > > if (dev->flags & VIRTIO_DEV_RUNNING) > - goto out; > + return dev; > > - /* check if we need to reallocate dev */ > - ret = get_mempolicy(&oldnode, NULL, 0, old_dev, > - MPOL_F_NODE | MPOL_F_ADDR); > + ret = get_mempolicy(&dev_node, NULL, 0, dev, MPOL_F_NODE | MPOL_F_ADDR); > if (ret) { > - VHOST_LOG_CONFIG(ERR, > - "Unable to get dev numa information.\n"); > - goto out; > + VHOST_LOG_CONFIG(ERR, "Unable to get Virtio dev %d numa > information.\n", dev->vid); > + return dev; > } > - if (oldnode != newnode) { > - struct rte_vhost_memory *old_mem; > - struct guest_page *old_gp; > - ssize_t mem_size, gp_size; > - > - VHOST_LOG_CONFIG(INFO, > - "reallocate dev from %d to %d node\n", > - oldnode, newnode); > - dev = rte_malloc_socket(NULL, sizeof(*dev), 0, newnode); > - if (!dev) { > - dev = old_dev; > - goto out; > - } > - > - memcpy(dev, old_dev, sizeof(*dev)); > - rte_free(old_dev); > - > - mem_size = sizeof(struct rte_vhost_memory) + > - sizeof(struct rte_vhost_mem_region) * > dev->mem->nregions; > - old_mem = dev->mem; > - dev->mem = rte_malloc_socket(NULL, mem_size, 0, newnode); > - if (!dev->mem) { > - dev->mem = old_mem; > - goto out; > - } > - > - memcpy(dev->mem, old_mem, mem_size); > - rte_free(old_mem); > > - gp_size = dev->max_guest_pages * sizeof(*dev->guest_pages); > - old_gp = dev->guest_pages; > - dev->guest_pages = rte_malloc_socket(NULL, gp_size, > RTE_CACHE_LINE_SIZE, newnode); > - if (!dev->guest_pages) { > - dev->guest_pages = old_gp; > - goto out; > - } > + if (dev_node == node) > + return dev; > > - memcpy(dev->guest_pages, old_gp, gp_size); > - rte_free(old_gp); > + dev = rte_realloc_socket(old_dev, sizeof(*dev), 0, node); > + if (!dev) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc dev on node %d\n", > node); > + return old_dev; > } > > -out: > - dev->virtqueue[index] = vq; > + VHOST_LOG_CONFIG(INFO, "reallocated device on node %d\n", node); > vhost_devices[dev->vid] = dev; > > - if (old_vq != vq) > - vhost_user_iotlb_init(dev, index); > + mem_size = sizeof(struct rte_vhost_memory) + > + sizeof(struct rte_vhost_mem_region) * dev->mem->nregions; > + mem = rte_realloc_socket(dev->mem, mem_size, 0, node); > + if (!mem) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc mem table on node > %d\n", > node); > + return dev; > + } > + dev->mem = mem; > + > + gp = rte_realloc_socket(dev->guest_pages, dev->max_guest_pages * > sizeof(*gp), > + RTE_CACHE_LINE_SIZE, node); > + if (!gp) { > + VHOST_LOG_CONFIG(ERR, "Failed to realloc guest pages on node > %d\n", > node); > + return dev; > + } > + dev->guest_pages = gp; > > return dev; > } > -- > 2.31.1
Reviewed-by: Chenbo Xia <chenbo....@intel.com>