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