aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-18 20:57:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-18 20:57:52 +0200
commite8405619fa28972eacff34d3dee030927c4afc24 (patch)
tree6bef4cfa8130c8c5f2fa8e844944bf416bb6c28b
parentf9d3a91a89251cc4470a3cb94e918a49191438d2 (diff)
downloadbusybox-w32-e8405619fa28972eacff34d3dee030927c4afc24.tar.gz
busybox-w32-e8405619fa28972eacff34d3dee030927c4afc24.tar.bz2
busybox-w32-e8405619fa28972eacff34d3dee030927c4afc24.zip
mkfs_ext2: more work. added test script
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/mkfs_ext2.c174
-rwxr-xr-xutil-linux/mkfs_ext2_test.sh54
2 files changed, 153 insertions, 75 deletions
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index 56203c789..38654ef04 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -163,17 +163,16 @@ int mkfs_ext2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
163int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) 163int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
164{ 164{
165 unsigned i, pos, n; 165 unsigned i, pos, n;
166 unsigned bs, blocksize, blocksize_log2; 166 unsigned bs, bpi;
167 unsigned blocksize, blocksize_log2;
167 unsigned nreserved = 5; 168 unsigned nreserved = 5;
168 unsigned long long nblocks_ull; 169 unsigned long long kilobytes;
169 uint32_t nblocks; 170 uint32_t nblocks;
170 uint32_t ngroups; 171 uint32_t ngroups;
171 unsigned bytes_per_inode; 172 uint32_t bytes_per_inode;
172 uint32_t nblocks_per_group;
173 uint32_t first_data_block; 173 uint32_t first_data_block;
174 uint32_t ninodes;
175 uint32_t ninodes_per_group; 174 uint32_t ninodes_per_group;
176 uint32_t gdtsz, rgdtsz, itsz; 175 uint32_t gdtsz, itsz;
177 time_t timestamp; 176 time_t timestamp;
178 unsigned opts; 177 unsigned opts;
179 const char *label; 178 const char *label;
@@ -186,7 +185,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
186 185
187 opt_complementary = "-1:b+:m+:i+"; 186 opt_complementary = "-1:b+:m+:i+";
188 opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS", 187 opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS",
189 NULL, &bs, NULL, &bytes_per_inode, NULL, NULL, NULL, NULL, 188 NULL, &bs, NULL, &bpi, NULL, NULL, NULL, NULL,
190 &nreserved, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL); 189 &nreserved, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL);
191 argv += optind; // argv[0] -- device 190 argv += optind; // argv[0] -- device
192 191
@@ -195,7 +194,8 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
195 bb_error_msg_and_die("-%c is bad", 'm'); 194 bb_error_msg_and_die("-%c is bad", 'm');
196 195
197 // check the device is a block device 196 // check the device is a block device
198 xstat(argv[0], &st); 197 xmove_fd(xopen(argv[0], O_WRONLY), fd);
198 fstat(fd, &st);
199 if (!S_ISBLK(st.st_mode) && !(opts & OPT_F)) 199 if (!S_ISBLK(st.st_mode) && !(opts & OPT_F))
200 bb_error_msg_and_die("not a block device"); 200 bb_error_msg_and_die("not a block device");
201 201
@@ -206,22 +206,29 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
206 bb_error_msg_and_die("can't format mounted filesystem"); 206 bb_error_msg_and_die("can't format mounted filesystem");
207 207
208 // open the device, get size in kbytes 208 // open the device, get size in kbytes
209 xmove_fd(xopen3(argv[0], O_WRONLY | O_CREAT, 0666), fd);
210 if (argv[1]) { 209 if (argv[1]) {
211 nblocks_ull = xatoull(argv[1]); 210 kilobytes = xatoull(argv[1]);
212 } else { 211 } else {
213 nblocks_ull = (uoff_t)xlseek(fd, 0, SEEK_END) / 1024; 212 kilobytes = (uoff_t)xlseek(fd, 0, SEEK_END) / 1024;
214 } 213 }
215 214
215 bytes_per_inode = 16384;
216 if (kilobytes < 512*1024)
217 bytes_per_inode = 4096;
218 if (kilobytes < 3*1024)
219 bytes_per_inode = 8192;
220 if (opts & OPT_i)
221 bytes_per_inode = bpi;
222
216 // block size is a multiple of 1024 223 // block size is a multiple of 1024
217 blocksize = 1024; 224 blocksize = 1024;
218 if (nblocks_ull >= 512*1024) // mke2fs 1.41.9 compat 225 if (kilobytes >= 512*1024) // mke2fs 1.41.9 compat
219 blocksize = 4096; 226 blocksize = 4096;
220 if (EXT2_MAX_BLOCK_SIZE > 4096) { 227 if (EXT2_MAX_BLOCK_SIZE > 4096) {
221 // nblocks_ull >> 22 == size in 4gigabyte chunks. 228 // kilobytes >> 22 == size in 4gigabyte chunks.
222 // if it is >= 16k gigs, blocksize must be increased. 229 // if it is >= 16k gigs, blocksize must be increased.
223 // Try "mke2fs -F image_std $((16 * 1024*1024*1024))" 230 // Try "mke2fs -F image_std $((16 * 1024*1024*1024))"
224 while ((nblocks_ull >> 22) >= blocksize) 231 while ((kilobytes >> 22) >= blocksize)
225 blocksize *= 2; 232 blocksize *= 2;
226 } 233 }
227 if (opts & OPT_b) 234 if (opts & OPT_b)
@@ -233,13 +240,49 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
233 bb_error_msg_and_die("blocksize %u is bad", blocksize); 240 bb_error_msg_and_die("blocksize %u is bad", blocksize);
234 } 241 }
235 blocksize_log2 = int_log2(blocksize); 242 blocksize_log2 = int_log2(blocksize);
236 nblocks_ull >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); 243 kilobytes >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
237 // nblocks: the total number of blocks in the filesystem 244 // nblocks: the total number of blocks in the filesystem
238 nblocks = nblocks_ull; 245 nblocks = kilobytes;
239 if (nblocks != nblocks_ull) 246 if (nblocks != kilobytes)
240 bb_error_msg_and_die("block count doesn't fit in 32 bits"); 247 bb_error_msg_and_die("block count doesn't fit in 32 bits");
241 if (nblocks < 8) 248 if (nblocks < 8)
242 bb_error_msg_and_die("need >= 8 blocks"); 249 bb_error_msg_and_die("need >= 8 blocks");
250#define kilobytes kilobytes_unused_after_this
251
252 // number of bits in one block, i.e. 8*blocksize
253#define blocks_per_group (8 * blocksize)
254
255/* e2fsprogs-1.41.9
256 overhead = 2 + fs->inode_blocks_per_group;
257 if (has_super(fs->group_desc_count - 1))
258 overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
259 rem = (nblocks - first_data_block) % blocks_per_group);
260 if ((fs->group_desc_count == 1) && rem && (rem < overhead)) {
261 retval = EXT2_ET_TOOSMALL;
262 goto cleanup;
263 }
264 if (rem && (rem < overhead+50)) {
265 nblocks -= rem;
266 goto retry;
267 }
268*/
269
270 // N.B. a block group can have no more than blocks_per_group blocks
271 first_data_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
272 ngroups = div_roundup(nblocks - first_data_block, blocks_per_group);
273 if (0 == ngroups)
274 bb_error_msg_and_die("ngroups");
275
276 {
277 // ninodes is the total number of inodes (files) in the file system
278 uint32_t ninodes = nblocks / (bytes_per_inode >> blocksize_log2);
279 if (ninodes < EXT2_GOOD_OLD_FIRST_INO+1)
280 ninodes = EXT2_GOOD_OLD_FIRST_INO+1;
281 ninodes_per_group = div_roundup(ninodes, ngroups);
282 // minimum number because the first EXT2_GOOD_OLD_FIRST_INO-1 are reserved
283 if (ninodes_per_group < 16)
284 ninodes_per_group = 16;
285 }
243 286
244 // TODO: 5?/5 WE MUST NOT DEPEND ON WHETHER DEVICE IS /dev/zero 'ed OR NOT 287 // TODO: 5?/5 WE MUST NOT DEPEND ON WHETHER DEVICE IS /dev/zero 'ed OR NOT
245 // TODO: 3/5 refuse if mounted 288 // TODO: 3/5 refuse if mounted
@@ -260,15 +303,13 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
260 sb->s_log_block_size = sb->s_log_frag_size = blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE; 303 sb->s_log_block_size = sb->s_log_frag_size = blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE;
261 // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then 304 // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then
262 // the first block available for data is 1, otherwise 0 305 // the first block available for data is 1, otherwise 0
263 first_data_block = sb->s_first_data_block = (EXT2_MIN_BLOCK_SIZE == blocksize); 306 sb->s_first_data_block = first_data_block; // 0 or 1
264 // block and inode bitmaps occupy no more than one block, so maximum number of blocks is 307 // block and inode bitmaps occupy no more than one block, so maximum number of blocks is
265 // number of bits in one block, i.e. 8*blocksize 308 sb->s_blocks_per_group = sb->s_frags_per_group = blocks_per_group;
266 nblocks_per_group = sb->s_blocks_per_group = sb->s_frags_per_group = sb->s_inodes_per_group = 8 * blocksize;
267 timestamp = time(NULL); 309 timestamp = time(NULL);
268 sb->s_mkfs_time = sb->s_wtime = sb->s_lastcheck = timestamp; 310 sb->s_mkfs_time = sb->s_wtime = sb->s_lastcheck = timestamp;
269 sb->s_state = 1; 311 sb->s_state = 1;
270 sb->s_creator_os = EXT2_OS_LINUX; 312 sb->s_creator_os = EXT2_OS_LINUX;
271 sb->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
272 sb->s_checkinterval = 24*60*60 * 180; // 180 days 313 sb->s_checkinterval = 24*60*60 * 180; // 180 days
273 sb->s_errors = EXT2_ERRORS_DEFAULT; 314 sb->s_errors = EXT2_ERRORS_DEFAULT;
274 sb->s_feature_compat = EXT2_FEATURE_COMPAT_SUPP 315 sb->s_feature_compat = EXT2_FEATURE_COMPAT_SUPP
@@ -289,17 +330,14 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
289 * don't check all the filesystems at the same time. We use a 330 * don't check all the filesystems at the same time. We use a
290 * kludgy hack of using the UUID to derive a random jitter value. 331 * kludgy hack of using the UUID to derive a random jitter value.
291 */ 332 */
292 sb->s_max_mnt_count += sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT; 333 sb->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT
334 + (sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT);
293 335
294 sb->s_blocks_count = nblocks; 336 sb->s_blocks_count = nblocks;
295 337
296 // reserve blocks for superuser 338 // reserve blocks for superuser
297 sb->s_r_blocks_count = ((uint64_t) nblocks * nreserved) / 100; 339 sb->s_r_blocks_count = ((uint64_t) nblocks * nreserved) / 100;
298 340
299 // N.B. a block group can have no more than nblocks_per_group blocks
300 ngroups = div_roundup(nblocks - first_data_block, nblocks_per_group);
301 if (0 == ngroups)
302 bb_error_msg_and_die("ngroups");
303 gdtsz = div_roundup(ngroups, EXT2_DESC_PER_BLOCK(sb)); 341 gdtsz = div_roundup(ngroups, EXT2_DESC_PER_BLOCK(sb));
304 /* 342 /*
305 * From e2fsprogs: Calculate the number of GDT blocks to reserve for online 343 * From e2fsprogs: Calculate the number of GDT blocks to reserve for online
@@ -310,44 +348,28 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
310 /* We set it at 1024x the current filesystem size, or 348 /* We set it at 1024x the current filesystem size, or
311 * the upper block count limit (2^32), whichever is lower. 349 * the upper block count limit (2^32), whichever is lower.
312 */ 350 */
313#if ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 351 if (ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT) {
314 rgdtsz = 0xFFFFFFFF; // maximum block number 352 uint32_t rgdtsz = 0xFFFFFFFF; // maximum block number
315 if (nblocks < rgdtsz / 1024) 353 if (nblocks < rgdtsz / 1024)
316 rgdtsz = nblocks * 1024; 354 rgdtsz = nblocks * 1024;
317 rgdtsz = div_roundup(rgdtsz - first_data_block, nblocks_per_group); 355 rgdtsz = div_roundup(rgdtsz - first_data_block, blocks_per_group);
318 rgdtsz = div_roundup(rgdtsz, EXT2_DESC_PER_BLOCK(sb)) - gdtsz; 356 rgdtsz = div_roundup(rgdtsz, EXT2_DESC_PER_BLOCK(sb)) - gdtsz;
319 if (rgdtsz > EXT2_ADDR_PER_BLOCK(sb)) 357 if (rgdtsz > EXT2_ADDR_PER_BLOCK(sb))
320 rgdtsz = EXT2_ADDR_PER_BLOCK(sb); 358 rgdtsz = EXT2_ADDR_PER_BLOCK(sb);
321 sb->s_reserved_gdt_blocks = rgdtsz; 359 STORE_LE(sb->s_reserved_gdt_blocks, rgdtsz);
322 //bb_info_msg("RSRVD[%u]", n); 360 gdtsz += rgdtsz;
323#else
324 rgdtsz = 0;
325#endif
326
327 // ninodes is the total number of inodes (files) in the file system
328 if (!(opts & OPT_i)) {
329 bytes_per_inode = 16384;
330 if (nblocks < 512*1024)
331 bytes_per_inode = 4096;
332 if (nblocks < 3*1024)
333 bytes_per_inode = 8192;
334 } 361 }
335 ninodes = nblocks / (bytes_per_inode >> blocksize_log2); 362
336 if (ninodes < EXT2_GOOD_OLD_FIRST_INO+1) 363 // N.B. a block group can have no more than 8*blocksize inodes
337 ninodes = EXT2_GOOD_OLD_FIRST_INO+1; 364 if (ninodes_per_group > blocks_per_group)
338 ninodes_per_group = div_roundup(ninodes, ngroups); 365 ninodes_per_group = blocks_per_group;
339 if (ninodes_per_group < 16)
340 ninodes_per_group = 16; // minimum number because the first EXT2_GOOD_OLD_FIRST_INO-1 are reserved
341 // N.B. a block group can have no more than 8*blocksize = sb->s_inodes_per_group inodes
342 if (ninodes_per_group > sb->s_inodes_per_group)
343 ninodes_per_group = sb->s_inodes_per_group;
344 // adjust inodes per group so they completely fill the inode table blocks in the descriptor 366 // adjust inodes per group so they completely fill the inode table blocks in the descriptor
345 ninodes_per_group = (div_roundup(ninodes_per_group * EXT2_INODE_SIZE(sb), blocksize) << blocksize_log2) / EXT2_INODE_SIZE(sb); 367 ninodes_per_group = (div_roundup(ninodes_per_group * EXT2_INODE_SIZE(sb), blocksize) << blocksize_log2) / EXT2_INODE_SIZE(sb);
346 // make sure the number of inodes per group is a multiple of 8 368 // make sure the number of inodes per group is a multiple of 8
347 ninodes_per_group &= ~7; 369 ninodes_per_group &= ~7;
348 sb->s_inodes_per_group = ninodes_per_group;// = div_roundup(ninodes_per_group * sb->s_inode_size, blocksize); 370 sb->s_inodes_per_group = ninodes_per_group;// = div_roundup(ninodes_per_group * sb->s_inode_size, blocksize);
349 // total ninodes 371 // total ninodes
350 ninodes = sb->s_inodes_count = ninodes_per_group * ngroups; 372 sb->s_inodes_count = ninodes_per_group * ngroups;
351 373
352 itsz = ninodes_per_group * sb->s_inode_size / blocksize; 374 itsz = ninodes_per_group * sb->s_inode_size / blocksize;
353 sb->s_free_inodes_count = sb->s_inodes_count - EXT2_GOOD_OLD_FIRST_INO; 375 sb->s_free_inodes_count = sb->s_inodes_count - EXT2_GOOD_OLD_FIRST_INO;
@@ -370,7 +392,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
370 "%u inodes, %u blocks\n" 392 "%u inodes, %u blocks\n"
371 "%u blocks (%u%%) reserved for the super user\n" 393 "%u blocks (%u%%) reserved for the super user\n"
372 "First data block=%u\n" 394 "First data block=%u\n"
373// "Maximum filesystem blocks=%lu\n" 395 "Maximum filesystem blocks=%u\n"
374 "%u block groups\n" 396 "%u block groups\n"
375 "%u blocks per group, %u fragments per group\n" 397 "%u blocks per group, %u fragments per group\n"
376 "%u inodes per group" 398 "%u inodes per group"
@@ -380,16 +402,17 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
380 , sb->s_inodes_count, sb->s_blocks_count 402 , sb->s_inodes_count, sb->s_blocks_count
381 , sb->s_r_blocks_count, nreserved 403 , sb->s_r_blocks_count, nreserved
382 , first_data_block 404 , first_data_block
383// , (rgdtsz + gdtsz) * EXT2_DESC_PER_BLOCK(sb) * nblocks_per_group 405 , gdtsz * EXT2_DESC_PER_BLOCK(sb) * blocks_per_group
384 , ngroups 406 , ngroups
385 , nblocks_per_group, nblocks_per_group 407 , blocks_per_group, blocks_per_group
386 , ninodes_per_group 408 , ninodes_per_group
387 ); 409 );
388 { 410 {
389 const char *fmt = "\nSuperblock backups stored on blocks: %u"; 411 const char *fmt = "\nSuperblock backups stored on blocks:\n"
412 "\t%u";
390 pos = first_data_block; 413 pos = first_data_block;
391 for (i = 1; i < ngroups; i++) { 414 for (i = 1; i < ngroups; i++) {
392 pos += nblocks_per_group; 415 pos += blocks_per_group;
393 if (has_super(i)) { 416 if (has_super(i)) {
394 printf(fmt, (unsigned)pos); 417 printf(fmt, (unsigned)pos);
395 fmt = ", %u"; 418 fmt = ", %u";
@@ -400,16 +423,16 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
400#endif 423#endif
401 424
402 if (opts & OPT_n) 425 if (opts & OPT_n)
403 return EXIT_SUCCESS; 426 goto done;
404 427
405 // fill group descriptors 428 // fill group descriptors
406 gd = xzalloc((gdtsz + rgdtsz) * blocksize); 429 gd = xzalloc(gdtsz * blocksize);
407 sb->s_free_blocks_count = 0; 430 sb->s_free_blocks_count = 0;
408 for (i = 0, pos = first_data_block, n = nblocks; 431 for (i = 0, pos = first_data_block, n = nblocks;
409 i < ngroups; 432 i < ngroups;
410 i++, pos += nblocks_per_group, n -= nblocks_per_group 433 i++, pos += blocks_per_group, n -= blocks_per_group
411 ) { 434 ) {
412 uint32_t overhead = pos + (has_super(i) ? (1/*sb*/ + gdtsz + rgdtsz) : 0); 435 uint32_t overhead = pos + (has_super(i) ? (1/*sb*/ + gdtsz) : 0);
413 gd[i].bg_block_bitmap = overhead + 0; 436 gd[i].bg_block_bitmap = overhead + 0;
414 gd[i].bg_inode_bitmap = overhead + 1; 437 gd[i].bg_inode_bitmap = overhead + 1;
415 gd[i].bg_inode_table = overhead + 2; 438 gd[i].bg_inode_table = overhead + 2;
@@ -427,7 +450,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
427 if (ngroups-1 == i) { 450 if (ngroups-1 == i) {
428 overhead += first_data_block; 451 overhead += first_data_block;
429 } 452 }
430 gd[i].bg_free_blocks_count = (n < nblocks_per_group ? n : nblocks_per_group) - overhead; 453 gd[i].bg_free_blocks_count = (n < blocks_per_group ? n : blocks_per_group) - overhead;
431 sb->s_free_blocks_count += gd[i].bg_free_blocks_count; 454 sb->s_free_blocks_count += gd[i].bg_free_blocks_count;
432 } 455 }
433 STORE_LE(sb->s_free_blocks_count, sb->s_free_blocks_count); 456 STORE_LE(sb->s_free_blocks_count, sb->s_free_blocks_count);
@@ -435,22 +458,22 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
435 // dump filesystem skeleton structures 458 // dump filesystem skeleton structures
436// printf("Writing superblocks and filesystem accounting information: "); 459// printf("Writing superblocks and filesystem accounting information: ");
437 buf = xmalloc(blocksize); 460 buf = xmalloc(blocksize);
438 for (i = 0, pos = first_data_block; i < ngroups; i++, pos += nblocks_per_group) { 461 for (i = 0, pos = first_data_block; i < ngroups; i++, pos += blocks_per_group) {
439 uint32_t overhead = has_super(i) ? (1/*sb*/ + gdtsz + rgdtsz) : 0; 462 uint32_t overhead = has_super(i) ? (1/*sb*/ + gdtsz) : 0;
440 uint32_t start;// = has_super(i) ? (1/*sb*/ + gdtsz + rgdtsz) : 0; 463 uint32_t start;
441 uint32_t end; 464 uint32_t end;
442 465
443 // dump superblock and group descriptors and their backups 466 // dump superblock and group descriptors and their backups
444 if (overhead) { // N.B. in fact, we want (has_super(i)) condition, but it is equal to (overhead != 0) and is cheaper 467 if (overhead) { // N.B. in fact, we want (has_super(i)) condition, but it is equal to (overhead != 0) and is cheaper
445 // N.B. 1024 byte blocks are special 468 // N.B. 1024 byte blocks are special
446 PUT(((uint64_t)pos << blocksize_log2) + ((0 == i && 0 == first_data_block) ? 1024 : 0), sb, 1024);//blocksize); 469 PUT(((uint64_t)pos << blocksize_log2) + ((0 == i && 0 == first_data_block) ? 1024 : 0), sb, 1024);//blocksize);
447 PUT(((uint64_t)pos << blocksize_log2) + blocksize, gd, (gdtsz + rgdtsz) * blocksize); 470 PUT(((uint64_t)pos << blocksize_log2) + blocksize, gd, gdtsz * blocksize);
448 } 471 }
449 472
450 start = overhead + 1/*bbmp*/ + 1/*ibmp*/ + itsz; 473 start = overhead + 1/*bbmp*/ + 1/*ibmp*/ + itsz;
451 if (i == 0) 474 if (i == 0)
452 start += 2; // for "/" and "/lost+found" 475 start += 2; // for "/" and "/lost+found"
453 end = nblocks_per_group - (start + gd[i].bg_free_blocks_count); 476 end = blocks_per_group - (start + gd[i].bg_free_blocks_count);
454 477
455 // mark preallocated blocks as allocated 478 // mark preallocated blocks as allocated
456 allocate(buf, blocksize, start, end); 479 allocate(buf, blocksize, start, end);
@@ -460,7 +483,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
460 // mark preallocated inodes as allocated 483 // mark preallocated inodes as allocated
461 allocate(buf, blocksize, 484 allocate(buf, blocksize,
462 ninodes_per_group - gd[i].bg_free_inodes_count, 485 ninodes_per_group - gd[i].bg_free_inodes_count,
463 8 * blocksize - ninodes_per_group 486 blocks_per_group - ninodes_per_group
464 ); 487 );
465 // dump inode bitmap 488 // dump inode bitmap
466 //PUT((uint64_t)(pos + overhead + 1) * blocksize, buf, blocksize); 489 //PUT((uint64_t)(pos + overhead + 1) * blocksize, buf, blocksize);
@@ -525,10 +548,11 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
525 548
526// bb_info_msg("done\n" 549// bb_info_msg("done\n"
527// "This filesystem will be automatically checked every %u mounts or\n" 550// "This filesystem will be automatically checked every %u mounts or\n"
528// "%u days, whichever comes first. Use tune2fs -c or -i to override.", 551// "180 days, whichever comes first. Use tune2fs -c or -i to override.",
529// sb->s_max_mnt_count, sb->s_checkinterval / (3600 * 24) 552// sb->s_max_mnt_count
530// ); 553// );
531 554
555 done:
532 // cleanup 556 // cleanup
533 if (ENABLE_FEATURE_CLEAN_UP) { 557 if (ENABLE_FEATURE_CLEAN_UP) {
534 free(buf); 558 free(buf);
diff --git a/util-linux/mkfs_ext2_test.sh b/util-linux/mkfs_ext2_test.sh
new file mode 100755
index 000000000..fe6291fc5
--- /dev/null
+++ b/util-linux/mkfs_ext2_test.sh
@@ -0,0 +1,54 @@
1#!/bin/sh
2
3test_mke2fs() {
4 echo Testing $kilobytes
5
6 >image_std
7 dd seek=$((kilobytes-1)) bs=1K count=1 </dev/zero of=image_std >/dev/null 2>&1 || exit 1
8 /usr/bin/mke2fs -F image_std $kilobytes >image_std.raw_out 2>&1 || return 1
9 cat image_std.raw_out \
10 | grep -v '^mke2fs ' \
11 | grep -v '^Maximum filesystem' \
12 | grep -v '^warning: .* blocks unused' \
13 | grep -v '^Writing inode tables' \
14 | grep -v '^Writing superblocks and filesystem accounting information' \
15 | grep -v '^This filesystem will be automatically checked every' \
16 | grep -v '^180 days, whichever comes first' \
17 | sed 's/block groups/block group/' \
18 | sed 's/ *$//' \
19 | sed 's/blocks (.*%) reserved/blocks reserved/' \
20 | grep -v '^$' \
21 >image_std.out
22
23 >image_bb
24 dd seek=$((kilobytes-1)) bs=1K count=1 </dev/zero of=image_bb >/dev/null 2>&1 || exit 1
25 ./busybox mke2fs -F image_bb $kilobytes >image_bb.raw_out 2>&1 || return 1
26 cat image_bb.raw_out \
27 | grep -v '^mke2fs ' \
28 | grep -v '^Maximum filesystem' \
29 | grep -v '^warning: .* blocks unused' \
30 | grep -v '^Writing inode tables' \
31 | grep -v '^Writing superblocks and filesystem accounting information' \
32 | grep -v '^This filesystem will be automatically checked every' \
33 | grep -v '^180 days, whichever comes first' \
34 | sed 's/block groups/block group/' \
35 | sed 's/ *$//' \
36 | sed 's/blocks (.*%) reserved/blocks reserved/' \
37 | grep -v '^$' \
38 >image_bb.out
39
40 diff -ua image_bb.out image_std.out >image.out.diff || {
41 cat image.out.diff
42 return 1
43 }
44}
45
46kilobytes=24908 test_mke2fs
47kilobytes=81940 test_mke2fs
48kilobytes=98392 test_mke2fs
49exit
50
51while true; do
52 kilobytes=$(( (RANDOM*RANDOM) % 100000 + 100))
53 test_mke2fs || exit 1
54done