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