svn commit: r294505 - in head/sys: compat/linuxkpi/common/include/linux compat/linuxkpi/common/src sys

Hans Petter Selasky hselasky at FreeBSD.org
Thu Jan 21 14:57:46 UTC 2016


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,


More information about the svn-src-head mailing list