All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy@infradead.org>
To: linux-kernel@vger.kernel.org
Cc: Matthew Wilcox <willy@infradead.org>
Subject: [PATCH 03/26] ida: Add new API
Date: Thu, 21 Jun 2018 14:28:12 -0700	[thread overview]
Message-ID: <20180621212835.5636-4-willy@infradead.org> (raw)
In-Reply-To: <20180621212835.5636-1-willy@infradead.org>

Add ida_alloc(), ida_alloc_min(), ida_alloc_max(), ida_alloc_range()
and ida_free().  The ida_alloc_max() and ida_alloc_range() functions
differ from ida_simple_get() in that they take an inclusive 'max'
parameter instead of an exclusive 'end' parameter.  Callers are about
evenly split whether they'd like inclusive or exclusive parameters and
'max' is easier to document than 'end'.

Change the IDA allocation to first attempt to allocate a bit using
existing memory, and only allocate memory afterwards.  Also change the
behaviour of 'min' > INT_MAX from being a BUG() to returning -ENOSPC.

Leave compatibility wrappers in place for ida_simple_get() and
ida_simple_remove() to avoid changing all callers.

Signed-off-by: Matthew Wilcox <willy@infradead.org>
---
 include/linux/idr.h | 59 ++++++++++++++++++++++++++++++++++++--
 lib/idr.c           | 70 ++++++++++++++++++++-------------------------
 2 files changed, 87 insertions(+), 42 deletions(-)

diff --git a/include/linux/idr.h b/include/linux/idr.h
index e856f4e0ab35..cd339da0b1aa 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -230,15 +230,68 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
 void ida_remove(struct ida *ida, int id);
 void ida_destroy(struct ida *ida);
 
-int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
-		   gfp_t gfp_mask);
-void ida_simple_remove(struct ida *ida, unsigned int id);
+int ida_alloc_range(struct ida *, unsigned int min, unsigned int max, gfp_t);
+void ida_free(struct ida *, unsigned int id);
+
+/**
+ * ida_alloc() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @gfp: Memory allocation flags.
+ *
+ * Allocate an ID between 0 and %INT_MAX, inclusive.
+ *
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
+ */
+static inline int ida_alloc(struct ida *ida, gfp_t gfp)
+{
+	return ida_alloc_range(ida, 0, ~0, gfp);
+}
+
+/**
+ * ida_alloc_min() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @min: Lowest ID to allocate.
+ * @gfp: Memory allocation flags.
+ *
+ * Allocate an ID between @min and %INT_MAX, inclusive.
+ *
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
+ */
+static inline int ida_alloc_min(struct ida *ida, unsigned int min, gfp_t gfp)
+{
+	return ida_alloc_range(ida, min, ~0, gfp);
+}
+
+/**
+ * ida_alloc_max() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @max: Highest ID to allocate.
+ * @gfp: Memory allocation flags.
+ *
+ * Allocate an ID between 0 and @max, inclusive.
+ *
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
+ */
+static inline int ida_alloc_max(struct ida *ida, unsigned int max, gfp_t gfp)
+{
+	return ida_alloc_range(ida, 0, max, gfp);
+}
 
 static inline void ida_init(struct ida *ida)
 {
 	INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT);
 }
 
+#define ida_simple_get(ida, start, end, gfp)	\
+			ida_alloc_range(ida, start, (end) - 1, gfp)
+#define ida_simple_remove(ida, id)	ida_free(ida, id)
+
 /**
  * ida_get_new - allocate new ID
  * @ida:	idr handle
diff --git a/lib/idr.c b/lib/idr.c
index 352c6160e2e0..8b3a5e7eb734 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -317,7 +317,8 @@ EXPORT_SYMBOL(idr_replace);
  * bit per ID, and so is more space efficient than an IDR.  To use an IDA,
  * define it using DEFINE_IDA() (or embed a &struct ida in a data structure,
  * then initialise it using ida_init()).  To allocate a new ID, call
- * ida_simple_get().  To free an ID, call ida_simple_remove().
+ * ida_alloc(), ida_alloc_max() or ida_alloc_range().  To free an ID, call
+ * ida_free().
  *
  * If you have more complex locking requirements, use a loop around
  * ida_pre_get() and ida_get_new() to allocate a new ID.  Then use
@@ -378,7 +379,7 @@ EXPORT_SYMBOL(idr_replace);
  * Allocate new ID above or equal to @start.  It should be called
  * with any required locks to ensure that concurrent calls to
  * ida_get_new_above() / ida_get_new() / ida_remove() are not allowed.
- * Consider using ida_simple_get() if you do not have complex locking
+ * Consider using ida_alloc_range() if you do not have complex locking
  * requirements.
  *
  * If memory is required, it will return %-EAGAIN, you should unlock
@@ -551,43 +552,34 @@ void ida_destroy(struct ida *ida)
 EXPORT_SYMBOL(ida_destroy);
 
 /**
- * ida_simple_get - get a new id.
- * @ida: the (initialized) ida.
- * @start: the minimum id (inclusive, < 0x8000000)
- * @end: the maximum id (exclusive, < 0x8000000 or 0)
- * @gfp_mask: memory allocation flags
- *
- * Allocates an id in the range start <= id < end, or returns -ENOSPC.
- * On memory allocation failure, returns -ENOMEM.
+ * ida_alloc_range() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @min: Lowest ID to allocate.
+ * @max: Highest ID to allocate.
+ * @gfp: Memory allocation flags.
  *
- * Compared to ida_get_new_above() this function does its own locking, and
- * should be used unless there are special requirements.
+ * Allocate an ID between @min and @max, inclusive.  The allocated ID will
+ * not exceed %INT_MAX, even if @max is larger.
  *
- * Use ida_simple_remove() to get rid of an id.
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
  */
-int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
-		   gfp_t gfp_mask)
+int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max,
+			gfp_t gfp)
 {
 	int ret, id;
-	unsigned int max;
 	unsigned long flags;
 
-	BUG_ON((int)start < 0);
-	BUG_ON((int)end < 0);
+	if ((int)min < 0)
+		return -ENOSPC;
 
-	if (end == 0)
-		max = 0x80000000;
-	else {
-		BUG_ON(end < start);
-		max = end - 1;
-	}
+	if ((int)max < 0)
+		max = INT_MAX;
 
 again:
-	if (!ida_pre_get(ida, gfp_mask))
-		return -ENOMEM;
-
 	xa_lock_irqsave(&ida->ida_rt, flags);
-	ret = ida_get_new_above(ida, start, &id);
+	ret = ida_get_new_above(ida, min, &id);
 	if (!ret) {
 		if (id > max) {
 			ida_remove(ida, id);
@@ -598,24 +590,24 @@ int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
 	}
 	xa_unlock_irqrestore(&ida->ida_rt, flags);
 
-	if (unlikely(ret == -EAGAIN))
+	if (unlikely(ret == -EAGAIN)) {
+		if (!ida_pre_get(ida, gfp))
+			return -ENOMEM;
 		goto again;
+	}
 
 	return ret;
 }
-EXPORT_SYMBOL(ida_simple_get);
+EXPORT_SYMBOL(ida_alloc_range);
 
 /**
- * ida_simple_remove - remove an allocated id.
- * @ida: the (initialized) ida.
- * @id: the id returned by ida_simple_get.
- *
- * Use to release an id allocated with ida_simple_get().
+ * ida_free() - Release an allocated ID.
+ * @ida: IDA handle.
+ * @id: Previously allocated ID.
  *
- * Compared to ida_remove() this function does its own locking, and should be
- * used unless there are special requirements.
+ * Context: Any context.
  */
-void ida_simple_remove(struct ida *ida, unsigned int id)
+void ida_free(struct ida *ida, unsigned int id)
 {
 	unsigned long flags;
 
@@ -624,4 +616,4 @@ void ida_simple_remove(struct ida *ida, unsigned int id)
 	ida_remove(ida, id);
 	xa_unlock_irqrestore(&ida->ida_rt, flags);
 }
-EXPORT_SYMBOL(ida_simple_remove);
+EXPORT_SYMBOL(ida_free);
-- 
2.17.1


  parent reply	other threads:[~2018-06-21 21:37 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-21 21:28 [PATCH 00/26] New IDA API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 01/26] radix tree test suite: fix build Matthew Wilcox
2018-06-21 21:28 ` [PATCH 02/26] ida: Lock the IDA in ida_destroy Matthew Wilcox
2018-06-21 21:28 ` Matthew Wilcox [this message]
2018-06-21 21:28 ` [PATCH 04/26] mtip32xx: Convert to new IDA API Matthew Wilcox
2018-06-25  8:20   ` Johannes Thumshirn
2018-06-25  8:20     ` Johannes Thumshirn
2018-06-21 21:28 ` [PATCH 05/26] fs: Convert unnamed_dev_ida to new API Matthew Wilcox
2018-06-22 19:45   ` Randy Dunlap
2018-06-22 21:12     ` Matthew Wilcox
2018-06-21 21:28 ` [PATCH 06/26] fs: Convert namespace IDAs " Matthew Wilcox
2018-06-21 21:28 ` [PATCH 07/26] devpts: Convert to new IDA API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 08/26] sd: Convert to new IDA interface Matthew Wilcox
2018-06-21 21:28 ` [PATCH 09/26] osd: Convert to new IDA API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 10/26] rsxx: " Matthew Wilcox
2018-06-21 21:28 ` [PATCH 11/26] cb710: " Matthew Wilcox
2018-06-21 21:33   ` Michał Mirosław
2018-06-21 21:28 ` [PATCH 12/26] Convert net_namespace " Matthew Wilcox
2018-06-21 21:28 ` [PATCH 13/26] ppc: Convert mmu context allocation " Matthew Wilcox
2018-06-22  2:15   ` Nicholas Piggin
2018-06-22  4:38     ` Matthew Wilcox
2018-06-22  4:53       ` Nicholas Piggin
2018-06-22  5:47       ` Aneesh Kumar K.V
2018-06-22  5:47     ` Aneesh Kumar K.V
2018-06-21 21:28 ` [PATCH 14/26] media: Convert entity ID " Matthew Wilcox
2018-07-24 11:05   ` Sakari Ailus
2018-07-30 14:55     ` Mauro Carvalho Chehab
2018-07-31 18:16       ` Matthew Wilcox
2018-06-21 21:28 ` [PATCH 15/26] ppc: Convert vas " Matthew Wilcox
2018-07-05 12:17   ` Matthew Wilcox
2018-06-21 21:28 ` [PATCH 17/26] drm/vmwgfx: Convert " Matthew Wilcox
2018-06-21 21:28 ` [PATCH 18/26] target/iscsi: Allocate session IDs from an IDA Matthew Wilcox
2018-06-21 21:28   ` Matthew Wilcox
2018-07-26 16:48   ` Mike Christie
2018-07-26 16:48     ` Mike Christie
2018-07-26 16:50     ` Mike Christie
2018-07-26 16:50       ` Mike Christie
2018-07-26 17:13     ` Mike Christie
2018-07-26 17:13       ` Mike Christie
2018-07-26 17:13       ` Mike Christie
2018-07-27 19:38       ` Matthew Wilcox
2018-07-27 19:38         ` Matthew Wilcox
2018-07-27 21:05         ` Mike Christie
2018-07-27 21:05           ` Mike Christie
2018-07-31  2:03           ` Martin K. Petersen
2018-07-31  2:03             ` Martin K. Petersen
2018-07-31 18:15             ` Matthew Wilcox
2018-07-31 18:15               ` Matthew Wilcox
2018-07-31 18:55               ` Mike Christie
2018-07-31 18:55                 ` Mike Christie
2018-06-21 21:28 ` [PATCH 19/26] ida: Start new test_ida module Matthew Wilcox
2018-06-21 21:28 ` [PATCH 20/26] idr-test: Convert ida_check_nomem to new API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 21/26] test_ida: Move ida_check_leaf Matthew Wilcox
2018-06-21 21:28 ` [PATCH 22/26] test_ida: Move ida_check_max Matthew Wilcox
2018-06-21 21:28 ` [PATCH 23/26] test_ida: Convert check_ida_conv to new API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 24/26] test_ida: check_ida_destroy and check_ida_alloc Matthew Wilcox
2018-06-21 21:28 ` [PATCH 25/26] ida: Remove old API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 26/26] ida: Change ida_get_new_above to return the id Matthew Wilcox
2018-06-21 21:28 [16/26] dmaengine: Convert to new IDA API Matthew Wilcox
2018-06-21 21:28 ` [PATCH 16/26] " Matthew Wilcox
2018-06-23 12:30 [16/26] " Vinod Koul
2018-06-23 12:30 ` [PATCH 16/26] " Vinod
2018-06-23 23:06 [16/26] " Matthew Wilcox
2018-06-23 23:06 ` [PATCH 16/26] " Matthew Wilcox
2018-06-24  7:57 [16/26] " Lars-Peter Clausen
2018-06-24  7:57 ` [PATCH 16/26] " Lars-Peter Clausen
2018-06-26 23:00 [16/26] " Matthew Wilcox
2018-06-26 23:00 ` [PATCH 16/26] " Matthew Wilcox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180621212835.5636-4-willy@infradead.org \
    --to=willy@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.