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

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