На первый взгляд, это простая dd
:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
Которая считывает весь файл и записывает в него все содержимое обратно.
Чтобы записать только саму дыру, сначала нужно определить, где находятся эти дыры. Вы можете сделать это, используя либо filefrag
, либо hdparm
:
filefrag:
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1048575: 187357696.. 188406271: 1048576:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188406272: last,eof
sparsefile: 2 extents found
hdparm:
# hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 1498861568 1507250175 8388608
6442450944 1605633024 1614021631 8388608
Этот файл примера, как вы говорите, имеет размер 10G
с отверстием 2G
. Он имеет два экстенциала, первый охватывает 0-1048575
, второй 1572864-2621439
, что означает, что отверстие имеет размер 1048576-1572864
(в блоках размером 4 кб, как показано в filefrag
). Информация, показанная в hdparm
, та же самая, просто отображается по-другому (первая степень охватывает 8388608
512-байтовые сектора, начиная с 0, так что это 0-4294967295
байты, так что отверстие находится в 4294967296-6442450944
в байтах.
Обратите внимание, что в любом случае при наличии фрагментации может быть показано значительно большее количество экстенсивностей. К сожалению, ни одна из команд не показывает дыры напрямую, и я не знаю ни одной, которая делает это, поэтому вы должны вывести это из показанных логических смещений.
Заполнение этого отверстия 1048576-1572864
dd
, как показано выше, может быть сделано путем добавления соответствующих (идентичных) значений seek
/skip
и счета count
. Обратите внимание, что bs=
был адаптирован для использования секторов 4k
, как это использовалось в filefrag
выше. (Для bs=1M
необходимо было бы адаптировать значения поиска/пропуска/счета для отражения блоков размера 1M
).
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
Хотя вы можете заполнить дыры с помощью /dev/zero
вместо чтения дыры в самом файле (что также даст только нули), в любом случае безопаснее читать из разреженного файла /dev/zero
, чтобы не повредить данные в случае, если вы получили неправильное смещение.
В новых версиях GNU dd
вы можете придерживаться большего размера блока и указывать все значения в байтах:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M \
iflag=skip_bytes,count_bytes oflag=seek_bytes \
seek=4294967296 skip=4294967296 count=$((-4294967296+6442450944))
filefrag
после выполнения этого:
# sync
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1572863: 187357696.. 188930559: 1572864:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188930560: last,eof
sparsefile: 2 extents found
Из-за фрагментации, это все еще два экстента. Однако, логические смещения показывают, что на этот раз дырки нет, поэтому файл больше не разрежен.
Естественно, это решение dd
является очень ручным подходом к вещам. Если вам это нужно регулярно, то будет легко написать небольшую программу, которая заполнит такие пробелы. Если она уже существует как стандартный инструмент, то я о ней еще не слышал.
В конце концов, инструмент все-таки есть, fallocate
, кажется, работает, в каком-то смысле:
fallocate -l $(stat --format="%s" sparsefile) sparsefile
Однако, наконец, в случае с XFS, хотя она и выделяет физическую область для этого файла, на самом деле она не обнуляет его. Файлфрагfilefrag
показывает такие расширения как выделенные, но не записанные.
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
Этого недостаточно, если намерение состоит в том, чтобы иметь возможность считывать правильные данные непосредственно с блочного устройства. Она резервирует только то место в памяти, которое необходимо для будущих записей.
Это уже делает полную резервную копию. Содержимое каталогов, которые исключаются (например, dev, run, etc), создаются во время выполнения и не должны быть созданы резервными копиями.
Копировальная папка загрузки не переопределяет ваш загрузочный сектор, так что это нормально.
Использование rsync вот правильный метод, так как rsync может работать в одной и той же системе или удаленно, и он также будет только обновлять изменения файлов, не буду держать копирование все каждый раз. Если вы регулярно выполняете эту команду, вы также можете добавить «--delete» до конца команды, чтобы она удалила удаленные файлы из пункта назначения.
Кроме того, вы, возможно, захотите добавить опции rsync для него для предопределения жестких ссылок.