void * idr_replace(struct idr *idr, void *ptr, int id) { struct idr_layer *il; void *res; int layer; int idx; res = ERR_PTR(-EINVAL); id &= MAX_ID_MASK; mtx_lock(&idr->lock); il = idr->top; layer = idr->layers - 1; if (il == NULL || id > idr_max(idr)) goto out; while (layer && il) { il = il->ary[idr_pos(id, layer)]; layer--; } idx = id & IDR_MASK; /* * Replace still returns an error if the item was not allocated. */ if (il != NULL && (il->bitmap & (1 << idx)) != 0) { res = il->ary[idx]; il->ary[idx] = ptr; } out: mtx_unlock(&idr->lock); return (res); }
static void idr_remove_locked(struct idr *idr, int id) { struct idr_layer *il; int layer; int idx; id &= MAX_ID_MASK; il = idr->top; layer = idr->layers - 1; if (il == NULL || id > idr_max(idr)) return; /* * Walk down the tree to this item setting bitmaps along the way * as we know at least one item will be free along this path. */ while (layer && il) { idx = idr_pos(id, layer); il->bitmap |= 1 << idx; il = il->ary[idx]; layer--; } idx = id & IDR_MASK; /* * At this point we've set free space bitmaps up the whole tree. * We could make this non-fatal and unwind but linux dumps a stack * and a warning so I don't think it's necessary. */ if (il == NULL || (il->bitmap & (1 << idx)) != 0) panic("idr_remove: Item %d not allocated (%p, %p)\n", id, idr, il); il->ary[idx] = NULL; il->bitmap |= 1 << idx; }
void * idr_get_next(struct idr *idr, int *nextidp) { void *res = NULL; int id = *nextidp; mtx_lock(&idr->lock); for (; id <= idr_max(idr); id++) { res = idr_find_locked(idr, id); if (res == NULL) continue; *nextidp = id; break; } mtx_unlock(&idr->lock); return (res); }
static inline struct idr_layer * idr_find_layer_locked(struct idr *idr, int id) { struct idr_layer *il; int layer; id &= MAX_ID_MASK; il = idr->top; layer = idr->layers - 1; if (il == NULL || id > idr_max(idr)) return (NULL); while (layer && il) { il = il->ary[idr_pos(id, layer)]; layer--; } return (il); }
static inline void * idr_find_locked(struct idr *idr, int id) { struct idr_layer *il; void *res; int layer; mtx_assert(&idr->lock, MA_OWNED); id &= MAX_ID_MASK; res = NULL; il = idr->top; layer = idr->layers - 1; if (il == NULL || id > idr_max(idr)) return (NULL); while (layer && il) { il = il->ary[idr_pos(id, layer)]; layer--; } if (il != NULL) res = il->ary[id & IDR_MASK]; return (res); }
void * idr_find(struct idr *idr, int id) { struct idr_layer *il; void *res; int layer; res = NULL; id &= MAX_ID_MASK; mtx_lock(&idr->lock); il = idr->top; layer = idr->layers - 1; if (il == NULL || id > idr_max(idr)) goto out; while (layer && il) { il = il->ary[idr_pos(id, layer)]; layer--; } if (il != NULL) res = il->ary[id & IDR_MASK]; out: mtx_unlock(&idr->lock); return (res); }