Skip to content

Commit 5e86443

Browse files
ming1axboe
authored andcommitted
ublk: replace xarray with IDA for shmem buffer index allocation
Remove struct ublk_buf which only contained nr_pages that was never read after registration. Use IDA for pure index allocation instead of xarray. Make __ublk_ctrl_unreg_buf() return int so the caller can detect invalid index without a separate lookup. Simplify ublk_buf_cleanup() to walk the maple tree directly and unpin all pages in one pass, instead of iterating the xarray by buffer index. Suggested-by: Caleb Sander Mateos <csander@purestorage.com> Signed-off-by: Ming Lei <tom.leiming@gmail.com> Link: https://patch.msgid.link/20260409133020.3780098-5-tom.leiming@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 8ea8566 commit 5e86443

1 file changed

Lines changed: 46 additions & 46 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,6 @@ struct ublk_queue {
297297
struct ublk_io ios[] __counted_by(q_depth);
298298
};
299299

300-
/* Per-registered shared memory buffer */
301-
struct ublk_buf {
302-
unsigned int nr_pages;
303-
};
304-
305300
/* Maple tree value: maps a PFN range to buffer location */
306301
struct ublk_buf_range {
307302
unsigned short buf_index;
@@ -345,7 +340,7 @@ struct ublk_device {
345340

346341
/* shared memory zero copy */
347342
struct maple_tree buf_tree;
348-
struct xarray bufs_xa;
343+
struct ida buf_ida;
349344

350345
struct ublk_queue *queues[];
351346
};
@@ -4698,7 +4693,7 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
46984693
spin_lock_init(&ub->lock);
46994694
mutex_init(&ub->cancel_mutex);
47004695
mt_init(&ub->buf_tree);
4701-
xa_init_flags(&ub->bufs_xa, XA_FLAGS_ALLOC);
4696+
ida_init(&ub->buf_ida);
47024697
INIT_WORK(&ub->partition_scan_work, ublk_partition_scan_work);
47034698

47044699
ret = ublk_alloc_dev_number(ub, header->dev_id);
@@ -5279,11 +5274,9 @@ static void ublk_buf_erase_ranges(struct ublk_device *ub, int buf_index)
52795274
}
52805275

52815276
static int __ublk_ctrl_reg_buf(struct ublk_device *ub,
5282-
struct ublk_buf *ubuf,
5283-
struct page **pages, int index,
5284-
unsigned short flags)
5277+
struct page **pages, unsigned long nr_pages,
5278+
int index, unsigned short flags)
52855279
{
5286-
unsigned long nr_pages = ubuf->nr_pages;
52875280
unsigned long i;
52885281
int ret;
52895282

@@ -5335,9 +5328,8 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
53355328
struct page **pages = NULL;
53365329
unsigned int gup_flags;
53375330
struct gendisk *disk;
5338-
struct ublk_buf *ubuf;
53395331
long pinned;
5340-
u32 index;
5332+
int index;
53415333
int ret;
53425334

53435335
if (!ublk_dev_support_shmem_zc(ub))
@@ -5367,16 +5359,10 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
53675359
return -ENODEV;
53685360

53695361
/* Pin pages before quiescing (may sleep) */
5370-
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
5371-
if (!ubuf) {
5372-
ret = -ENOMEM;
5373-
goto put_disk;
5374-
}
5375-
53765362
pages = kvmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL);
53775363
if (!pages) {
53785364
ret = -ENOMEM;
5379-
goto err_free;
5365+
goto put_disk;
53805366
}
53815367

53825368
gup_flags = FOLL_LONGTERM;
@@ -5392,7 +5378,6 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
53925378
ret = -EFAULT;
53935379
goto err_unpin;
53945380
}
5395-
ubuf->nr_pages = nr_pages;
53965381

53975382
/*
53985383
* Drain inflight I/O and quiesce the queue so no new requests
@@ -5403,13 +5388,15 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
54035388

54045389
mutex_lock(&ub->mutex);
54055390

5406-
ret = xa_alloc(&ub->bufs_xa, &index, ubuf, xa_limit_16b, GFP_KERNEL);
5407-
if (ret)
5391+
index = ida_alloc_max(&ub->buf_ida, USHRT_MAX, GFP_KERNEL);
5392+
if (index < 0) {
5393+
ret = index;
54085394
goto err_unlock;
5395+
}
54095396

5410-
ret = __ublk_ctrl_reg_buf(ub, ubuf, pages, index, buf_reg.flags);
5397+
ret = __ublk_ctrl_reg_buf(ub, pages, nr_pages, index, buf_reg.flags);
54115398
if (ret) {
5412-
xa_erase(&ub->bufs_xa, index);
5399+
ida_free(&ub->buf_ida, index);
54135400
goto err_unlock;
54145401
}
54155402

@@ -5427,19 +5414,17 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
54275414
unpin_user_pages(pages, pinned);
54285415
err_free_pages:
54295416
kvfree(pages);
5430-
err_free:
5431-
kfree(ubuf);
54325417
put_disk:
54335418
ublk_put_disk(disk);
54345419
return ret;
54355420
}
54365421

5437-
static void __ublk_ctrl_unreg_buf(struct ublk_device *ub,
5438-
struct ublk_buf *ubuf, int buf_index)
5422+
static int __ublk_ctrl_unreg_buf(struct ublk_device *ub, int buf_index)
54395423
{
54405424
MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX);
54415425
struct ublk_buf_range *range;
54425426
struct page *pages[32];
5427+
int ret = -ENOENT;
54435428

54445429
mas_lock(&mas);
54455430
mas_for_each(&mas, range, ULONG_MAX) {
@@ -5448,6 +5433,7 @@ static void __ublk_ctrl_unreg_buf(struct ublk_device *ub,
54485433
if (range->buf_index != buf_index)
54495434
continue;
54505435

5436+
ret = 0;
54515437
base = mas.index;
54525438
nr = mas.last - base + 1;
54535439
mas_erase(&mas);
@@ -5465,19 +5451,23 @@ static void __ublk_ctrl_unreg_buf(struct ublk_device *ub,
54655451
kfree(range);
54665452
}
54675453
mas_unlock(&mas);
5468-
kfree(ubuf);
5454+
5455+
return ret;
54695456
}
54705457

54715458
static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54725459
struct ublksrv_ctrl_cmd *header)
54735460
{
54745461
int index = (int)header->data[0];
54755462
struct gendisk *disk;
5476-
struct ublk_buf *ubuf;
5463+
int ret;
54775464

54785465
if (!ublk_dev_support_shmem_zc(ub))
54795466
return -EOPNOTSUPP;
54805467

5468+
if (index < 0 || index > USHRT_MAX)
5469+
return -EINVAL;
5470+
54815471
disk = ublk_get_disk(ub);
54825472
if (!disk)
54835473
return -ENODEV;
@@ -5487,32 +5477,42 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54875477

54885478
mutex_lock(&ub->mutex);
54895479

5490-
ubuf = xa_erase(&ub->bufs_xa, index);
5491-
if (!ubuf) {
5492-
mutex_unlock(&ub->mutex);
5493-
ublk_unquiesce_and_resume(disk);
5494-
ublk_put_disk(disk);
5495-
return -ENOENT;
5496-
}
5497-
5498-
__ublk_ctrl_unreg_buf(ub, ubuf, index);
5480+
ret = __ublk_ctrl_unreg_buf(ub, index);
5481+
if (!ret)
5482+
ida_free(&ub->buf_ida, index);
54995483

55005484
mutex_unlock(&ub->mutex);
55015485

55025486
ublk_unquiesce_and_resume(disk);
55035487
ublk_put_disk(disk);
5504-
return 0;
5488+
return ret;
55055489
}
55065490

55075491
static void ublk_buf_cleanup(struct ublk_device *ub)
55085492
{
5509-
struct ublk_buf *ubuf;
5510-
unsigned long index;
5493+
MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX);
5494+
struct ublk_buf_range *range;
5495+
struct page *pages[32];
5496+
5497+
mas_for_each(&mas, range, ULONG_MAX) {
5498+
unsigned long base = mas.index;
5499+
unsigned long nr = mas.last - base + 1;
5500+
unsigned long off;
55115501

5512-
xa_for_each(&ub->bufs_xa, index, ubuf)
5513-
__ublk_ctrl_unreg_buf(ub, ubuf, index);
5514-
xa_destroy(&ub->bufs_xa);
5502+
for (off = 0; off < nr; ) {
5503+
unsigned int batch = min_t(unsigned long,
5504+
nr - off, 32);
5505+
unsigned int j;
5506+
5507+
for (j = 0; j < batch; j++)
5508+
pages[j] = pfn_to_page(base + off + j);
5509+
unpin_user_pages(pages, batch);
5510+
off += batch;
5511+
}
5512+
kfree(range);
5513+
}
55155514
mtree_destroy(&ub->buf_tree);
5515+
ida_destroy(&ub->buf_ida);
55165516
}
55175517

55185518
/* Check if request pages match a registered shared memory buffer */

0 commit comments

Comments
 (0)