]>
Commit | Line | Data |
---|---|---|
8804a96f DW |
1 | #!/bin/sh |
2 | ||
3 | dir="$1" | |
4 | dev="$2" | |
5 | ||
6 | if [ "$1" = "--help" ] || [ ! -d "${dir}" ]; then | |
7 | echo "Usage: $0 dir [mke2fs args] dev" | |
8 | exit 1 | |
9 | fi | |
10 | ||
11 | shift | |
12 | ||
13 | # Goal: Put all the files at the beginning (which mke2fs does) and minimize | |
14 | # the number of free inodes given the minimum number of blocks required. | |
15 | # Hence all this math to get the inode ratio just right. | |
16 | ||
17 | bytes="$(du -ks "${dir}" | awk '{print $1}')" | |
18 | bytes="$((bytes * 1024))" | |
19 | inodes="$(find "${dir}" -print0 | xargs -0 stat -c '%i' | sort -g | uniq | wc -l)" | |
20 | block_sz=4096 | |
21 | inode_sz=256 | |
22 | sb_overhead=4096 | |
23 | blocks_per_group="$((block_sz * 8))" | |
24 | bytes_per_group="$((blocks_per_group * block_sz))" | |
25 | inode_bytes="$((inodes * inode_sz))" | |
26 | ||
27 | # Estimate overhead with the minimum number of groups... | |
28 | nr_groups="$(( (bytes + inode_bytes + bytes_per_group - 1) / bytes_per_group))" | |
29 | inode_bytes_per_group="$((inode_bytes / nr_groups))" | |
30 | inode_blocks_per_group="$(( (inode_bytes_per_group + (block_sz - 1)) / block_sz ))" | |
31 | per_grp_overhead="$(( ((3 + inode_blocks_per_group) * block_sz) + 64 ))" | |
32 | overhead="$(( sb_overhead + (per_grp_overhead * nr_groups) ))" | |
33 | used_bytes="$((bytes + overhead))" | |
34 | ||
35 | # Then do it again with the real number of groups. | |
36 | nr_groups="$(( (used_bytes + (bytes_per_group - 1)) / bytes_per_group))" | |
37 | tot_blocks="$((nr_groups * blocks_per_group))" | |
38 | tot_bytes="$((tot_blocks * block_sz))" | |
39 | ||
40 | ratio="$((bytes / inodes))" | |
41 | mkfs_blocks="$((tot_blocks * 4 / 3))" | |
42 | ||
43 | mke2fs -i "${ratio}" -T ext4 -d "${dir}" -O ^resize_inode,sparse_super2,metadata_csum,64bit,^has_journal -E packed_meta_blocks=1,num_backup_sb=0 -b "${block_sz}" -I "${inodesz}" -F "${dev}" "${mkfs_blocks}" || exit | |
44 | ||
45 | e2fsck -fyD "${dev}" | |
46 | ||
47 | blocks="$(dumpe2fs -h "${dev}" 2>&1 | grep 'Block count:' | awk '{print $3}')" | |
48 | while resize2fs -f -M "${dev}"; do | |
49 | new_blocks="$(dumpe2fs -h "${dev}" 2>&1 | grep 'Block count:' | awk '{print $3}')" | |
50 | if [ "${new_blocks}" -eq "${blocks}" ]; then | |
51 | break; | |
52 | fi | |
53 | blocks="${new_blocks}" | |
54 | done | |
55 | ||
56 | if [ ! -b "${dev}" ]; then | |
57 | truncate -s "$((blocks * block_sz))" "${dev}" || (e2image -ar "${dev}" "${dev}.min"; mv "${dev}.min" "${dev}") | |
58 | fi | |
59 | ||
60 | e2fsck -fy "${dev}" | |
61 | ||
62 | dir_blocks="$((bytes / block_sz))" | |
63 | overhead="$((blocks - dir_blocks))" | |
64 | echo "Minimized image overhead: $((100 * overhead / dir_blocks))%" | |
65 | ||
66 | exit 0 |