linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] lib/bsearch.c: introduce bsearch_idx
@ 2019-10-19  7:20 Thomas Meyer
  2019-10-19  7:20 ` [PATCH 2/2] xfs: replace homemade binary search Thomas Meyer
  0 siblings, 1 reply; 3+ messages in thread
From: Thomas Meyer @ 2019-10-19  7:20 UTC (permalink / raw)
  To: linux-kernel, linux-xfs; +Cc: Thomas Meyer

many existing bsearch implementations don't want to have the pointer to the
found element, but the index position, or if the searched element doesn't
exist, the index position the search element would be placed in the array.

Signed-off-by: Thomas Meyer <thomas@m3y3r.de>
---
 include/linux/bsearch.h |  7 +++++
 lib/bsearch.c           | 62 +++++++++++++++++++++++++++++++++--------
 2 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/include/linux/bsearch.h b/include/linux/bsearch.h
index 62b1eb3488584..0c40c8b39b881 100644
--- a/include/linux/bsearch.h
+++ b/include/linux/bsearch.h
@@ -7,4 +7,11 @@
 void *bsearch(const void *key, const void *base, size_t num, size_t size,
 	      int (*cmp)(const void *key, const void *elt));
 
+struct bsearch_result { size_t idx; bool found; };
+
+struct bsearch_result bsearch_idx(const void *key, const void *base,
+		      size_t num,
+		      size_t size,
+		      int (*cmp)(const void *key, const void *elt));
+
 #endif /* _LINUX_BSEARCH_H */
diff --git a/lib/bsearch.c b/lib/bsearch.c
index 8baa839681628..5c46d0ec1e473 100644
--- a/lib/bsearch.c
+++ b/lib/bsearch.c
@@ -10,8 +10,8 @@
 #include <linux/bsearch.h>
 #include <linux/kprobes.h>
 
-/*
- * bsearch - binary search an array of elements
+/**
+ * bsearch() - binary search an array of elements
  * @key: pointer to item being searched for
  * @base: pointer to first element to search
  * @num: number of elements
@@ -27,28 +27,68 @@
  * could compare the string with the struct's name field.  However, if
  * the key and elements in the array are of the same type, you can use
  * the same comparison function for both sort() and bsearch().
+ *
+ * Return: Either a pointer to the search element or NULL if not found.
  */
 void *bsearch(const void *key, const void *base, size_t num, size_t size,
 	      int (*cmp)(const void *key, const void *elt))
 {
-	const char *pivot;
+	struct bsearch_result idx = bsearch_idx(key, base, num, size, cmp);
+
+	if (idx.found == true)
+		return (void *)base + idx.idx * size;
+
+	return NULL;
+}
+EXPORT_SYMBOL(bsearch);
+NOKPROBE_SYMBOL(bsearch);
+
+/**
+ * bsearch_idx() - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Returns an index position and a bool if an exact match was found
+ * if an exact match was found the idx is the index in the base array.
+ * if no exact match was found the idx will point the the next higher index
+ * entry in the base array. this can also be base[num], i.e. after the actual
+ * allocated array.
+ */
+struct bsearch_result bsearch_idx(const void *key, const void *base,
+				  size_t num,
+				  size_t size,
+				  int (*cmp)(const void *key, const void *elt))
+{
+	struct bsearch_result res = { .found = false };
 	int result;
+	size_t base_idx = 0;
+	size_t pivot_idx;
 
 	while (num > 0) {
-		pivot = base + (num >> 1) * size;
-		result = cmp(key, pivot);
+		pivot_idx = base_idx + (num >> 1);
+		result = cmp(key, base + pivot_idx * size);
 
-		if (result == 0)
-			return (void *)pivot;
+		if (result == 0) {
+			res.idx = pivot_idx;
+			res.found = true;
+			return res;
+		}
 
 		if (result > 0) {
-			base = pivot + size;
+			base_idx = pivot_idx + 1;
 			num--;
 		}
 		num >>= 1;
 	}
 
-	return NULL;
+	res.idx = base_idx;
+	return res;
 }
-EXPORT_SYMBOL(bsearch);
-NOKPROBE_SYMBOL(bsearch);
+EXPORT_SYMBOL(bsearch_idx);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] xfs: replace homemade binary search
  2019-10-19  7:20 [PATCH 1/2] lib/bsearch.c: introduce bsearch_idx Thomas Meyer
@ 2019-10-19  7:20 ` Thomas Meyer
  2019-10-19  8:12   ` Christoph Hellwig
  0 siblings, 1 reply; 3+ messages in thread
From: Thomas Meyer @ 2019-10-19  7:20 UTC (permalink / raw)
  To: linux-kernel, linux-xfs; +Cc: Thomas Meyer

use newly introduced bsearch_idx instead.

Signed-off-by: Thomas Meyer <thomas@m3y3r.de>
---
 fs/xfs/libxfs/xfs_dir2_block.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 9595ced393dce..e484ec68944fb 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -20,6 +20,7 @@
 #include "xfs_error.h"
 #include "xfs_trace.h"
 #include "xfs_log.h"
+#include <linux/bsearch.h>
 
 /*
  * Local function prototypes.
@@ -314,6 +315,19 @@ xfs_dir2_block_compact(
 		xfs_dir2_data_freescan(args->dp, hdr, needlog);
 }
 
+static int cmp_hashval(const void *key, const void *elt)
+{
+	xfs_dahash_t _search_key = *(xfs_dahash_t *)key;
+	xfs_dahash_t _curren_key = be32_to_cpu((
+				(xfs_dir2_leaf_entry_t *) elt)->hashval);
+
+	if (_search_key == _curren_key)
+		return 0;
+	else if (_search_key < _curren_key)
+		return -1;
+	return 1;
+}
+
 /*
  * Add an entry to a block directory.
  */
@@ -331,19 +345,17 @@ xfs_dir2_block_addname(
 	xfs_dir2_data_unused_t	*dup;		/* block unused entry */
 	int			error;		/* error return value */
 	xfs_dir2_data_unused_t	*enddup=NULL;	/* unused at end of data */
-	xfs_dahash_t		hash;		/* hash value of found entry */
-	int			high;		/* high index for binary srch */
 	int			highstale;	/* high stale index */
 	int			lfloghigh=0;	/* last final leaf to log */
 	int			lfloglow=0;	/* first final leaf to log */
 	int			len;		/* length of the new entry */
-	int			low;		/* low index for binary srch */
 	int			lowstale;	/* low stale index */
 	int			mid=0;		/* midpoint for binary srch */
 	int			needlog;	/* need to log header */
 	int			needscan;	/* need to rescan freespace */
 	__be16			*tagp;		/* pointer to tag value */
 	xfs_trans_t		*tp;		/* transaction structure */
+	struct bsearch_result	idx;		/* bsearch result */
 
 	trace_xfs_dir2_block_addname(args);
 
@@ -420,15 +432,9 @@ xfs_dir2_block_addname(
 	/*
 	 * Find the slot that's first lower than our hash value, -1 if none.
 	 */
-	for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) {
-		mid = (low + high) >> 1;
-		if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
-			break;
-		if (hash < args->hashval)
-			low = mid + 1;
-		else
-			high = mid - 1;
-	}
+	idx = bsearch_idx(&args->hashval, blp, be32_to_cpu(btp->count) - 1,
+			  sizeof(xfs_dir2_leaf_entry_t), cmp_hashval);
+	mid = idx.idx;
 	while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) {
 		mid--;
 	}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 2/2] xfs: replace homemade binary search
  2019-10-19  7:20 ` [PATCH 2/2] xfs: replace homemade binary search Thomas Meyer
@ 2019-10-19  8:12   ` Christoph Hellwig
  0 siblings, 0 replies; 3+ messages in thread
From: Christoph Hellwig @ 2019-10-19  8:12 UTC (permalink / raw)
  To: Thomas Meyer; +Cc: linux-kernel, linux-xfs

On Sat, Oct 19, 2019 at 09:20:33AM +0200, Thomas Meyer wrote:
> use newly introduced bsearch_idx instead.
> 
> Signed-off-by: Thomas Meyer <thomas@m3y3r.de>

What is the point?  This adds more code, and makes it slower by
adding an indirect function call.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-10-19  8:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-19  7:20 [PATCH 1/2] lib/bsearch.c: introduce bsearch_idx Thomas Meyer
2019-10-19  7:20 ` [PATCH 2/2] xfs: replace homemade binary search Thomas Meyer
2019-10-19  8:12   ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).