Назад | Перейти на главную страницу

Как я могу пассивно исследовать содержимое потока отправки ZFS?

У меня есть некоторые сохраненные "потоки отправки" ZFS (т.е. они были созданы путем перенаправления вывода zfs send в файл). Я хотел бы изучить содержимое этих потоков, не получая и не записывая их в файловую систему - например, я хотел бы просмотреть список имен файлов внутри потока. Есть какой-либо способ сделать это?

Я читал и искал, но не нашел ничего похожего на то, о чем я говорю. Я использую как FreeBSD и ZFS в Linux реализации ZFS.

Вы можете получить некоторую информацию, подключив их к zstreamdump -d, но это не даст никакой информации об именах файлов напрямую, потому что в потоке нет файлов. Ручей - это разница между двумя деревьями, описанными в блоках. Однако код является общедоступным, поэтому, если вам удастся добавить обнаружение и анализ структуры ZFS, вы сможете получить от него больше.

Внутренняя структура ZFS является дерево внутри, и все операции выполняются над этим деревом. Файлы, каталоги, имена файлов, атрибуты и все остальное - это просто данные в этом дереве. Снимки, тома и файловая система являются корнями дерева, и когда вы делаете еще один снимок, вы просто где-то сохраняете текущий корень. Живые системы генерируют новые корни для каждой транзакции, постоянно уходя от старых корней, при этом сохраняя нетронутыми «листья» данных из предыдущего дерева. Поток представляет собой список операций, которые должны быть выполнены на дереве A, чтобы стать B.

Я просто пытаюсь сказать, что вы можете не видеть данные, которые ищете, в потоке, потому что они не обязательны. Когда файл удаляется, соответствующие блоки просто освобождаются, поэтому вы не можете определить, какое имя или содержимое было у файла. Когда файл изменяется, на него ссылается идентификатор объекта, поэтому вы ничего не получите из потока, даже если файл был перезаписан с нуля, но запись в каталоге не была обновлена.

Вам повезет, если поток не является дифференциальным потоком или если у вас есть данные по его предыдущему состоянию. Но это только потому, что полный поток преобразует пустой корень в целевое дерево, содержащее все необходимые данные. Следовательно, вы можете добавить код разбора блока в zstreamdump для обнаружения и обработки внутренних данных ZFS.

Короткий ответ:

Я не верю, что есть какой-либо способ с пользой каталогизировать содержимое потока отправки, который имеет меньший вес, чем передача его в zfs receive, чтобы воссоздать его в виде набора данных.

Гораздо более длинный ответ:

Поток отправки - это набор данных на уровне блока хранения, не сбор данных на уровне файловой системы. Поток отправки не знает и не заботится об отдельных файлах; он предназначен для копирования того, что по сути является необработанными блочными устройствами. Хотя один пользователь может использовать исключительно zfs send для репликации наборов данных ZFS с файлами, хранящимися непосредственно на них, другой может использовать его для репликации файлов ZVOL, отформатированных с помощью ext4, ntfs, или даже зашифрованной системы, такой как LUKS - в этих случаях ZFS абсолютно не знает, что такое содержимое тома, он просто хранит для них необработанные блоки.

zfs send работает точно так же, реплицируете ли вы набор данных или необработанный zvol, потому что он просто не заботится ни о чем ниже уровня необработанного блочного хранилища. Он не знает имен файлов, размеров файлов, путей или чего-либо еще - он знает, какие блоки принадлежат данному снимку zvol или снимку, но он знает не знать, как эти блоки связаны друг с другом.

Итак, нет легкого способа каталогизировать содержимое файла zfs send поток, потому что там является нет внутреннего каталога файлов в одном. Даже если вы точно знаете, что этот конкретный поток представляет собой полную (а не инкрементную) репликацию незашифрованного набора данных ZFS, вам придется анализировать каждый его блок построчно, чтобы попытаться определить, какие блоки содержат имена файлов.

По сути, чтобы извлечь имена файлов из потока отправки, вы должны будете выполнять ту же работу, что и zfs receive делает это, в первую очередь применяя этот поток к набору данных.