1*d96e5996SHans Petter Selasky /*- 2*d96e5996SHans Petter Selasky * Copyright (c) 2020 Mellanox Technologies, Ltd. 3*d96e5996SHans Petter Selasky * All rights reserved. 4*d96e5996SHans Petter Selasky * 5*d96e5996SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 6*d96e5996SHans Petter Selasky * modification, are permitted provided that the following conditions 7*d96e5996SHans Petter Selasky * are met: 8*d96e5996SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 9*d96e5996SHans Petter Selasky * notice unmodified, this list of conditions, and the following 10*d96e5996SHans Petter Selasky * disclaimer. 11*d96e5996SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 12*d96e5996SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 13*d96e5996SHans Petter Selasky * documentation and/or other materials provided with the distribution. 14*d96e5996SHans Petter Selasky * 15*d96e5996SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*d96e5996SHans Petter Selasky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*d96e5996SHans Petter Selasky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*d96e5996SHans Petter Selasky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*d96e5996SHans Petter Selasky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*d96e5996SHans Petter Selasky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*d96e5996SHans Petter Selasky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*d96e5996SHans Petter Selasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*d96e5996SHans Petter Selasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*d96e5996SHans Petter Selasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*d96e5996SHans Petter Selasky */ 26*d96e5996SHans Petter Selasky 27*d96e5996SHans Petter Selasky #include <sys/cdefs.h> 28*d96e5996SHans Petter Selasky __FBSDID("$FreeBSD$"); 29*d96e5996SHans Petter Selasky 30*d96e5996SHans Petter Selasky #include <linux/xarray.h> 31*d96e5996SHans Petter Selasky 32*d96e5996SHans Petter Selasky #include <vm/vm_pageout.h> 33*d96e5996SHans Petter Selasky 34*d96e5996SHans Petter Selasky /* 35*d96e5996SHans Petter Selasky * This function removes the element at the given index and returns 36*d96e5996SHans Petter Selasky * the pointer to the removed element, if any. 37*d96e5996SHans Petter Selasky */ 38*d96e5996SHans Petter Selasky void * 39*d96e5996SHans Petter Selasky __xa_erase(struct xarray *xa, uint32_t index) 40*d96e5996SHans Petter Selasky { 41*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 42*d96e5996SHans Petter Selasky 43*d96e5996SHans Petter Selasky return (radix_tree_delete(&xa->root, index)); 44*d96e5996SHans Petter Selasky } 45*d96e5996SHans Petter Selasky 46*d96e5996SHans Petter Selasky void * 47*d96e5996SHans Petter Selasky xa_erase(struct xarray *xa, uint32_t index) 48*d96e5996SHans Petter Selasky { 49*d96e5996SHans Petter Selasky void *retval; 50*d96e5996SHans Petter Selasky 51*d96e5996SHans Petter Selasky xa_lock(xa); 52*d96e5996SHans Petter Selasky retval = __xa_erase(xa, index); 53*d96e5996SHans Petter Selasky xa_unlock(xa); 54*d96e5996SHans Petter Selasky 55*d96e5996SHans Petter Selasky return (retval); 56*d96e5996SHans Petter Selasky } 57*d96e5996SHans Petter Selasky 58*d96e5996SHans Petter Selasky /* 59*d96e5996SHans Petter Selasky * This function returns the element pointer at the given index. A 60*d96e5996SHans Petter Selasky * value of NULL is returned if the element does not exist. 61*d96e5996SHans Petter Selasky */ 62*d96e5996SHans Petter Selasky void * 63*d96e5996SHans Petter Selasky xa_load(struct xarray *xa, uint32_t index) 64*d96e5996SHans Petter Selasky { 65*d96e5996SHans Petter Selasky void *retval; 66*d96e5996SHans Petter Selasky 67*d96e5996SHans Petter Selasky xa_lock(xa); 68*d96e5996SHans Petter Selasky retval = radix_tree_lookup(&xa->root, index); 69*d96e5996SHans Petter Selasky xa_unlock(xa); 70*d96e5996SHans Petter Selasky 71*d96e5996SHans Petter Selasky return (retval); 72*d96e5996SHans Petter Selasky } 73*d96e5996SHans Petter Selasky 74*d96e5996SHans Petter Selasky /* 75*d96e5996SHans Petter Selasky * This is an internal function used to sleep until more memory 76*d96e5996SHans Petter Selasky * becomes available. 77*d96e5996SHans Petter Selasky */ 78*d96e5996SHans Petter Selasky static void 79*d96e5996SHans Petter Selasky xa_vm_wait_locked(struct xarray *xa) 80*d96e5996SHans Petter Selasky { 81*d96e5996SHans Petter Selasky xa_unlock(xa); 82*d96e5996SHans Petter Selasky vm_wait(NULL); 83*d96e5996SHans Petter Selasky xa_lock(xa); 84*d96e5996SHans Petter Selasky } 85*d96e5996SHans Petter Selasky 86*d96e5996SHans Petter Selasky /* 87*d96e5996SHans Petter Selasky * This function iterates the xarray until it finds a free slot where 88*d96e5996SHans Petter Selasky * it can insert the element pointer to by "ptr". It starts at the 89*d96e5996SHans Petter Selasky * index pointed to by "pindex" and updates this value at return. The 90*d96e5996SHans Petter Selasky * "mask" argument defines the maximum index allowed, inclusivly, and 91*d96e5996SHans Petter Selasky * must be a power of two minus one value. The "gfp" argument 92*d96e5996SHans Petter Selasky * basically tells if we can wait for more memory to become available 93*d96e5996SHans Petter Selasky * or not. This function returns zero upon success or a negative error 94*d96e5996SHans Petter Selasky * code on failure. A typical error code is -ENOMEM which means either 95*d96e5996SHans Petter Selasky * the xarray is full, or there was not enough internal memory 96*d96e5996SHans Petter Selasky * available to complete the radix tree insertion. 97*d96e5996SHans Petter Selasky */ 98*d96e5996SHans Petter Selasky int 99*d96e5996SHans Petter Selasky __xa_alloc(struct xarray *xa, uint32_t *pindex, void *ptr, uint32_t mask, gfp_t gfp) 100*d96e5996SHans Petter Selasky { 101*d96e5996SHans Petter Selasky int retval; 102*d96e5996SHans Petter Selasky 103*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 104*d96e5996SHans Petter Selasky 105*d96e5996SHans Petter Selasky /* mask cannot be zero */ 106*d96e5996SHans Petter Selasky MPASS(mask != 0); 107*d96e5996SHans Petter Selasky 108*d96e5996SHans Petter Selasky /* mask can be any power of two value minus one */ 109*d96e5996SHans Petter Selasky MPASS((mask & (mask + 1)) == 0); 110*d96e5996SHans Petter Selasky 111*d96e5996SHans Petter Selasky *pindex = 0; 112*d96e5996SHans Petter Selasky retry: 113*d96e5996SHans Petter Selasky retval = radix_tree_insert(&xa->root, *pindex, ptr); 114*d96e5996SHans Petter Selasky 115*d96e5996SHans Petter Selasky switch (retval) { 116*d96e5996SHans Petter Selasky case -EEXIST: 117*d96e5996SHans Petter Selasky if (likely(*pindex != mask)) { 118*d96e5996SHans Petter Selasky (*pindex)++; 119*d96e5996SHans Petter Selasky goto retry; 120*d96e5996SHans Petter Selasky } 121*d96e5996SHans Petter Selasky retval = -ENOMEM; 122*d96e5996SHans Petter Selasky break; 123*d96e5996SHans Petter Selasky case -ENOMEM: 124*d96e5996SHans Petter Selasky if (likely(gfp & M_WAITOK)) { 125*d96e5996SHans Petter Selasky xa_vm_wait_locked(xa); 126*d96e5996SHans Petter Selasky goto retry; 127*d96e5996SHans Petter Selasky } 128*d96e5996SHans Petter Selasky break; 129*d96e5996SHans Petter Selasky default: 130*d96e5996SHans Petter Selasky break; 131*d96e5996SHans Petter Selasky } 132*d96e5996SHans Petter Selasky return (retval); 133*d96e5996SHans Petter Selasky } 134*d96e5996SHans Petter Selasky 135*d96e5996SHans Petter Selasky int 136*d96e5996SHans Petter Selasky xa_alloc(struct xarray *xa, uint32_t *pindex, void *ptr, uint32_t mask, gfp_t gfp) 137*d96e5996SHans Petter Selasky { 138*d96e5996SHans Petter Selasky int retval; 139*d96e5996SHans Petter Selasky 140*d96e5996SHans Petter Selasky xa_lock(xa); 141*d96e5996SHans Petter Selasky retval = __xa_alloc(xa, pindex, ptr, mask, gfp); 142*d96e5996SHans Petter Selasky xa_unlock(xa); 143*d96e5996SHans Petter Selasky 144*d96e5996SHans Petter Selasky return (retval); 145*d96e5996SHans Petter Selasky } 146*d96e5996SHans Petter Selasky 147*d96e5996SHans Petter Selasky /* 148*d96e5996SHans Petter Selasky * This function works the same like the "xa_alloc" function, except 149*d96e5996SHans Petter Selasky * it wraps the next index value to zero when there are no entries 150*d96e5996SHans Petter Selasky * left at the end of the xarray searching for a free slot from the 151*d96e5996SHans Petter Selasky * beginning of the array. If the xarray is full -ENOMEM is returned. 152*d96e5996SHans Petter Selasky */ 153*d96e5996SHans Petter Selasky int 154*d96e5996SHans Petter Selasky __xa_alloc_cyclic(struct xarray *xa, uint32_t *pindex, void *ptr, uint32_t mask, 155*d96e5996SHans Petter Selasky uint32_t *pnext_index, gfp_t gfp) 156*d96e5996SHans Petter Selasky { 157*d96e5996SHans Petter Selasky int retval; 158*d96e5996SHans Petter Selasky int timeout = 1; 159*d96e5996SHans Petter Selasky 160*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 161*d96e5996SHans Petter Selasky 162*d96e5996SHans Petter Selasky /* mask cannot be zero */ 163*d96e5996SHans Petter Selasky MPASS(mask != 0); 164*d96e5996SHans Petter Selasky 165*d96e5996SHans Petter Selasky /* mask can be any power of two value minus one */ 166*d96e5996SHans Petter Selasky MPASS((mask & (mask + 1)) == 0); 167*d96e5996SHans Petter Selasky 168*d96e5996SHans Petter Selasky *pnext_index = 0; 169*d96e5996SHans Petter Selasky retry: 170*d96e5996SHans Petter Selasky retval = radix_tree_insert(&xa->root, *pnext_index, ptr); 171*d96e5996SHans Petter Selasky 172*d96e5996SHans Petter Selasky switch (retval) { 173*d96e5996SHans Petter Selasky case -EEXIST: 174*d96e5996SHans Petter Selasky if (unlikely(*pnext_index == mask) && !timeout--) { 175*d96e5996SHans Petter Selasky retval = -ENOMEM; 176*d96e5996SHans Petter Selasky break; 177*d96e5996SHans Petter Selasky } 178*d96e5996SHans Petter Selasky (*pnext_index)++; 179*d96e5996SHans Petter Selasky (*pnext_index) &= mask; 180*d96e5996SHans Petter Selasky goto retry; 181*d96e5996SHans Petter Selasky case -ENOMEM: 182*d96e5996SHans Petter Selasky if (likely(gfp & M_WAITOK)) { 183*d96e5996SHans Petter Selasky xa_vm_wait_locked(xa); 184*d96e5996SHans Petter Selasky goto retry; 185*d96e5996SHans Petter Selasky } 186*d96e5996SHans Petter Selasky break; 187*d96e5996SHans Petter Selasky default: 188*d96e5996SHans Petter Selasky break; 189*d96e5996SHans Petter Selasky } 190*d96e5996SHans Petter Selasky *pindex = *pnext_index; 191*d96e5996SHans Petter Selasky 192*d96e5996SHans Petter Selasky return (retval); 193*d96e5996SHans Petter Selasky } 194*d96e5996SHans Petter Selasky 195*d96e5996SHans Petter Selasky int 196*d96e5996SHans Petter Selasky xa_alloc_cyclic(struct xarray *xa, uint32_t *pindex, void *ptr, uint32_t mask, 197*d96e5996SHans Petter Selasky uint32_t *pnext_index, gfp_t gfp) 198*d96e5996SHans Petter Selasky { 199*d96e5996SHans Petter Selasky int retval; 200*d96e5996SHans Petter Selasky 201*d96e5996SHans Petter Selasky xa_lock(xa); 202*d96e5996SHans Petter Selasky retval = __xa_alloc_cyclic(xa, pindex, ptr, mask, pnext_index, gfp); 203*d96e5996SHans Petter Selasky xa_unlock(xa); 204*d96e5996SHans Petter Selasky 205*d96e5996SHans Petter Selasky return (retval); 206*d96e5996SHans Petter Selasky } 207*d96e5996SHans Petter Selasky 208*d96e5996SHans Petter Selasky /* 209*d96e5996SHans Petter Selasky * This function tries to insert an element at the given index. The 210*d96e5996SHans Petter Selasky * "gfp" argument basically decides of this function can sleep or not 211*d96e5996SHans Petter Selasky * trying to allocate internal memory for its radix tree. The 212*d96e5996SHans Petter Selasky * function returns an error code upon failure. Typical error codes 213*d96e5996SHans Petter Selasky * are element exists (-EEXIST) or out of memory (-ENOMEM). 214*d96e5996SHans Petter Selasky */ 215*d96e5996SHans Petter Selasky int 216*d96e5996SHans Petter Selasky __xa_insert(struct xarray *xa, uint32_t index, void *ptr, gfp_t gfp) 217*d96e5996SHans Petter Selasky { 218*d96e5996SHans Petter Selasky int retval; 219*d96e5996SHans Petter Selasky 220*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 221*d96e5996SHans Petter Selasky retry: 222*d96e5996SHans Petter Selasky retval = radix_tree_insert(&xa->root, index, ptr); 223*d96e5996SHans Petter Selasky 224*d96e5996SHans Petter Selasky switch (retval) { 225*d96e5996SHans Petter Selasky case -ENOMEM: 226*d96e5996SHans Petter Selasky if (likely(gfp & M_WAITOK)) { 227*d96e5996SHans Petter Selasky xa_vm_wait_locked(xa); 228*d96e5996SHans Petter Selasky goto retry; 229*d96e5996SHans Petter Selasky } 230*d96e5996SHans Petter Selasky break; 231*d96e5996SHans Petter Selasky default: 232*d96e5996SHans Petter Selasky break; 233*d96e5996SHans Petter Selasky } 234*d96e5996SHans Petter Selasky return (retval); 235*d96e5996SHans Petter Selasky } 236*d96e5996SHans Petter Selasky 237*d96e5996SHans Petter Selasky int 238*d96e5996SHans Petter Selasky xa_insert(struct xarray *xa, uint32_t index, void *ptr, gfp_t gfp) 239*d96e5996SHans Petter Selasky { 240*d96e5996SHans Petter Selasky int retval; 241*d96e5996SHans Petter Selasky 242*d96e5996SHans Petter Selasky xa_lock(xa); 243*d96e5996SHans Petter Selasky retval = __xa_insert(xa, index, ptr, gfp); 244*d96e5996SHans Petter Selasky xa_unlock(xa); 245*d96e5996SHans Petter Selasky 246*d96e5996SHans Petter Selasky return (retval); 247*d96e5996SHans Petter Selasky } 248*d96e5996SHans Petter Selasky 249*d96e5996SHans Petter Selasky /* 250*d96e5996SHans Petter Selasky * This function updates the element at the given index and returns a 251*d96e5996SHans Petter Selasky * pointer to the old element. The "gfp" argument basically decides of 252*d96e5996SHans Petter Selasky * this function can sleep or not trying to allocate internal memory 253*d96e5996SHans Petter Selasky * for its radix tree. The function returns an XA_ERROR() pointer code 254*d96e5996SHans Petter Selasky * upon failure. Code using this function must always check if the 255*d96e5996SHans Petter Selasky * return value is an XA_ERROR() code before using the returned value. 256*d96e5996SHans Petter Selasky */ 257*d96e5996SHans Petter Selasky void * 258*d96e5996SHans Petter Selasky __xa_store(struct xarray *xa, uint32_t index, void *ptr, gfp_t gfp) 259*d96e5996SHans Petter Selasky { 260*d96e5996SHans Petter Selasky int retval; 261*d96e5996SHans Petter Selasky 262*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 263*d96e5996SHans Petter Selasky retry: 264*d96e5996SHans Petter Selasky retval = radix_tree_store(&xa->root, index, &ptr); 265*d96e5996SHans Petter Selasky 266*d96e5996SHans Petter Selasky switch (retval) { 267*d96e5996SHans Petter Selasky case 0: 268*d96e5996SHans Petter Selasky break; 269*d96e5996SHans Petter Selasky case -ENOMEM: 270*d96e5996SHans Petter Selasky if (likely(gfp & M_WAITOK)) { 271*d96e5996SHans Petter Selasky xa_vm_wait_locked(xa); 272*d96e5996SHans Petter Selasky goto retry; 273*d96e5996SHans Petter Selasky } 274*d96e5996SHans Petter Selasky ptr = XA_ERROR(retval); 275*d96e5996SHans Petter Selasky break; 276*d96e5996SHans Petter Selasky default: 277*d96e5996SHans Petter Selasky ptr = XA_ERROR(retval); 278*d96e5996SHans Petter Selasky break; 279*d96e5996SHans Petter Selasky } 280*d96e5996SHans Petter Selasky return (ptr); 281*d96e5996SHans Petter Selasky } 282*d96e5996SHans Petter Selasky 283*d96e5996SHans Petter Selasky void * 284*d96e5996SHans Petter Selasky xa_store(struct xarray *xa, uint32_t index, void *ptr, gfp_t gfp) 285*d96e5996SHans Petter Selasky { 286*d96e5996SHans Petter Selasky void *retval; 287*d96e5996SHans Petter Selasky 288*d96e5996SHans Petter Selasky xa_lock(xa); 289*d96e5996SHans Petter Selasky retval = __xa_store(xa, index, ptr, gfp); 290*d96e5996SHans Petter Selasky xa_unlock(xa); 291*d96e5996SHans Petter Selasky 292*d96e5996SHans Petter Selasky return (retval); 293*d96e5996SHans Petter Selasky } 294*d96e5996SHans Petter Selasky 295*d96e5996SHans Petter Selasky /* 296*d96e5996SHans Petter Selasky * This function initialize an xarray structure. 297*d96e5996SHans Petter Selasky */ 298*d96e5996SHans Petter Selasky void 299*d96e5996SHans Petter Selasky xa_init_flags(struct xarray *xa, uint32_t flags) 300*d96e5996SHans Petter Selasky { 301*d96e5996SHans Petter Selasky memset(xa, 0, sizeof(*xa)); 302*d96e5996SHans Petter Selasky 303*d96e5996SHans Petter Selasky mtx_init(&xa->mtx, "lkpi-xarray", NULL, MTX_DEF | MTX_RECURSE); 304*d96e5996SHans Petter Selasky xa->root.gfp_mask = GFP_NOWAIT; 305*d96e5996SHans Petter Selasky } 306*d96e5996SHans Petter Selasky 307*d96e5996SHans Petter Selasky /* 308*d96e5996SHans Petter Selasky * This function destroys an xarray structure and all its internal 309*d96e5996SHans Petter Selasky * memory and locks. 310*d96e5996SHans Petter Selasky */ 311*d96e5996SHans Petter Selasky void 312*d96e5996SHans Petter Selasky xa_destroy(struct xarray *xa) 313*d96e5996SHans Petter Selasky { 314*d96e5996SHans Petter Selasky struct radix_tree_iter iter; 315*d96e5996SHans Petter Selasky void **ppslot; 316*d96e5996SHans Petter Selasky 317*d96e5996SHans Petter Selasky radix_tree_for_each_slot(ppslot, &xa->root, &iter, 0) 318*d96e5996SHans Petter Selasky radix_tree_iter_delete(&xa->root, &iter, ppslot); 319*d96e5996SHans Petter Selasky mtx_destroy(&xa->mtx); 320*d96e5996SHans Petter Selasky } 321*d96e5996SHans Petter Selasky 322*d96e5996SHans Petter Selasky /* 323*d96e5996SHans Petter Selasky * This function checks if an xarray is empty or not. 324*d96e5996SHans Petter Selasky * It returns true if empty, else false. 325*d96e5996SHans Petter Selasky */ 326*d96e5996SHans Petter Selasky bool 327*d96e5996SHans Petter Selasky __xa_empty(struct xarray *xa) 328*d96e5996SHans Petter Selasky { 329*d96e5996SHans Petter Selasky struct radix_tree_iter iter = {}; 330*d96e5996SHans Petter Selasky void **temp; 331*d96e5996SHans Petter Selasky 332*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 333*d96e5996SHans Petter Selasky 334*d96e5996SHans Petter Selasky return (!radix_tree_iter_find(&xa->root, &iter, &temp)); 335*d96e5996SHans Petter Selasky } 336*d96e5996SHans Petter Selasky 337*d96e5996SHans Petter Selasky bool 338*d96e5996SHans Petter Selasky xa_empty(struct xarray *xa) 339*d96e5996SHans Petter Selasky { 340*d96e5996SHans Petter Selasky bool retval; 341*d96e5996SHans Petter Selasky 342*d96e5996SHans Petter Selasky xa_lock(xa); 343*d96e5996SHans Petter Selasky retval = __xa_empty(xa); 344*d96e5996SHans Petter Selasky xa_unlock(xa); 345*d96e5996SHans Petter Selasky 346*d96e5996SHans Petter Selasky return (retval); 347*d96e5996SHans Petter Selasky } 348*d96e5996SHans Petter Selasky 349*d96e5996SHans Petter Selasky /* 350*d96e5996SHans Petter Selasky * This function returns the next valid xarray entry based on the 351*d96e5996SHans Petter Selasky * index given by "pindex". The valued pointed to by "pindex" is 352*d96e5996SHans Petter Selasky * updated before return. 353*d96e5996SHans Petter Selasky */ 354*d96e5996SHans Petter Selasky void * 355*d96e5996SHans Petter Selasky __xa_next(struct xarray *xa, unsigned long *pindex, bool not_first) 356*d96e5996SHans Petter Selasky { 357*d96e5996SHans Petter Selasky struct radix_tree_iter iter = { .index = *pindex }; 358*d96e5996SHans Petter Selasky void **ppslot; 359*d96e5996SHans Petter Selasky void *retval; 360*d96e5996SHans Petter Selasky bool found; 361*d96e5996SHans Petter Selasky 362*d96e5996SHans Petter Selasky XA_ASSERT_LOCKED(xa); 363*d96e5996SHans Petter Selasky 364*d96e5996SHans Petter Selasky if (not_first) { 365*d96e5996SHans Petter Selasky /* advance to next index, if any */ 366*d96e5996SHans Petter Selasky iter.index++; 367*d96e5996SHans Petter Selasky if (iter.index == 0) 368*d96e5996SHans Petter Selasky return (NULL); 369*d96e5996SHans Petter Selasky } 370*d96e5996SHans Petter Selasky 371*d96e5996SHans Petter Selasky found = radix_tree_iter_find(&xa->root, &iter, &ppslot); 372*d96e5996SHans Petter Selasky if (likely(found)) { 373*d96e5996SHans Petter Selasky retval = *ppslot; 374*d96e5996SHans Petter Selasky *pindex = iter.index; 375*d96e5996SHans Petter Selasky } else { 376*d96e5996SHans Petter Selasky retval = NULL; 377*d96e5996SHans Petter Selasky } 378*d96e5996SHans Petter Selasky return (retval); 379*d96e5996SHans Petter Selasky } 380*d96e5996SHans Petter Selasky 381*d96e5996SHans Petter Selasky void * 382*d96e5996SHans Petter Selasky xa_next(struct xarray *xa, unsigned long *pindex, bool not_first) 383*d96e5996SHans Petter Selasky { 384*d96e5996SHans Petter Selasky void *retval; 385*d96e5996SHans Petter Selasky 386*d96e5996SHans Petter Selasky xa_lock(xa); 387*d96e5996SHans Petter Selasky retval = __xa_next(xa, pindex, not_first); 388*d96e5996SHans Petter Selasky xa_unlock(xa); 389*d96e5996SHans Petter Selasky 390*d96e5996SHans Petter Selasky return (retval); 391*d96e5996SHans Petter Selasky } 392