1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include "basefs_allocator.h" 4 #include "block_range.h" 5 #include "hashmap.h" 6 #include "base_fs.h" 7 8 struct base_fs_allocator { 9 struct hashmap *entries; 10 struct basefs_entry *cur_entry; 11 }; 12 13 static errcode_t basefs_block_allocator(ext2_filsys, blk64_t, blk64_t *, 14 struct blk_alloc_ctx *ctx); 15 16 static void fs_free_blocks_range(ext2_filsys fs, struct block_range *blocks) 17 { 18 while (blocks) { 19 ext2fs_unmark_block_bitmap_range2(fs->block_map, blocks->start, 20 blocks->end - blocks->start + 1); 21 blocks = blocks->next; 22 } 23 } 24 25 static void fs_reserve_blocks_range(ext2_filsys fs, struct block_range *blocks) 26 { 27 while (blocks) { 28 ext2fs_mark_block_bitmap_range2(fs->block_map, 29 blocks->start, blocks->end - blocks->start + 1); 30 blocks = blocks->next; 31 } 32 } 33 34 errcode_t base_fs_alloc_load(ext2_filsys fs, const char *file, 35 const char *mountpoint) 36 { 37 errcode_t retval; 38 struct basefs_entry *e; 39 struct hashmap_entry *it = NULL; 40 struct base_fs_allocator *allocator; 41 struct hashmap *entries = basefs_parse(file, mountpoint); 42 if (!entries) 43 return -1; 44 45 allocator = malloc(sizeof(*allocator)); 46 if (!allocator) 47 goto err_alloc; 48 49 retval = ext2fs_read_bitmaps(fs); 50 if (retval) 51 goto err_bitmap; 52 while ((e = hashmap_iter_in_order(entries, &it))) 53 fs_reserve_blocks_range(fs, e->head); 54 55 allocator->cur_entry = NULL; 56 allocator->entries = entries; 57 58 /* Overhide the default allocator */ 59 fs->get_alloc_block2 = basefs_block_allocator; 60 fs->priv_data = allocator; 61 62 return 0; 63 64 err_bitmap: 65 free(allocator); 66 err_alloc: 67 hashmap_free(entries); 68 return EXIT_FAILURE; 69 } 70 71 static errcode_t basefs_block_allocator(ext2_filsys fs, blk64_t goal, 72 blk64_t *ret, struct blk_alloc_ctx *ctx) 73 { 74 errcode_t retval; 75 struct block_range *next_range; 76 struct base_fs_allocator *allocator = fs->priv_data; 77 struct basefs_entry *e = allocator->cur_entry; 78 79 /* Try to get a block from the base_fs */ 80 if (e && e->head && ctx && (ctx->flags & BLOCK_ALLOC_DATA)) { 81 *ret = e->head->start; 82 e->head->start += 1; 83 if (e->head->start > e->head->end) { 84 next_range = e->head->next; 85 free(e->head); 86 e->head = next_range; 87 } 88 } else { /* Allocate a new block */ 89 retval = ext2fs_new_block2(fs, goal, fs->block_map, ret); 90 if (retval) 91 return retval; 92 ext2fs_mark_block_bitmap2(fs->block_map, *ret); 93 } 94 return 0; 95 } 96 97 void base_fs_alloc_cleanup(ext2_filsys fs) 98 { 99 struct basefs_entry *e; 100 struct hashmap_entry *it = NULL; 101 struct base_fs_allocator *allocator = fs->priv_data; 102 103 while ((e = hashmap_iter_in_order(allocator->entries, &it))) { 104 fs_free_blocks_range(fs, e->head); 105 delete_block_ranges(e->head); 106 e->head = e->tail = NULL; 107 } 108 109 fs->priv_data = NULL; 110 fs->get_alloc_block2 = NULL; 111 hashmap_free(allocator->entries); 112 free(allocator); 113 } 114 115 errcode_t base_fs_alloc_set_target(ext2_filsys fs, const char *target_path, 116 const char *name EXT2FS_ATTR((unused)), 117 ext2_ino_t parent_ino EXT2FS_ATTR((unused)), 118 ext2_ino_t root EXT2FS_ATTR((unused)), mode_t mode) 119 { 120 struct base_fs_allocator *allocator = fs->priv_data; 121 122 if (mode != S_IFREG) 123 return 0; 124 125 if (allocator) 126 allocator->cur_entry = hashmap_lookup(allocator->entries, 127 target_path); 128 return 0; 129 } 130 131 errcode_t base_fs_alloc_unset_target(ext2_filsys fs, 132 const char *target_path EXT2FS_ATTR((unused)), 133 const char *name EXT2FS_ATTR((unused)), 134 ext2_ino_t parent_ino EXT2FS_ATTR((unused)), 135 ext2_ino_t root EXT2FS_ATTR((unused)), mode_t mode) 136 { 137 struct base_fs_allocator *allocator = fs->priv_data; 138 139 if (!allocator || !allocator->cur_entry || mode != S_IFREG) 140 return 0; 141 142 fs_free_blocks_range(fs, allocator->cur_entry->head); 143 delete_block_ranges(allocator->cur_entry->head); 144 allocator->cur_entry->head = allocator->cur_entry->tail = NULL; 145 allocator->cur_entry = NULL; 146 return 0; 147 } 148