1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * region.c --- code which manages allocations within a region.
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2001 Theodore Ts'o.
5*6a54128fSAndroid Build Coastguard Worker *
6*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the GNU Public
8*6a54128fSAndroid Build Coastguard Worker * License.
9*6a54128fSAndroid Build Coastguard Worker * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker */
11*6a54128fSAndroid Build Coastguard Worker
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
14*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
15*6a54128fSAndroid Build Coastguard Worker #endif
16*6a54128fSAndroid Build Coastguard Worker #include <string.h>
17*6a54128fSAndroid Build Coastguard Worker
18*6a54128fSAndroid Build Coastguard Worker #ifdef TEST_PROGRAM
19*6a54128fSAndroid Build Coastguard Worker #undef ENABLE_NLS
20*6a54128fSAndroid Build Coastguard Worker #endif
21*6a54128fSAndroid Build Coastguard Worker #include "e2fsck.h"
22*6a54128fSAndroid Build Coastguard Worker
23*6a54128fSAndroid Build Coastguard Worker struct region_el {
24*6a54128fSAndroid Build Coastguard Worker region_addr_t start;
25*6a54128fSAndroid Build Coastguard Worker region_addr_t end;
26*6a54128fSAndroid Build Coastguard Worker struct region_el *next;
27*6a54128fSAndroid Build Coastguard Worker };
28*6a54128fSAndroid Build Coastguard Worker
29*6a54128fSAndroid Build Coastguard Worker struct region_struct {
30*6a54128fSAndroid Build Coastguard Worker region_addr_t min;
31*6a54128fSAndroid Build Coastguard Worker region_addr_t max;
32*6a54128fSAndroid Build Coastguard Worker struct region_el *allocated;
33*6a54128fSAndroid Build Coastguard Worker struct region_el *last;
34*6a54128fSAndroid Build Coastguard Worker };
35*6a54128fSAndroid Build Coastguard Worker
region_create(region_addr_t min,region_addr_t max)36*6a54128fSAndroid Build Coastguard Worker region_t region_create(region_addr_t min, region_addr_t max)
37*6a54128fSAndroid Build Coastguard Worker {
38*6a54128fSAndroid Build Coastguard Worker region_t region;
39*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
40*6a54128fSAndroid Build Coastguard Worker
41*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_memzero(sizeof(struct region_struct), ®ion);
42*6a54128fSAndroid Build Coastguard Worker if (retval)
43*6a54128fSAndroid Build Coastguard Worker return NULL;
44*6a54128fSAndroid Build Coastguard Worker
45*6a54128fSAndroid Build Coastguard Worker region->min = min;
46*6a54128fSAndroid Build Coastguard Worker region->max = max;
47*6a54128fSAndroid Build Coastguard Worker region->last = NULL;
48*6a54128fSAndroid Build Coastguard Worker return region;
49*6a54128fSAndroid Build Coastguard Worker }
50*6a54128fSAndroid Build Coastguard Worker
region_free(region_t region)51*6a54128fSAndroid Build Coastguard Worker void region_free(region_t region)
52*6a54128fSAndroid Build Coastguard Worker {
53*6a54128fSAndroid Build Coastguard Worker struct region_el *r, *next;
54*6a54128fSAndroid Build Coastguard Worker
55*6a54128fSAndroid Build Coastguard Worker for (r = region->allocated; r; r = next) {
56*6a54128fSAndroid Build Coastguard Worker next = r->next;
57*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&r);
58*6a54128fSAndroid Build Coastguard Worker }
59*6a54128fSAndroid Build Coastguard Worker memset(region, 0, sizeof(struct region_struct));
60*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(®ion);
61*6a54128fSAndroid Build Coastguard Worker }
62*6a54128fSAndroid Build Coastguard Worker
region_allocate(region_t region,region_addr_t start,int n)63*6a54128fSAndroid Build Coastguard Worker int region_allocate(region_t region, region_addr_t start, int n)
64*6a54128fSAndroid Build Coastguard Worker {
65*6a54128fSAndroid Build Coastguard Worker struct region_el *r, *new_region, *prev, *next;
66*6a54128fSAndroid Build Coastguard Worker region_addr_t end;
67*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
68*6a54128fSAndroid Build Coastguard Worker
69*6a54128fSAndroid Build Coastguard Worker end = start+n;
70*6a54128fSAndroid Build Coastguard Worker if ((start < region->min) || (end > region->max))
71*6a54128fSAndroid Build Coastguard Worker return -1;
72*6a54128fSAndroid Build Coastguard Worker if (n == 0)
73*6a54128fSAndroid Build Coastguard Worker return 1;
74*6a54128fSAndroid Build Coastguard Worker
75*6a54128fSAndroid Build Coastguard Worker if (region->last && region->last->end == start &&
76*6a54128fSAndroid Build Coastguard Worker !region->last->next) {
77*6a54128fSAndroid Build Coastguard Worker region->last->end = end;
78*6a54128fSAndroid Build Coastguard Worker return 0;
79*6a54128fSAndroid Build Coastguard Worker }
80*6a54128fSAndroid Build Coastguard Worker if (region->last && start > region->last->end &&
81*6a54128fSAndroid Build Coastguard Worker !region->last->next) {
82*6a54128fSAndroid Build Coastguard Worker r = NULL;
83*6a54128fSAndroid Build Coastguard Worker prev = region->last;
84*6a54128fSAndroid Build Coastguard Worker goto append_to_list;
85*6a54128fSAndroid Build Coastguard Worker }
86*6a54128fSAndroid Build Coastguard Worker
87*6a54128fSAndroid Build Coastguard Worker /*
88*6a54128fSAndroid Build Coastguard Worker * Search through the linked list. If we find that it
89*6a54128fSAndroid Build Coastguard Worker * conflicts with something that's already allocated, return
90*6a54128fSAndroid Build Coastguard Worker * 1; if we can find an existing region which we can grow, do
91*6a54128fSAndroid Build Coastguard Worker * so. Otherwise, stop when we find the appropriate place
92*6a54128fSAndroid Build Coastguard Worker * insert a new region element into the linked list.
93*6a54128fSAndroid Build Coastguard Worker */
94*6a54128fSAndroid Build Coastguard Worker for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
95*6a54128fSAndroid Build Coastguard Worker if (((start >= r->start) && (start < r->end)) ||
96*6a54128fSAndroid Build Coastguard Worker ((end > r->start) && (end <= r->end)) ||
97*6a54128fSAndroid Build Coastguard Worker ((start <= r->start) && (end >= r->end)))
98*6a54128fSAndroid Build Coastguard Worker return 1;
99*6a54128fSAndroid Build Coastguard Worker if (end == r->start) {
100*6a54128fSAndroid Build Coastguard Worker r->start = start;
101*6a54128fSAndroid Build Coastguard Worker return 0;
102*6a54128fSAndroid Build Coastguard Worker }
103*6a54128fSAndroid Build Coastguard Worker if (start == r->end) {
104*6a54128fSAndroid Build Coastguard Worker if ((next = r->next)) {
105*6a54128fSAndroid Build Coastguard Worker if (end > next->start)
106*6a54128fSAndroid Build Coastguard Worker return 1;
107*6a54128fSAndroid Build Coastguard Worker if (end == next->start) {
108*6a54128fSAndroid Build Coastguard Worker r->end = next->end;
109*6a54128fSAndroid Build Coastguard Worker r->next = next->next;
110*6a54128fSAndroid Build Coastguard Worker ext2fs_free_mem(&next);
111*6a54128fSAndroid Build Coastguard Worker if (!r->next)
112*6a54128fSAndroid Build Coastguard Worker region->last = r;
113*6a54128fSAndroid Build Coastguard Worker return 0;
114*6a54128fSAndroid Build Coastguard Worker }
115*6a54128fSAndroid Build Coastguard Worker }
116*6a54128fSAndroid Build Coastguard Worker r->end = end;
117*6a54128fSAndroid Build Coastguard Worker return 0;
118*6a54128fSAndroid Build Coastguard Worker }
119*6a54128fSAndroid Build Coastguard Worker if (start < r->start)
120*6a54128fSAndroid Build Coastguard Worker break;
121*6a54128fSAndroid Build Coastguard Worker }
122*6a54128fSAndroid Build Coastguard Worker /*
123*6a54128fSAndroid Build Coastguard Worker * Insert a new region element structure into the linked list
124*6a54128fSAndroid Build Coastguard Worker */
125*6a54128fSAndroid Build Coastguard Worker append_to_list:
126*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_get_mem(sizeof(struct region_el), &new_region);
127*6a54128fSAndroid Build Coastguard Worker if (retval)
128*6a54128fSAndroid Build Coastguard Worker return -1;
129*6a54128fSAndroid Build Coastguard Worker new_region->start = start;
130*6a54128fSAndroid Build Coastguard Worker new_region->end = start + n;
131*6a54128fSAndroid Build Coastguard Worker new_region->next = r;
132*6a54128fSAndroid Build Coastguard Worker if (!new_region->next)
133*6a54128fSAndroid Build Coastguard Worker region->last = new_region;
134*6a54128fSAndroid Build Coastguard Worker if (prev)
135*6a54128fSAndroid Build Coastguard Worker prev->next = new_region;
136*6a54128fSAndroid Build Coastguard Worker else
137*6a54128fSAndroid Build Coastguard Worker region->allocated = new_region;
138*6a54128fSAndroid Build Coastguard Worker return 0;
139*6a54128fSAndroid Build Coastguard Worker }
140*6a54128fSAndroid Build Coastguard Worker
141*6a54128fSAndroid Build Coastguard Worker #ifdef TEST_PROGRAM
142*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
143*6a54128fSAndroid Build Coastguard Worker
144*6a54128fSAndroid Build Coastguard Worker #define BCODE_END 0
145*6a54128fSAndroid Build Coastguard Worker #define BCODE_CREATE 1
146*6a54128fSAndroid Build Coastguard Worker #define BCODE_FREE 2
147*6a54128fSAndroid Build Coastguard Worker #define BCODE_ALLOCATE 3
148*6a54128fSAndroid Build Coastguard Worker #define BCODE_PRINT 4
149*6a54128fSAndroid Build Coastguard Worker
150*6a54128fSAndroid Build Coastguard Worker int bcode_program[] = {
151*6a54128fSAndroid Build Coastguard Worker BCODE_CREATE, 1, 1001,
152*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
153*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 10, 10,
154*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 30, 10,
155*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
156*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 1, 15,
157*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 15, 8,
158*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 1, 20,
159*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 1, 8,
160*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
161*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 40, 10,
162*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
163*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 22, 5,
164*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
165*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 27, 3,
166*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
167*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 20, 2,
168*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
169*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 49, 1,
170*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 50, 5,
171*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 9, 2,
172*6a54128fSAndroid Build Coastguard Worker BCODE_ALLOCATE, 9, 1,
173*6a54128fSAndroid Build Coastguard Worker BCODE_PRINT,
174*6a54128fSAndroid Build Coastguard Worker BCODE_FREE,
175*6a54128fSAndroid Build Coastguard Worker BCODE_END
176*6a54128fSAndroid Build Coastguard Worker };
177*6a54128fSAndroid Build Coastguard Worker
region_print(region_t region,FILE * f)178*6a54128fSAndroid Build Coastguard Worker void region_print(region_t region, FILE *f)
179*6a54128fSAndroid Build Coastguard Worker {
180*6a54128fSAndroid Build Coastguard Worker struct region_el *r;
181*6a54128fSAndroid Build Coastguard Worker int i = 0;
182*6a54128fSAndroid Build Coastguard Worker
183*6a54128fSAndroid Build Coastguard Worker fprintf(f, "Printing region (min=%llu. max=%llu)\n\t",
184*6a54128fSAndroid Build Coastguard Worker (unsigned long long) region->min,
185*6a54128fSAndroid Build Coastguard Worker (unsigned long long) region->max);
186*6a54128fSAndroid Build Coastguard Worker for (r = region->allocated; r; r = r->next) {
187*6a54128fSAndroid Build Coastguard Worker fprintf(f, "(%llu, %llu) ",
188*6a54128fSAndroid Build Coastguard Worker (unsigned long long) r->start,
189*6a54128fSAndroid Build Coastguard Worker (unsigned long long) r->end);
190*6a54128fSAndroid Build Coastguard Worker if (++i >= 8)
191*6a54128fSAndroid Build Coastguard Worker fprintf(f, "\n\t");
192*6a54128fSAndroid Build Coastguard Worker }
193*6a54128fSAndroid Build Coastguard Worker fprintf(f, "\n");
194*6a54128fSAndroid Build Coastguard Worker }
195*6a54128fSAndroid Build Coastguard Worker
main(int argc,char ** argv)196*6a54128fSAndroid Build Coastguard Worker int main(int argc, char **argv)
197*6a54128fSAndroid Build Coastguard Worker {
198*6a54128fSAndroid Build Coastguard Worker region_t r = NULL;
199*6a54128fSAndroid Build Coastguard Worker int pc = 0, ret;
200*6a54128fSAndroid Build Coastguard Worker region_addr_t start, end;
201*6a54128fSAndroid Build Coastguard Worker
202*6a54128fSAndroid Build Coastguard Worker
203*6a54128fSAndroid Build Coastguard Worker while (1) {
204*6a54128fSAndroid Build Coastguard Worker switch (bcode_program[pc++]) {
205*6a54128fSAndroid Build Coastguard Worker case BCODE_END:
206*6a54128fSAndroid Build Coastguard Worker exit(0);
207*6a54128fSAndroid Build Coastguard Worker case BCODE_CREATE:
208*6a54128fSAndroid Build Coastguard Worker start = bcode_program[pc++];
209*6a54128fSAndroid Build Coastguard Worker end = bcode_program[pc++];
210*6a54128fSAndroid Build Coastguard Worker printf("Creating region with args(%llu, %llu)\n",
211*6a54128fSAndroid Build Coastguard Worker (unsigned long long) start,
212*6a54128fSAndroid Build Coastguard Worker (unsigned long long) end);
213*6a54128fSAndroid Build Coastguard Worker r = region_create(start, end);
214*6a54128fSAndroid Build Coastguard Worker if (!r) {
215*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Couldn't create region.\n");
216*6a54128fSAndroid Build Coastguard Worker exit(1);
217*6a54128fSAndroid Build Coastguard Worker }
218*6a54128fSAndroid Build Coastguard Worker break;
219*6a54128fSAndroid Build Coastguard Worker case BCODE_ALLOCATE:
220*6a54128fSAndroid Build Coastguard Worker start = bcode_program[pc++];
221*6a54128fSAndroid Build Coastguard Worker end = bcode_program[pc++];
222*6a54128fSAndroid Build Coastguard Worker ret = region_allocate(r, start, end);
223*6a54128fSAndroid Build Coastguard Worker printf("Region_allocate(%llu, %llu) returns %d\n",
224*6a54128fSAndroid Build Coastguard Worker (unsigned long long) start,
225*6a54128fSAndroid Build Coastguard Worker (unsigned long long) end, ret);
226*6a54128fSAndroid Build Coastguard Worker break;
227*6a54128fSAndroid Build Coastguard Worker case BCODE_PRINT:
228*6a54128fSAndroid Build Coastguard Worker region_print(r, stdout);
229*6a54128fSAndroid Build Coastguard Worker break;
230*6a54128fSAndroid Build Coastguard Worker }
231*6a54128fSAndroid Build Coastguard Worker }
232*6a54128fSAndroid Build Coastguard Worker if (r)
233*6a54128fSAndroid Build Coastguard Worker region_free(r);
234*6a54128fSAndroid Build Coastguard Worker }
235*6a54128fSAndroid Build Coastguard Worker
236*6a54128fSAndroid Build Coastguard Worker #endif /* TEST_PROGRAM */
237