You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.2 KiB
66 lines
2.2 KiB
#!/bin/sh |
|
|
|
dir="$1" |
|
dev="$2" |
|
|
|
if [ "$1" = "--help" ] || [ ! -d "${dir}" ]; then |
|
echo "Usage: $0 dir [mke2fs args] dev" |
|
exit 1 |
|
fi |
|
|
|
shift |
|
|
|
# Goal: Put all the files at the beginning (which mke2fs does) and minimize |
|
# the number of free inodes given the minimum number of blocks required. |
|
# Hence all this math to get the inode ratio just right. |
|
|
|
bytes="$(du -ks "${dir}" | awk '{print $1}')" |
|
bytes="$((bytes * 1024))" |
|
inodes="$(find "${dir}" -print0 | xargs -0 stat -c '%i' | sort -g | uniq | wc -l)" |
|
block_sz=4096 |
|
inode_sz=256 |
|
sb_overhead=4096 |
|
blocks_per_group="$((block_sz * 8))" |
|
bytes_per_group="$((blocks_per_group * block_sz))" |
|
inode_bytes="$((inodes * inode_sz))" |
|
|
|
# Estimate overhead with the minimum number of groups... |
|
nr_groups="$(( (bytes + inode_bytes + bytes_per_group - 1) / bytes_per_group))" |
|
inode_bytes_per_group="$((inode_bytes / nr_groups))" |
|
inode_blocks_per_group="$(( (inode_bytes_per_group + (block_sz - 1)) / block_sz ))" |
|
per_grp_overhead="$(( ((3 + inode_blocks_per_group) * block_sz) + 64 ))" |
|
overhead="$(( sb_overhead + (per_grp_overhead * nr_groups) ))" |
|
used_bytes="$((bytes + overhead))" |
|
|
|
# Then do it again with the real number of groups. |
|
nr_groups="$(( (used_bytes + (bytes_per_group - 1)) / bytes_per_group))" |
|
tot_blocks="$((nr_groups * blocks_per_group))" |
|
tot_bytes="$((tot_blocks * block_sz))" |
|
|
|
ratio="$((bytes / inodes))" |
|
mkfs_blocks="$((tot_blocks * 4 / 3))" |
|
|
|
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 |
|
|
|
e2fsck -fyD "${dev}" |
|
|
|
blocks="$(dumpe2fs -h "${dev}" 2>&1 | grep 'Block count:' | awk '{print $3}')" |
|
while resize2fs -f -M "${dev}"; do |
|
new_blocks="$(dumpe2fs -h "${dev}" 2>&1 | grep 'Block count:' | awk '{print $3}')" |
|
if [ "${new_blocks}" -eq "${blocks}" ]; then |
|
break; |
|
fi |
|
blocks="${new_blocks}" |
|
done |
|
|
|
if [ ! -b "${dev}" ]; then |
|
truncate -s "$((blocks * block_sz))" "${dev}" || (e2image -ar "${dev}" "${dev}.min"; mv "${dev}.min" "${dev}") |
|
fi |
|
|
|
e2fsck -fy "${dev}" |
|
|
|
dir_blocks="$((bytes / block_sz))" |
|
overhead="$((blocks - dir_blocks))" |
|
echo "Minimized image overhead: $((100 * overhead / dir_blocks))%" |
|
|
|
exit 0
|
|
|