From 81f9aea3dbdec74149aaa1c58ceacfa9b63ed33f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 9 Jan 2019 08:34:37 -0500 Subject: [PATCH] target: Convert devices_idr to XArray Signed-off-by: Matthew Wilcox --- drivers/target/target_core_device.c | 94 +++++++++++------------------ 1 file changed, 34 insertions(+), 60 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 04bf2acd3800..1c86613a5cc4 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -36,9 +36,7 @@ #include "target_core_pr.h" #include "target_core_ua.h" -static DEFINE_MUTEX(device_mutex); -static LIST_HEAD(device_list); -static DEFINE_IDR(devices_idr); +static DEFINE_XARRAY_ALLOC(device_list); static struct se_hba *lun0_hba; /* not static, needed by tpg.c */ @@ -853,42 +851,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) } EXPORT_SYMBOL(target_to_linux_sector); -struct devices_idr_iter { - struct config_item *prev_item; - int (*fn)(struct se_device *dev, void *data); - void *data; -}; - -static int target_devices_idr_iter(int id, void *p, void *data) - __must_hold(&device_mutex) -{ - struct devices_idr_iter *iter = data; - struct se_device *dev = p; - int ret; - - config_item_put(iter->prev_item); - iter->prev_item = NULL; - - /* - * We add the device early to the idr, so it can be used - * by backend modules during configuration. We do not want - * to allow other callers to access partially setup devices, - * so we skip them here. - */ - if (!target_dev_configured(dev)) - return 0; - - iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); - if (!iter->prev_item) - return 0; - mutex_unlock(&device_mutex); - - ret = iter->fn(dev, iter->data); - - mutex_lock(&device_mutex); - return ret; -} - /** * target_for_each_device - iterate over configured devices * @fn: iterator function @@ -900,20 +862,41 @@ static int target_devices_idr_iter(int id, void *p, void *data) int target_for_each_device(int (*fn)(struct se_device *dev, void *data), void *data) { - struct devices_idr_iter iter = { .fn = fn, .data = data }; - int ret; + unsigned long i; + struct se_device *dev; + int ret = 0; + + xa_for_each(&device_list, i, dev) { + struct config_item *item; + + /* + * We add the device early to the list, so it can be used + * by backend modules during configuration. We do not want + * to allow other callers to access partially setup devices, + * so we skip them here. + */ + if (!target_dev_configured(dev)) + continue; + + item = config_item_get_unless_zero(&dev->dev_group.cg_item); + if (!item) + continue; + + ret = fn(dev, data); + + config_item_put(item); + if (ret) + break; + } - mutex_lock(&device_mutex); - ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); - mutex_unlock(&device_mutex); - config_item_put(iter.prev_item); return ret; } int target_configure_device(struct se_device *dev) { + static u32 next; struct se_hba *hba = dev->se_hba; - int ret, id; + int ret; if (target_dev_configured(dev)) { pr_err("se_dev->se_dev_ptr already set for storage" @@ -924,19 +907,15 @@ int target_configure_device(struct se_device *dev) /* * Add early so modules like tcmu can use during its * configuration. - */ - mutex_lock(&device_mutex); - /* * Use cyclic to try and avoid collisions with devices * that were recently removed. */ - id = idr_alloc_cyclic(&devices_idr, dev, 0, INT_MAX, GFP_KERNEL); - mutex_unlock(&device_mutex); - if (id < 0) { + ret = xa_alloc_cyclic(&device_list, &dev->dev_index, dev, xa_limit_32b, + &next, GFP_KERNEL); + if (ret < 0) { ret = -ENOMEM; goto out; } - dev->dev_index = id; ret = dev->transport->configure_device(dev); if (ret) @@ -979,9 +958,7 @@ int target_configure_device(struct se_device *dev) out_destroy_device: dev->transport->destroy_device(dev); out_free_index: - mutex_lock(&device_mutex); - idr_remove(&devices_idr, dev->dev_index); - mutex_unlock(&device_mutex); + xa_erase(&device_list, dev->dev_index); out: se_release_vpd_for_dev(dev); return ret; @@ -995,10 +972,7 @@ void target_free_device(struct se_device *dev) if (target_dev_configured(dev)) { dev->transport->destroy_device(dev); - - mutex_lock(&device_mutex); - idr_remove(&devices_idr, dev->dev_index); - mutex_unlock(&device_mutex); + xa_erase(&device_list, dev->dev_index); spin_lock(&hba->device_lock); hba->dev_count--; -- 2.50.1