@@ -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 */
306301struct 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
52815276static 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 );
54285415err_free_pages :
54295416 kvfree (pages );
5430- err_free :
5431- kfree (ubuf );
54325417put_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
54715458static 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
55075491static 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