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

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