Как восстановить обнуленные блоки разреженного файла?

StackOverflow https://stackoverflow.com/questions/1982749

Вопрос

Рассмотрим разреженный файл с 1s, записанный в часть файла.

Я хочу освободить фактическое пространство на диске для этих единиц, поскольку мне больше не нужна эта часть разреженного файла.Часть файла, содержащая эти единицы, должна стать "дырой", какой она была до того, как сами единицы были записаны.

Чтобы сделать это, я очистил область до 0s.Это делает не восстановите блоки на диске.

Как мне на самом деле сделать разреженный файл, ну, снова разреженным?

Этот вопрос похож на этот но общепринятого ответа на этот вопрос нет.

Рассмотрим следующую последовательность событий, выполняемых на стандартном сервере Linux:

$ cat /tmp/test.c
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char **argv) {
    int fd;
    char c[1024];

    memset(c,argc==1,1024);

    fd = open("test",O_CREAT|O_WRONLY,0777);
    lseek(fd,10000,SEEK_SET);
    write(fd,c,1024);
    close(fd);

    return 0;
}

$ gcc -o /tmp/test /tmp/test.c

$ /tmp/test

$ hexdump -C ./test
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002710  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
*
00002b10

$ du -B1 test; du -B1 --apparent-size test
4096        test
11024       test

$ /tmp/test clear

$ hexdump -C ./test
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002b10

$ du -B1 test; du -B1 --apparent-size test
4096        test
11024       test

# NO CHANGE IN SIZE.... HMM....

Редактировать -

Позвольте мне дополнительно уточнить, что я не хочу переписывать файлы, копировать их и т.д.Если невозможно каким-либо образом освободить ранее выделенные блоки на месте, пусть будет так, но я хотел бы определить, действительно ли такое возможно или нет.На данный момент это похоже на "нет, это не так".Я полагаю, что я ищу sys_punchhole для Linux (обсуждения, на которые я только что наткнулся).

Это было полезно?

Решение

Прямо сейчас кажется, что только NTFS поддерживает пробивание отверстий.Исторически это было проблемой в большинстве файловых систем.POSIX, насколько я знаю, не определяет интерфейс операционной системы для пробивания отверстий, поэтому ни одна из стандартных файловых систем Linux не поддерживает его.NetApp поддерживает пробивание отверстий в Windows в своем ВАФЛЯ файловая система.Об этом есть хороший пост в блоге здесь.

Для вашей проблемы, как указывали другие, единственное решение - переместить файл, оставив блоки, содержащие нули.Да, это будет медленно.Или напишите расширение для вашей файловой системы в Linux, которое делает это и Отправить a патч к тому хорошие люди в команде ядра Linux.;)

Редактировать: Похоже, XFS поддерживает пробивание отверстий.Проверить этот поток.

Другим действительно извращенным вариантом может быть использование отладчик файловой системы пойти и пробить дыры во всех косвенных блоках, которые указывают на обнуленные блоки в вашем файле (возможно, вы можете написать это скриптом).Затем запустите fsck, который исправит все связанные подсчеты блоков, соберет все потерянные блоки (обнуленные) и поместит их в каталог lost + found (вы можете удалить их, чтобы освободить место) и исправит другие свойства в файловой системе.Страшно, да?


Отказ от ответственности:Делайте это на свой страх и риск.Я не несу ответственности за любую потерю данных, которую вы понесете. ;)

Другие советы

Похоже, что Linux добавила системный вызов с именем fallocate для "пробивания отверстий" в файлах.Реализации в отдельных файловых системах, по-видимому, сосредоточены на возможности использовать это для предварительного выделения большего непрерывного количества блоков.

Существует также posix_fallocate вызов, который фокусируется только на последнем и не может быть использован для пробивки отверстий.

Рон Йорстон предлагает несколько решений;но все они включают либо подключение FS, доступного только для чтения (или его размонтирование), во время выполнения разрежающего;или создание нового разреженного файла, затем копирование тех фрагментов оригинала, которые не являются просто 0s, а затем замена исходного файла на недавно разреженный файл.

Однако это действительно зависит от вашей файловой системы.Мы уже видели, что NTFS справляется с этим.Я полагаю, что любая из других файловых систем Списки в Википедии поскольку обработка прозрачного сжатия производила бы точно то же самое - это, в конце концов, эквивалентно прозрачному сжатию файла.

После того как вы "обнулили" некоторую область файла, вы должны сообщить файловой системе, что эта новая область предназначена для разреженной области.Таким образом, в случае NTFS вам придется снова вызвать DeviceIoControl() для этого региона.По крайней мере, я делаю это в своей утилите: "sparse_checker" (проверка разности)

Для меня большая проблема заключается в том, как вернуть разреженную область обратно :).

С уважением

Этот способ дешевый, но он работает.:-П

  1. Считайте все данные, прошедшие через нужное вам отверстие, в память (или другой файл, или что угодно еще).
  2. Сократите файл до начала отверстия (ftruncate является вашим другом).
  3. Доберитесь до конца отверстия.
  4. Запишите данные обратно.

смонтируйте вашу файловую систему и отредактируйте файловую систему непосредственно способом, аналогичным debugfs или fsck.обычно вам нужен драйвер для каждой используемой fs.

Похоже, что логично попробовать записать нули (как в упомянутом вопросе) в ту часть, с которой вы закончили.Вот ссылка на вопрос MSDN по разреженным файлам NTFS, который делает именно это, чтобы "освободить" "неиспользуемую" часть.ИММВ.

http://msdn.microsoft.com/en-us/library/ms810500.aspx

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top