From 90c86f0c36efbebe395fa8d658499f45772d5786 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 30 Sep 2018 00:12:02 -0400 Subject: [PATCH] xen: Convert pvcalls-back to XArray Pull the XArray out from under the semaphore as it is serialised by its own spinlock. In pvcalls_back_release(), it's more efficient to erase the element than to load it then erase it if it was present. Signed-off-by: Matthew Wilcox --- drivers/xen/pvcalls-back.c | 59 +++++++++++--------------------------- 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index 69a626b0e594..c741075167c8 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -6,10 +6,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -41,7 +41,7 @@ struct pvcalls_fedata { struct xen_pvcalls_back_ring ring; int irq; struct list_head socket_mappings; - struct radix_tree_root socketpass_mappings; + struct xarray socketpass_mappings; struct semaphore socket_lock; }; @@ -368,8 +368,8 @@ static struct sock_mapping *pvcalls_new_active_socket( out: down(&fedata->socket_lock); list_del(&map->list); - pvcalls_back_release_active(fedata->dev, fedata, map); up(&fedata->socket_lock); + pvcalls_back_release_active(fedata->dev, fedata, map); return NULL; } @@ -482,14 +482,10 @@ static int pvcalls_back_release(struct xenbus_device *dev, goto out; } } - mappass = radix_tree_lookup(&fedata->socketpass_mappings, - req->u.release.id); - if (mappass != NULL) { - radix_tree_delete(&fedata->socketpass_mappings, mappass->id); - up(&fedata->socket_lock); + up(&fedata->socket_lock); + mappass = xa_erase(&fedata->socketpass_mappings, req->u.release.id); + if (mappass) ret = pvcalls_back_release_passive(dev, fedata, mappass); - } else - up(&fedata->socket_lock); out: rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++); @@ -640,10 +636,8 @@ static int pvcalls_back_bind(struct xenbus_device *dev, map->fedata = fedata; map->id = req->u.bind.id; - down(&fedata->socket_lock); - ret = radix_tree_insert(&fedata->socketpass_mappings, map->id, - map); - up(&fedata->socket_lock); + ret = xa_err(xa_store(&fedata->socketpass_mappings, map->id, map, + GFP_KERNEL)); if (ret) goto out; @@ -679,9 +673,7 @@ static int pvcalls_back_listen(struct xenbus_device *dev, fedata = dev_get_drvdata(&dev->dev); - down(&fedata->socket_lock); - map = radix_tree_lookup(&fedata->socketpass_mappings, req->u.listen.id); - up(&fedata->socket_lock); + map = xa_load(&fedata->socketpass_mappings, req->u.listen.id); if (map == NULL) goto out; @@ -707,10 +699,7 @@ static int pvcalls_back_accept(struct xenbus_device *dev, fedata = dev_get_drvdata(&dev->dev); - down(&fedata->socket_lock); - mappass = radix_tree_lookup(&fedata->socketpass_mappings, - req->u.accept.id); - up(&fedata->socket_lock); + mappass = xa_load(&fedata->socketpass_mappings, req->u.accept.id); if (mappass == NULL) goto out_error; @@ -755,10 +744,7 @@ static int pvcalls_back_poll(struct xenbus_device *dev, fedata = dev_get_drvdata(&dev->dev); - down(&fedata->socket_lock); - mappass = radix_tree_lookup(&fedata->socketpass_mappings, - req->u.poll.id); - up(&fedata->socket_lock); + mappass = xa_load(&fedata->socketpass_mappings, req->u.poll.id); if (mappass == NULL) return -EINVAL; @@ -950,7 +936,7 @@ static int backend_connect(struct xenbus_device *dev) fedata->dev = dev; INIT_LIST_HEAD(&fedata->socket_mappings); - INIT_RADIX_TREE(&fedata->socketpass_mappings, GFP_KERNEL); + xa_init(&fedata->socketpass_mappings); sema_init(&fedata->socket_lock, 1); dev_set_drvdata(&dev->dev, fedata); @@ -974,9 +960,7 @@ static int backend_disconnect(struct xenbus_device *dev) struct pvcalls_fedata *fedata; struct sock_mapping *map, *n; struct sockpass_mapping *mappass; - struct radix_tree_iter iter; - void **slot; - + unsigned long index; fedata = dev_get_drvdata(&dev->dev); @@ -985,21 +969,12 @@ static int backend_disconnect(struct xenbus_device *dev) list_del(&map->list); pvcalls_back_release_active(dev, fedata, map); } + up(&fedata->socket_lock); - radix_tree_for_each_slot(slot, &fedata->socketpass_mappings, &iter, 0) { - mappass = radix_tree_deref_slot(slot); - if (!mappass) - continue; - if (radix_tree_exception(mappass)) { - if (radix_tree_deref_retry(mappass)) - slot = radix_tree_iter_retry(&iter); - } else { - radix_tree_delete(&fedata->socketpass_mappings, - mappass->id); - pvcalls_back_release_passive(dev, fedata, mappass); - } + xa_for_each(&fedata->socketpass_mappings, index, mappass) { + xa_erase(&fedata->socketpass_mappings, index); + pvcalls_back_release_passive(dev, fedata, mappass); } - up(&fedata->socket_lock); unbind_from_irqhandler(fedata->irq, dev); xenbus_unmap_ring_vfree(dev, fedata->sring); -- 2.50.1