Blame SOURCES/0052-fs-ntfs3-Limit-binary-search-table-size.patch

Kmods SIG 8b815c
From 162333efa8dc4984d2ca0a2eb85528e13366f271 Mon Sep 17 00:00:00 2001
Kmods SIG 8b815c
From: Kari Argillander <kari.argillander@gmail.com>
Kmods SIG 8b815c
Date: Thu, 2 Sep 2021 18:40:48 +0300
Kmods SIG 8b815c
Subject: [Backport 162333efa8dc] src: Limit binary search table size
Kmods SIG 8b815c
Kmods SIG 8b815c
Current binary search allocates memory for table and fill whole table
Kmods SIG 8b815c
before we start actual binary search. This is quite inefficient because
Kmods SIG 8b815c
table fill will always be O(n). Also if table is huge we need to
Kmods SIG 8b815c
reallocate memory which is costly.
Kmods SIG 8b815c
Kmods SIG 8b815c
This implementation use just stack memory and always when table is full
Kmods SIG 8b815c
we will check if last element is <= and if not start table fill again.
Kmods SIG 8b815c
The idea was that it would be same cost as table reallocation.
Kmods SIG 8b815c
Kmods SIG 8b815c
Signed-off-by: Kari Argillander <kari.argillander@gmail.com>
Kmods SIG 8b815c
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Kmods SIG 8b815c
---
Kmods SIG 8b815c
 src/index.c | 110 ++++++++++++++++++-----------------------------
Kmods SIG 8b815c
 1 file changed, 41 insertions(+), 69 deletions(-)
Kmods SIG 8b815c
Kmods SIG 8b815c
diff --git a/src/index.c b/src/index.c
Kmods SIG 8b815c
index 35b77c92e96dc661baac0cc1ecaa3d0f130ef8e6..a16256ab3e9ffd5bcc660c602194c9bd2de7cfc9 100644
Kmods SIG 8b815c
--- a/src/index.c
Kmods SIG 8b815c
+++ b/src/index.c
Kmods SIG 8b815c
@@ -677,98 +677,70 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx,
Kmods SIG 8b815c
 	u32 off = le32_to_cpu(hdr->de_off);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 #ifdef NTFS3_INDEX_BINARY_SEARCH
Kmods SIG 8b815c
-	int max_idx = 0, fnd, min_idx;
Kmods SIG 8b815c
-	int nslots = 64;
Kmods SIG 8b815c
-	u16 *offs;
Kmods SIG 8b815c
+	struct NTFS_DE *found = NULL;
Kmods SIG 8b815c
+	int min_idx = 0, mid_idx, max_idx = 0;
Kmods SIG 8b815c
+	int diff2;
Kmods SIG 8b815c
+	u16 offs[64];
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	if (end > 0x10000)
Kmods SIG 8b815c
 		goto next;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	offs = kmalloc(sizeof(u16) * nslots, GFP_NOFS);
Kmods SIG 8b815c
-	if (!offs)
Kmods SIG 8b815c
-		goto next;
Kmods SIG 8b815c
+fill_table:
Kmods SIG 8b815c
+	if (off + sizeof(struct NTFS_DE) > end)
Kmods SIG 8b815c
+		return NULL;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	/* Use binary search algorithm. */
Kmods SIG 8b815c
-next1:
Kmods SIG 8b815c
-	if (off + sizeof(struct NTFS_DE) > end) {
Kmods SIG 8b815c
-		e = NULL;
Kmods SIG 8b815c
-		goto out1;
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
 	e = Add2Ptr(hdr, off);
Kmods SIG 8b815c
 	e_size = le16_to_cpu(e->size);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	if (e_size < sizeof(struct NTFS_DE) || off + e_size > end) {
Kmods SIG 8b815c
-		e = NULL;
Kmods SIG 8b815c
-		goto out1;
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	if (max_idx >= nslots) {
Kmods SIG 8b815c
-		u16 *ptr;
Kmods SIG 8b815c
-		int new_slots = ALIGN(2 * nslots, 8);
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-		ptr = kmalloc(sizeof(u16) * new_slots, GFP_NOFS);
Kmods SIG 8b815c
-		if (ptr)
Kmods SIG 8b815c
-			memcpy(ptr, offs, sizeof(u16) * max_idx);
Kmods SIG 8b815c
-		kfree(offs);
Kmods SIG 8b815c
-		offs = ptr;
Kmods SIG 8b815c
-		nslots = new_slots;
Kmods SIG 8b815c
-		if (!ptr)
Kmods SIG 8b815c
-			goto next;
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-	/* Store entry table. */
Kmods SIG 8b815c
-	offs[max_idx] = off;
Kmods SIG 8b815c
+	if (e_size < sizeof(struct NTFS_DE) || off + e_size > end)
Kmods SIG 8b815c
+		return NULL;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	if (!de_is_last(e)) {
Kmods SIG 8b815c
+		offs[max_idx] = off;
Kmods SIG 8b815c
 		off += e_size;
Kmods SIG 8b815c
-		max_idx += 1;
Kmods SIG 8b815c
-		goto next1;
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	/*
Kmods SIG 8b815c
-	 * Table of pointers is created.
Kmods SIG 8b815c
-	 * Use binary search to find entry that is <= to the search value.
Kmods SIG 8b815c
-	 */
Kmods SIG 8b815c
-	fnd = -1;
Kmods SIG 8b815c
-	min_idx = 0;
Kmods SIG 8b815c
+		max_idx++;
Kmods SIG 8b815c
+		if (max_idx < ARRAY_SIZE(offs))
Kmods SIG 8b815c
+			goto fill_table;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	while (min_idx <= max_idx) {
Kmods SIG 8b815c
-		int mid_idx = min_idx + ((max_idx - min_idx) >> 1);
Kmods SIG 8b815c
-		int diff2;
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-		e = Add2Ptr(hdr, offs[mid_idx]);
Kmods SIG 8b815c
+		max_idx--;
Kmods SIG 8b815c
+	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-		e_key_len = le16_to_cpu(e->key_size);
Kmods SIG 8b815c
+binary_search:
Kmods SIG 8b815c
+	e_key_len = le16_to_cpu(e->key_size);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-		diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx);
Kmods SIG 8b815c
+	diff2 = (*cmp)(key, key_len, e + 1, e_key_len, ctx);
Kmods SIG 8b815c
+	if (diff2 > 0) {
Kmods SIG 8b815c
+		if (found) {
Kmods SIG 8b815c
+			min_idx = mid_idx + 1;
Kmods SIG 8b815c
+		} else {
Kmods SIG 8b815c
+			if (de_is_last(e))
Kmods SIG 8b815c
+				return NULL;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-		if (!diff2) {
Kmods SIG 8b815c
-			*diff = 0;
Kmods SIG 8b815c
-			goto out1;
Kmods SIG 8b815c
+			max_idx = 0;
Kmods SIG 8b815c
+			goto fill_table;
Kmods SIG 8b815c
 		}
Kmods SIG 8b815c
-
Kmods SIG 8b815c
-		if (diff2 < 0) {
Kmods SIG 8b815c
+	} else if (diff2 < 0) {
Kmods SIG 8b815c
+		if (found)
Kmods SIG 8b815c
 			max_idx = mid_idx - 1;
Kmods SIG 8b815c
-			fnd = mid_idx;
Kmods SIG 8b815c
-			if (!fnd)
Kmods SIG 8b815c
-				break;
Kmods SIG 8b815c
-		} else {
Kmods SIG 8b815c
-			min_idx = mid_idx + 1;
Kmods SIG 8b815c
-		}
Kmods SIG 8b815c
-	}
Kmods SIG 8b815c
+		else
Kmods SIG 8b815c
+			max_idx--;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	if (fnd == -1) {
Kmods SIG 8b815c
-		e = NULL;
Kmods SIG 8b815c
-		goto out1;
Kmods SIG 8b815c
+		found = e;
Kmods SIG 8b815c
+	} else {
Kmods SIG 8b815c
+		*diff = 0;
Kmods SIG 8b815c
+		return e;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	*diff = -1;
Kmods SIG 8b815c
-	e = Add2Ptr(hdr, offs[fnd]);
Kmods SIG 8b815c
+	if (min_idx > max_idx) {
Kmods SIG 8b815c
+		*diff = -1;
Kmods SIG 8b815c
+		return found;
Kmods SIG 8b815c
+	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-out1:
Kmods SIG 8b815c
-	kfree(offs);
Kmods SIG 8b815c
+	mid_idx = (min_idx + max_idx) >> 1;
Kmods SIG 8b815c
+	e = Add2Ptr(hdr, offs[mid_idx]);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-	return e;
Kmods SIG 8b815c
+	goto binary_search;
Kmods SIG 8b815c
 #endif
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 next:
Kmods SIG 8b815c
-- 
Kmods SIG 8b815c
2.31.1
Kmods SIG 8b815c