diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-18 20:57:52 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-18 20:57:52 +0200 |
commit | e8405619fa28972eacff34d3dee030927c4afc24 (patch) | |
tree | 6bef4cfa8130c8c5f2fa8e844944bf416bb6c28b | |
parent | f9d3a91a89251cc4470a3cb94e918a49191438d2 (diff) | |
download | busybox-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.c | 174 | ||||
-rwxr-xr-x | util-linux/mkfs_ext2_test.sh | 54 |
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; | |||
163 | int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | 163 | int 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 | |||
3 | test_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 | |||
46 | kilobytes=24908 test_mke2fs | ||
47 | kilobytes=81940 test_mke2fs | ||
48 | kilobytes=98392 test_mke2fs | ||
49 | exit | ||
50 | |||
51 | while true; do | ||
52 | kilobytes=$(( (RANDOM*RANDOM) % 100000 + 100)) | ||
53 | test_mke2fs || exit 1 | ||
54 | done | ||