@@ -5413,35 +5413,48 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
54135413 return ret ;
54145414}
54155415
5416- static int __ublk_ctrl_unreg_buf (struct ublk_device * ub , int buf_index )
5416+ static void ublk_unpin_range_pages (unsigned long base_pfn ,
5417+ unsigned long nr_pages )
5418+ {
5419+ #define UBLK_UNPIN_BATCH 32
5420+ struct page * pages [UBLK_UNPIN_BATCH ];
5421+ unsigned long off ;
5422+
5423+ for (off = 0 ; off < nr_pages ; ) {
5424+ unsigned int batch = min_t (unsigned long ,
5425+ nr_pages - off , UBLK_UNPIN_BATCH );
5426+ unsigned int j ;
5427+
5428+ for (j = 0 ; j < batch ; j ++ )
5429+ pages [j ] = pfn_to_page (base_pfn + off + j );
5430+ unpin_user_pages (pages , batch );
5431+ off += batch ;
5432+ }
5433+ }
5434+
5435+ /*
5436+ * Remove ranges from the maple tree matching buf_index, unpin pages
5437+ * and free range structs. If buf_index < 0, remove all ranges.
5438+ */
5439+ static int ublk_shmem_remove_ranges (struct ublk_device * ub , int buf_index )
54175440{
54185441 MA_STATE (mas , & ub -> buf_tree , 0 , ULONG_MAX );
54195442 struct ublk_buf_range * range ;
5420- struct page * pages [32 ];
54215443 int ret = - ENOENT ;
54225444
54235445 mas_lock (& mas );
54245446 mas_for_each (& mas , range , ULONG_MAX ) {
5425- unsigned long base , nr , off ;
5447+ unsigned long base , nr ;
54265448
5427- if (range -> buf_index != buf_index )
5449+ if (buf_index >= 0 && range -> buf_index != buf_index )
54285450 continue ;
54295451
54305452 ret = 0 ;
54315453 base = mas .index ;
54325454 nr = mas .last - base + 1 ;
54335455 mas_erase (& mas );
54345456
5435- for (off = 0 ; off < nr ; ) {
5436- unsigned int batch = min_t (unsigned long ,
5437- nr - off , 32 );
5438- unsigned int j ;
5439-
5440- for (j = 0 ; j < batch ; j ++ )
5441- pages [j ] = pfn_to_page (base + off + j );
5442- unpin_user_pages (pages , batch );
5443- off += batch ;
5444- }
5457+ ublk_unpin_range_pages (base , nr );
54455458 kfree (range );
54465459 }
54475460 mas_unlock (& mas );
@@ -5464,7 +5477,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54645477
54655478 memflags = ublk_lock_buf_tree (ub );
54665479
5467- ret = __ublk_ctrl_unreg_buf (ub , index );
5480+ ret = ublk_shmem_remove_ranges (ub , index );
54685481 if (!ret )
54695482 ida_free (& ub -> buf_ida , index );
54705483
@@ -5474,31 +5487,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54745487
54755488static void ublk_buf_cleanup (struct ublk_device * ub )
54765489{
5477- MA_STATE (mas , & ub -> buf_tree , 0 , ULONG_MAX );
5478- struct ublk_buf_range * range ;
5479- struct page * pages [32 ];
5480-
5481- mas_lock (& mas );
5482- mas_for_each (& mas , range , ULONG_MAX ) {
5483- unsigned long base = mas .index ;
5484- unsigned long nr = mas .last - base + 1 ;
5485- unsigned long off ;
5486-
5487- mas_erase (& mas );
5488-
5489- for (off = 0 ; off < nr ; ) {
5490- unsigned int batch = min_t (unsigned long ,
5491- nr - off , 32 );
5492- unsigned int j ;
5493-
5494- for (j = 0 ; j < batch ; j ++ )
5495- pages [j ] = pfn_to_page (base + off + j );
5496- unpin_user_pages (pages , batch );
5497- off += batch ;
5498- }
5499- kfree (range );
5500- }
5501- mas_unlock (& mas );
5490+ ublk_shmem_remove_ranges (ub , -1 );
55025491 mtree_destroy (& ub -> buf_tree );
55035492 ida_destroy (& ub -> buf_ida );
55045493}
0 commit comments