@@ -83,7 +83,7 @@
#include <linux/uaccess.h>
-static DEFINE_IDR(loop_index_idr);
+static DEFINE_XARRAY_ALLOC(loop_devs);
static DEFINE_MUTEX(loop_ctl_mutex);
static int max_part;
@@ -1812,28 +1812,23 @@ int loop_register_transfer(struct loop_func_table *funcs)
return 0;
}
-static int unregister_transfer_cb(int id, void *ptr, void *data)
-{
- struct loop_device *lo = ptr;
- struct loop_func_table *xfer = data;
-
- mutex_lock(&loop_ctl_mutex);
- if (lo->lo_encryption == xfer)
- loop_release_xfer(lo);
- mutex_unlock(&loop_ctl_mutex);
- return 0;
-}
-
int loop_unregister_transfer(int number)
{
unsigned int n = number;
struct loop_func_table *xfer;
+ struct loop_device *lo;
+ unsigned long index;
if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL)
return -EINVAL;
xfer_funcs[n] = NULL;
- idr_for_each(&loop_index_idr, &unregister_transfer_cb, xfer);
+ xa_for_each(&loop_devs, index, lo) {
+ mutex_lock(&loop_ctl_mutex);
+ if (lo->lo_encryption == xfer)
+ loop_release_xfer(lo);
+ mutex_unlock(&loop_ctl_mutex);
+ }
return 0;
}
@@ -1935,15 +1930,14 @@ static int loop_add(struct loop_device **l, int i)
/* allocate id, if @id >= 0, we're requesting that specific id */
if (i >= 0) {
- err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL);
- if (err == -ENOSPC)
- err = -EEXIST;
+ err = xa_insert(&loop_devs, i, lo, GFP_KERNEL);
} else {
- err = idr_alloc(&loop_index_idr, lo, 0, 0, GFP_KERNEL);
+ err = xa_alloc(&loop_devs, &i, lo, xa_limit_32b, GFP_KERNEL);
}
+ if (err == -EBUSY)
+ err = -EEXIST;
if (err < 0)
goto out_free_dev;
- i = err;
err = -ENOMEM;
lo->tag_set.ops = &loop_mq_ops;
@@ -1956,7 +1950,7 @@ static int loop_add(struct loop_device **l, int i)
err = blk_mq_alloc_tag_set(&lo->tag_set);
if (err)
- goto out_free_idr;
+ goto out_free_xa;
lo->lo_queue = blk_mq_init_queue(&lo->tag_set);
if (IS_ERR(lo->lo_queue)) {
@@ -2018,8 +2012,8 @@ static int loop_add(struct loop_device **l, int i)
blk_cleanup_queue(lo->lo_queue);
out_cleanup_tags:
blk_mq_free_tag_set(&lo->tag_set);
-out_free_idr:
- idr_remove(&loop_index_idr, i);
+out_free_xa:
+ xa_erase(&loop_devs, i);
out_free_dev:
kfree(lo);
out:
@@ -2035,41 +2029,28 @@ static void loop_remove(struct loop_device *lo)
kfree(lo);
}
-static int find_free_cb(int id, void *ptr, void *data)
-{
- struct loop_device *lo = ptr;
- struct loop_device **l = data;
-
- if (lo->lo_state == Lo_unbound) {
- *l = lo;
- return 1;
- }
- return 0;
-}
-
static int loop_lookup(struct loop_device **l, int i)
{
struct loop_device *lo;
int ret = -ENODEV;
if (i < 0) {
- int err;
+ unsigned long index;
- err = idr_for_each(&loop_index_idr, &find_free_cb, &lo);
- if (err == 1) {
- *l = lo;
- ret = lo->lo_number;
+ xa_for_each(&loop_devs, index, lo) {
+ if (lo->lo_state != Lo_unbound)
+ continue;
+ break;
}
- goto out;
+ } else {
+ /* lookup and return a specific i */
+ lo = xa_load(&loop_devs, i);
}
- /* lookup and return a specific i */
- lo = idr_find(&loop_index_idr, i);
if (lo) {
*l = lo;
ret = lo->lo_number;
}
-out:
return ret;
}
@@ -2126,7 +2107,7 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
break;
}
lo->lo_disk->private_data = NULL;
- idr_remove(&loop_index_idr, lo->lo_number);
+ xa_erase(&loop_devs, lo->lo_number);
loop_remove(lo);
break;
case LOOP_CTL_GET_FREE:
@@ -2233,23 +2214,16 @@ static int __init loop_init(void)
return err;
}
-static int loop_exit_cb(int id, void *ptr, void *data)
-{
- struct loop_device *lo = ptr;
-
- loop_remove(lo);
- return 0;
-}
-
static void __exit loop_exit(void)
{
- unsigned long range;
-
- range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
+ struct loop_device *lo;
+ unsigned long range, index;
- idr_for_each(&loop_index_idr, &loop_exit_cb, NULL);
- idr_destroy(&loop_index_idr);
+ xa_for_each(&loop_devs, index, lo)
+ loop_remove(lo);
+ xa_destroy(&loop_devs);
+ range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
unregister_blkdev(LOOP_MAJOR, "loop");
Signed-off-by: Matthew Wilcox <willy@infradead.org> --- drivers/block/loop.c | 88 ++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 57 deletions(-)