aboutsummaryrefslogtreecommitdiff
path: root/util-linux/mkfs_ext2.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-18 18:05:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-18 18:05:27 +0200
commitf9d3a91a89251cc4470a3cb94e918a49191438d2 (patch)
tree680c90260abb0ba65e6bb84acde6adfe80557d4b /util-linux/mkfs_ext2.c
parent77da1cae94acbeef90da66bf6530556fe191a6e2 (diff)
downloadbusybox-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.c66
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?
71static unsigned div_roundup(uint32_t size, uint32_t n) 71static 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
76static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32_t end) 80static 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