alloc.c revision c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4e
1/* 2 * alloc.c --- allocate new inodes, blocks for ext2fs 3 * 4 * Copyright (C) 1993, 1994, 1995, 1996 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 13#include <stdio.h> 14#if HAVE_UNISTD_H 15#include <unistd.h> 16#endif 17#include <time.h> 18#include <string.h> 19#if HAVE_SYS_STAT_H 20#include <sys/stat.h> 21#endif 22#if HAVE_SYS_TYPES_H 23#include <sys/types.h> 24#endif 25 26#include "ext2_fs.h" 27#include "ext2fs.h" 28 29/* 30 * Right now, just search forward from the parent directory's block 31 * group to find the next free inode. 32 * 33 * Should have a special policy for directories. 34 */ 35errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode, 36 ext2fs_inode_bitmap map, ext2_ino_t *ret) 37{ 38 ext2_ino_t dir_group = 0; 39 ext2_ino_t i; 40 ext2_ino_t start_inode; 41 42 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 43 44 if (!map) 45 map = fs->inode_map; 46 if (!map) 47 return EXT2_ET_NO_INODE_BITMAP; 48 49 if (dir > 0) 50 dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super); 51 52 start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1; 53 if (start_inode < EXT2_FIRST_INODE(fs->super)) 54 start_inode = EXT2_FIRST_INODE(fs->super); 55 i = start_inode; 56 57 do { 58 if (!ext2fs_fast_test_inode_bitmap(map, i)) 59 break; 60 i++; 61 if (i > fs->super->s_inodes_count) 62 i = EXT2_FIRST_INODE(fs->super); 63 } while (i != start_inode); 64 65 if (ext2fs_test_inode_bitmap(map, i)) 66 return EXT2_ET_INODE_ALLOC_FAIL; 67 *ret = i; 68 return 0; 69} 70 71/* 72 * Stupid algorithm --- we now just search forward starting from the 73 * goal. Should put in a smarter one someday.... 74 */ 75errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, 76 ext2fs_block_bitmap map, blk_t *ret) 77{ 78 blk_t i; 79 80 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 81 82 if (!map) 83 map = fs->block_map; 84 if (!map) 85 return EXT2_ET_NO_BLOCK_BITMAP; 86 if (!goal || (goal >= fs->super->s_blocks_count)) 87 goal = fs->super->s_first_data_block; 88 i = goal; 89 do { 90 if (!ext2fs_fast_test_block_bitmap(map, i)) { 91 *ret = i; 92 return 0; 93 } 94 i++; 95 if (i >= fs->super->s_blocks_count) 96 i = fs->super->s_first_data_block; 97 } while (i != goal); 98 return EXT2_ET_BLOCK_ALLOC_FAIL; 99} 100 101/* 102 * This function zeros out the allocated block, and updates all of the 103 * appropriate filesystem records. 104 */ 105errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, 106 char *block_buf, blk_t *ret) 107{ 108 errcode_t retval; 109 blk_t block; 110 char *buf = 0; 111 112 if (!block_buf) { 113 retval = ext2fs_get_mem(fs->blocksize, &buf); 114 if (retval) 115 return retval; 116 block_buf = buf; 117 } 118 memset(block_buf, 0, fs->blocksize); 119 120 if (!fs->block_map) { 121 retval = ext2fs_read_block_bitmap(fs); 122 if (retval) 123 goto fail; 124 } 125 126 retval = ext2fs_new_block(fs, goal, 0, &block); 127 if (retval) 128 goto fail; 129 130 retval = io_channel_write_blk(fs->io, block, 1, block_buf); 131 if (retval) 132 goto fail; 133 134 ext2fs_block_alloc_stats(fs, block, +1); 135 *ret = block; 136 return 0; 137 138fail: 139 if (buf) 140 ext2fs_free_mem(&buf); 141 return retval; 142} 143 144errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish, 145 int num, ext2fs_block_bitmap map, blk_t *ret) 146{ 147 blk_t b = start; 148 149 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 150 151 if (!map) 152 map = fs->block_map; 153 if (!map) 154 return EXT2_ET_NO_BLOCK_BITMAP; 155 if (!b) 156 b = fs->super->s_first_data_block; 157 if (!finish) 158 finish = start; 159 if (!num) 160 num = 1; 161 do { 162 if (b+num-1 > fs->super->s_blocks_count) 163 b = fs->super->s_first_data_block; 164 if (ext2fs_fast_test_block_bitmap_range(map, b, num)) { 165 *ret = b; 166 return 0; 167 } 168 b++; 169 } while (b != finish); 170 return EXT2_ET_BLOCK_ALLOC_FAIL; 171} 172 173