|
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 |
|