1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * extent.c --- ext2 extent abstraction
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * This abstraction is used to provide a compact way of representing a
5*6a54128fSAndroid Build Coastguard Worker * translation table, for moving multiple contiguous ranges (extents)
6*6a54128fSAndroid Build Coastguard Worker * of blocks or inodes.
7*6a54128fSAndroid Build Coastguard Worker *
8*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1997, 1998 by Theodore Ts'o and
9*6a54128fSAndroid Build Coastguard Worker * PowerQuest, Inc.
10*6a54128fSAndroid Build Coastguard Worker *
11*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 1999, 2000 by Theodore Ts'o
12*6a54128fSAndroid Build Coastguard Worker *
13*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
14*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Public
15*6a54128fSAndroid Build Coastguard Worker * License.
16*6a54128fSAndroid Build Coastguard Worker * %End-Header%
17*6a54128fSAndroid Build Coastguard Worker */
18*6a54128fSAndroid Build Coastguard Worker
19*6a54128fSAndroid Build Coastguard Worker #include "config.h"
20*6a54128fSAndroid Build Coastguard Worker #include "resize2fs.h"
21*6a54128fSAndroid Build Coastguard Worker
22*6a54128fSAndroid Build Coastguard Worker struct ext2_extent_entry {
23*6a54128fSAndroid Build Coastguard Worker __u64 old_loc, new_loc;
24*6a54128fSAndroid Build Coastguard Worker __u64 size;
25*6a54128fSAndroid Build Coastguard Worker };
26*6a54128fSAndroid Build Coastguard Worker
27*6a54128fSAndroid Build Coastguard Worker struct _ext2_extent {
28*6a54128fSAndroid Build Coastguard Worker struct ext2_extent_entry *list;
29*6a54128fSAndroid Build Coastguard Worker __u64 cursor;
30*6a54128fSAndroid Build Coastguard Worker __u64 size;
31*6a54128fSAndroid Build Coastguard Worker __u64 num;
32*6a54128fSAndroid Build Coastguard Worker __u64 sorted;
33*6a54128fSAndroid Build Coastguard Worker };
34*6a54128fSAndroid Build Coastguard Worker
35*6a54128fSAndroid Build Coastguard Worker /*
36*6a54128fSAndroid Build Coastguard Worker * Create an extent table
37*6a54128fSAndroid Build Coastguard Worker */
ext2fs_create_extent_table(ext2_extent * ret_extent,__u64 size)38*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_create_extent_table(ext2_extent *ret_extent, __u64 size)
39*6a54128fSAndroid Build Coastguard Worker {
40*6a54128fSAndroid Build Coastguard Worker ext2_extent extent;
41*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
42*6a54128fSAndroid Build Coastguard Worker
43*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_mem(sizeof(struct _ext2_extent), &extent);
44*6a54128fSAndroid Build Coastguard Worker if (retval)
45*6a54128fSAndroid Build Coastguard Worker return retval;
46*6a54128fSAndroid Build Coastguard Worker memset(extent, 0, sizeof(struct _ext2_extent));
47*6a54128fSAndroid Build Coastguard Worker
48*6a54128fSAndroid Build Coastguard Worker extent->size = size ? size : 50;
49*6a54128fSAndroid Build Coastguard Worker extent->cursor = 0;
50*6a54128fSAndroid Build Coastguard Worker extent->num = 0;
51*6a54128fSAndroid Build Coastguard Worker extent->sorted = 1;
52*6a54128fSAndroid Build Coastguard Worker
53*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_arrayzero(sizeof(struct ext2_extent_entry),
54*6a54128fSAndroid Build Coastguard Worker extent->size, &extent->list);
55*6a54128fSAndroid Build Coastguard Worker if (retval) {
56*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&extent);
57*6a54128fSAndroid Build Coastguard Worker return retval;
58*6a54128fSAndroid Build Coastguard Worker }
59*6a54128fSAndroid Build Coastguard Worker *ret_extent = extent;
60*6a54128fSAndroid Build Coastguard Worker return 0;
61*6a54128fSAndroid Build Coastguard Worker }
62*6a54128fSAndroid Build Coastguard Worker
63*6a54128fSAndroid Build Coastguard Worker /*
64*6a54128fSAndroid Build Coastguard Worker * Free an extent table
65*6a54128fSAndroid Build Coastguard Worker */
ext2fs_free_extent_table(ext2_extent extent)66*6a54128fSAndroid Build Coastguard Worker void ext2fs_free_extent_table(ext2_extent extent)
67*6a54128fSAndroid Build Coastguard Worker {
68*6a54128fSAndroid Build Coastguard Worker if (extent->list)
69*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&extent->list);
70*6a54128fSAndroid Build Coastguard Worker extent->list = 0;
71*6a54128fSAndroid Build Coastguard Worker extent->size = 0;
72*6a54128fSAndroid Build Coastguard Worker extent->num = 0;
73*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&extent);
74*6a54128fSAndroid Build Coastguard Worker }
75*6a54128fSAndroid Build Coastguard Worker
76*6a54128fSAndroid Build Coastguard Worker /*
77*6a54128fSAndroid Build Coastguard Worker * Add an entry to the extent table
78*6a54128fSAndroid Build Coastguard Worker */
ext2fs_add_extent_entry(ext2_extent extent,__u64 old_loc,__u64 new_loc)79*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_add_extent_entry(ext2_extent extent, __u64 old_loc, __u64 new_loc)
80*6a54128fSAndroid Build Coastguard Worker {
81*6a54128fSAndroid Build Coastguard Worker struct ext2_extent_entry *ent;
82*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
83*6a54128fSAndroid Build Coastguard Worker __u64 newsize;
84*6a54128fSAndroid Build Coastguard Worker __u64 curr;
85*6a54128fSAndroid Build Coastguard Worker
86*6a54128fSAndroid Build Coastguard Worker if (extent->num >= extent->size) {
87*6a54128fSAndroid Build Coastguard Worker newsize = extent->size + 100;
88*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_resize_mem(sizeof(struct ext2_extent_entry) *
89*6a54128fSAndroid Build Coastguard Worker extent->size,
90*6a54128fSAndroid Build Coastguard Worker sizeof(struct ext2_extent_entry) *
91*6a54128fSAndroid Build Coastguard Worker newsize, &extent->list);
92*6a54128fSAndroid Build Coastguard Worker if (retval)
93*6a54128fSAndroid Build Coastguard Worker return retval;
94*6a54128fSAndroid Build Coastguard Worker extent->size = newsize;
95*6a54128fSAndroid Build Coastguard Worker }
96*6a54128fSAndroid Build Coastguard Worker curr = extent->num;
97*6a54128fSAndroid Build Coastguard Worker ent = extent->list + curr;
98*6a54128fSAndroid Build Coastguard Worker if (curr) {
99*6a54128fSAndroid Build Coastguard Worker /*
100*6a54128fSAndroid Build Coastguard Worker * Check to see if this can be coalesced with the last
101*6a54128fSAndroid Build Coastguard Worker * extent
102*6a54128fSAndroid Build Coastguard Worker */
103*6a54128fSAndroid Build Coastguard Worker ent--;
104*6a54128fSAndroid Build Coastguard Worker if ((ent->old_loc + ent->size == old_loc) &&
105*6a54128fSAndroid Build Coastguard Worker (ent->new_loc + ent->size == new_loc)) {
106*6a54128fSAndroid Build Coastguard Worker ent->size++;
107*6a54128fSAndroid Build Coastguard Worker return 0;
108*6a54128fSAndroid Build Coastguard Worker }
109*6a54128fSAndroid Build Coastguard Worker /*
110*6a54128fSAndroid Build Coastguard Worker * Now see if we're going to ruin the sorting
111*6a54128fSAndroid Build Coastguard Worker */
112*6a54128fSAndroid Build Coastguard Worker if (ent->old_loc + ent->size > old_loc)
113*6a54128fSAndroid Build Coastguard Worker extent->sorted = 0;
114*6a54128fSAndroid Build Coastguard Worker ent++;
115*6a54128fSAndroid Build Coastguard Worker }
116*6a54128fSAndroid Build Coastguard Worker ent->old_loc = old_loc;
117*6a54128fSAndroid Build Coastguard Worker ent->new_loc = new_loc;
118*6a54128fSAndroid Build Coastguard Worker ent->size = 1;
119*6a54128fSAndroid Build Coastguard Worker extent->num++;
120*6a54128fSAndroid Build Coastguard Worker return 0;
121*6a54128fSAndroid Build Coastguard Worker }
122*6a54128fSAndroid Build Coastguard Worker
123*6a54128fSAndroid Build Coastguard Worker /*
124*6a54128fSAndroid Build Coastguard Worker * Helper function for qsort
125*6a54128fSAndroid Build Coastguard Worker */
extent_cmp(const void * a,const void * b)126*6a54128fSAndroid Build Coastguard Worker static EXT2_QSORT_TYPE extent_cmp(const void *a, const void *b)
127*6a54128fSAndroid Build Coastguard Worker {
128*6a54128fSAndroid Build Coastguard Worker const struct ext2_extent_entry *db_a;
129*6a54128fSAndroid Build Coastguard Worker const struct ext2_extent_entry *db_b;
130*6a54128fSAndroid Build Coastguard Worker
131*6a54128fSAndroid Build Coastguard Worker db_a = (const struct ext2_extent_entry *) a;
132*6a54128fSAndroid Build Coastguard Worker db_b = (const struct ext2_extent_entry *) b;
133*6a54128fSAndroid Build Coastguard Worker
134*6a54128fSAndroid Build Coastguard Worker return (db_a->old_loc - db_b->old_loc);
135*6a54128fSAndroid Build Coastguard Worker }
136*6a54128fSAndroid Build Coastguard Worker
137*6a54128fSAndroid Build Coastguard Worker /*
138*6a54128fSAndroid Build Coastguard Worker * Given an inode map and inode number, look up the old inode number
139*6a54128fSAndroid Build Coastguard Worker * and return the new inode number.
140*6a54128fSAndroid Build Coastguard Worker */
ext2fs_extent_translate(ext2_extent extent,__u64 old_loc)141*6a54128fSAndroid Build Coastguard Worker __u64 ext2fs_extent_translate(ext2_extent extent, __u64 old_loc)
142*6a54128fSAndroid Build Coastguard Worker {
143*6a54128fSAndroid Build Coastguard Worker __s64 low, high, mid;
144*6a54128fSAndroid Build Coastguard Worker __u64 lowval, highval;
145*6a54128fSAndroid Build Coastguard Worker float range;
146*6a54128fSAndroid Build Coastguard Worker
147*6a54128fSAndroid Build Coastguard Worker if (!extent->sorted) {
148*6a54128fSAndroid Build Coastguard Worker qsort(extent->list, extent->num,
149*6a54128fSAndroid Build Coastguard Worker sizeof(struct ext2_extent_entry), extent_cmp);
150*6a54128fSAndroid Build Coastguard Worker extent->sorted = 1;
151*6a54128fSAndroid Build Coastguard Worker }
152*6a54128fSAndroid Build Coastguard Worker low = 0;
153*6a54128fSAndroid Build Coastguard Worker high = extent->num-1;
154*6a54128fSAndroid Build Coastguard Worker while (low <= high) {
155*6a54128fSAndroid Build Coastguard Worker #if 0
156*6a54128fSAndroid Build Coastguard Worker mid = (low+high)/2;
157*6a54128fSAndroid Build Coastguard Worker #else
158*6a54128fSAndroid Build Coastguard Worker if (low == high)
159*6a54128fSAndroid Build Coastguard Worker mid = low;
160*6a54128fSAndroid Build Coastguard Worker else {
161*6a54128fSAndroid Build Coastguard Worker /* Interpolate for efficiency */
162*6a54128fSAndroid Build Coastguard Worker lowval = extent->list[low].old_loc;
163*6a54128fSAndroid Build Coastguard Worker highval = extent->list[high].old_loc;
164*6a54128fSAndroid Build Coastguard Worker
165*6a54128fSAndroid Build Coastguard Worker if (old_loc < lowval)
166*6a54128fSAndroid Build Coastguard Worker range = 0;
167*6a54128fSAndroid Build Coastguard Worker else if (old_loc > highval)
168*6a54128fSAndroid Build Coastguard Worker range = 1;
169*6a54128fSAndroid Build Coastguard Worker else {
170*6a54128fSAndroid Build Coastguard Worker range = ((float) (old_loc - lowval)) /
171*6a54128fSAndroid Build Coastguard Worker (highval - lowval);
172*6a54128fSAndroid Build Coastguard Worker if (range > 0.9)
173*6a54128fSAndroid Build Coastguard Worker range = 0.9;
174*6a54128fSAndroid Build Coastguard Worker if (range < 0.1)
175*6a54128fSAndroid Build Coastguard Worker range = 0.1;
176*6a54128fSAndroid Build Coastguard Worker }
177*6a54128fSAndroid Build Coastguard Worker mid = low + ((__u64) (range * (high-low)));
178*6a54128fSAndroid Build Coastguard Worker }
179*6a54128fSAndroid Build Coastguard Worker #endif
180*6a54128fSAndroid Build Coastguard Worker if ((old_loc >= extent->list[mid].old_loc) &&
181*6a54128fSAndroid Build Coastguard Worker (old_loc < extent->list[mid].old_loc + extent->list[mid].size))
182*6a54128fSAndroid Build Coastguard Worker return (extent->list[mid].new_loc +
183*6a54128fSAndroid Build Coastguard Worker (old_loc - extent->list[mid].old_loc));
184*6a54128fSAndroid Build Coastguard Worker if (old_loc < extent->list[mid].old_loc)
185*6a54128fSAndroid Build Coastguard Worker high = mid-1;
186*6a54128fSAndroid Build Coastguard Worker else
187*6a54128fSAndroid Build Coastguard Worker low = mid+1;
188*6a54128fSAndroid Build Coastguard Worker }
189*6a54128fSAndroid Build Coastguard Worker return 0;
190*6a54128fSAndroid Build Coastguard Worker }
191*6a54128fSAndroid Build Coastguard Worker
192*6a54128fSAndroid Build Coastguard Worker /*
193*6a54128fSAndroid Build Coastguard Worker * For debugging only
194*6a54128fSAndroid Build Coastguard Worker */
ext2fs_extent_dump(ext2_extent extent,FILE * out)195*6a54128fSAndroid Build Coastguard Worker void ext2fs_extent_dump(ext2_extent extent, FILE *out)
196*6a54128fSAndroid Build Coastguard Worker {
197*6a54128fSAndroid Build Coastguard Worker __u64 i;
198*6a54128fSAndroid Build Coastguard Worker struct ext2_extent_entry *ent;
199*6a54128fSAndroid Build Coastguard Worker
200*6a54128fSAndroid Build Coastguard Worker fputs(_("# Extent dump:\n"), out);
201*6a54128fSAndroid Build Coastguard Worker fprintf(out, _("#\tNum=%llu, Size=%llu, Cursor=%llu, Sorted=%llu\n"),
202*6a54128fSAndroid Build Coastguard Worker (unsigned long long) extent->num,
203*6a54128fSAndroid Build Coastguard Worker (unsigned long long) extent->size,
204*6a54128fSAndroid Build Coastguard Worker (unsigned long long) extent->cursor,
205*6a54128fSAndroid Build Coastguard Worker (unsigned long long) extent->sorted);
206*6a54128fSAndroid Build Coastguard Worker for (i=0, ent=extent->list; i < extent->num; i++, ent++) {
207*6a54128fSAndroid Build Coastguard Worker fprintf(out, "#\t\t %llu -> %llu (%llu)\n",
208*6a54128fSAndroid Build Coastguard Worker (unsigned long long) ent->old_loc,
209*6a54128fSAndroid Build Coastguard Worker (unsigned long long) ent->new_loc,
210*6a54128fSAndroid Build Coastguard Worker (unsigned long long) ent->size);
211*6a54128fSAndroid Build Coastguard Worker }
212*6a54128fSAndroid Build Coastguard Worker }
213*6a54128fSAndroid Build Coastguard Worker
214*6a54128fSAndroid Build Coastguard Worker /*
215*6a54128fSAndroid Build Coastguard Worker * Iterate over the contents of the extent table
216*6a54128fSAndroid Build Coastguard Worker */
ext2fs_iterate_extent(ext2_extent extent,__u64 * old_loc,__u64 * new_loc,__u64 * size)217*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_iterate_extent(ext2_extent extent, __u64 *old_loc,
218*6a54128fSAndroid Build Coastguard Worker __u64 *new_loc, __u64 *size)
219*6a54128fSAndroid Build Coastguard Worker {
220*6a54128fSAndroid Build Coastguard Worker struct ext2_extent_entry *ent;
221*6a54128fSAndroid Build Coastguard Worker
222*6a54128fSAndroid Build Coastguard Worker if (!old_loc) {
223*6a54128fSAndroid Build Coastguard Worker extent->cursor = 0;
224*6a54128fSAndroid Build Coastguard Worker return 0;
225*6a54128fSAndroid Build Coastguard Worker }
226*6a54128fSAndroid Build Coastguard Worker
227*6a54128fSAndroid Build Coastguard Worker if (extent->cursor >= extent->num) {
228*6a54128fSAndroid Build Coastguard Worker *old_loc = 0;
229*6a54128fSAndroid Build Coastguard Worker *new_loc = 0;
230*6a54128fSAndroid Build Coastguard Worker *size = 0;
231*6a54128fSAndroid Build Coastguard Worker return 0;
232*6a54128fSAndroid Build Coastguard Worker }
233*6a54128fSAndroid Build Coastguard Worker
234*6a54128fSAndroid Build Coastguard Worker ent = extent->list + extent->cursor++;
235*6a54128fSAndroid Build Coastguard Worker
236*6a54128fSAndroid Build Coastguard Worker *old_loc = ent->old_loc;
237*6a54128fSAndroid Build Coastguard Worker *new_loc = ent->new_loc;
238*6a54128fSAndroid Build Coastguard Worker *size = ent->size;
239*6a54128fSAndroid Build Coastguard Worker return 0;
240*6a54128fSAndroid Build Coastguard Worker }
241*6a54128fSAndroid Build Coastguard Worker
242*6a54128fSAndroid Build Coastguard Worker
243*6a54128fSAndroid Build Coastguard Worker
244*6a54128fSAndroid Build Coastguard Worker
245