2 * alloc.c --- allocate new inodes, blocks for ext2fs
4 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Public
23 #include <sys/types.h>
30 * Check for uninit block bitmaps and deal with them appropriately
32 static void check_block_uninit(ext2_filsys fs
, ext2fs_block_bitmap map
,
36 blk64_t blk
, super_blk
, old_desc_blk
, new_desc_blk
;
39 if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
40 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
)) ||
41 !(ext2fs_bg_flag_test(fs
, group
, EXT2_BG_BLOCK_UNINIT
)))
44 blk
= (group
* fs
->super
->s_blocks_per_group
) +
45 fs
->super
->s_first_data_block
;
47 ext2fs_super_and_bgd_loc2(fs
, group
, &super_blk
,
48 &old_desc_blk
, &new_desc_blk
, 0);
50 if (fs
->super
->s_feature_incompat
&
51 EXT2_FEATURE_INCOMPAT_META_BG
)
52 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
54 old_desc_blocks
= fs
->desc_blocks
+ fs
->super
->s_reserved_gdt_blocks
;
56 for (i
=0; i
< fs
->super
->s_blocks_per_group
; i
++, blk
++) {
57 if ((blk
== super_blk
) ||
58 (old_desc_blk
&& old_desc_blocks
&&
59 (blk
>= old_desc_blk
) &&
60 (blk
< old_desc_blk
+ old_desc_blocks
)) ||
61 (new_desc_blk
&& (blk
== new_desc_blk
)) ||
62 (blk
== fs
->group_desc
[group
].bg_block_bitmap
) ||
63 (blk
== fs
->group_desc
[group
].bg_inode_bitmap
) ||
64 (blk
>= fs
->group_desc
[group
].bg_inode_table
&&
65 (blk
< fs
->group_desc
[group
].bg_inode_table
66 + fs
->inode_blocks_per_group
)))
67 ext2fs_fast_mark_block_bitmap2(map
, blk
);
69 ext2fs_fast_unmark_block_bitmap2(map
, blk
);
71 ext2fs_bg_flag_clear(fs
, group
, EXT2_BG_BLOCK_UNINIT
);
72 ext2fs_group_desc_csum_set(fs
, group
);
76 * Check for uninit inode bitmaps and deal with them appropriately
78 static void check_inode_uninit(ext2_filsys fs
, ext2fs_inode_bitmap map
,
83 if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
84 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
)) ||
85 !(ext2fs_bg_flag_test(fs
, group
, EXT2_BG_INODE_UNINIT
)))
88 ino
= (group
* fs
->super
->s_inodes_per_group
) + 1;
89 for (i
=0; i
< fs
->super
->s_inodes_per_group
; i
++, ino
++)
90 ext2fs_fast_unmark_inode_bitmap2(map
, ino
);
92 ext2fs_bg_flag_clear(fs
, group
, EXT2_BG_INODE_UNINIT
);
93 check_block_uninit(fs
, fs
->block_map
, group
);
97 * Right now, just search forward from the parent directory's block
98 * group to find the next free inode.
100 * Should have a special policy for directories.
102 errcode_t
ext2fs_new_inode(ext2_filsys fs
, ext2_ino_t dir
,
103 int mode
EXT2FS_ATTR((unused
)),
104 ext2fs_inode_bitmap map
, ext2_ino_t
*ret
)
106 ext2_ino_t dir_group
= 0;
108 ext2_ino_t start_inode
;
110 EXT2_CHECK_MAGIC(fs
, EXT2_ET_MAGIC_EXT2FS_FILSYS
);
115 return EXT2_ET_NO_INODE_BITMAP
;
118 dir_group
= (dir
- 1) / EXT2_INODES_PER_GROUP(fs
->super
);
120 start_inode
= (dir_group
* EXT2_INODES_PER_GROUP(fs
->super
)) + 1;
121 if (start_inode
< EXT2_FIRST_INODE(fs
->super
))
122 start_inode
= EXT2_FIRST_INODE(fs
->super
);
123 if (start_inode
> fs
->super
->s_inodes_count
)
124 return EXT2_ET_INODE_ALLOC_FAIL
;
128 if (((i
- 1) % EXT2_INODES_PER_GROUP(fs
->super
)) == 0)
129 check_inode_uninit(fs
, map
, (i
- 1) /
130 EXT2_INODES_PER_GROUP(fs
->super
));
132 if (!ext2fs_fast_test_inode_bitmap2(map
, i
))
135 if (i
> fs
->super
->s_inodes_count
)
136 i
= EXT2_FIRST_INODE(fs
->super
);
137 } while (i
!= start_inode
);
139 if (ext2fs_test_inode_bitmap2(map
, i
))
140 return EXT2_ET_INODE_ALLOC_FAIL
;
146 * Stupid algorithm --- we now just search forward starting from the
147 * goal. Should put in a smarter one someday....
149 errcode_t
ext2fs_new_block2(ext2_filsys fs
, blk64_t goal
,
150 ext2fs_block_bitmap map
, blk64_t
*ret
)
154 EXT2_CHECK_MAGIC(fs
, EXT2_ET_MAGIC_EXT2FS_FILSYS
);
159 return EXT2_ET_NO_BLOCK_BITMAP
;
160 if (!goal
|| (goal
>= ext2fs_blocks_count(fs
->super
)))
161 goal
= fs
->super
->s_first_data_block
;
163 check_block_uninit(fs
, map
,
164 (i
- fs
->super
->s_first_data_block
) /
165 EXT2_BLOCKS_PER_GROUP(fs
->super
));
167 if (((i
- fs
->super
->s_first_data_block
) %
168 EXT2_BLOCKS_PER_GROUP(fs
->super
)) == 0)
169 check_block_uninit(fs
, map
,
170 (i
- fs
->super
->s_first_data_block
) /
171 EXT2_BLOCKS_PER_GROUP(fs
->super
));
173 if (!ext2fs_fast_test_block_bitmap2(map
, i
)) {
178 if (i
>= ext2fs_blocks_count(fs
->super
))
179 i
= fs
->super
->s_first_data_block
;
181 return EXT2_ET_BLOCK_ALLOC_FAIL
;
184 errcode_t
ext2fs_new_block(ext2_filsys fs
, blk_t goal
,
185 ext2fs_block_bitmap map
, blk_t
*ret
)
189 retval
= ext2fs_new_block2(fs
, goal
, map
, &val
);
196 * This function zeros out the allocated block, and updates all of the
197 * appropriate filesystem records.
199 errcode_t
ext2fs_alloc_block2(ext2_filsys fs
, blk64_t goal
,
200 char *block_buf
, blk64_t
*ret
)
207 retval
= ext2fs_get_mem(fs
->blocksize
, &buf
);
212 memset(block_buf
, 0, fs
->blocksize
);
214 if (fs
->get_alloc_block
) {
215 retval
= (fs
->get_alloc_block
)(fs
, goal
, &block
);
219 if (!fs
->block_map
) {
220 retval
= ext2fs_read_block_bitmap(fs
);
225 retval
= ext2fs_new_block2(fs
, goal
, 0, &block
);
230 retval
= io_channel_write_blk64(fs
->io
, block
, 1, block_buf
);
234 ext2fs_block_alloc_stats2(fs
, block
, +1);
239 ext2fs_free_mem(&buf
);
243 errcode_t
ext2fs_alloc_block(ext2_filsys fs
, blk_t goal
,
244 char *block_buf
, blk_t
*ret
)
248 retval
= ext2fs_alloc_block2(fs
, goal
, block_buf
, &val
);
254 errcode_t
ext2fs_get_free_blocks2(ext2_filsys fs
, blk64_t start
, blk64_t finish
,
255 int num
, ext2fs_block_bitmap map
, blk64_t
*ret
)
259 EXT2_CHECK_MAGIC(fs
, EXT2_ET_MAGIC_EXT2FS_FILSYS
);
264 return EXT2_ET_NO_BLOCK_BITMAP
;
266 b
= fs
->super
->s_first_data_block
;
272 if (b
+num
-1 > ext2fs_blocks_count(fs
->super
))
273 b
= fs
->super
->s_first_data_block
;
274 if (ext2fs_fast_test_block_bitmap_range2(map
, b
, num
)) {
279 } while (b
!= finish
);
280 return EXT2_ET_BLOCK_ALLOC_FAIL
;
283 errcode_t
ext2fs_get_free_blocks(ext2_filsys fs
, blk_t start
, blk_t finish
,
284 int num
, ext2fs_block_bitmap map
, blk_t
*ret
)
288 retval
= ext2fs_get_free_blocks2(fs
, start
, finish
, num
, map
, &val
);
294 void ext2fs_set_alloc_block_callback(ext2_filsys fs
,
295 errcode_t (*func
)(ext2_filsys fs
,
298 errcode_t (**old
)(ext2_filsys fs
,
302 if (!fs
|| fs
->magic
!= EXT2_ET_MAGIC_EXT2FS_FILSYS
)
306 *old
= fs
->get_alloc_block
;
308 fs
->get_alloc_block
= func
;