Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: refactor common helper ublk_shmem_remove_ranges()

Extract the shared walk+erase+unpin+kfree loop into
ublk_shmem_remove_ranges(). When buf_index >= 0, only ranges matching
that index are removed; when buf_index < 0, all ranges are removed.

Also extract ublk_unpin_range_pages() to share the page unpinning
loop.

Convert both __ublk_ctrl_unreg_buf() and ublk_buf_cleanup() to use
the new helper.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260423033058.2805135-3-tom.leiming@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ming Lei and committed by
Jens Axboe
ea1db795 47903faa

+29 -40
+29 -40
drivers/block/ublk_drv.c
··· 5421 5421 return ret; 5422 5422 } 5423 5423 5424 - static int __ublk_ctrl_unreg_buf(struct ublk_device *ub, int buf_index) 5424 + static void ublk_unpin_range_pages(unsigned long base_pfn, 5425 + unsigned long nr_pages) 5426 + { 5427 + #define UBLK_UNPIN_BATCH 32 5428 + struct page *pages[UBLK_UNPIN_BATCH]; 5429 + unsigned long off; 5430 + 5431 + for (off = 0; off < nr_pages; ) { 5432 + unsigned int batch = min_t(unsigned long, 5433 + nr_pages - off, UBLK_UNPIN_BATCH); 5434 + unsigned int j; 5435 + 5436 + for (j = 0; j < batch; j++) 5437 + pages[j] = pfn_to_page(base_pfn + off + j); 5438 + unpin_user_pages(pages, batch); 5439 + off += batch; 5440 + } 5441 + } 5442 + 5443 + /* 5444 + * Remove ranges from the maple tree matching buf_index, unpin pages 5445 + * and free range structs. If buf_index < 0, remove all ranges. 5446 + */ 5447 + static int ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index) 5425 5448 { 5426 5449 MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX); 5427 5450 struct ublk_buf_range *range; 5428 - struct page *pages[32]; 5429 5451 int ret = -ENOENT; 5430 5452 5431 5453 mas_lock(&mas); 5432 5454 mas_for_each(&mas, range, ULONG_MAX) { 5433 - unsigned long base, nr, off; 5455 + unsigned long base, nr; 5434 5456 5435 - if (range->buf_index != buf_index) 5457 + if (buf_index >= 0 && range->buf_index != buf_index) 5436 5458 continue; 5437 5459 5438 5460 ret = 0; ··· 5462 5440 nr = mas.last - base + 1; 5463 5441 mas_erase(&mas); 5464 5442 5465 - for (off = 0; off < nr; ) { 5466 - unsigned int batch = min_t(unsigned long, 5467 - nr - off, 32); 5468 - unsigned int j; 5469 - 5470 - for (j = 0; j < batch; j++) 5471 - pages[j] = pfn_to_page(base + off + j); 5472 - unpin_user_pages(pages, batch); 5473 - off += batch; 5474 - } 5443 + ublk_unpin_range_pages(base, nr); 5475 5444 kfree(range); 5476 5445 } 5477 5446 mas_unlock(&mas); ··· 5485 5472 5486 5473 memflags = ublk_lock_buf_tree(ub); 5487 5474 5488 - ret = __ublk_ctrl_unreg_buf(ub, index); 5475 + ret = ublk_shmem_remove_ranges(ub, index); 5489 5476 if (!ret) 5490 5477 ida_free(&ub->buf_ida, index); 5491 5478 ··· 5495 5482 5496 5483 static void ublk_buf_cleanup(struct ublk_device *ub) 5497 5484 { 5498 - MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX); 5499 - struct ublk_buf_range *range; 5500 - struct page *pages[32]; 5501 - 5502 - mas_lock(&mas); 5503 - mas_for_each(&mas, range, ULONG_MAX) { 5504 - unsigned long base = mas.index; 5505 - unsigned long nr = mas.last - base + 1; 5506 - unsigned long off; 5507 - 5508 - mas_erase(&mas); 5509 - 5510 - for (off = 0; off < nr; ) { 5511 - unsigned int batch = min_t(unsigned long, 5512 - nr - off, 32); 5513 - unsigned int j; 5514 - 5515 - for (j = 0; j < batch; j++) 5516 - pages[j] = pfn_to_page(base + off + j); 5517 - unpin_user_pages(pages, batch); 5518 - off += batch; 5519 - } 5520 - kfree(range); 5521 - } 5522 - mas_unlock(&mas); 5485 + ublk_shmem_remove_ranges(ub, -1); 5523 5486 mtree_destroy(&ub->buf_tree); 5524 5487 ida_destroy(&ub->buf_ida); 5525 5488 }