1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "ext4_utils.h" 18 #include "allocate.h" 19 20 #include <sparse/sparse.h> 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 25 struct region { 26 u32 block; 27 u32 len; 28 int bg; 29 struct region *next; 30 struct region *prev; 31 }; 32 33 struct block_group_info { 34 u32 first_block; 35 int header_blocks; 36 int data_blocks_used; 37 int has_superblock; 38 u8 *bitmaps; 39 u8 *block_bitmap; 40 u8 *inode_bitmap; 41 u8 *inode_table; 42 u32 free_blocks; 43 u32 first_free_block; 44 u32 free_inodes; 45 u32 first_free_inode; 46 u16 flags; 47 u16 used_dirs; 48 }; 49 50 struct xattr_list_element { 51 struct ext4_inode *inode; 52 struct ext4_xattr_header *header; 53 struct xattr_list_element *next; 54 }; 55 56 struct block_allocation *create_allocation() 57 { 58 struct block_allocation *alloc = malloc(sizeof(struct block_allocation)); 59 alloc->list.first = NULL; 60 alloc->list.last = NULL; 61 alloc->oob_list.first = NULL; 62 alloc->oob_list.last = NULL; 63 alloc->list.iter = NULL; 64 alloc->list.partial_iter = 0; 65 alloc->oob_list.iter = NULL; 66 alloc->oob_list.partial_iter = 0; 67 alloc->filename = NULL; 68 alloc->next = NULL; 69 return alloc; 70 } 71 72 static struct ext4_xattr_header *xattr_list_find(struct ext4_inode *inode) 73 { 74 struct xattr_list_element *element; 75 for (element = aux_info.xattrs; element != NULL; element = element->next) { 76 if (element->inode == inode) 77 return element->header; 78 } 79 return NULL; 80 } 81 82 static void xattr_list_insert(struct ext4_inode *inode, struct ext4_xattr_header *header) 83 { 84 struct xattr_list_element *element = malloc(sizeof(struct xattr_list_element)); 85 element->inode = inode; 86 element->header = header; 87 element->next = aux_info.xattrs; 88 aux_info.xattrs = element; 89 } 90 91 static void region_list_remove(struct region_list *list, struct region *reg) 92 { 93 if (reg->prev) 94 reg->prev->next = reg->next; 95 96 if (reg->next) 97 reg->next->prev = reg->prev; 98 99 if (list->first == reg) 100 list->first = reg->next; 101 102 if (list->last == reg) 103 list->last = reg->prev; 104 105 reg->next = NULL; 106 reg->prev = NULL; 107 } 108 109 static void region_list_append(struct region_list *list, struct region *reg) 110 { 111 if (list->first == NULL) { 112 list->first = reg; 113 list->last = reg; 114 list->iter = reg; 115 list->partial_iter = 0; 116 reg->prev = NULL; 117 } else { 118 list->last->next = reg; 119 reg->prev = list->last; 120 list->last = reg; 121 } 122 reg->next = NULL; 123 } 124 125 #if 0 126 static void dump_starting_from(struct region *reg) 127 { 128 for (; reg; reg = reg->next) { 129 printf("%p: Blocks %d-%d (%d)\n", reg, 130 reg->block, reg->block + reg->len - 1, reg->len) 131 } 132 } 133 134 static void dump_region_lists(struct block_allocation *alloc) { 135 136 printf("Main list:\n"); 137 dump_starting_from(alloc->list.first); 138 139 printf("OOB list:\n"); 140 dump_starting_from(alloc->oob_list.first); 141 } 142 #endif 143 144 void print_blocks(FILE* f, struct block_allocation *alloc) 145 { 146 struct region *reg; 147 for (reg = alloc->list.first; reg; reg = reg->next) { 148 if (reg->len == 1) { 149 fprintf(f, " %d", reg->block); 150 } else { 151 fprintf(f, " %d-%d", reg->block, reg->block + reg->len - 1); 152 } 153 } 154 fputc('\n', f); 155 } 156 157 void append_region(struct block_allocation *alloc, 158 u32 block, u32 len, int bg_num) 159 { 160 struct region *reg; 161 reg = malloc(sizeof(struct region)); 162 reg->block = block; 163 reg->len = len; 164 reg->bg = bg_num; 165 reg->next = NULL; 166 167 region_list_append(&alloc->list, reg); 168 } 169 170 static void allocate_bg_inode_table(struct block_group_info *bg) 171 { 172 if (bg->inode_table != NULL) 173 return; 174 175 u32 block = bg->first_block + 2; 176 177 if (bg->has_superblock) 178 block += aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks + 1; 179 180 bg->inode_table = calloc(aux_info.inode_table_blocks, info.block_size); 181 if (bg->inode_table == NULL) 182 critical_error_errno("calloc"); 183 184 sparse_file_add_data(ext4_sparse_file, bg->inode_table, 185 aux_info.inode_table_blocks * info.block_size, block); 186 187 bg->flags &= ~EXT4_BG_INODE_UNINIT; 188 } 189 190 static int bitmap_set_bit(u8 *bitmap, u32 bit) 191 { 192 if (bitmap[bit / 8] & 1 << (bit % 8)) 193 return 1; 194 195 bitmap[bit / 8] |= 1 << (bit % 8); 196 return 0; 197 } 198 199 static int bitmap_set_8_bits(u8 *bitmap, u32 bit) 200 { 201 int ret = bitmap[bit / 8]; 202 bitmap[bit / 8] = 0xFF; 203 return ret; 204 } 205 206 /* Marks a the first num_blocks blocks in a block group as used, and accounts 207 for them in the block group free block info. */ 208 static int reserve_blocks(struct block_group_info *bg, u32 start, u32 num) 209 { 210 unsigned int i = 0; 211 212 u32 block = start; 213 if (num > bg->free_blocks) 214 return -1; 215 216 for (i = 0; i < num && block % 8 != 0; i++, block++) { 217 if (bitmap_set_bit(bg->block_bitmap, block)) { 218 error("attempted to reserve already reserved block"); 219 return -1; 220 } 221 } 222 223 for (; i + 8 <= (num & ~7); i += 8, block += 8) { 224 if (bitmap_set_8_bits(bg->block_bitmap, block)) { 225 error("attempted to reserve already reserved block"); 226 return -1; 227 } 228 } 229 230 for (; i < num; i++, block++) { 231 if (bitmap_set_bit(bg->block_bitmap, block)) { 232 error("attempted to reserve already reserved block"); 233 return -1; 234 } 235 } 236 237 bg->free_blocks -= num; 238 if (start == bg->first_free_block) 239 bg->first_free_block = start + num; 240 241 return 0; 242 } 243 244 static void free_blocks(struct block_group_info *bg, u32 num_blocks) 245 { 246 unsigned int i; 247 u32 block = bg->first_free_block - 1; 248 for (i = 0; i < num_blocks; i++, block--) 249 bg->block_bitmap[block / 8] &= ~(1 << (block % 8)); 250 bg->free_blocks += num_blocks; 251 bg->first_free_block -= num_blocks; 252 } 253 254 /* Reduces an existing allocation by len blocks by return the last blocks 255 to the free pool in their block group. Assumes that the blocks being 256 returned were the last ones allocated out of the block group */ 257 void reduce_allocation(struct block_allocation *alloc, u32 len) 258 { 259 while (len) { 260 struct region *last_reg = alloc->list.last; 261 262 if (last_reg->len > len) { 263 free_blocks(&aux_info.bgs[last_reg->bg], len); 264 last_reg->len -= len; 265 len = 0; 266 } else { 267 struct region *reg = alloc->list.last->prev; 268 free_blocks(&aux_info.bgs[last_reg->bg], last_reg->len); 269 len -= last_reg->len; 270 if (reg) { 271 reg->next = NULL; 272 } else { 273 alloc->list.first = NULL; 274 alloc->list.last = NULL; 275 alloc->list.iter = NULL; 276 alloc->list.partial_iter = 0; 277 } 278 free(last_reg); 279 } 280 } 281 } 282 283 static void init_bg(struct block_group_info *bg, unsigned int i) 284 { 285 int header_blocks = 2 + aux_info.inode_table_blocks; 286 287 bg->has_superblock = ext4_bg_has_super_block(i); 288 289 if (bg->has_superblock) 290 header_blocks += 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks; 291 292 bg->bitmaps = calloc(info.block_size, 2); 293 bg->block_bitmap = bg->bitmaps; 294 bg->inode_bitmap = bg->bitmaps + info.block_size; 295 296 bg->header_blocks = header_blocks; 297 bg->first_block = aux_info.first_data_block + i * info.blocks_per_group; 298 299 u32 block = bg->first_block; 300 if (bg->has_superblock) 301 block += 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks; 302 sparse_file_add_data(ext4_sparse_file, bg->bitmaps, 2 * info.block_size, 303 block); 304 305 bg->data_blocks_used = 0; 306 bg->free_blocks = info.blocks_per_group; 307 bg->first_free_block = 0; 308 bg->free_inodes = info.inodes_per_group; 309 bg->first_free_inode = 1; 310 bg->flags = EXT4_BG_INODE_UNINIT; 311 312 if (reserve_blocks(bg, bg->first_free_block, bg->header_blocks) < 0) 313 error("failed to reserve %u blocks in block group %u\n", bg->header_blocks, i); 314 315 if (bg->first_block + info.blocks_per_group > aux_info.len_blocks) { 316 u32 overrun = bg->first_block + info.blocks_per_group - aux_info.len_blocks; 317 reserve_blocks(bg, info.blocks_per_group - overrun, overrun); 318 } 319 } 320 321 void block_allocator_init() 322 { 323 unsigned int i; 324 325 aux_info.bgs = calloc(sizeof(struct block_group_info), aux_info.groups); 326 if (aux_info.bgs == NULL) 327 critical_error_errno("calloc"); 328 329 for (i = 0; i < aux_info.groups; i++) 330 init_bg(&aux_info.bgs[i], i); 331 } 332 333 void block_allocator_free() 334 { 335 unsigned int i; 336 337 for (i = 0; i < aux_info.groups; i++) { 338 free(aux_info.bgs[i].bitmaps); 339 free(aux_info.bgs[i].inode_table); 340 } 341 free(aux_info.bgs); 342 } 343 344 static u32 ext4_allocate_blocks_from_block_group(u32 len, int bg_num) 345 { 346 if (get_free_blocks(bg_num) < len) 347 return EXT4_ALLOCATE_FAILED; 348 349 u32 block = aux_info.bgs[bg_num].first_free_block; 350 struct block_group_info *bg = &aux_info.bgs[bg_num]; 351 if (reserve_blocks(bg, bg->first_free_block, len) < 0) { 352 error("failed to reserve %u blocks in block group %u\n", len, bg_num); 353 return EXT4_ALLOCATE_FAILED; 354 } 355 356 aux_info.bgs[bg_num].data_blocks_used += len; 357 358 return bg->first_block + block; 359 } 360 361 /* Allocate a single block and return its block number */ 362 u32 allocate_block() 363 { 364 unsigned int i; 365 for (i = 0; i < aux_info.groups; i++) { 366 u32 block = ext4_allocate_blocks_from_block_group(1, i); 367 368 if (block != EXT4_ALLOCATE_FAILED) 369 return block; 370 } 371 372 return EXT4_ALLOCATE_FAILED; 373 } 374 375 static struct region *ext4_allocate_best_fit_partial(u32 len) 376 { 377 unsigned int i; 378 unsigned int found_bg = 0; 379 u32 found_bg_len = 0; 380 381 for (i = 0; i < aux_info.groups; i++) { 382 u32 bg_len = aux_info.bgs[i].free_blocks; 383 384 if ((len <= bg_len && (found_bg_len == 0 || bg_len < found_bg_len)) || 385 (len > found_bg_len && bg_len > found_bg_len)) { 386 found_bg = i; 387 found_bg_len = bg_len; 388 } 389 } 390 391 if (found_bg_len) { 392 u32 allocate_len = min(len, found_bg_len); 393 struct region *reg; 394 u32 block = ext4_allocate_blocks_from_block_group(allocate_len, found_bg); 395 if (block == EXT4_ALLOCATE_FAILED) { 396 error("failed to allocate %d blocks in block group %d", allocate_len, found_bg); 397 return NULL; 398 } 399 reg = malloc(sizeof(struct region)); 400 reg->block = block; 401 reg->len = allocate_len; 402 reg->next = NULL; 403 reg->prev = NULL; 404 reg->bg = found_bg; 405 return reg; 406 } else { 407 error("failed to allocate %u blocks, out of space?", len); 408 } 409 410 return NULL; 411 } 412 413 static struct region *ext4_allocate_best_fit(u32 len) 414 { 415 struct region *first_reg = NULL; 416 struct region *prev_reg = NULL; 417 struct region *reg; 418 419 while (len > 0) { 420 reg = ext4_allocate_best_fit_partial(len); 421 if (reg == NULL) 422 return NULL; 423 424 if (first_reg == NULL) 425 first_reg = reg; 426 427 if (prev_reg) { 428 prev_reg->next = reg; 429 reg->prev = prev_reg; 430 } 431 432 prev_reg = reg; 433 len -= reg->len; 434 } 435 436 return first_reg; 437 } 438 439 /* Allocate len blocks. The blocks may be spread across multiple block groups, 440 and are returned in a linked list of the blocks in each block group. The 441 allocation algorithm is: 442 1. If the remaining allocation is larger than any available contiguous region, 443 allocate the largest contiguous region and loop 444 2. Otherwise, allocate the smallest contiguous region that it fits in 445 */ 446 struct block_allocation *allocate_blocks(u32 len) 447 { 448 struct region *reg = ext4_allocate_best_fit(len); 449 450 if (reg == NULL) 451 return NULL; 452 453 struct block_allocation *alloc = create_allocation(); 454 alloc->list.first = reg; 455 alloc->list.last = reg; 456 alloc->list.iter = alloc->list.first; 457 alloc->list.partial_iter = 0; 458 return alloc; 459 } 460 461 /* Returns the number of discontiguous regions used by an allocation */ 462 int block_allocation_num_regions(struct block_allocation *alloc) 463 { 464 unsigned int i; 465 struct region *reg = alloc->list.first; 466 467 for (i = 0; reg != NULL; reg = reg->next) 468 i++; 469 470 return i; 471 } 472 473 int block_allocation_len(struct block_allocation *alloc) 474 { 475 unsigned int i; 476 struct region *reg = alloc->list.first; 477 478 for (i = 0; reg != NULL; reg = reg->next) 479 i += reg->len; 480 481 return i; 482 } 483 484 /* Returns the block number of the block'th block in an allocation */ 485 u32 get_block(struct block_allocation *alloc, u32 block) 486 { 487 struct region *reg = alloc->list.iter; 488 block += alloc->list.partial_iter; 489 490 for (; reg; reg = reg->next) { 491 if (block < reg->len) 492 return reg->block + block; 493 block -= reg->len; 494 } 495 return EXT4_ALLOCATE_FAILED; 496 } 497 498 u32 get_oob_block(struct block_allocation *alloc, u32 block) 499 { 500 struct region *reg = alloc->oob_list.iter; 501 block += alloc->oob_list.partial_iter; 502 503 for (; reg; reg = reg->next) { 504 if (block < reg->len) 505 return reg->block + block; 506 block -= reg->len; 507 } 508 return EXT4_ALLOCATE_FAILED; 509 } 510 511 /* Gets the starting block and length in blocks of the first region 512 of an allocation */ 513 void get_region(struct block_allocation *alloc, u32 *block, u32 *len) 514 { 515 *block = alloc->list.iter->block; 516 *len = alloc->list.iter->len - alloc->list.partial_iter; 517 } 518 519 /* Move to the next region in an allocation */ 520 void get_next_region(struct block_allocation *alloc) 521 { 522 alloc->list.iter = alloc->list.iter->next; 523 alloc->list.partial_iter = 0; 524 } 525 526 /* Returns the number of free blocks in a block group */ 527 u32 get_free_blocks(u32 bg) 528 { 529 return aux_info.bgs[bg].free_blocks; 530 } 531 532 int last_region(struct block_allocation *alloc) 533 { 534 return (alloc->list.iter == NULL); 535 } 536 537 void rewind_alloc(struct block_allocation *alloc) 538 { 539 alloc->list.iter = alloc->list.first; 540 alloc->list.partial_iter = 0; 541 } 542 543 static struct region *do_split_allocation(struct block_allocation *alloc, u32 len) 544 { 545 struct region *reg = alloc->list.iter; 546 struct region *new; 547 struct region *tmp; 548 549 while (reg && len >= reg->len) { 550 len -= reg->len; 551 reg = reg->next; 552 } 553 554 if (reg == NULL && len > 0) 555 return NULL; 556 557 if (len > 0) { 558 new = malloc(sizeof(struct region)); 559 560 new->bg = reg->bg; 561 new->block = reg->block + len; 562 new->len = reg->len - len; 563 new->next = reg->next; 564 new->prev = reg; 565 566 reg->next = new; 567 reg->len = len; 568 569 tmp = alloc->list.iter; 570 alloc->list.iter = new; 571 return tmp; 572 } else { 573 return reg; 574 } 575 } 576 577 /* Splits an allocation into two allocations. The returned allocation will 578 point to the first half, and the original allocation ptr will point to the 579 second half. */ 580 static struct region *split_allocation(struct block_allocation *alloc, u32 len) 581 { 582 /* First make sure there is a split at the current ptr */ 583 do_split_allocation(alloc, alloc->list.partial_iter); 584 585 /* Then split off len blocks */ 586 struct region *middle = do_split_allocation(alloc, len); 587 alloc->list.partial_iter = 0; 588 return middle; 589 } 590 591 /* Reserve the next blocks for oob data (indirect or extent blocks) */ 592 int reserve_oob_blocks(struct block_allocation *alloc, int blocks) 593 { 594 struct region *oob = split_allocation(alloc, blocks); 595 struct region *next; 596 597 if (oob == NULL) 598 return -1; 599 600 while (oob && oob != alloc->list.iter) { 601 next = oob->next; 602 region_list_remove(&alloc->list, oob); 603 region_list_append(&alloc->oob_list, oob); 604 oob = next; 605 } 606 607 return 0; 608 } 609 610 static int advance_list_ptr(struct region_list *list, int blocks) 611 { 612 struct region *reg = list->iter; 613 614 while (reg != NULL && blocks > 0) { 615 if (reg->len > list->partial_iter + blocks) { 616 list->partial_iter += blocks; 617 return 0; 618 } 619 620 blocks -= (reg->len - list->partial_iter); 621 list->partial_iter = 0; 622 reg = reg->next; 623 } 624 625 if (blocks > 0) 626 return -1; 627 628 return 0; 629 } 630 631 /* Move the allocation pointer forward */ 632 int advance_blocks(struct block_allocation *alloc, int blocks) 633 { 634 return advance_list_ptr(&alloc->list, blocks); 635 } 636 637 int advance_oob_blocks(struct block_allocation *alloc, int blocks) 638 { 639 return advance_list_ptr(&alloc->oob_list, blocks); 640 } 641 642 int append_oob_allocation(struct block_allocation *alloc, u32 len) 643 { 644 struct region *reg = ext4_allocate_best_fit(len); 645 646 if (reg == NULL) { 647 error("failed to allocate %d blocks", len); 648 return -1; 649 } 650 651 for (; reg; reg = reg->next) 652 region_list_append(&alloc->oob_list, reg); 653 654 return 0; 655 } 656 657 /* Returns an ext4_inode structure for an inode number */ 658 struct ext4_inode *get_inode(u32 inode) 659 { 660 inode -= 1; 661 int bg = inode / info.inodes_per_group; 662 inode %= info.inodes_per_group; 663 664 allocate_bg_inode_table(&aux_info.bgs[bg]); 665 return (struct ext4_inode *)(aux_info.bgs[bg].inode_table + inode * 666 info.inode_size); 667 } 668 669 struct ext4_xattr_header *get_xattr_block_for_inode(struct ext4_inode *inode) 670 { 671 struct ext4_xattr_header *block = xattr_list_find(inode); 672 if (block != NULL) 673 return block; 674 675 u32 block_num = allocate_block(); 676 block = calloc(info.block_size, 1); 677 if (block == NULL) { 678 error("get_xattr: failed to allocate %d", info.block_size); 679 return NULL; 680 } 681 682 block->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); 683 block->h_refcount = cpu_to_le32(1); 684 block->h_blocks = cpu_to_le32(1); 685 inode->i_blocks_lo = cpu_to_le32(le32_to_cpu(inode->i_blocks_lo) + (info.block_size / 512)); 686 inode->i_file_acl_lo = cpu_to_le32(block_num); 687 688 int result = sparse_file_add_data(ext4_sparse_file, block, info.block_size, block_num); 689 if (result != 0) { 690 error("get_xattr: sparse_file_add_data failure %d", result); 691 free(block); 692 return NULL; 693 } 694 xattr_list_insert(inode, block); 695 return block; 696 } 697 698 /* Mark the first len inodes in a block group as used */ 699 u32 reserve_inodes(int bg, u32 num) 700 { 701 unsigned int i; 702 u32 inode; 703 704 if (get_free_inodes(bg) < num) 705 return EXT4_ALLOCATE_FAILED; 706 707 for (i = 0; i < num; i++) { 708 inode = aux_info.bgs[bg].first_free_inode + i - 1; 709 aux_info.bgs[bg].inode_bitmap[inode / 8] |= 1 << (inode % 8); 710 } 711 712 inode = aux_info.bgs[bg].first_free_inode; 713 714 aux_info.bgs[bg].first_free_inode += num; 715 aux_info.bgs[bg].free_inodes -= num; 716 717 return inode; 718 } 719 720 /* Returns the first free inode number 721 TODO: Inodes should be allocated in the block group of the data? */ 722 u32 allocate_inode() 723 { 724 unsigned int bg; 725 u32 inode; 726 727 for (bg = 0; bg < aux_info.groups; bg++) { 728 inode = reserve_inodes(bg, 1); 729 if (inode != EXT4_ALLOCATE_FAILED) 730 return bg * info.inodes_per_group + inode; 731 } 732 733 return EXT4_ALLOCATE_FAILED; 734 } 735 736 /* Returns the number of free inodes in a block group */ 737 u32 get_free_inodes(u32 bg) 738 { 739 return aux_info.bgs[bg].free_inodes; 740 } 741 742 /* Increments the directory count of the block group that contains inode */ 743 void add_directory(u32 inode) 744 { 745 int bg = (inode - 1) / info.inodes_per_group; 746 aux_info.bgs[bg].used_dirs += 1; 747 } 748 749 /* Returns the number of inodes in a block group that are directories */ 750 u16 get_directories(int bg) 751 { 752 return aux_info.bgs[bg].used_dirs; 753 } 754 755 /* Returns the flags for a block group */ 756 u16 get_bg_flags(int bg) 757 { 758 return aux_info.bgs[bg].flags; 759 } 760 761 /* Frees the memory used by a linked list of allocation regions */ 762 void free_alloc(struct block_allocation *alloc) 763 { 764 struct region *reg; 765 766 reg = alloc->list.first; 767 while (reg) { 768 struct region *next = reg->next; 769 free(reg); 770 reg = next; 771 } 772 773 reg = alloc->oob_list.first; 774 while (reg) { 775 struct region *next = reg->next; 776 free(reg); 777 reg = next; 778 } 779 780 free(alloc); 781 } 782
This page was automatically generated by LXR 0.3.1. • OpenWrt