Date: Thu, 21 Jan 2016 14:57:45 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r294505 - in head/sys: compat/linuxkpi/common/include/linux compat/linuxkpi/common/src sys Message-ID: <201601211457.u0LEvjQP058492@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Thu Jan 21 14:57:45 2016 New Revision: 294505 URL: https://svnweb.freebsd.org/changeset/base/294505 Log: 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 Modified: head/sys/compat/linuxkpi/common/include/linux/idr.h head/sys/compat/linuxkpi/common/src/linux_idr.c head/sys/sys/param.h Modified: head/sys/compat/linuxkpi/common/include/linux/idr.h ============================================================================== --- head/sys/compat/linuxkpi/common/include/linux/idr.h Thu Jan 21 14:50:28 2016 (r294504) +++ head/sys/compat/linuxkpi/common/include/linux/idr.h Thu Jan 21 14:57:45 2016 (r294505) @@ -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_ */ Modified: head/sys/compat/linuxkpi/common/src/linux_idr.c ============================================================================== --- head/sys/compat/linuxkpi/common/src/linux_idr.c Thu Jan 21 14:50:28 2016 (r294504) +++ head/sys/compat/linuxkpi/common/src/linux_idr.c Thu Jan 21 14:57:45 2016 (r294505) @@ -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 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 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); +} Modified: head/sys/sys/param.h ============================================================================== --- head/sys/sys/param.h Thu Jan 21 14:50:28 2016 (r294504) +++ head/sys/sys/param.h Thu Jan 21 14:57:45 2016 (r294505) @@ -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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601211457.u0LEvjQP058492>