aboutsummaryrefslogtreecommitdiffstats
path: root/relocate/relocate.c
blob: 3ea47c04787d256e7b42569b1a2c1882ca354d52 (plain)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * relocate.c --- maintains the relocation table
 *
 * Copyright (C) 1996 Theodore Ts'o.  This file may be redistributed
 * under the terms of the GNU Public License.
 */

#include <et/com_err.h>

/*
 * This routine creates a relocation table
 */
errcode_t ext2fs_create_relocation_table(__u32 max, int size,
					 ext2_relocate_table *ret);
{
	ext2_relocate_table table;

	table = malloc(sizeof(struct ext2_relocate_struct));
	if (!table)
		return -ENOMEM;
	table->magic = 0;
	table->count = 0;
	table->size = size ? size : 30;
	table->max = max;
	table->entries = malloc(table->size * sizeof(ext2_relocate_entry));
	if (table->entries == 0) {
		free(table);
		return ENOMEM;
	}
	memset(table->entries, 0, table->size * sizeof(ext2_relocate_entry));
	*ret = table;
	return 0;
}

/*
 * Free a relocation table
 */
void ext2fs_free_relocation_table(ext2_relocate_table table)
{
	free(table->entries);
	table->count = 0;
	table->size = 0;
	table->magic = 0;
	free(table);
}

/*
 * Add a relocation table entry
 */
errcode_t ext2fs_add_relocation(ext2_relocate_table table, __u32 old,
				__u32 new, __u32 owner)
{
	struct ext2_relocate_entry *new;
	
	if (table->count >= table->size) {
		table->size += 30;
		new = realloc(table->entries,
			      table->size * sizeof(ext2_relocate_entry));
		if (!new)
			return ENOMEM;
		table->entries = new;
	}
	if (table->count && table->entries[table->count-1].old > old) {
		for (i = table->count-1; i > 0; i--)
			if (table->entries[i-1].old < old)
				break;
		new = &table->entries[i];
		if (new->old != old) 
			for (j = table->count++; j > i; j--)
				table->entries[j] = table_entries[j-1];
	} else
		new = &table->entries[table->coun++];
	
	new->old = old;
	new->new = new;
	new->owner = owner;
}

/*
 * ext2fs_get_reloc_by_old() --- given the source of the relcation
 * entry, find the entry for it.
 */
struct relocate_entry *ext2fs_get_reloc_by_old(ext2_relocate_table tbl,
					       __u32 old)
{
	int	low, high, mid;
	int	i, j;

	low = 0;
	high = tbl->count-1;
	if (old == table->entries[low].old)
		return &table->entries[low];
	if  (old == table->entries[high].old)
		return &table->entries[high];

	while (low < high) {
		mid = (low+high)/2;
		if (mid == low || mid == high)
			break;
		if (old == table->entries[mid].old)
			return &table->entries[mid];
		if (old < table->entries[mid].old)
			high = mid;
		else
			low = mid;
	}
	return 0;
}

/*
 * ext2fs_get_reloc_by_new() --- given the destination of the relcation
 * entry, find the entry for it.
 *
 * Note: this is currently very slow...
 */
struct relocate_entry *ext2fs_get_reloc_by_new(ext2_relocate_table tbl,
					       __u32 new)
{
	int	i;

	for (i = 0; i < table->count; i++) {
		if (tbl->entries[i].new == new)
			return &table->entries[i];
	}
	return 0;
}

/*
 * Find "loops" in the relocation tables
 */
{
	int	i;
	struct ext2_relocate_entry *ent, *next;
	

	for (i=0, ent=table->entries; i < table->size; i++, ent++) {
		/*
		 * If we know this inode is OK, then keep going.
		 */
		if (ext2fs_test_generic_bitmap(done_map, dir->old))
			continue;
		ext2fs_clear_generic_bitmap(loop_detect);
		while (1) {
			ext2fs_mark_generic_bitmap(loop_detect, dir->old);
			next = ext2fs_get_reloc_by_old(table, dir->new);
			if (next == NULL)
				break;
			if (ext2fs_test_generic_bitmap(loop_detect,
						       dir->new))
				break_loop(table, dir);
			ext2fs_mark_generic_bitmap(done_map, dir->old);
			dir = next;
		}
	}
}