diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-18 18:05:27 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-18 18:05:27 +0200 |
commit | f9d3a91a89251cc4470a3cb94e918a49191438d2 (patch) | |
tree | 680c90260abb0ba65e6bb84acde6adfe80557d4b /util-linux/mkfs_ext2.c | |
parent | 77da1cae94acbeef90da66bf6530556fe191a6e2 (diff) | |
download | busybox-w32-f9d3a91a89251cc4470a3cb94e918a49191438d2.tar.gz busybox-w32-f9d3a91a89251cc4470a3cb94e918a49191438d2.tar.bz2 busybox-w32-f9d3a91a89251cc4470a3cb94e918a49191438d2.zip |
mkfs_ext2: fixes for huge filesystems
function old new delta
mkfs_ext2_main 2145 2617 +472
div_roundup 15 35 +20
packed_usage 26792 26776 -16
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux/mkfs_ext2.c')
-rw-r--r-- | util-linux/mkfs_ext2.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index a990668df..56203c789 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c | |||
@@ -70,7 +70,11 @@ static unsigned int_log2(unsigned arg) | |||
70 | // taken from mkfs_minix.c. libbb candidate? | 70 | // taken from mkfs_minix.c. libbb candidate? |
71 | static unsigned div_roundup(uint32_t size, uint32_t n) | 71 | static unsigned div_roundup(uint32_t size, uint32_t n) |
72 | { | 72 | { |
73 | return (size + n-1) / n; | 73 | // Overflow-resistant |
74 | uint32_t res = size / n; | ||
75 | if (res * n != size) | ||
76 | res++; | ||
77 | return res; | ||
74 | } | 78 | } |
75 | 79 | ||
76 | static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32_t end) | 80 | static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32_t end) |
@@ -161,6 +165,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | |||
161 | unsigned i, pos, n; | 165 | unsigned i, pos, n; |
162 | unsigned bs, blocksize, blocksize_log2; | 166 | unsigned bs, blocksize, blocksize_log2; |
163 | unsigned nreserved = 5; | 167 | unsigned nreserved = 5; |
168 | unsigned long long nblocks_ull; | ||
164 | uint32_t nblocks; | 169 | uint32_t nblocks; |
165 | uint32_t ngroups; | 170 | uint32_t ngroups; |
166 | unsigned bytes_per_inode; | 171 | unsigned bytes_per_inode; |
@@ -179,23 +184,13 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | |||
179 | struct ext2_dir *dir; | 184 | struct ext2_dir *dir; |
180 | uint8_t *buf; | 185 | uint8_t *buf; |
181 | 186 | ||
182 | bs = EXT2_MIN_BLOCK_SIZE; | ||
183 | opt_complementary = "-1:b+:m+:i+"; | 187 | opt_complementary = "-1:b+:m+:i+"; |
184 | opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS", | 188 | opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS", |
185 | NULL, &bs, NULL, &bytes_per_inode, NULL, NULL, NULL, NULL, | 189 | NULL, &bs, NULL, &bytes_per_inode, NULL, NULL, NULL, NULL, |
186 | &nreserved, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL); | 190 | &nreserved, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL); |
187 | argv += optind; // argv[0] -- device | 191 | argv += optind; // argv[0] -- device |
188 | 192 | ||
189 | // block size minimax, block size is a multiple of minimum | 193 | // reserved blocks percentage |
190 | blocksize = bs; | ||
191 | if (blocksize < EXT2_MIN_BLOCK_SIZE | ||
192 | || blocksize > EXT2_MAX_BLOCK_SIZE | ||
193 | || (blocksize & (blocksize - 1)) // not power of 2 | ||
194 | ) { | ||
195 | bb_error_msg_and_die("-%c is bad", 'b'); | ||
196 | } | ||
197 | |||
198 | // reserved blocks count | ||
199 | if (nreserved > 50) | 194 | if (nreserved > 50) |
200 | bb_error_msg_and_die("-%c is bad", 'm'); | 195 | bb_error_msg_and_die("-%c is bad", 'm'); |
201 | 196 | ||
@@ -210,6 +205,42 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | |||
210 | if (find_mount_point(argv[0], 0)) | 205 | if (find_mount_point(argv[0], 0)) |
211 | bb_error_msg_and_die("can't format mounted filesystem"); | 206 | bb_error_msg_and_die("can't format mounted filesystem"); |
212 | 207 | ||
208 | // open the device, get size in kbytes | ||
209 | xmove_fd(xopen3(argv[0], O_WRONLY | O_CREAT, 0666), fd); | ||
210 | if (argv[1]) { | ||
211 | nblocks_ull = xatoull(argv[1]); | ||
212 | } else { | ||
213 | nblocks_ull = (uoff_t)xlseek(fd, 0, SEEK_END) / 1024; | ||
214 | } | ||
215 | |||
216 | // block size is a multiple of 1024 | ||
217 | blocksize = 1024; | ||
218 | if (nblocks_ull >= 512*1024) // mke2fs 1.41.9 compat | ||
219 | blocksize = 4096; | ||
220 | if (EXT2_MAX_BLOCK_SIZE > 4096) { | ||
221 | // nblocks_ull >> 22 == size in 4gigabyte chunks. | ||
222 | // if it is >= 16k gigs, blocksize must be increased. | ||
223 | // Try "mke2fs -F image_std $((16 * 1024*1024*1024))" | ||
224 | while ((nblocks_ull >> 22) >= blocksize) | ||
225 | blocksize *= 2; | ||
226 | } | ||
227 | if (opts & OPT_b) | ||
228 | blocksize = bs; | ||
229 | if (blocksize < EXT2_MIN_BLOCK_SIZE | ||
230 | || blocksize > EXT2_MAX_BLOCK_SIZE | ||
231 | || (blocksize & (blocksize - 1)) // not power of 2 | ||
232 | ) { | ||
233 | bb_error_msg_and_die("blocksize %u is bad", blocksize); | ||
234 | } | ||
235 | blocksize_log2 = int_log2(blocksize); | ||
236 | nblocks_ull >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); | ||
237 | // nblocks: the total number of blocks in the filesystem | ||
238 | nblocks = nblocks_ull; | ||
239 | if (nblocks != nblocks_ull) | ||
240 | bb_error_msg_and_die("block count doesn't fit in 32 bits"); | ||
241 | if (nblocks < 8) | ||
242 | bb_error_msg_and_die("need >= 8 blocks"); | ||
243 | |||
213 | // TODO: 5?/5 WE MUST NOT DEPEND ON WHETHER DEVICE IS /dev/zero 'ed OR NOT | 244 | // TODO: 5?/5 WE MUST NOT DEPEND ON WHETHER DEVICE IS /dev/zero 'ed OR NOT |
214 | // TODO: 3/5 refuse if mounted | 245 | // TODO: 3/5 refuse if mounted |
215 | // TODO: 4/5 compat options | 246 | // TODO: 4/5 compat options |
@@ -226,7 +257,6 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | |||
226 | sb->s_magic = EXT2_SUPER_MAGIC; | 257 | sb->s_magic = EXT2_SUPER_MAGIC; |
227 | sb->s_inode_size = sizeof(*inode); | 258 | sb->s_inode_size = sizeof(*inode); |
228 | sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; | 259 | sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; |
229 | blocksize_log2 = int_log2(blocksize); | ||
230 | sb->s_log_block_size = sb->s_log_frag_size = blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE; | 260 | sb->s_log_block_size = sb->s_log_frag_size = blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE; |
231 | // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then | 261 | // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then |
232 | // the first block available for data is 1, otherwise 0 | 262 | // the first block available for data is 1, otherwise 0 |
@@ -261,18 +291,8 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | |||
261 | */ | 291 | */ |
262 | sb->s_max_mnt_count += sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT; | 292 | sb->s_max_mnt_count += sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT; |
263 | 293 | ||
264 | // open the device, get number of blocks | ||
265 | xmove_fd(xopen3(argv[0], O_WRONLY | O_CREAT, 0666), fd); | ||
266 | if (argv[1]) { | ||
267 | nblocks = xatou(argv[1]); | ||
268 | } else { | ||
269 | nblocks = (uoff_t)xlseek(fd, 0, SEEK_END) >> blocksize_log2; | ||
270 | } | ||
271 | sb->s_blocks_count = nblocks; | 294 | sb->s_blocks_count = nblocks; |
272 | 295 | ||
273 | // nblocks is the total number of blocks in the filesystem | ||
274 | if (nblocks < 8) | ||
275 | bb_error_msg_and_die("nblocks"); | ||
276 | // reserve blocks for superuser | 296 | // reserve blocks for superuser |
277 | sb->s_r_blocks_count = ((uint64_t) nblocks * nreserved) / 100; | 297 | sb->s_r_blocks_count = ((uint64_t) nblocks * nreserved) / 100; |
278 | 298 | ||