2 * initialize.c --- initialize a filesystem handle given superblock
3 * parameters. Used by mke2fs when initializing a filesystem.
13 #include <sys/types.h>
15 #include <linux/ext2_fs.h>
19 errcode_t
ext2fs_initialize(const char *name
, int flags
,
20 struct ext2_super_block
*param
,
21 io_manager manager
, ext2_filsys
*ret_fs
)
25 struct ext2_super_block
*super
;
34 if (!param
|| !param
->s_blocks_count
)
37 fs
= (ext2_filsys
) malloc(sizeof(struct struct_ext2_filsys
));
41 memset(fs
, 0, sizeof(struct struct_ext2_filsys
));
42 fs
->magic
= EXT2_ET_MAGIC_EXT2FS_FILSYS
;
43 fs
->flags
= flags
| EXT2_FLAG_RW
;
44 retval
= manager
->open(name
, IO_FLAG_RW
, &fs
->io
);
47 fs
->device_name
= malloc(strlen(name
)+1);
48 if (!fs
->device_name
) {
52 strcpy(fs
->device_name
, name
);
53 fs
->super
= super
= malloc(SUPERBLOCK_SIZE
);
58 memset(super
, 0, SUPERBLOCK_SIZE
);
60 #define set_field(field, default) (super->field = param->field ? \
61 param->field : (default))
63 super
->s_magic
= EXT2_SUPER_MAGIC
;
64 super
->s_state
= EXT2_VALID_FS
;
66 set_field(s_log_block_size
, 0); /* default blocksize: 1024 bytes */
67 set_field(s_log_frag_size
, 0); /* default fragsize: 1024 bytes */
68 set_field(s_first_data_block
, super
->s_log_block_size
? 0 : 1);
69 set_field(s_max_mnt_count
, EXT2_DFL_MAX_MNT_COUNT
);
70 set_field(s_errors
, EXT2_ERRORS_DEFAULT
);
72 set_field(s_checkinterval
, EXT2_DFL_CHECKINTERVAL
);
73 super
->s_lastcheck
= time(NULL
);
76 super
->s_creator_os
= EXT2_OS_LINUX
;
79 fs
->blocksize
= EXT2_BLOCK_SIZE(super
);
80 fs
->fragsize
= EXT2_FRAG_SIZE(super
);
81 frags_per_block
= fs
->blocksize
/ fs
->fragsize
;
83 set_field(s_blocks_per_group
, 8192); /* default: 8192 blocks/group */
84 super
->s_frags_per_group
= super
->s_blocks_per_group
* frags_per_block
;
86 super
->s_blocks_count
= param
->s_blocks_count
;
87 super
->s_r_blocks_count
= param
->s_r_blocks_count
;
88 if (super
->s_r_blocks_count
>= param
->s_blocks_count
) {
94 fs
->group_desc_count
= (super
->s_blocks_count
-
95 super
->s_first_data_block
+
96 EXT2_BLOCKS_PER_GROUP(super
) - 1)
97 / EXT2_BLOCKS_PER_GROUP(super
);
98 fs
->desc_blocks
= (fs
->group_desc_count
+
99 EXT2_DESC_PER_BLOCK(super
) - 1)
100 / EXT2_DESC_PER_BLOCK(super
);
102 set_field(s_inodes_count
, (super
->s_blocks_count
*fs
->blocksize
)/4096);
105 * There should be at least as many inodes as the user
106 * requested. Figure out how many inodes per group that
109 super
->s_inodes_per_group
= (super
->s_inodes_count
+
110 fs
->group_desc_count
- 1) /
111 fs
->group_desc_count
;
114 * Make sure the number of inodes per group completely fills
115 * the inode table blocks in the descriptor. If not, add some
116 * additional inodes/group. Waste not, want not...
118 fs
->inode_blocks_per_group
= (super
->s_inodes_per_group
+
119 EXT2_INODES_PER_BLOCK(super
) - 1) /
120 EXT2_INODES_PER_BLOCK(super
);
121 super
->s_inodes_per_group
= fs
->inode_blocks_per_group
*
122 EXT2_INODES_PER_BLOCK(super
);
125 * adjust inode count to reflect the adjusted inodes_per_group
127 super
->s_inodes_count
= super
->s_inodes_per_group
*
128 fs
->group_desc_count
;
129 super
->s_free_inodes_count
= super
->s_inodes_count
;
132 * Overhead is the number of bookkeeping blocks per group. It
133 * includes the superblock backup, the group descriptor
134 * backups, the inode bitmap, the block bitmap, and the inode
137 overhead
= 3 + fs
->desc_blocks
+ fs
->inode_blocks_per_group
;
138 super
->s_free_blocks_count
= super
->s_blocks_count
-
139 super
->s_first_data_block
- (overhead
*fs
->group_desc_count
);
142 * See if the last group is big enough to support the
143 * necessary data structures. If not, we need to get rid of
146 rem
= (super
->s_blocks_count
- super
->s_first_data_block
) %
147 super
->s_blocks_per_group
;
148 if ((fs
->group_desc_count
== 1) && rem
&& (rem
< overhead
))
149 return EXT2_ET_TOOSMALL
;
150 if (rem
&& (rem
< overhead
+50)) {
151 super
->s_blocks_count
-= rem
;
156 * At this point we know how big the filesystem will be. So
157 * we can do any and all allocations that depend on the block
161 buf
= malloc(strlen(fs
->device_name
) + 80);
167 sprintf(buf
, "block bitmap for %s", fs
->device_name
);
168 retval
= ext2fs_allocate_block_bitmap(fs
, buf
, &fs
->block_map
);
172 sprintf(buf
, "inode bitmap for %s", fs
->device_name
);
173 retval
= ext2fs_allocate_inode_bitmap(fs
, 0, &fs
->inode_map
);
179 fs
->group_desc
= malloc(fs
->desc_blocks
* fs
->blocksize
);
180 if (!fs
->group_desc
) {
184 memset(fs
->group_desc
, 0, fs
->desc_blocks
* fs
->blocksize
);
187 * Reserve the superblock and group descriptors for each
188 * group, and fill in the correct group statistics for group.
189 * Note that although the block bitmap, inode bitmap, and
190 * inode table have not been allocated (and in fact won't be
191 * by this routine), they are accounted for nevertheless.
193 group_block
= super
->s_first_data_block
;
194 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
195 for (j
=0; j
< fs
->desc_blocks
+1; j
++)
196 ext2fs_mark_block_bitmap(fs
->block_map
,
199 if (i
== fs
->group_desc_count
-1) {
200 numblocks
= (fs
->super
->s_blocks_count
-
201 fs
->super
->s_first_data_block
) %
202 fs
->super
->s_blocks_per_group
;
204 numblocks
= fs
->super
->s_blocks_per_group
;
206 numblocks
= fs
->super
->s_blocks_per_group
;
207 numblocks
-= 3 + fs
->desc_blocks
+ fs
->inode_blocks_per_group
;
209 fs
->group_desc
[i
].bg_free_blocks_count
= numblocks
;
210 fs
->group_desc
[i
].bg_free_inodes_count
=
211 fs
->super
->s_inodes_per_group
;
212 fs
->group_desc
[i
].bg_used_dirs_count
= 0;
214 group_block
+= super
->s_blocks_per_group
;
217 ext2fs_mark_super_dirty(fs
);
218 ext2fs_mark_bb_dirty(fs
);
219 ext2fs_mark_ib_dirty(fs
);
221 io_channel_set_blksize(fs
->io
, fs
->blocksize
);