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