Implement idr_preload(), idr_preload_end(), idr_alloc() and
idr_alloc_cyclic() in the LinuxKPI. Bump the FreeBSD version to force recompilation of all KLDs due to IDR structure size change. MFC after: 2 weeks Sponsored by: Mellanox Technologies
This commit is contained in:
parent
d16eeed462
commit
a4e93c419f
@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2010 Isilon Systems, Inc.
|
||||
* Copyright (c) 2010 iX Systems, Inc.
|
||||
* Copyright (c) 2010 Panasas, Inc.
|
||||
* Copyright (c) 2013 Mellanox Technologies, Ltd.
|
||||
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -60,6 +60,7 @@ struct idr {
|
||||
struct idr_layer *top;
|
||||
struct idr_layer *free;
|
||||
int layers;
|
||||
int next_cyclic_id;
|
||||
};
|
||||
|
||||
#define DEFINE_IDR(name) \
|
||||
@ -67,6 +68,9 @@ struct idr {
|
||||
SYSINIT(name##_idr_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, \
|
||||
idr_init, &(name));
|
||||
|
||||
#define idr_preload(x) do { } while (0)
|
||||
#define idr_preload_end() do { } while (0)
|
||||
|
||||
void *idr_find(struct idr *idp, int id);
|
||||
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
|
||||
int idr_get_new(struct idr *idp, void *ptr, int *id);
|
||||
@ -76,5 +80,7 @@ void idr_remove(struct idr *idp, int id);
|
||||
void idr_remove_all(struct idr *idp);
|
||||
void idr_destroy(struct idr *idp);
|
||||
void idr_init(struct idr *idp);
|
||||
int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t);
|
||||
int idr_alloc_cyclic(struct idr *idp, void *ptr, int start, int end, gfp_t);
|
||||
|
||||
#endif /* _LINUX_IDR_H_ */
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2010 Isilon Systems, Inc.
|
||||
* Copyright (c) 2010 iX Systems, Inc.
|
||||
* Copyright (c) 2010 Panasas, Inc.
|
||||
* Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
|
||||
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -116,21 +116,18 @@ idr_remove_all(struct idr *idr)
|
||||
mtx_unlock(&idr->lock);
|
||||
}
|
||||
|
||||
void
|
||||
idr_remove(struct idr *idr, int id)
|
||||
static void
|
||||
idr_remove_locked(struct idr *idr, int id)
|
||||
{
|
||||
struct idr_layer *il;
|
||||
int layer;
|
||||
int idx;
|
||||
|
||||
id &= MAX_ID_MASK;
|
||||
mtx_lock(&idr->lock);
|
||||
il = idr->top;
|
||||
layer = idr->layers - 1;
|
||||
if (il == NULL || id > idr_max(idr)) {
|
||||
mtx_unlock(&idr->lock);
|
||||
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.
|
||||
@ -152,8 +149,14 @@ idr_remove(struct idr *idr, int id)
|
||||
id, idr, il);
|
||||
il->ary[idx] = NULL;
|
||||
il->bitmap |= 1 << idx;
|
||||
}
|
||||
|
||||
void
|
||||
idr_remove(struct idr *idr, int id)
|
||||
{
|
||||
mtx_lock(&idr->lock);
|
||||
idr_remove_locked(idr, id);
|
||||
mtx_unlock(&idr->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
@ -278,8 +281,8 @@ idr_get(struct idr *idr)
|
||||
* Could be implemented as get_new_above(idr, ptr, 0, idp) but written
|
||||
* first for simplicity sake.
|
||||
*/
|
||||
int
|
||||
idr_get_new(struct idr *idr, void *ptr, int *idp)
|
||||
static int
|
||||
idr_get_new_locked(struct idr *idr, void *ptr, int *idp)
|
||||
{
|
||||
struct idr_layer *stack[MAX_LEVEL];
|
||||
struct idr_layer *il;
|
||||
@ -288,8 +291,9 @@ idr_get_new(struct idr *idr, void *ptr, int *idp)
|
||||
int idx;
|
||||
int id;
|
||||
|
||||
mtx_assert(&idr->lock, MA_OWNED);
|
||||
|
||||
error = -EAGAIN;
|
||||
mtx_lock(&idr->lock);
|
||||
/*
|
||||
* Expand the tree until there is free space.
|
||||
*/
|
||||
@ -350,12 +354,22 @@ out:
|
||||
idr, id, ptr);
|
||||
}
|
||||
#endif
|
||||
mtx_unlock(&idr->lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
idr_get_new_above(struct idr *idr, void *ptr, int starting_id, int *idp)
|
||||
idr_get_new(struct idr *idr, void *ptr, int *idp)
|
||||
{
|
||||
int retval;
|
||||
|
||||
mtx_lock(&idr->lock);
|
||||
retval = idr_get_new_locked(idr, ptr, idp);
|
||||
mtx_unlock(&idr->lock);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
idr_get_new_above_locked(struct idr *idr, void *ptr, int starting_id, int *idp)
|
||||
{
|
||||
struct idr_layer *stack[MAX_LEVEL];
|
||||
struct idr_layer *il;
|
||||
@ -364,8 +378,9 @@ idr_get_new_above(struct idr *idr, void *ptr, int starting_id, int *idp)
|
||||
int idx, sidx;
|
||||
int id;
|
||||
|
||||
mtx_assert(&idr->lock, MA_OWNED);
|
||||
|
||||
error = -EAGAIN;
|
||||
mtx_lock(&idr->lock);
|
||||
/*
|
||||
* Compute the layers required to support starting_id and the mask
|
||||
* at the top layer.
|
||||
@ -457,6 +472,70 @@ out:
|
||||
idr, id, ptr);
|
||||
}
|
||||
#endif
|
||||
mtx_unlock(&idr->lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
idr_get_new_above(struct idr *idr, void *ptr, int starting_id, int *idp)
|
||||
{
|
||||
int retval;
|
||||
|
||||
mtx_lock(&idr->lock);
|
||||
retval = idr_get_new_above_locked(idr, ptr, starting_id, idp);
|
||||
mtx_unlock(&idr->lock);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
idr_alloc_locked(struct idr *idr, void *ptr, int start, int end)
|
||||
{
|
||||
int max = end > 0 ? end - 1 : INT_MAX;
|
||||
int error;
|
||||
int id;
|
||||
|
||||
mtx_assert(&idr->lock, MA_OWNED);
|
||||
|
||||
if (unlikely(start < 0))
|
||||
return (-EINVAL);
|
||||
if (unlikely(max < start))
|
||||
return (-ENOSPC);
|
||||
|
||||
if (start == 0)
|
||||
error = idr_get_new_locked(idr, ptr, &id);
|
||||
else
|
||||
error = idr_get_new_above_locked(idr, ptr, start, &id);
|
||||
|
||||
if (unlikely(error < 0))
|
||||
return (error);
|
||||
if (unlikely(id > max)) {
|
||||
idr_remove_locked(idr, id);
|
||||
return (-ENOSPC);
|
||||
}
|
||||
return (id);
|
||||
}
|
||||
|
||||
int
|
||||
idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask)
|
||||
{
|
||||
int retval;
|
||||
|
||||
mtx_lock(&idr->lock);
|
||||
retval = idr_alloc_locked(idr, ptr, start, end);
|
||||
mtx_unlock(&idr->lock);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
int
|
||||
idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask)
|
||||
{
|
||||
int retval;
|
||||
|
||||
mtx_lock(&idr->lock);
|
||||
retval = idr_alloc_locked(idr, ptr, max(start, idr->next_cyclic_id), end);
|
||||
if (unlikely(retval == -ENOSPC))
|
||||
retval = idr_alloc_locked(idr, ptr, start, end);
|
||||
if (likely(retval >= 0))
|
||||
idr->next_cyclic_id = retval + 1;
|
||||
mtx_unlock(&idr->lock);
|
||||
return (retval);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@
|
||||
* in the range 5 to 9.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1100095 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 1100096 /* Master, propagated to newvers */
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
Loading…
x
Reference in New Issue
Block a user