Определение размера образа диска / файловой системы для хранения определенного набора файлов с почти нулевым свободным пространством

Мне нужно создать код, подходящий для сценариев / make / automation, образ диска (два раздела, файловая система FAT и файловая система ext4 для загрузки UEFI / Syslinux USB Linux [установщик ОС], который никогда не изменится в процессе производства) размер, который содержит точно (или очень близко) набор файлов произвольного размера. Другими словами, учитывая набор встроенных файлов, мне нужно знать, как создавать образы файловой системы FAT и ext4 и образ диска, который разбит на разделы, чтобы иметь размеры, рассчитанные на то, чтобы получить как можно меньше нулевого пространства, как разумно иметь. Это нормально, чтобы ошибиться на стороне небольшой дополнительной комнаты, но это не нормально, если кто-то добавит N + 1 байт к файлу через два года. Это должно быть подходящим для make-файла, т. Е. Пробная версия и ошибка не режут ее (хотя я полагаю, что если худшее пришло к худшему, может работать итеративное решение с порогом). Это похоже на образ ISO-9660 (который раньше использовался в предыдущем проекте, но Syslinux не поддерживает изображения ISO-9660 на UEFI).

Я создаю файлы, используя dd (для выделения образа диска), mkfs.vfat , dd (для размещения файловой системы FAT), mkfs.vfat , dd (для ext4), mkfs.ext4 , kpartx (для отображения разделов), dd (для записи раздела FAT), dd (для записи раздела ext4) и, наконец, dd для записи образа диска на USB для загрузки на реальном оборудовании.

Моя нынешняя идея состоит в том, чтобы использовать du чтобы определить, сколько места файлы на диске сборки, затем добавить некоторый запас для дополнительной файловой системы и накладных расходов на разделы, а также погрешность. Поэтому мне нужно знать количество блоков для каждого из dd с учетом выходов du .

Другой вариант – создать крупное изображение фиксированного размера, записать файлы, а затем изменить размер FAT, ext4 и разделов на минимальный размер. Файловые системы ext4 могут быть сокращены, и я вижу, что файловые системы FAT могут быть сокращены. Но тогда у вас все еще остается проблема с вычислением того, как ее уменьшить. Удивление, если кто-то сделал это раньше, имел некоторые конкретные идеи (или пример кода).

В итоге я использовал комбинацию факторов выдумки и итеративный подход (как отказоустойчивый). Это не должно быть таким сложным, как я изначально предполагал. Оказывается, на данный момент для FAT требуется небольшая подделка, но для ext требуется огромное количество негативных мокрок; с нулевым коэффициентом выдумки для ext4, у меня было много свободного места (более 21 М). Я преобразовал в ext2 (кому нужен журнал stinkin?), Увеличил размер блока и тщательно подсчитал нужные мне почтовые индексы и получил от него еще больше мегабайт свободного места. Полагаю, я мог бы получить «реальный размер» от du и отработать оттуда, но я решил, что подсчет накладных расходов, даже если они являются разными файловыми системами, будет более близким приближением.

 # Estimated filesystem overhead, in 512-byte blocks FS_ESP_FUDGE=256 FS_ISO_FUDGE=-80000 # Wow! FS_FUDGE_INCR=1024 ... read ESP_RSIZE d < <(du --summarize --block-size=512 $ESP) read ISO_RSIZE d < <(du --summarize --block-size=512 $ISO) success=false until $success; do let ESP_SIZE=ESP_RSIZE+FS_ESP_FUDGE let ISO_SIZE=ISO_RSIZE+FS_ISO_FUDGE let ESP_START=2048 let IMG_SIZE=ESP_SIZE+ISO_SIZE+ESP_START let ESP_END=ESP_START+ESP_SIZE-1 let ISO_START=ESP_END+1 success=true ... sudo /sbin/mkfs.vfat /dev/mapper/$p1 -F 16 \ || error_exit "mkfs.vfat failed" 5 # -N: Count the inodes (all files, plus . and .. for each directory, # which I can't get "find" to include). sudo /sbin/mke2fs -b 4096 -N $(( $(find $ISO | wc -l ) + 2 * $(find $ISO -type d | wc -l))) -m 0 -q /dev/mapper/$p2 \ || error_exit "mke2fs failed" 6 ... if ! tar -C $ESP -c --exclude-vcs --exclude-backups . | \ sudo tar -C mnt/esp -x; then { read read fs onek used avail use rest } < <(df mnt/esp) # Are we out of disk space? If not, bail, else increase margin, retry [[ $onek -ne $used || $avail -ne 0 || $use != "100%" ]] && \ error_exit "esp tar failed" 9 let FS_ESP_FUDGE=FS_ESP_FUDGE+FS_FUDGE_INCR success=false fi if ! tar -C $ISO -c --exclude-vcs --exclude-backups . | \ sudo tar -C mnt/iso --owner=root --group=root -x ; then { read read fs onek used avail use rest } < <(df mnt/iso) # Are we out of disk space? If not, bail, else increase margin, retry [[ $onek -ne $used || $avail -ne 0 || $use != "100%" ]] && \ error_exit "iso tar failed" 10 let FS_ISO_FUDGE=FS_ISO_FUDGE+FS_FUDGE_INCR success=false fi $success || echo "Whoops, I guessed too small; please adjust fudge factor. Retrying ..." ... done