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