-
Notifications
You must be signed in to change notification settings - Fork 156
/
bktr.c
88 lines (76 loc) · 3.42 KB
/
bktr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "bktr.h"
#include "utils.h"
bktr_relocation_bucket_t *bktr_get_relocation_bucket(bktr_relocation_block_t *block, uint32_t i) {
return (bktr_relocation_bucket_t *)((uint8_t *)block->buckets + (sizeof(bktr_relocation_bucket_t) + sizeof(bktr_relocation_entry_t)) * i);
}
/* Get a relocation entry from offset and relocation block. */
bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uint64_t offset) {
/* Weak check for invalid offset. */
if (offset > block->total_size) {
fprintf(stderr, "Too big offset looked up in BKTR relocation table!\n");
exit(EXIT_FAILURE);
}
uint32_t bucket_num = 0;
for (unsigned int i = 1; i < block->num_buckets; i++) {
if (block->bucket_virtual_offsets[i] <= offset) {
bucket_num++;
}
}
bktr_relocation_bucket_t *bucket = bktr_get_relocation_bucket(block, bucket_num);
if (bucket->num_entries == 1) { /* Check for edge case, short circuit. */
return &bucket->entries[0];
}
/* Binary search. */
uint32_t low = 0, high = bucket->num_entries - 1;
while (low <= high) {
uint32_t mid = (low + high) / 2;
if (bucket->entries[mid].virt_offset > offset) { /* Too high. */
high = mid - 1;
} else { /* block->entries[mid].offset <= offset. */
/* Check for success. */
if (mid == bucket->num_entries - 1 || bucket->entries[mid+1].virt_offset > offset) {
return &bucket->entries[mid];
}
low = mid + 1;
}
}
fprintf(stderr, "Failed to find offset %012"PRIx64" in BKTR relocation table!\n", offset);
exit(EXIT_FAILURE);
}
bktr_subsection_bucket_t *bktr_get_subsection_bucket(bktr_subsection_block_t *block, uint32_t i) {
return (bktr_subsection_bucket_t *)((uint8_t *)block->buckets + (sizeof(bktr_subsection_bucket_t) + sizeof(bktr_subsection_entry_t)) * i);
}
/* Get a subsection entry from offset and subsection block .*/
bktr_subsection_entry_t *bktr_get_subsection(bktr_subsection_block_t *block, uint64_t offset) {
/* If offset is past the virtual, we're reading from the BKTR_HEADER subsection. */
bktr_subsection_bucket_t *last_bucket = bktr_get_subsection_bucket(block, block->num_buckets - 1);
if (offset >= last_bucket->entries[last_bucket->num_entries].offset) {
return &last_bucket->entries[last_bucket->num_entries];
}
uint32_t bucket_num = 0;
for (unsigned int i = 1; i < block->num_buckets; i++) {
if (block->bucket_physical_offsets[i] <= offset) {
bucket_num++;
}
}
bktr_subsection_bucket_t *bucket = bktr_get_subsection_bucket(block, bucket_num);
if (bucket->num_entries == 1) { /* Check for edge case, short circuit. */
return &bucket->entries[0];
}
/* Binary search. */
uint32_t low = 0, high = bucket->num_entries - 1;
while (low <= high) {
uint32_t mid = (low + high) / 2;
if (bucket->entries[mid].offset > offset) { /* Too high. */
high = mid - 1;
} else { /* block->entries[mid].offset <= offset. */
/* Check for success. */
if (mid == bucket->num_entries - 1 || bucket->entries[mid+1].offset > offset) {
return &bucket->entries[mid];
}
low = mid + 1;
}
}
fprintf(stderr, "Failed to find offset %012"PRIx64" in BKTR subsection table!\n", offset);
exit(EXIT_FAILURE);
}