diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 8a6f845285ce..f82b13a16192 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -5510,39 +5510,36 @@ static void ublk_unpin_range_pages(unsigned long base_pfn, /* * Inner loop: erase up to UBLK_REMOVE_BATCH matching ranges under - * mas_lock, collecting them into an xarray. Then drop the lock and - * unpin pages + free ranges outside spinlock context. + * mas_lock, collecting the page ranges in a fixed-size array. Then + * drop the lock and unpin pages + free ranges outside spinlock context. * * Returns true if the tree walk completed, false if more ranges remain. - * Xarray key is the base PFN, value encodes nr_pages via xa_mk_value(). */ #define UBLK_REMOVE_BATCH 64 +struct ublk_unpin_range { + unsigned long base_pfn; + unsigned long nr_pages; +}; + static bool __ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index, int *ret) { MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX); struct ublk_buf_range *range; - struct xarray to_unpin; - unsigned long idx; + struct ublk_unpin_range to_unpin[UBLK_REMOVE_BATCH]; unsigned int count = 0; + unsigned int i; bool done = false; - void *entry; - - xa_init(&to_unpin); mas_lock(&mas); mas_for_each(&mas, range, ULONG_MAX) { - unsigned long nr; - if (buf_index >= 0 && range->buf_index != buf_index) continue; *ret = 0; - nr = mas.last - mas.index + 1; - if (xa_err(xa_store(&to_unpin, mas.index, - xa_mk_value(nr), GFP_ATOMIC))) - goto unlock; + to_unpin[count].base_pfn = mas.index; + to_unpin[count].nr_pages = mas.last - mas.index + 1; mas_erase(&mas); kfree(range); if (++count >= UBLK_REMOVE_BATCH) @@ -5552,9 +5549,9 @@ static bool __ublk_shmem_remove_ranges(struct ublk_device *ub, unlock: mas_unlock(&mas); - xa_for_each(&to_unpin, idx, entry) - ublk_unpin_range_pages(idx, xa_to_value(entry)); - xa_destroy(&to_unpin); + for (i = 0; i < count; i++) + ublk_unpin_range_pages(to_unpin[i].base_pfn, + to_unpin[i].nr_pages); return done; }