1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: Mke2fs
3*c2c66affSColin Finck * FILE: Super.c
4*c2c66affSColin Finck * PROGRAMMER: Matt Wu <mattwu@163.com>
5*c2c66affSColin Finck * HOMEPAGE: http://ext2.yeah.net
6*c2c66affSColin Finck */
7*c2c66affSColin Finck
8*c2c66affSColin Finck /* INCLUDES **************************************************************/
9*c2c66affSColin Finck
10*c2c66affSColin Finck #include "Mke2fs.h"
11*c2c66affSColin Finck #include <debug.h>
12*c2c66affSColin Finck
13*c2c66affSColin Finck /* DEFINITIONS ***********************************************************/
14*c2c66affSColin Finck
15*c2c66affSColin Finck extern int inode_ratio;
16*c2c66affSColin Finck
17*c2c66affSColin Finck
18*c2c66affSColin Finck /* FUNCTIONS *************************************************************/
19*c2c66affSColin Finck
ext2_print_super(PEXT2_SUPER_BLOCK pExt2Sb)20*c2c66affSColin Finck void ext2_print_super(PEXT2_SUPER_BLOCK pExt2Sb)
21*c2c66affSColin Finck {
22*c2c66affSColin Finck int i;
23*c2c66affSColin Finck
24*c2c66affSColin Finck DPRINT("\nExt2 Super Block Details ...\n\n");
25*c2c66affSColin Finck DPRINT(" Inode Count: %lu\n", pExt2Sb->s_inodes_count);
26*c2c66affSColin Finck DPRINT(" Block Count: %lu\n", pExt2Sb->s_blocks_count);
27*c2c66affSColin Finck DPRINT(" Reserved Block Count: %lu\n", pExt2Sb->s_r_blocks_count);
28*c2c66affSColin Finck DPRINT(" Free Blocks: %lu\n", pExt2Sb->s_free_blocks_count);
29*c2c66affSColin Finck DPRINT(" Free Inodes: %lu\n", pExt2Sb->s_free_inodes_count);
30*c2c66affSColin Finck DPRINT(" First Data Block: %lu\n", pExt2Sb->s_first_data_block);
31*c2c66affSColin Finck DPRINT(" Log Block Size: %lu\n", pExt2Sb->s_log_block_size);
32*c2c66affSColin Finck DPRINT(" Log Frag Size: %ld\n", pExt2Sb->s_log_frag_size);
33*c2c66affSColin Finck DPRINT(" Blocks per Group: %lu\n", pExt2Sb->s_blocks_per_group);
34*c2c66affSColin Finck DPRINT(" Fragments per Group: %lu\n", pExt2Sb->s_frags_per_group);
35*c2c66affSColin Finck DPRINT(" Inodes per Group: %lu\n", pExt2Sb->s_inodes_per_group);
36*c2c66affSColin Finck // DPRINT(" Mount Time: %s", ctime((time_t *) & (pExt2Sb->s_mtime)));
37*c2c66affSColin Finck // DPRINT(" Write Time: %s", ctime((time_t *) & (pExt2Sb->s_wtime)));
38*c2c66affSColin Finck DPRINT(" Mount Count: %u\n", pExt2Sb->s_mnt_count);
39*c2c66affSColin Finck DPRINT(" Max Mount Count: %d\n", pExt2Sb->s_max_mnt_count);
40*c2c66affSColin Finck DPRINT(" Magic Number: %X (%s)\n", pExt2Sb->s_magic,
41*c2c66affSColin Finck pExt2Sb->s_magic == EXT2_SUPER_MAGIC ? "OK" : "BAD");
42*c2c66affSColin Finck DPRINT(" File System State: %X\n", pExt2Sb->s_state);
43*c2c66affSColin Finck DPRINT(" Error Behaviour: %X\n", pExt2Sb->s_errors);
44*c2c66affSColin Finck DPRINT(" Minor rev: %u\n", pExt2Sb->s_minor_rev_level);
45*c2c66affSColin Finck // DPRINT(" Last Check: %s", ctime((time_t *) & (pExt2Sb->s_lastcheck)));
46*c2c66affSColin Finck DPRINT(" Check Interval: %lu\n", pExt2Sb->s_checkinterval);
47*c2c66affSColin Finck DPRINT(" Creator OS: %lu\n", pExt2Sb->s_creator_os);
48*c2c66affSColin Finck DPRINT(" Revision Level: %lu\n", pExt2Sb->s_rev_level);
49*c2c66affSColin Finck DPRINT(" Reserved Block Default UID: %u\n", pExt2Sb->s_def_resuid);
50*c2c66affSColin Finck DPRINT(" Reserved Block Default GID: %u\n", pExt2Sb->s_def_resgid);
51*c2c66affSColin Finck DPRINT(" uuid = ");
52*c2c66affSColin Finck for (i=0; i < 16; i++)
53*c2c66affSColin Finck DbgPrint("%x ", pExt2Sb->s_uuid[i]);
54*c2c66affSColin Finck DbgPrint("\n");
55*c2c66affSColin Finck
56*c2c66affSColin Finck DPRINT(" volume label name: ");
57*c2c66affSColin Finck for (i=0; i < 16; i++)
58*c2c66affSColin Finck {
59*c2c66affSColin Finck if (pExt2Sb->s_volume_name[i] == 0)
60*c2c66affSColin Finck break;
61*c2c66affSColin Finck DbgPrint("%c", pExt2Sb->s_volume_name[i]);
62*c2c66affSColin Finck }
63*c2c66affSColin Finck DbgPrint("\n");
64*c2c66affSColin Finck
65*c2c66affSColin Finck DPRINT("\n\n");
66*c2c66affSColin Finck }
67*c2c66affSColin Finck
68*c2c66affSColin Finck #define set_field(field, default) if (!pExt2Sb->field) pExt2Sb->field = (default);
69*c2c66affSColin Finck
70*c2c66affSColin Finck /*
71*c2c66affSColin Finck * Initialize super block ...
72*c2c66affSColin Finck */
73*c2c66affSColin Finck
ext2_initialize_sb(PEXT2_FILESYS Ext2Sys)74*c2c66affSColin Finck bool ext2_initialize_sb(PEXT2_FILESYS Ext2Sys)
75*c2c66affSColin Finck {
76*c2c66affSColin Finck int frags_per_block = 0;
77*c2c66affSColin Finck ULONG overhead = 0;
78*c2c66affSColin Finck ULONG rem = 0;
79*c2c66affSColin Finck ULONG i = 0;
80*c2c66affSColin Finck ULONG group_block = 0;
81*c2c66affSColin Finck ULONG numblocks = 0;
82*c2c66affSColin Finck PEXT2_SUPER_BLOCK pExt2Sb = Ext2Sys->ext2_sb;
83*c2c66affSColin Finck LARGE_INTEGER SysTime;
84*c2c66affSColin Finck
85*c2c66affSColin Finck NtQuerySystemTime(&SysTime);
86*c2c66affSColin Finck
87*c2c66affSColin Finck Ext2Sys->blocksize = EXT2_BLOCK_SIZE(pExt2Sb);
88*c2c66affSColin Finck Ext2Sys->fragsize = EXT2_FRAG_SIZE(pExt2Sb);
89*c2c66affSColin Finck frags_per_block = Ext2Sys->blocksize / Ext2Sys->fragsize;
90*c2c66affSColin Finck
91*c2c66affSColin Finck pExt2Sb->s_magic = EXT2_SUPER_MAGIC;
92*c2c66affSColin Finck pExt2Sb->s_state = EXT2_VALID_FS;
93*c2c66affSColin Finck
94*c2c66affSColin Finck pExt2Sb->s_first_data_block = (pExt2Sb->s_log_block_size) ? 0 : 1;
95*c2c66affSColin Finck pExt2Sb->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
96*c2c66affSColin Finck
97*c2c66affSColin Finck pExt2Sb->s_errors = EXT2_ERRORS_DEFAULT;
98*c2c66affSColin Finck
99*c2c66affSColin Finck pExt2Sb->s_checkinterval = EXT2_DFL_CHECKINTERVAL;
100*c2c66affSColin Finck
101*c2c66affSColin Finck if (!pExt2Sb->s_rev_level)
102*c2c66affSColin Finck pExt2Sb->s_rev_level = EXT2_GOOD_OLD_REV;
103*c2c66affSColin Finck
104*c2c66affSColin Finck if (pExt2Sb->s_rev_level >= EXT2_DYNAMIC_REV)
105*c2c66affSColin Finck {
106*c2c66affSColin Finck set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
107*c2c66affSColin Finck set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
108*c2c66affSColin Finck }
109*c2c66affSColin Finck
110*c2c66affSColin Finck RtlTimeToSecondsSince1970(&SysTime, &pExt2Sb->s_wtime);
111*c2c66affSColin Finck pExt2Sb->s_lastcheck = pExt2Sb->s_mtime = pExt2Sb->s_wtime;
112*c2c66affSColin Finck
113*c2c66affSColin Finck if (!pExt2Sb->s_blocks_per_group)
114*c2c66affSColin Finck pExt2Sb->s_blocks_per_group = Ext2Sys->blocksize * 8;
115*c2c66affSColin Finck
116*c2c66affSColin Finck pExt2Sb->s_frags_per_group = pExt2Sb->s_blocks_per_group * frags_per_block;
117*c2c66affSColin Finck pExt2Sb->s_creator_os = EXT2_OS_WINNT;
118*c2c66affSColin Finck
119*c2c66affSColin Finck if (pExt2Sb->s_r_blocks_count >= pExt2Sb->s_blocks_count)
120*c2c66affSColin Finck {
121*c2c66affSColin Finck goto cleanup;
122*c2c66affSColin Finck }
123*c2c66affSColin Finck
124*c2c66affSColin Finck /*
125*c2c66affSColin Finck * If we're creating an external journal device, we don't need
126*c2c66affSColin Finck * to bother with the rest.
127*c2c66affSColin Finck */
128*c2c66affSColin Finck if (pExt2Sb->s_feature_incompat &
129*c2c66affSColin Finck EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
130*c2c66affSColin Finck {
131*c2c66affSColin Finck Ext2Sys->group_desc_count = 0;
132*c2c66affSColin Finck // ext2fs_mark_super_dirty(fs);
133*c2c66affSColin Finck return true;
134*c2c66affSColin Finck }
135*c2c66affSColin Finck
136*c2c66affSColin Finck retry:
137*c2c66affSColin Finck
138*c2c66affSColin Finck Ext2Sys->group_desc_count = (pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block
139*c2c66affSColin Finck + EXT2_BLOCKS_PER_GROUP(pExt2Sb) - 1) / EXT2_BLOCKS_PER_GROUP(pExt2Sb);
140*c2c66affSColin Finck
141*c2c66affSColin Finck if (Ext2Sys->group_desc_count == 0)
142*c2c66affSColin Finck return false;
143*c2c66affSColin Finck
144*c2c66affSColin Finck Ext2Sys->desc_blocks = (Ext2Sys->group_desc_count + EXT2_DESC_PER_BLOCK(pExt2Sb)
145*c2c66affSColin Finck - 1) / EXT2_DESC_PER_BLOCK(pExt2Sb);
146*c2c66affSColin Finck
147*c2c66affSColin Finck if (!pExt2Sb->s_inodes_count)
148*c2c66affSColin Finck pExt2Sb->s_inodes_count = pExt2Sb->s_blocks_count / ( inode_ratio /Ext2Sys->blocksize);
149*c2c66affSColin Finck
150*c2c66affSColin Finck /*
151*c2c66affSColin Finck * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
152*c2c66affSColin Finck * that we have enough inodes for the filesystem(!)
153*c2c66affSColin Finck */
154*c2c66affSColin Finck if (pExt2Sb->s_inodes_count < EXT2_FIRST_INODE(pExt2Sb)+1)
155*c2c66affSColin Finck pExt2Sb->s_inodes_count = EXT2_FIRST_INODE(pExt2Sb)+1;
156*c2c66affSColin Finck
157*c2c66affSColin Finck /*
158*c2c66affSColin Finck * There should be at least as many inodes as the user
159*c2c66affSColin Finck * requested. Figure out how many inodes per group that
160*c2c66affSColin Finck * should be. But make sure that we don't allocate more than
161*c2c66affSColin Finck * one bitmap's worth of inodes
162*c2c66affSColin Finck */
163*c2c66affSColin Finck pExt2Sb->s_inodes_per_group = (pExt2Sb->s_inodes_count + Ext2Sys->group_desc_count - 1)
164*c2c66affSColin Finck /Ext2Sys->group_desc_count;
165*c2c66affSColin Finck
166*c2c66affSColin Finck if (pExt2Sb->s_inodes_per_group > (ULONG)(Ext2Sys->blocksize*8))
167*c2c66affSColin Finck pExt2Sb->s_inodes_per_group = Ext2Sys->blocksize*8;
168*c2c66affSColin Finck
169*c2c66affSColin Finck /*
170*c2c66affSColin Finck * Make sure the number of inodes per group completely fills
171*c2c66affSColin Finck * the inode table blocks in the descriptor. If not, add some
172*c2c66affSColin Finck * additional inodes/group. Waste not, want not...
173*c2c66affSColin Finck */
174*c2c66affSColin Finck Ext2Sys->inode_blocks_per_group = (((pExt2Sb->s_inodes_per_group * EXT2_INODE_SIZE(pExt2Sb))
175*c2c66affSColin Finck + EXT2_BLOCK_SIZE(pExt2Sb) - 1) / EXT2_BLOCK_SIZE(pExt2Sb));
176*c2c66affSColin Finck
177*c2c66affSColin Finck pExt2Sb->s_inodes_per_group = ((Ext2Sys->inode_blocks_per_group * EXT2_BLOCK_SIZE(pExt2Sb))
178*c2c66affSColin Finck / EXT2_INODE_SIZE(pExt2Sb));
179*c2c66affSColin Finck
180*c2c66affSColin Finck /*
181*c2c66affSColin Finck * Finally, make sure the number of inodes per group is a
182*c2c66affSColin Finck * multiple of 8. This is needed to simplify the bitmap
183*c2c66affSColin Finck * splicing code.
184*c2c66affSColin Finck */
185*c2c66affSColin Finck pExt2Sb->s_inodes_per_group &= ~7;
186*c2c66affSColin Finck Ext2Sys->inode_blocks_per_group = (((pExt2Sb->s_inodes_per_group * EXT2_INODE_SIZE(pExt2Sb))
187*c2c66affSColin Finck + EXT2_BLOCK_SIZE(pExt2Sb) - 1) / EXT2_BLOCK_SIZE(pExt2Sb));
188*c2c66affSColin Finck
189*c2c66affSColin Finck /*
190*c2c66affSColin Finck * adjust inode count to reflect the adjusted inodes_per_group
191*c2c66affSColin Finck */
192*c2c66affSColin Finck pExt2Sb->s_inodes_count = pExt2Sb->s_inodes_per_group * Ext2Sys->group_desc_count;
193*c2c66affSColin Finck pExt2Sb->s_free_inodes_count = pExt2Sb->s_inodes_count;
194*c2c66affSColin Finck
195*c2c66affSColin Finck /*
196*c2c66affSColin Finck * Overhead is the number of bookkeeping blocks per group. It
197*c2c66affSColin Finck * includes the superblock backup, the group descriptor
198*c2c66affSColin Finck * backups, the inode bitmap, the block bitmap, and the inode
199*c2c66affSColin Finck * table.
200*c2c66affSColin Finck *
201*c2c66affSColin Finck * XXX Not all block groups need the descriptor blocks, but
202*c2c66affSColin Finck * being clever is tricky...
203*c2c66affSColin Finck */
204*c2c66affSColin Finck overhead = (3 + Ext2Sys->desc_blocks + Ext2Sys->inode_blocks_per_group);
205*c2c66affSColin Finck
206*c2c66affSColin Finck /*
207*c2c66affSColin Finck * See if the last group is big enough to support the
208*c2c66affSColin Finck * necessary data structures. If not, we need to get rid of
209*c2c66affSColin Finck * it.
210*c2c66affSColin Finck */
211*c2c66affSColin Finck rem = ((pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block) %
212*c2c66affSColin Finck pExt2Sb->s_blocks_per_group);
213*c2c66affSColin Finck
214*c2c66affSColin Finck if ((Ext2Sys->group_desc_count == 1) && rem && (rem < overhead))
215*c2c66affSColin Finck return false;
216*c2c66affSColin Finck
217*c2c66affSColin Finck if (rem && (rem < overhead+50))
218*c2c66affSColin Finck {
219*c2c66affSColin Finck pExt2Sb->s_blocks_count -= rem;
220*c2c66affSColin Finck goto retry;
221*c2c66affSColin Finck }
222*c2c66affSColin Finck
223*c2c66affSColin Finck /*
224*c2c66affSColin Finck * At this point we know how big the filesystem will be. So we can do
225*c2c66affSColin Finck * any and all allocations that depend on the block count.
226*c2c66affSColin Finck */
227*c2c66affSColin Finck
228*c2c66affSColin Finck // Allocate block bitmap
229*c2c66affSColin Finck if(!ext2_allocate_block_bitmap(Ext2Sys))
230*c2c66affSColin Finck {
231*c2c66affSColin Finck goto cleanup;
232*c2c66affSColin Finck }
233*c2c66affSColin Finck
234*c2c66affSColin Finck // Allocate inode bitmap
235*c2c66affSColin Finck if(!ext2_allocate_inode_bitmap(Ext2Sys))
236*c2c66affSColin Finck {
237*c2c66affSColin Finck goto cleanup;
238*c2c66affSColin Finck }
239*c2c66affSColin Finck
240*c2c66affSColin Finck // Allocate gourp desc
241*c2c66affSColin Finck if(!ext2_allocate_group_desc(Ext2Sys))
242*c2c66affSColin Finck {
243*c2c66affSColin Finck goto cleanup;
244*c2c66affSColin Finck }
245*c2c66affSColin Finck
246*c2c66affSColin Finck /*
247*c2c66affSColin Finck * Reserve the superblock and group descriptors for each
248*c2c66affSColin Finck * group, and fill in the correct group statistics for group.
249*c2c66affSColin Finck * Note that although the block bitmap, inode bitmap, and
250*c2c66affSColin Finck * inode table have not been allocated (and in fact won't be
251*c2c66affSColin Finck * by this routine), they are accounted for nevertheless.
252*c2c66affSColin Finck */
253*c2c66affSColin Finck group_block = pExt2Sb->s_first_data_block;
254*c2c66affSColin Finck numblocks = 0;
255*c2c66affSColin Finck
256*c2c66affSColin Finck pExt2Sb->s_free_blocks_count = 0;
257*c2c66affSColin Finck
258*c2c66affSColin Finck for (i = 0; i < Ext2Sys->group_desc_count; i++)
259*c2c66affSColin Finck {
260*c2c66affSColin Finck if (i == Ext2Sys->group_desc_count-1)
261*c2c66affSColin Finck {
262*c2c66affSColin Finck numblocks = (pExt2Sb->s_blocks_count - pExt2Sb->s_first_data_block)
263*c2c66affSColin Finck % pExt2Sb->s_blocks_per_group;
264*c2c66affSColin Finck
265*c2c66affSColin Finck if (!numblocks)
266*c2c66affSColin Finck numblocks = pExt2Sb->s_blocks_per_group;
267*c2c66affSColin Finck }
268*c2c66affSColin Finck else
269*c2c66affSColin Finck {
270*c2c66affSColin Finck numblocks = pExt2Sb->s_blocks_per_group;
271*c2c66affSColin Finck }
272*c2c66affSColin Finck
273*c2c66affSColin Finck if (ext2_bg_has_super(pExt2Sb, i))
274*c2c66affSColin Finck {
275*c2c66affSColin Finck ULONG j;
276*c2c66affSColin Finck
277*c2c66affSColin Finck for (j=0; j < Ext2Sys->desc_blocks+1; j++)
278*c2c66affSColin Finck ext2_mark_bitmap(Ext2Sys->block_map, group_block + j);
279*c2c66affSColin Finck
280*c2c66affSColin Finck numblocks -= 1 + Ext2Sys->desc_blocks;
281*c2c66affSColin Finck }
282*c2c66affSColin Finck
283*c2c66affSColin Finck numblocks -= 2 + Ext2Sys->inode_blocks_per_group;
284*c2c66affSColin Finck
285*c2c66affSColin Finck pExt2Sb->s_free_blocks_count += numblocks;
286*c2c66affSColin Finck Ext2Sys->group_desc[i].bg_free_blocks_count = (__u16)numblocks;
287*c2c66affSColin Finck Ext2Sys->group_desc[i].bg_free_inodes_count = (__u16)pExt2Sb->s_inodes_per_group;
288*c2c66affSColin Finck Ext2Sys->group_desc[i].bg_used_dirs_count = 0;
289*c2c66affSColin Finck
290*c2c66affSColin Finck group_block += pExt2Sb->s_blocks_per_group;
291*c2c66affSColin Finck }
292*c2c66affSColin Finck
293*c2c66affSColin Finck return true;
294*c2c66affSColin Finck
295*c2c66affSColin Finck cleanup:
296*c2c66affSColin Finck
297*c2c66affSColin Finck ext2_free_group_desc(Ext2Sys);
298*c2c66affSColin Finck ext2_free_block_bitmap(Ext2Sys);
299*c2c66affSColin Finck ext2_free_inode_bitmap(Ext2Sys);
300*c2c66affSColin Finck
301*c2c66affSColin Finck return false;
302*c2c66affSColin Finck }
303