@ Карта сайта News Автора!

Bog BOS: Файловая система ZFS

Последние изменения:
2024.11.11: sysadmin: Linux: пространства имён
2024.11.06: sysadmin: настройка TCP/IP в Linux: виртуальный интерфейс и виртуальный мост
2024.10.25: sysadmin: Linux VFS, атрибуты, расширенные атрибуты, ACL
2024.10.22: sysadmin: Монтирование файловых систем: bind, shared и OverlayFS

Последнее изменение файла: 2024.11.20
Скопировано с www.bog.pp.ru: 2024.11.21

Bog BOS: Файловая система ZFS

Файловая система ZFS рассматривается с целью организации крупного архива под Linux (CentOS) как альтернатива btrfs.

Особенности

ZFS объединяет управление пулом устройств (zpool: избыточность, контрольные суммы, выделение места, дедупликация) и наборами данных (dataset - блочные устройства и файловые системы POSIX), zfs (строчными буквами): снимки, клоны, иерархические контрольные суммы, сжатие. Особый упор сделан на сохранность данных, точнее на обнаружение их повреждения. В частности, рекомендуется использовать ОП с ECC, т.к. прочие источники повреждений устранены. Развитие идёт в сторону управления корзинами и устройствами хранения: управление индикацией, питанием, заливка прошивок.

Опробовал устойчивость. Сделал (OpenZFS/ZFSonLinux 0.6 и 0.8) пул из 3 vdev, которые в свою очередь представляют собой массивы RAID-6 над LSI Logic MegaRAID SAS 9266-8i; выдернул 3 диска из одного из массивов, в результате чего он перешёл в режим Offline; попытался считать обещанные доступные файлы из zfs. Не тут-то было (особенно понравилось про отсутствие привилегий - исправлено после 0.7.0-rc3), ни прочитать, ни удалить, ни размонтировать, только перезагрузиться:

kernel: WARNING: Pool 'tm_small' has encountered an uncorrectable I/O failure and has been suspended.

zpool status -v 
  pool: tm_small
 state: UNAVAIL
status: One or more devices are faulted in response to IO failures.
action: Make sure the affected devices are connected, then run 'zpool clear'.
   see: http://zfsonlinux.org/msg/ZFS-8000-HC
  scan: scrub repaired 0 in 57h52m with 0 errors on Mon Mar 20 11:34:28 2017
config:

	NAME                                      STATE     READ WRITE CKSUM
	tm_small                                  UNAVAIL     64     0     0  insufficient replicas
	  scsi-3600605b008ca05c01fc0c51340366923  ONLINE       0     0     0
	  wwn-0x600605b008ca052020111fe9d78370c6  ONLINE       0     0     0
	  wwn-0x600605b008ca0500202630e6fda1c4eb  FAULTED      1     1     0  too many errors
	cache
	  l2arc                                   ONLINE       0     0     0

errors: List of errors unavailable (insufficient privileges)

zpool set failmode=continue tm_small
cannot set property for 'tm_small': pool I/O is currently suspended

zpool clear tm_small
cannot clear errors for tm_small: I/O error

но счётчик ошибок обнулился

zpool status -v
  pool: tm_small
 state: UNAVAIL
status: One or more devices are faulted in response to IO failures.
action: Make sure the affected devices are connected, then run 'zpool clear'.
   see: http://zfsonlinux.org/msg/ZFS-8000-HC
  scan: scrub repaired 0 in 57h52m with 0 errors on Mon Mar 20 11:34:28 2017
config:

	NAME                                      STATE     READ WRITE CKSUM
	tm_small                                  UNAVAIL      0     0     0  insufficient replicas
	  scsi-3600605b008ca05c01fc0c51340366923  ONLINE       0     0     0
	  wwn-0x600605b008ca052020111fe9d78370c6  ONLINE       0     0     0
	  wwn-0x600605b008ca0500202630e6fda1c4eb  UNAVAIL      0     0     0
	cache
	  l2arc                                   ONLINE       0     0     0

errors: 74 data errors, use '-v' for a list
# а с "-v" так:
errors: List of errors unavailable (insufficient privileges)

zpool scrub -s tm_small
cannot cancel scrubbing tm_small: pool I/O is currently suspended

zpool export tm_small
cannot export 'tm_small': pool I/O is currently suspended

rmmod zfs
rmmod: ERROR: Module zfs is in use

zfs umount tm_small
cannot open 'tm_small': pool I/O is currently suspended

zpool reopen tm_small
cannot reopen 'tm_small': pool I/O is currently suspended

zpool destroy -f tm_small # в Linux "umount -f" не работает
umount: /time_machine: target is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
cannot unmount '/time_machine': umount failed
could not destroy 'tm_small': could not unmount datasets

перезагрузка (на удивление удалась)

zpool status -x
  pool: tm_small
 state: UNAVAIL
status: One or more devices could not be used because the label is missing 
	or invalid.  There are insufficient replicas for the pool to continue
	functioning.
action: Destroy and re-create the pool from
	a backup source.
   see: http://zfsonlinux.org/msg/ZFS-8000-5E
  scan: none requested
config:

	NAME                                      STATE     READ WRITE CKSUM
	tm_small                                  UNAVAIL      0     0     0  insufficient replicas
	  scsi-3600605b008ca05c01fc0c51340366923  ONLINE       0     0     0
	  wwn-0x600605b008ca052020111fe9d78370c6  ONLINE       0     0     0
	  wwn-0x600605b008ca0500202630e6fda1c4eb  UNAVAIL      0     0     0

zpool destroy -f tm_small
cannot destroy 'tm_small': no such pool or dataset

zpool list
NAME       SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small      -      -      -         -      -      -      -  FAULTED  -

zpool labelclear /dev/disk/by-id/scsi-3600605b008ca05c01fc0c51340366923
zpool labelclear /dev/disk/by-id/wwn-0x600605b008ca052020111fe9d78370c6

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small      -      -      -         -      -      -      -  FAULTED  -
  scsi-3600605b008ca05c01fc0c51340366923      -      -      -     16.0E      -      -
  wwn-0x600605b008ca052020111fe9d78370c6      -      -      -     16.0E      -      -
  wwn-0x600605b008ca0500202630e6fda1c4eb      -      -      -     16.0E      -      -

кеш бессмертен:

zdb -C
tm_small:
    version: 5000
    name: 'tm_small'
    state: 0
    txg: 755843
    pool_guid: 17750235030682792318
    vdev_tree:
        type: 'root'
        id: 0
        guid: 17750235030682792318
        create_txg: 4
        children[0]:
            type: 'disk'
            id: 0
            guid: 5817601266406712916
            path: '/dev/disk/by-id/scsi-3600605b008ca05c01fc0c51340366923-part1'
...

zpool create -f ... tm_small scsi-3600605b008ca05c01fc0c51340366923 cache /dev/system/l2arc
cannot create 'tm_small': pool already exists

rmmod zfs
mv /etc/zfs/zpool.cache ...
modprobe zfs

Архитектура

ZFS (прописными) объединяет в единое целое управление пулом свободного места zpool и файловую систему zfs (строчными).

Пул (zpool) представляется в виде дерева, корнем которого является корневой vdev, который собирается из виртуальных блочных устройств vdev различных типов (vdev верхнего уровня) - обычное блочное устройство, зеркало (mirror), zraid{1,2,3} (подобие RAID массивов с 1, 2 или 3 контрольными суммами), кеш (L2ARC), запасной диск (spare) и журнал (log, SLOG для ZIL). Зеркало (2 и более) и zraid* собираются из vdev (утилиты умеют собирать только из блочных устройств).

Для ускорения работы используется кеш в памяти ARC и кеш чтения на выделенном устройстве (рекомендуется SSD) L2ARC.

Каждая операция записи является частью транзакции. Транзакция является атомарной операцией - она либо выполняется целиком, либо не выполняется вовсе. Каждая транзакция является частью группы транзакций (TXG, txg). Группы транзакций нумеруются последовательно. Группа транзакций может быть последовательно в одном из состояний (в каждом состоянии только одна группа в каждый момент времени): открыта, в покое (quiescing) или синхронизации (запись на диск). Транзакции добавляются в открытую группу, выполняются когда группа открыта или в покое. Группа закрывается когда достигнут предел по времени, объёму или требуется синхронизация (создание снимка и т.д.). Накопленные изменения пишутся на диск в состоянии синхронизации. Синхронизация может потребовать дополнительных изменений (например, в карте пространства при выделении новых блоков), т.е. требуется несколько проходов, после превышения лимита проходов ZFS откладывает освобождение и останавливает сжатие.

Для обеспечения синхронной записи применяется механизм ZIL и выделенное устройство для кеширования ZIL - SLOG.

Пул обеспечивает местом произвольное количество наборов данных (файловые системы zfs, тома, снимки и пр.). Файловые системы монтируются автоматически в точку "/имя-набора" (можно изменить в свойстве mountpoint), каталог создаётся автоматически.

Для набора данных можно создавать неизменяемые снимки, которые доступны по имени как файловые системы или тома. Снимки файловой системы автоматически монтируются при первом обращении к файлам. На базе снимков можно делать изменяемые клоны исходного набора данных, удалять исходный снимок нельзя на время жизни клона, можно поменять ролями исходый набор данных и его клон (promote) после чего удалить набор бывший исходным и ставшиий клоном. Кроме снимков (snapshot) можно делать отметки (bookmark) - привязываются к снимку, недоступны как файловые системы.

Наборы данных можно экспортировать по NFS, SMB и iSCSI (тома как блочные устройства).

Компоненты (слои), снизу вверх:

История и совместимость, ZFS on Linux и OpenZFS

ZFS (торговая марка Oracle) разработана в Sun Microsystems (ныне Oracle), начало работ - 2001 год, включён в Solaris 10 в 2006.

Код открыт в 2005 (в рамках OpenSolaris) под лицензией CDDL, закрыт в 2010 (OpenSolaris форкнули в Illumos). Код разделился на ZFS Oracle и других.

Другие объединились под именем OpenZFS. Обеспечивает совместимость пулов хранения между реализациями. OpenZFS стал посредником для обмена кодом из Illumos/DelphixOS (2/3 исходных разработчиков ZFS ушли сюда после закрытия OpenSolaris), FreeBSD, OS X и ZFS on Linux (ZOL). В последующем оказалось, что Illumos фактически мёртв, FreeBSD использует код от OpenZFS, который в основном пополняется от ZOL. В результате ZOL перепаковали в OpenZFS.

В связи с якобы несовместимостью CDDL и GPL некогда была разработана FUSE реализация ZFS в Linux, покойная с 2016 года (ещё есть в EPEL6, но нет в EPEL7).

Первоначально ZFS имела (ZFS Oracle и сейчас имеет) версии формата на диске, затем OpenZFS приняла единую версию 5000 и систему флагов возможностей (feature flags) - фич. Предполагается, что реализация версии 5000 включает все возможности на момент закрытия OpenSolaris - ZVOL (ZFS Emulated Volume) версии 28 и ZPL (ZFS POSIX Layer) 5.

Фича пула (свойство пула с именем feature@название-фичи, полное имя - feature@org.zfsonlinux:имя, но можно сократить до "имя", если нет совпадений) может находиться в состоянии:

Преобразование пула происходит по команде "zpool upgrade" или при установке свойства в состояние enabled.

Пул с неподдерживаемыми фичами может быть импортирован, если фича не была активирована (свойство пула unsupported@название-фичи=inactive) или используется в режиме только чтения (свойство readonly) и фича такой импорт допускает (свойство пула unsupported@название-фичи=readonly).

Некоторые фичи зависят от других.

Свойство compatibility (zpool create -o compatibility=...) позволяет задать список совместимости:

Фичи пула (сравнение производительности алгоритмов вычисления контрольной суммы - /proc/spl/kstat/zfs/chksum_bench и /proc/spl/kstat/zfs/fletcher_4_bench):

zhack позволяет узнать состояние фич пула или поменять их "вручную"

Предполагается (предполагалось?) введение фич ZPL.

ZFS on Linux (ныне OpenZFS)

ZFS on Linux - ZOL (под лицензией CDDL, якобы несовместимой с GPL) представлял собой адаптацию OpenZFS для самостоятельной установки на Linux (требуется самостоятельная сборка модуля ядра из исходных текстов). В дальнейшем ZOL был перепакован под именем OpenZFS. В Ubuntu 16.04 LTS устанавливается прямо бинарным модулем (и никто их не осудил), в Gentoo, Debian и ALT Linux через сборку с помощью DKMS. В дополнение к собственно ZFS поставляется SPL (Solaris Porting Layer). Для текущей версии (OpenZFS 2.2.2) необходимо ядро не менее Linux 3.10 (RHEL/CentOS 7).

Каждый раз при обновлении ядра модуль пересобирается через DKMS (Dynamic Kernel Module Support, автоматическая перекомпиляция модуля при обновлении ядра) или используется стабильный API через kABI-tracking kmod (Kernel Application Binary Interface, стиль ELRepo, родной пакет kmod, не требуется переустановка модулей при обновлении ядра, если модуль использует внешние символы из белого списка). Разработчики рекомендовали использовать kABI-tracking kmod, а DKMS оставить для пользователей нестандартных ядер и любителей внести свои изменения в исходные тексты ZFS. Однако в RHEL 7.3 стабильность API дала маху, в RHEL 7.4 история повторилась, в RHEL 7.5 ещё раз и в RHEL 7.6 ещё. С тех пор обеспечивается отдельный репозиторий для каждой минорной версии RHEL.

Для установки требуется добавить репозиторий yum от OpenZFS (для RHEL/CentOS 7 (поддерживается только последняя минорная версия). В связи со сломом совместимости kABI установка kABI на 7.3 (7.4) требует дополнительных действий: всё остановить, удалить и поставить заново. Ключ кладётся в /etc/pki/rpm-gpg/RPM-GPG-KEY-zfsonlinux, описание репозитория в /etc/yum.repos.d/zfs.repo

Создание зеркала репозитория yum (от 0.5GB до 4GB!), в последнее время тестовые ветки содержат предпоследнюю версию, а основные ещё более старую:

Установка [в варианте kABI]:

Предпочитающие погорячее (ибо в репозитории времён 2.2.2 лежит версия 2.0.7 и в testing - 2.1.13) могут поставить только что сделанные BuildBot-ом пакеты (testing сломан), например, оглавление для CentOS 7

Устанавливаемые пакеты и файлы (2.0.6-1 для CentOS 7):

Или ещё горячее - собрать свои rpm:

# нужна инфраструктура сборки модулей ядра (для Rocky Linux 8.9: autoconf, automake, libtool, libuuid-devel, libblkid-devel, 
       libtirpc-devel, rpm-build, ncompress, libaio-devel, libffi-devel, libudev-devel, python3-cffi, python3-packaging

GIT_SSL_NO_VERIFY=true git clone --branch=zfs-2.2.2 https://github.com/openzfs/zfs.git zfs
cd zfs
./autogen.sh
./configure # --prefix=/usr --libdir=/lib64 --sysconfdir=/etc/zfs --datarootdir=/usr/share --mandir=/usr/share/man --enable-linux-builtin=yes --with-linux=?
# нужны пакеты python36-devel (в CentOS7 имеется python3-devel.x86_64, поменял rpm/redhat/zfs.spec), python36-packaging, python36-cffi
make rpm
# zfs-kmod-2.2.2-1.el7.src.rpm
# kmod-zfs-3.10.0-1160.53.1.el7.x86_64-2.2.2-1.el7.x86_64.rpm
# kmod-zfs-devel-2.2.2-1.el7.x86_64.rpm
# kmod-zfs-devel-3.10.0-1160.53.1.el7.x86_64-2.2.2-1.el7.x86_64.rpm
# zfs-dkms-2.2.2-1.el7.src.rpm
# zfs-dkms-2.2.2-1.el7.noarch.rpm
# zfs-2.2.2-1.el7.src.rpm
# zfs-dracut-2.2.2-1.el7.noarch.rpm
# python3-pyzfs-2.2.2-1.el7.noarch.rpm
# libzfs5-2.2.2-1.el7.x86_64.rpm
# libuutil3-2.2.2-1.el7.x86_64.rpm
# libnvpair3-2.2.2-1.el7.x86_64.rpm
# pam_zfs_key-2.2.2-1.el7.x86_64.rpm
# libzpool5-2.2.2-1.el7.x86_64.rpm
# libzfs5-devel-2.2.2-1.el7.x86_64.rpm
# zfs-2.2.2-1.el7.x86_64.rpm
# zfs-test-2.2.2-1.el7.x86_64.rpm

Устанавливаемые пакеты и файлы (2.2.2-1 для CentOS 7.9) в варианте DKMS:

С dracut не разбирался, т.к. не использую ZFS в качестве корневой файловой системы.

Модули ядра нужно загружать явно (systemd или sysv init) - к версии 2.2.2 остались только модули spl и zfs,

Отредактировать /etc/modprobe.d/zfs.conf (spl.conf). Выгрузить и загрузить модуль zfs.

После установки надо загрузить модуль zfs вручную (systemd позаботится о вас)

modprobe zfs
Jan  3 18:42:06 x136 kernel: spl: module verification failed: signature and/or required key missing - tainting kernel
Jan  3 18:42:06 x136 kernel: SPL: Loaded module v0.6.5.8-1
Jan  3 18:42:06 x136 kernel: znvpair: module license 'CDDL' taints kernel.
Jan  3 18:42:06 x136 kernel: Disabling lock debugging due to kernel taint
Jan  3 18:42:06 x136 kernel: ZFS: Loaded module v0.6.5.8-1, ZFS pool version 5000, ZFS filesystem version 5
Jan  3 18:42:10 x136 kernel: SPL: using hostid 0x00000000

Nov 22 20:23:41 grid0001 kernel: spl: loading out-of-tree module taints kernel.
Nov 22 20:23:41 grid0001 kernel: spl: module verification failed: signature and/or required key missing - tainting kernel
Nov 22 20:23:41 grid0001 kernel: icp: module license 'CDDL' taints kernel.
Nov 22 20:23:41 grid0001 kernel: Disabling lock debugging due to kernel taint
Nov 22 20:23:41 grid0001 kernel: ZFS: Loaded module v2.0.6-1, ZFS pool version 5000, ZFS filesystem version 5

Feb 15 18:15:10 grid0156 kernel: Request for unknown module key 'DKMS module signing key: 4b5f14880c6a862f1cfb0e7b663f1c4ba4c18502' err -11
Feb 15 18:15:10 grid0156 kernel: spl: loading out-of-tree module taints kernel.
Feb 15 18:15:10 grid0156 kernel: spl: module verification failed: signature and/or required key missing - tainting kernel
Feb 15 18:15:10 grid0156 kernel: Request for unknown module key 'DKMS module signing key: 4b5f14880c6a862f1cfb0e7b663f1c4ba4c18502' err -11
Feb 15 18:15:10 grid0156 kernel: zfs: module license 'CDDL' taints kernel.
Feb 15 18:15:10 grid0156 kernel: Disabling lock debugging due to kernel taint
Feb 15 18:15:12 grid0156 kernel: ZFS: Loaded module v2.2.2-1, ZFS pool version 5000, ZFS filesystem version 5

По умолчанию установлен параметр zfs_autoimport_disable модуля zfs, импортировать пул также придётся вручную (systemd позаботится о вас):

zpool import -a

Под нагрузкой rngd забирал более 50% CPU. Лечилось записью 2048 в /proc/sys/kernel/random/read_wakeup_threshold (или "kernel.random.read_wakeup_threshold = 2048" в /etc/sysctl.conf).

Устройство управления - /dev/zfs (c,10:58).

Головная боль OpenZFS (ZoL) - борьба ядра и ZFS за память. ZFS расходует ОП на ARC (данные с диска, метаданные с диска и вспомогательные данные; информация в /proc/spl/kstat/zfs/arcstats и /proc/spl/kstat/zfs/dbufstats, size - представление ARC о занятом месте, c_max - верхний предел), объекты из slab (информация в /proc/spl/kmem/slab, предоставляет ядру заниматься объектами размером менее spl_kmem_cache_slab_limit=16КиБ - информация в /proc/slabinfo, dmu_buf_impl_t - место под ссылки на объекты, часть slab слита с информацией от других подсистем ядра), неиспользуемое место (частично освобождённые slab). Однако ZFS ничего не знает о потерях памяти в результате фрагментации, в результате его сведения оказываются черезчур оптимистичными и система может подвиснуть по исчерпанию памяти. В версии 0.7 переделали списочная структура ARC Buffer Data (ABD) - /proc/spl/kstat/zfs/abdstats, данные хранятся в сжатом виде, но теперь растут в трёх местах, насколько это помогло не исследовал. /proc/spl и /proc/zfs содержат море статистики. В версии 2.0 встроили автоматическую настройку параметров ARC.

Параметры модуля ядра spl для ZFS on Linux

spl - Solaris Porting Layer, изображает Solaris на Linux. Параметры можно установить при загрузке системы (spl.имя-параметра=значение), при загрузке модуля из файла /etc/modprobe.d/spl.conf, динамически в /sys/module/spl/parameters/имя-параметра (kmem - собственная подсистема выделения памяти ядра, taskq - собственная подсистема управления потоками в ядре):

Параметры модуля ядра zfs для ZFS on Linux

Модуль реализует SPA, DMU, ZVOL и ZPL. Параметры (273 штуки в версии 2.0.0-rc1; 320 штук в версии 2.2.2) можно установить при загрузке системы (zfs.имя-параметра=значение), при загрузке модуля из файла /etc/modprobe.d/zfs.conf, динамически в /sys/module/zfs/parameters/имя-параметра.

Общее поведение, обработка ошибок:

Отладка:

send/receive:

Выделение места:

Базовый ввод/вывод:

Транзакции (открытие и наполнение, завершение, синхронизация (запись изменений) на устройство; синхронизация может потребовать выделения места, которое требует записи для себя и т.д. - несколько проходов):

Ограничение потока записи (уменьшение процентов уменьшает эффективность буферизации за счёт снижения расхода памяти и уменьшения задержек, при чрезмерном увеличении подлежащее устройство будет захлёбываться; статистика в /proc/spl/kstat/zfs/dmu_tx (dmu_tx_assigned - всего транзакций, dmu_tx_dirty_delay - задержано, dmu_tx_dirty_throttle - задержка не помогла и устройство захлебнулось)):

Шифрование:

Предварительное чтение:

Обслуживание синхронной записи (ZIL, SLOG):

ARC кеш (статистика в /proc/spl/kstat/zfs/dbufstats):

L2ARC кеш:

Планировщик ввода/вывода (отдельные очереди для задач каждого типа):

Выбор алгоритма рассчёта контрольной суммы:

Работа с vdev:

scrub и лечение:

Тома и снимки:

События:

Что это:

Пул хранения (zpool)

Набор данных (в частности, файловая система zfs) использует ресурсы виртуального пула хранения (zpool), который конструируется из виртуальных устройств vdev, которые образуются из группы (1 штука - это тоже группа) блочных устройств: файлы, разделы или целые устройства. Разработчики рекомендуют указывать целое устройство - ZFS может включить кеш записи диска (для ZFS это считается безопасным, если по всей цепочке работает команда сброса кеша; см. параметр zfs_nocacheflush модуля zfs) в Solaris и FreeBSD, в ZFS on Linux для устройства устанавливается планировщик noop и создаётся GPT таблица разделов - маленький раздел на 8МБ и большой под ZFS (как выключить создание GPT? - можно сделать VG из 1 диска и LV на весь том, заодно с именами станет хорошо). Рекомендуется использовать имена дисков из каталога /dev/disk/by-id/ (ata-изготовитель_модель_серийный-номер, scsi-изготовитель_модель_серийный-номер, scsi-WWID, wwn-WWN (8 байт), wwn-WWID (16 байт)) или /dev/disk/by-path/ (позволяет разнести диски по ящикам, но нельзя тасовать их; в Solaris работает логика замены сбойнувшего диска на новый в ту же ячейку, а в Linux?) или /dev/disk/by-vdev/ (надо предварительно заполнить /etc/zfs/vdev_id.conf).

Пул может хранить содержимое нескольих наборов данных, их снимков и клонов. Место выделяется из пула по требованию.

Типы vdev:

При создании пула он сразу импортируется, на нём создаётся корневая файловая система, которая сразу монтируется.

Имя пула должно начинаться с буквы и может содержать буквы, цифры, "_", "-", ".", ":", " ". Зарезервированы имена "mirror*", "raidz*", "cache", "spare*", "log", "draid*".

Пул, каждый vdev и каждое блочное устройство имеют уникальные GUID (не настоящие 128-битные в специальном формате, а просто случайные 64 бита).

Изменить количество блочных устройств в vdev невозможно (кроме расширения зеркала и разбиения состоящего из зеркал zpool), но можно добавить новый vdev в zpool. Также можно заменить устройство в vdev на большее (при наличии избыточности!): дождаться завершения лечения (resilver), повторить процедуру для оставшихся устройств (необходимо установить свойство пула autoexpand до замены первого диска - не сработало для LVM2). Данные распределяются по vdev, но ZFS не имеет средств ребалансировки, т.е. в новые vdev будут записаваться только новые данные. Кстати, до версии 0.8 лечение диска на 10ТБ потребует нескольких дней - лечение (как и scrub) идёт не последовательно, а по ссылкам инфраструктуры, так что замена одного диска вызывает полный проход по всем дискам. Да и в новых версиях идёт очень долго, если метаданные не вынесены в special на SSD ("19.8T scanned at 49.2M/s, 19.8T issued at 49.1M/s, 287T total, 65 days 21:30:16 to go").

В raidz (однопоточная?) производительность vdev на запись будет равна производительности 1 (самого медленного) диска, т.к. ZFS распределяет записи по vdev, не по конечным устройствам внутри него. При добавлении vdev распределение динамически увеличивается. Чтение может распараллеливаться внутри vdev. Придётся отказаться от традиции использовать LVM из нескольких подлежащих устройств в режиме RAID-0 (stripe) - надо добавлять в пул ZFS сами устройства.

В статье ZFS RAIDZ stripe width, or: How I Learned to Stop Worrying and Love RAIDZ рассказывается как в реальности раскладываются блоки данных, чётности и заполнителя и даётся таблица для расчёта "пропавшего" места для различных типов raidz, размера блока и размера сектора в процентах от сжатых данных. Если вкратце, то всё очень плохо - например, для raidz2 и сектора 4 КиБ:

Для получение больших IOPS необходимо делать маленькие группы, для экономии места - большие. Однако при таких потерях и большие группы не помогут (на нашем корпусе данных 75% файлов имеют размер менее 4КиБ).

Рекомендации по построению пула (Things Nobody Told You About ZFS 2013 год):

В реальности zpool - это дерево, которое начинается с корневого vdev, который состоит из vdev типа зеркало, raidz*, диск, файл, spare, cache, special и log. vdev типа зеркало и raidz* также могут включать vdev типа зеркало, raidz*, диск, файл. Вот только утилита создания не поддерживает такую конструкцию. Зато отладчик (zdb -C) показывает пул в виде дерева.

Метки ZFS присутствуют на физическом носителе, если на него производится запись данных (обычные диски в raidz, mirros и slog, но не spare). Для повышения надёжности на диске присутствуют 4 метки (по 256 КиБ) - две в начале диска и две в конце (по номерам, соответственно, 1, 2 и 3, 4). Кроме того, при обновлении данных в метках вначале обновляются первая и третья, а потом - вторая и четвёртая. Первая пара меток дополнительно содержит свободное пространство (8k) под EFI-метки и место под Boot Block Header (8k). За первой парой меток оставляется свободное пространство в 3.5 МиБ. Метка содержит описание и структуру устройств пула (кроме spare и cache) размером 112 КиБ и кольцевой буфер из 128 суперблоков размером 1 КиБ каждый. При изменении кофигурации суперблок перезаписывается на все устройства, иначе (закрытие транзакции) для перезаписи случайным образом выбирается не более 3 vdev; если выбранным оказался верхний vdev, то делается запись на все его физические устройства (пишутся 2 начальные метки, пишутся суперблоки, пишутся 2 конечные метки). При импорте по умолчанию выбирается корректный суперблок с наибольшим номером транзакции и временной меткой, но можно вручную выбрать любой из 128 (освобождённое место не используется на протяжении 3 транзакций, далее - как повезёт). Суперблок содержит указатель на MOS (Meta Object Set), GUID пула (?) и контрольную сумму GUID всех vdev. Указатель имеет длину 128 байт и содержит 3 DVA длиной 128 бит (Device Virtual Address: размер объекта длиной 24 бита в единицах - ashift - верхнего vdev, номер vdev длиной 32 бита, смещение в ashift длиной 63 бита; ashift=12 - блоки по 4 КиБ), флаги: индианистость, дедупликация, шифрование, сжатие, встроенные данные, тип контрольной суммы и пр., номер транзакции выделения места, номер транзакции создания ссылки, контрольная сумма. 2 и 3 DVA используются для копий метанных (данных), см. свойство файловой системы copies. Дерево косвенных блоков данных без использования экстентов, по 128 бит указатель на блок (по умолчанию размером 16 КиБ).

Каждый vdev разделен на логические разделы (metaslab), которые создаются автоматически при добавлении в zpool. Количество таких разделов определяется параметром metaslabs_per_vdev модуля zfs (по умолчанию - 200) и ? (получаются разделы по 2^34 байт). При поиске свободного места сначал выбирается vdev (предпочтение незаполненному vdev - metaslab_bias_enabled, поочередно (512 KiB?)), затем метаслаб в нём (группа метаслабов) исходя из процента заполненности, фрагментированности свободного места (metaslab_fragmentation_factor_enabled) и пр. (см. параметры модуля zfs). Рекомендуется убрать дисковую оптимизацию при использовании SSD (metaslab_lba_weighting_enabled=0). При поиске свободного места внутри метаслаба используется карта пространства (space map, список диапазонов с журнальной структурой - журнал выделений и освобождений, отсортированный по номеру группы транзакций; при чтении с диска в память формируется отсортированный список свободных пространств, который при записи преобразуется в журнал выделений). При выделении места из метаслаба, в котором более 4% свободного места, используется алгоритм первого подходящего, иначе самого подходящего, что значительно медленнее. Чтобы предотвратить это не допускайте уменьшения свободного места в пуле ниже 10%. Или metaslab_lba_weighting_enabled=0 и можно опускать до 5%. В сильно изменяющемся пуле необходимо держать 20% свободного пространства, в слабоизменяющемся (архив) достаточно 4%.

В файле /etc/zfs/zpool.cache хранится список известных пулов (не файловых систем, посмотреть: "zdb -C"), манипуляции

Переменные окружения для утилиты zpool:

Неизменяемые свойства пула (статистика и т.п.):

Свойства пула, которые можно задать при создании, импортировании и изменении (свойства требуют места в пуле и при его заполнении их невозможно изменить):

Пул может иметь пользовательские свойства, которые не влияют на поведение ZFS. Имя пользовательского свойства должно содержать ":" и быть короче 256 символов (байт?). Предполагается, что имя начинается с DNS имени в обратном порядке. Значение может быть произвольной строкой до 8192 байт.

Отдельные vdev также имеют встроенные и пользовательские свойства (zpool get -o all all имя-пула all-vdevs) начиная с версии 2.2:

zpool -? # вывести список команд.

zpool version # вывести версию ZFS (аналогично "zpool -V" или "zpool --version").

zpool create [ключи] имя-пула [тип-vdev] устройство1 ... [тип-vdev устройствоN ...] ... # создать пул и корневую файловую систему, администратор ответственнен за неиспользование устройств одновременно в 2 пулах; ключи:

zpool get список-свойств-через-запятую|all [имя-пула [all-vdevs|имя-vdev]] # выводится имя пула, имя свойства, значение и источник, ключи:

zpool set имя-свойства=значение имя-пула [имя-vdev] # изменить значение свойства пула или vdev на ходу.

zpool status [имя-пула ...] [интервал [отсчётов]] # показывает состояние (см. health) пула и фоновых задач (scrub и resilver); осторожно - пытается обратиться ко всем устройствам, что может вызвать большие задержки; ключи:

zpool list [имя-пула] ... [интервал [отсчётов]] # выдать список пулов с информацией о состоянии и заполненности, ключи:

zpool iostat [имя-пула-и/или-vdev] ... [интервал [отсчётов]] # логическая статистика ввода/вывода (для физической статистики см. iostat), информация о ёмкости, свободном месте, операциях ввода и вывода, пропускной способности ввода и вывода, числа двоичные, ключи:

zpool import # выдать список экспортированных пулов, доступных для импорта, имена, уникальные идентификаторы, топологию и состояние; ключи:

zpool import [имя-пула | идентификатор-пула [новое-имя-пула]] # перед использованием для монтирования файловой системы пул д.б. импортирован; при импорте в режиме только чтение не проигрывается ZIL и нельзя изменять свойства; при импорте много пишется (txg_sync - 100% ЦП) на носитель (6ГБ со скоростью 300 МБ/сек для файловой системы в 10ТБ); ключи:

zpool destroy [-f] имя-пула # размонтировать файловые системы и уничтожить пул, подтверждения не запрашивается.

zpool labelclear [-f] устройство # затереть метку zfs; заодно удаляет GPT, созданную zfs

zpool export имя-пула # отпустить пул перед переносом дисков на другой сервер - данные из кеша сбрасываются на диск, файловые системы размонтируются, устройства помечаются как экспортированные, помечается запрет на автоматический импорт и монтирование, пул удаляется из кеша; не экспортируется без ключа "-f", если к пулу приписано разделяемок устройство горячего резерва и оно используется; пул недоступен для работы пока его не импортируют явно, если сервер умер и устройства хранения приходится переставлять без экспорта, то импортировать придётся с ключом "-f"; ключи:

zpool add имя-пула устройство ... # добавить vdev к пулу, ключи:

zpool remove имя-пула устройство ... # удалить диск замены, кеш (L2ARC), SLOG (ZIL) устройство, vdev (включая dedup и special, но не raidz); данные с удаляемых vdev переписываются на оставшиеся устройства в фоновом режиме (см. zpool status); требует фичи device_removal; скорость высокая (346G copied out of 5.31T at 1.19G/s); вместо старого vdev в таблице остаётся устройство indirect-1; ключи:

zpool scrub имя-пула # запуск или продолжение в фоновом режиме (состояние смотреть "zpool status") проверки контрольных сумм каждой копии каждого используемого логического блока и проверку чётности для RAIDZ (а при обычном чтении делается?), лечение по возможности; рекомендуется раз в неделю/месяц; если совсем всё плохо: "zpool import -o readonly=on имя-пула; zpool scrub имя-пула"; в версии до 0.8 scrub (и лечение) осуществляет проход по структуре, а не последовательное чтение, причём однопоточное синхронное, т.е. безумно медленно; проверка структуры производится по минимому - лишь бы можно было пройти; scrub производит 2 типа ввода/вывода: чтение каталогов и dnode производится с помощью обычного механизма (предварительное загрузка, синхронное чтение через механизм ARC, без всяких проверок, не учитывается в отчёте сканирования) и асинхронное чтение всех копий блоков с проверкой (учитывается в отчёте сканирования, настраивается с помощью параметров модуля вплоть до отключения); можно запустить только одну проверку пула одновременно: ключи:

Примеры производительности

версия 0.6

массив из обычных дисков, собранный в LSI/LVM, 500 снимков, без нагрузки
  scan: scrub in progress since Thu Jan 26 18:36:45 2017
    877M scanned out of 40.8T at 5.10M/s, (scan is slow, no estimated time)
    0 repaired, 0.00% done

массив из быстрых дисков (SAS 10k rpm), собранный в LSI/LVM, 100 снимков, DDT, без нагрузки
  scan: scrub in progress since Fri Jan 27 22:35:58 2017
    20.5G scanned out of 13.2T at 35.8M/s, 107h17m to go
    0 repaired, 0.15% done

2 масива из разных дисков, 15 снимков, DDT, 10.5 ТБ (ALLOC) за 23.5 часа, без нагрузки, пробовал (без пользы)
   128 в /sys/module/zfs/parameters/zfs_top_maxinflight
   1 в /sys/module/zfs/parameters/zfs_no_scrub_prefetch

  299G scanned out of 9.56T at 52.3M/s, 51h36m to go
  384G scanned out of 9.56T at 50.4M/s, 53h6m to go
  640G scanned out of 9.56T at 47.0M/s, 55h20m to go
  884G scanned out of 9.56T at 45.6M/s, 55h28m to go
  1.09T scanned out of 9.56T at 44.8M/s, 55h6m to go
  2.22T scanned out of 9.56T at 47.6M/s, 44h50m to go
  2.59T scanned out of 9.56T at 41.2M/s, 49h18m to go
  5.18T scanned out of 9.56T at 71.9M/s, 17h44m to go
  6.17T scanned out of 9.56T at 84.1M/s, 11h43m to go
  7.52T scanned out of 9.56T at 100M/s, 5h56m to go # оба массива читают по 600 МБ/сек
  8.20T scanned out of 9.56T at 108M/s, 3h40m to go
  8.63T scanned out of 9.56T at 113M/s, 2h24m to go
  8.84T scanned out of 9.56T at 115M/s, 1h50m to go
  9.28T scanned out of 9.56T at 117M/s, 0h42m to go
  9.41T scanned out of 9.56T at 118M/s, 0h21m to go

версия ?

2 массива из разных дисков (RAID6 из 17 дисков SATA 2TB LFF 7200 в LSI MegaRAID), собранных в LVM (stripe), без снимков, без DDT, без нагрузки
  scan: scrub in progress since Fri Oct 26 19:48:04 2018
	5.58T scanned out of 9.67T at 1.36G/s, 0h51m to go
	0B repaired, 57.72% done

3 массива из разных дисков, добавлялись последовательно по мере наполнения, 28.9TB (ALLOC), без нагрузки
    2.61T scanned out of 28.9T at 59.1M/s, 129h36m to go
    4.33T scanned out of 28.9T at 59.1M/s, 121h8m to go
    5.06T scanned out of 28.9T at 57.8M/s, 120h18m to go
    10.7T scanned out of 28.9T at 83.8M/s, 63h29m to go
    17.0T scanned out of 28.9T at 115M/s, 30h16m to go
    19.0T scanned out of 28.9T at 121M/s, 23h47m to go
  scan: scrub repaired 0 in 57h52m with 0 errors on Mon Mar 20 11:34:28 2017

реальный архив, много снимков, DDT, без нагрузки
NAME           SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine   116T  69.1T  46.9T         -    22%    59%  1.52x  ONLINE  -

  scan: scrub repaired 0 in 236h0m with 0 errors

версия 2.1.7
2 массива из дисков (RAID6 из 18 дисков SAS 10TB LFF 7200 в LSI MegaRAID), собранных в LVM (stripe), l2arc и lvmcache на SSD
  scan: scrub in progress since Thu Mar 14 18:42:02 2024
	4.28T scanned at 57.9M/s, 3.51T issued at 47.6M/s, 287T total
	0B repaired, 1.23% done, 72 days 05:27:09 to go

версия 2.2
2 массива из дисков (RAID6 из 17 дисков SAS 16TB LFF 7200 в LSI), собранных в LVM (stripe), SSD для метаданных, много снимков, DDT, без нагрузки
  scan: scrub in progress since Wed Mar 13 22:23:44 2024
	176T / 244T scanned at 2.54G/s, 95.3T / 244T issued at 1.38G/s
	0B repaired, 39.11% done, 1 days 06:41:06 to go

zpool resilver имя-пула # запуск в фоновом режиме проверки и исправления контрольных сумм каждой копии каждого используемого блока; в отличие от scrub проверяет не все устройства, а только недавно добавленные или подменённые; приостановки нет, при запуске во время выполнения начинает с начала.

zpool attach имя-пула старое-vdev устройство # добавить устройство к vdev, простое vdev превращается в зеркало (начинается лечение), raidz расширить нельзя, ключи:

zpool detach имя-пула старое-устройство # извлечь устройство из зеркала, для временного извлечения рекомендуется "zpool offline".

zpool replace имя-пула старое-устройство [устройство-замены] # эквивалент процедуры: подсоединить устройство замены (mirror или raidz), дождаться завершения лечения, отсоединить старое устройство; устройство замены можно не указывать, если неисправное устройство уже было заменено новым на том же месте; ключи:

zpool clear [--power] имя-пула [устройство] # сбросить счётчики ошибок; пул может быть автоматически возвращён в работу; "--power" или переменная окружения ZPOOL_AUTO_POWER_ON_SLOT включает питание слота (но как?!).

zpool offline [--power] имя-пула устройство-хранения # объявить устройство нерабочим или сбойным (остаётся сбойным даже после импортирования), ключи:

zpool online [--power] имя-пула устройство-хранения # объявить устройство рабочим, ключ "-e" - расширение доступного к распределению на устройстве места до полного.

zpool reopen [имя-пула] # заново открыть (зачем? случайно выдернули устройство и тут же вставили его обратно?) все vdev пула, ключ "-n" - не возобновлять идущую процедуру проверки (scrub).

zpool reguid # сгенерировать новый GUID пула (длительный процесс?).

zpool split имя-пула новый-пул [устройство ...] # только для пула из зеркал и пул не д.б. в состоянии лечения; отщепить от каждого зеркала указанные устройства (по умолчанию последнее устройство) и собрать из них новый пул (GUID одинаковый? пулы останутся из зеркал?), ключи:

zpool upgrade # выдать список пулов, которые можно перевести на новую версию или добавить фичу.

zpool upgrade -v # выдать список поддерживаемых версий и фич.

zpool upgrade {имя-пула | -a} # перевод пула на новую версию с добавлением поддержки всех фич, вернуться нельзя (есть более гуманный способ: "zpool set feature@...=enable").

zpool history [имя-пула] # вывести историю команд, история хранится в пуле и её нельзя отключить (а если пул заполнен на 100%?), используется кольцевой буфер (32 МиБ?); отличный способ подсмотреть, что там сделала send -r/receive; ключи:

zpool events [имя-пула] # выдать список событий zfs, сгенерированных модулем ядром zfs и используемых zed (ошибки, зависания), см. zpool-events(8); сюда же попадают "события" создания записи в history; ключи:

zpool checkpoint имя-пула # создать контрольную точку для пула (может существовать только 1 точка); откатиться можно командой "zpool import --rewind-to-checkpoint"; наличие контрольной точки запрещает использование команд remove, attach, detach, split и reguid; команда "zpool status" показывает наличие контрольной точки; команда "zpool list" показывает количество места, потраченного на контрольную точку; ключи:

zpool initialize имя-пула [устройство] # начать или продолжить заполнение незанятого пространство в пуле ерундой (а зачем?); ключи:

zpool sync [имя-пула] # все изменённые данные записать из ОП на устройство (не в SLOG/ZIL).

zpool trim имя-пула [имя-устройства] # ручная инициализация или продолжение посылки команд TRIM/UNMAP на устройство для всех неиспользуемых секторов; имеется свойство пула для автоматической посылки - autotrim; "zpool status -t" показывает устройства, которые не поддерживают TRIM/UNMAP (trim unsupported) или которые поддерживают, но ожидают ручной инициализации (untrimmed); как это выключить насовсем? ключи:

zpool wait имя-пула [интервал-информирования] # ждать прекращения фоновых операций по завершению, прекращению или приостановке операции или уничтожению или экспорту пула; ключи:

Кеш в памяти - ARC

Для ускорения работы используется кеш данных и метаданных в памяти - ARC (Adaptive Replacement Cache). ARC является модифицированной реализацией запатентованного IBM механизма кеширования как последних (LRU - Least Recently Used), так и частых запросов (LFU - Least Frequently Used), поддерживаются следующие очереди:

Кеш блоков общий. На один и тот же блок могут быть ссылки из MRU и MFU. Ghost MRU и Ghost MFU ведутся и при отсутствии L2ARC - блоки легче извлекать из пула при наличии этих ссылок. При извлечении блоков по ссылке из Ghost MRU расширяется список MRU за счёт MFU, и наоборот. Таким образом кеш автоматически подстраивается под тип нагрузки. Размер кеша может меняться по требованию ядра (и в Linux?), блоки имеют разный размер, блоки могут быть заблокированы от удаления (?).

Место в ARC расходуется на данные, метаданные и вспомогательную информацию. Тип кешируемой информации можно установить с помощью свойств набора данных primarycache. Статистика ARC и L2ARC доступна через /proc/spl/kstat/zfs/arcstats, в удобном виде показывается утилитой arc_summary.py (в новых версиях просто arc_summary). По умолчанию размер используемой ОП колеблется от 1/32 (zfs_arc_min) до 1/2 (zfs_arc_max) всей ОП. Если предполагается запуск программ, требовательных к ОП, рекомендуется заранее ограничить ARC. Некоторые программы перед запуском проверяют размер свободной памяти и отказываются запускаться при её недостатке, хотя в реальности память могла быть освобождена системой по требованию. Некоторые программы могут требовать больших непрерывных сегментов памяти или huge pages, которые ARC без настроек фрагментирует.

По умолчанию только 3/4 ARC может использоваться под метаданные (включая таблицу дедупликации), объём метаданных оценивается как 1% от ёмкости хранилища. Изменить можно параметром zfs_arc_meta_limit модуля zfs или командой "zfs set primarycache=metadata|all|none".

ARC в реализации ZFS on Linux не связан с системой кеширования ОС (страницы виртуальной памяти), например, команда free показывает ARC в графе used. Это требует тщательного планирования и управления (лучше не запускать на файловом сервере требовательных к ОП программ). Фрагментация памяти в Linux приводит к тому, что в реальности используется больше памяти, чем показывается (и как представляется управляющей программе ARC). mmap() не умеет брать из ARC, только из страниц виртуальной памяти.

В ZoL 0.7 вместо отображения страниц используется списочная структура ARC Buffer Data (ABD), что теоретически позволяет бороться с фрагментацией, последствия не исследовал.

В OpenZFS 2.2 сделали адаптивную очистку и удалили множество ручных настроек. Последствия пока непонятны.

Кеш второго уровня на SSD - L2ARC

Кеш ARC может быть расширен (только для операций чтения) с помощью быстрого SSD устройства - L2ARC (second level ARC). L2ARC может входить в пул с момента создания или быть добавлен в пул и убран из пула без остановки его работы:

zpool add имя-пула cache устройство

Место в L2ARC расходуется на данные, метаданные (включая таблицу дедупликации) и вспомогательную информацию. Тип кешируемой информации можно установить с помощью свойств набора данных secondarycache. Нежелательно превышать 5 (?) размеров ARC: место в ARC расходуется на ссылки на L2ARC (Ghost, ARC_SPACE_L2HDRS), причём оно не освобождается даже под давлением - производительность может уменьшиться. Статистика ARC и L2ARC доступна через /proc/spl/kstat/zfs/arcstats, в удобном виде показывается утилитой arc_summary.py (в новых версиях просто arc_summary). Статистика L2ARC общая для модуля zfs, не обнулишь, пока не выгрузишь модуль.

Потеря устройства не ведёт к потере данных (кешируется только чтение). Можно использовать несколько L2ARC устройств (без страйпинга, заполняются по очереди). Зеркало и raidz не поддерживаются.

Может заполняться несколько часов.

ARC - глобальный, L2ARC - привязан к пулу, неразделяемый, а ссылки на L2ARC в ARC занимают общее место.

Samsung 840 Pro теряет 1% жизни в день или два (настроенная дедупликация - L2ARC размером 300GB (529.86 GiB сжатого до 200.24 GiB), Hit Ratio - 8.03%, входящий поток 1Gbps). В общем, если нет хотя бы Intel DC S3600, то установить secondarycache=metadata, иначе будет тормозить, а потом умрёт.

После появления возможности выделить под метаданные отдельный быстрый и устойчивый к истиранию SSD я не использую L2ARC.

Управление синхронной записью - ZIL

Асинхронная запись кешируется в ОП (ARC), при коммите транзакции (transaction group commits, каждые N секунд или другие условия) накопленные (грязные) данные сбрасываются на устройство постоянного хранения. Но запросы на синхронную запись должны быть записаны на устройство постоянного хранения немедленно с подтверждением, для этого используется механизм временного хранения ZIL (ZFS intent log). По умолчанию ZIL располагается на устройствах хранения обслуживаемого пула (отдельная структура для каждого набора данных - файловой системы или тома). Внешний ZIL читается только при восстановлении после падения сервера. После размещения данных из ARC на постоянное место хранения место во внешнем ZIL освобождается. Структуры ZIL в ОП накапливают все записи, относящиеся к незавершённым транзакциям (все записи, т.к. неизвестно какие из них будут синхронными) Операции над метаданными (создание, переименование) по умолчанию являются синхронными. Набор данных может иметь свойство "sync=always", что объявляет каждую запись синхронной, или "sync=disabled", что отключает логику внешнего ZIL, но структуры ZIL в ОП продолжают накопление записей, которые сбрасываются на устройство хранения при завершении транзакции.

ZFS имеет механизм обхода ZIL для потоковой нагрузки - данные пишутся сразу на место. При монтировании NFS с флагом async большинство записи проходит мимо ZIL. Локальная запись обычно также асинхронна.

При необходимости можно выделить специальное устройство SLOG (ZIL device), учитывая режим работы - однопоточная синхронная запись (для одного dataset) и защита от отключения питания - рекомендуется STEC ZeusRAM (ОП с батарейкой), SSD SLC и т.п. Размер определяется максимальным трафиком записи за тройное время между комитами транзакций (по умолчанию параметр zfs_txg_timeout модуля zfs был 30, потом 5, потом 10), но не более размера ARC. Для MLC/TLC SSD для продления его жизни надо взять устройство (раздел) побольше. Потеря SLOG приведёт к потере последних данных (но не метаданных), пул не будет импортироваться автоматически (можно импортировать вручную), поэтому желательно использовать vdev типа зеркало (raidz не поддерживается). Можно поставить несколько vdev типа slog - они будут работать паралллельно.

Статистику можно посмотреть в /proc/spl/kstat/zfs/zil.

Советы:

Основные настройки:

Контроллер RAID и SSD класса DC превращают синхронную запись в асинхронную с помощью буферизации в память, защищённую батарейкой. ZIL не нужен.

Наборы данных: файловая система и том

В пуле может быть создано несколько именованных (длина имени не более 256 байт, глубина вложенности - 50) наборов данных (datasets) следующих типов:

Каждый набор данных имеет неизменяемый всё время существования уникальный между пулами GUID, сохраняется при пересылке. Также имеется уникальный внутри пула objsetid, не сохраняется при пересылке, может использоваться повторно после удаления набора данных.

Свойства набора данных наследуются от пула или родительского набора данных, задаются при создании (постоянно, ключ "-O" при создании пула, ключ "-o" при создании файловой системы) или монтировании (временно). Имеется возможность задавать свои (пользовательские) свойства, они не влияют на работу ZFS, всегда наследуются, имя - до 256 байт (обязательно наличие символа ":"), значение - до 8192 (ранее 1024) байт. Свойства требуют места в пуле и при его заполнении их невозможно изменить.

Задаваемые свойства набора данных (свойства наследуются; изменение свойства действует на файлы, создаваемые после изменения, разбиение на логические блоки и сжатие и подсчёт контрольной суммы происходит до дедупликации - не надо ничего менять при включённой дедупликации на полпути):

Информационные свойства набора данных (не наследуются, не устанавливаются):

Размер свободного использованного места в zfs ещё более сложен, чем в btrfs (см. выше описание параметров used*, referenced, logicalused, logicalreferenced). df и du показывают занятое место на диске после сжатия с учётом метаданных, но без учёта дедупликации (даёт ответ на вопрос - "сколько места освободится на диске после удаления, если все блоки были последними в таблице дедупликации?"). Чтобы узнать размер файлов до сжатия необходимо использовать "du --apparent-size". Команда "ls -l" показывает исходный размер файла, команда "ls -lsh" показывает размер файла на диске без учёта дедупликации. Полный размер файловой системы (total), выдаваемый командой df, изменяется по мере изменения коэффициента дедупликации (и сжатия?). Счётчики обновляются в момент завершения транзакции. При использовании vdev типа raidz2 каждый блок содержит как минимум 2 сектора (512 байт или с учётом ashift?) чётности, которые не попадают ни в какие отчёты.

Свойства, устанавливаемые на время монтирования: atime/noatime (atime), auto/noauto (canmount), dev/nodev (devices), exec/noexec (exec), ro/rw (readonly), relatime/norelatime (relatime), suid/nosuid (setuid), xattr/noxattr (xattr), mand/nomand (nbmand), context=, fscontext=, defcontext=, rootcontext=.

Набор данных может иметь пользовательские свойства, которые не влияют на поведение ZFS. Имя пользовательского свойства должно содержать ":" и быть короче 256 символов (байт?). Предполагается, что имя начинается с DNS имени в обратном порядке. Значение может быть произвольной строкой до 8192 байт.

Переменные окружения для утилиты zfs

zfs -?.

zfs version

zfs get {свойство[,...]|all} [имя-пула[/имя-набора-данных[@имя-снимка]]] ... # выдать список значений свойств; выводятся колонки: имя набора данных, имя свойства, значение свойства, источник; в колонке источник (SOURCE) могут быть выданы значения: default (значение взято по умолчанию), inherited (значение унаследовано от пула или родительского набора данных), local (значение свойства установлено явно этого набора данных), temporary (значение установлено временно при монтировании), received (send/receive) или '-' (none, вычисляемый); ключи:

zfs set свойство=значение ... имя-пула[/имя-набора-данных[@имя-снимка]] ... # изменить свойство; ключи:

zfs inherit свойство имя-пула[/имя-набора-данных] ... # унаследовать свойство от родительского набора или пула или умолчания; ключи:

zfs create имя-пула/имя-файловой-системы # создание файловой системы (монтируется автоматически), ключи:

zfs create -V размер имя-пула/имя-тома # создание тома (zvol), экспортируется в блочное устройство /dev/zvol/имя-пула/имя-тома, размер округляется до размера блока, указанный размер резервируется, ключи:

zfs destroy имя-пула/имя-набора-данных # удаление файловой системы или тома; файловая система размонтируется и разшаривается; не д.б. наследников и зависимых клонов (см. ключ "-r" и "-R"); осторожно: приводит к необходимости изменения миллионов (сотен миллионов) блоков метаданных, при использовании фичи async_destroy изменения идут в фоновом режиме и продолжаются с точки остановки после перезагрузки; ключи:

zfs destroy имя-пула[/имя-набора-данных]@имя-снимка[%имя-снимка][,...] # удаление снимков, можно указать список интервалов снимков; удаляется немедленно, если нет блокировок (hold) и зависимых клонов, иначе помечается для удаления после выполнения указанных условий (ни разу не удалялся немедленно, хотя не было ни блокировок, ни клонов). Снимок 84 GiB (самый большой) удалился быстро (lvmcache); интервал снимков (482 GiB) удалялся полторы минуты (в фоне, использовался lvmcache); на заполненной системе интервал снимков 854 ГБ удалялся более 4 часов (без lvmcache); при удалении может потребоваться место; ключи:

Следить за фоновым освобождением места можно командой (freeing)

zpool list -p -o name,size,allocated,free,freeing,leaked,fragmentation,expandsize,capacity,dedupratio,health 30

zfs destroy имя-пула/имя-набора-данных#имя-закладки # удалить закладку

zfs snapshot имя-пула/имя-набора-данных@имя-снимка # создать снимок; при изменениях в файловой системе в снимке остаются старые значения, менять нельзя; ключи:

zfs rollback имя-пула/имя-набора-данных@имя-снимка # откатить состояние файловой системы или тома на время создания снимка; все сделанные после создания указанного снимка изменения удаляются; промежуточные снимки и закладки требуется удалить (ключ "-r" или "-R"); снимки подчинённых файловых систем не удаляются даже с ключами "-rR", каждую требуется откатить отдельно; ключи:

zfs clone имя-пула/имя-набора-данных@имя-снимка имя-пула/новое-имя-набора-данных # создать новую файловую систему или том на основе снимка; файловая система будет смонтирована по умолчанию в /имя-пула/новое-имя-файловой-системы с возможностью записи; снимок нельзя будет удалить без удаления клона; ключи:

zfs promote клонированная-файловая-система # исходная файловая система, с которой делался снимок, с которого делался клон становится клоном (его можно потом удалить, но снимок - нет!), клон становится самостоятельной файловой системой, а снимок привязывается к ней (origin и clone меняются местами), все предыдущие снимки также привязываются к бывшему клону, последующие остаются привязанными к бывшей исходной файловой системе. Предварительно необходимо разрешить все конфликты имён. Пример из документации

zfs create pool/project/production
zfs snapshot pool/project/production@today
zfs clone pool/project/production@today pool/project/beta
zfs promote pool/project/beta
zfs rename pool/project/production pool/project/legacy
zfs rename pool/project/beta pool/project/production
zfs destroy pool/project/legacy

zfs bookmark имя-пула/имя-набора-данных{@имя-снимка|#имя-закладки} имя-пула#имя-новой-закладки # создать закладку.

zfs rename имя-пула/имя-набора-данных[@имя-снимка] новое-имя; переименовать набор данных или снимок; при необходимости производится перемонтирование; ключи:

zfs list [имя-набора-данных|имя-снимка] ... # выдать список наборов данных и их свойств; ключи:

zfs mount # вывести список смонтированных файловых систем; временно смонтированные файловые системы для снимков не показывает.

zfs mount {имя-пула/имя-файловой-системы|-a} # смонтировать файловую систему или все; автоматически выполняется при импорте пула, если разрешено в mountpoint; ключи:

zfs unmount|umount {-a | имя-пула/имя-файловой-системы | точка-монтирования} # размонтирование файловой системы; ключи:

zfs share {-a | имя-пула/имя-файловой-системы} # выдаёт (экспортирует, расшаривает) файловую систему наружу для NFS, SMB или iSCSI (удалено) для файловых систем и томов с установленными свойствами sharenfs, sharesmb или shareiscsi (удалено); выполняется автоматически при импорте пула; шары создаются в подкаталоге .zfs/shares/ корня файловой системы (?); снимки экспортируются вместе с файловой системой (при первом обращении к .zfs/snapshot); можно экспортировать непосредственно .zfs/snapshot.

zfs unshare {-a | имя-пула/имя-файловой-системы | точка-монтирования} # закрывает файловую систему для экспорта; выполняется автоматически при завершении работы сервера.

zfs send имя-пула/имя-набора-данных@имя-снимка # вывести на stdout поток, представляющий содержимое снимка; этот поток можно сохранить или сразу использовать локально или удалённо (например, с помощью ssh, nc, mbuffer) командой "zfs receive"; формат потока стандартизован и зафиксирован; send делает hold на снимки; посмотреть заголовки и статистику можно с помощью утилиты zstreamdump; на передающем конце данные разжимаются (если не указано -c), на приёмном сжимаются обратно; ключи:

Пример копирования цепочки снимков (основанные на снимках клоны не копируются):

принимающий сервер (пул bigpool создан, а файловая система нет)
mbuffer -I 7777 -m 1G -s 1048576| zfs receive -vd -F -s -o свойство ... -o mountpoint=/time_machine bigpool

передающий сервер (имеются снимки и клоны с 20150101 по 20240131):
zfs send -R -p -Lec -V bigpool/time_machine@20240131 | mbuffer -O принимающий-сервер:7777 -m 1G -s 1048576

создаются поштучно
receiving full stream of bigpool/time_machine@20150101 into bigpool/time_machine@20150101
in @ 28.0 MiB/s, out @ 28.0 MiB/s, 11.2 TiB total, buffer   0% fullreceived 11.2T stream in 113336.17 seconds (104M/sec)
receiving incremental stream of bigpool/time_machine@20150102 into bigpool/time_machine@20150102
in @ 53.9 MiB/s, out @ 49.9 MiB/s, 11.3 TiB total, buffer   0% fullreceived 29.1G stream in 145.54 seconds (205M/sec)
...

клоны не дошли, пришлось воссоздавать
for DATE in `ls /time_machine/.zfs/snapshot/`; do zfs clone -o mountpoint=/clones/$DATE -p bigpool/time_machine@$DATE bigpool/clones/$DATE; done

следующая пачка (в промежутке на приёмном конце ничего не делать):

mbuffer -I 7777 -m 1G -s 1048576| zfs receive -vd -F -o ... -o mountpoint=/time_machine bigpool

zfs send -R -Lec -I bigpool/time_machine@20240131 bigpool/time_machine@20240229 | mbuffer -O принимающий-сервер:7777 -m 1G -s 1048576

zfs send имя-пула/имя-набора-данных|имя-пула # вывести на stdout поток, представляющий содержимое файловой системы; снимки и клоны не передаются; файловая система должна быть размонтирована или пул импортирован только на чтение; на приёмном конце создаётся искусственный снимок с именем "--head--" (не удаляется при завершении); ключи:

Пример копирования файловой системы целиком (без снимков и клонов)

принимающий сервер (пул bigpool создан, файловая система создана)
mbuffer -I 7777 -m 1G -s 1048576| zfs receive -ve -F -s bigpool

передающий сервер (клоны с 20150101 по 20240131, пришлось всё размонтировать):
zfs send --Lec -V bigpool/time_machine| mbuffer -O принимающий-сервер:7777 -m 1G -s 1048576
summary: 36.8 TiByte in 52h 48min 30.1sec - average of  203 MiB/s

receiving full stream of bigpool/time_machine@--head-- into bigpool/time_machine@--head--
...

zfs send -t ключ-возобновления # возобновить прерванную ранее передачу; ключ брать в свойстве receive_resume_token на принимающем конце (см. "zfs receive -s"). Можно использовать только ключи -PVenv.

zfs send [-i снимок|закладка] -S набор-данных # выдать поток, который мы сами получили не полностью.

zfs send --redact имя-закладки имя-пула/имя-набора-данных@имя-снимка # вывести на stdout поток, представляющий содержимое снимка, отредактированный командами из закладки (записываются командой "zfs redact"); мутная вещь.

zfs redact снимок закладка редактирующий-снимок # создать закладку для последующего редактирования потока. Ещё более мутная вещь.

zfs receive имя-пула/имя-набора-данных[@имя-снимка] # принять поток от "zfs send" на stdin и создать из него снимок; для инкрементального потока файловая система должна существовать, самый свежий снимок на приёмном конце должен соответствовать опроному снимку на передающем; если имя-снимка указано в команде, то берётся из команды, иначе - из потока; при приёме полного потока создаются файловая система и снимок; при приёме пакета потоков (-R) на приёмном конце удаляются снимки, отсутствующие у источника ("zfs destroy -d"); при приёме тома ссылка на устройство пересоздаётся (не получится его использовать во время передачи); если не использован ключ "-s", то при прерывании передачи файловая система откатывается к моменту начала; после передачи первого снимка монтирования не произошло, попытался вручную - файловая система пуста, передача прервалась ("dataset is busy"), не трогайте приёмник до завершения всей передачи; пример send/receive с использованием mbuffer ключи:

Что происходит при передаче снимка на самом деле? Подсмотрено из "zpool events -v" и "zpool history -il":

"послойная" передача

receive bigpool/time_machine (387)
set bigpool/time_machine (387) $hasrecvd=
set bigpool/time_machine (387) aclinherit=3
...
finish receiving bigpool/time_machine (387) snap=20150101
snapshot bigpool/time_machine@20150101 (44623)
set bigpool/time_machine (387) sharesmb=off
set bigpool/time_machine (387) sharesmb=off
receive bigpool/time_machine/%recv (44746)
set bigpool/time_machine (387) aclinherit=3
...
finish receiving bigpool/time_machine/%recv (44746) snap=20150102
clone swap bigpool/time_machine/%recv (44746) parent=time_machine
snapshot bigpool/time_machine@20150102 (45407)
destroy bigpool/time_machine/%recv (44746) (bptree, mintxg=44320)
set bigpool/time_machine (387) sharesmb=off
receive bigpool/time_machine/%recv (43639)
set bigpool/time_machine (387) aclinherit=3
...
finish receiving bigpool/time_machine/%recv (2255790) snap=20240131
clone swap bigpool/time_machine/%recv (2255790) parent=time_machine
snapshot bigpool/time_machine@20240131 (2258108)
destroy bigpool/time_machine/%recv (2255790) (bptree, mintxg=1666790)
set bigpool/time_machine (387) sharesmb=off
zfs receive -vd -F -o ... bigpool

создание клонов

clone bigpool/clones/20150101 (2255968) origin=bigpool/time_machine@20150101 (44623)
set bigpool/clones/20150101 (2255968) mountpoint=/clones/20150101
zfs clone -o mountpoint=/clones/20150101 -p bigpool/time_machine@20150101 bigpool/clones/20150101
...

целиковая передача

receive bigpool/time_machine/%recv (390)
finish receiving bigpool/time_machine/%recv (390) snap=--head--
clone swap bigpool/time_machine/%recv (390) parent=time_machine
snapshot bigpool/time_machine@--head-- (115448)
destroy bigpool/time_machine/%recv (390) (bptree, mintxg=1)
ioctl receive
    input:
        snapname: 'bigpool/time_machine@--head--'
        begin_record[0]: 0
        begin_record[1]: 0
...
        begin_record[311]: 0
        input_fd: 0
        force
        resumable
    output:
        read_bytes: 40412783039912
        error_flags: 0
        errors:
zfs receive -ve -F -s bigpool

zfs diff имя-пула/имя-файловой-системы@имя-снимка имя-пула/имя-файловой-системы[@имя-снимка] # вывести список файлов, изменившихся между снимками ("-" - удалён, "+" - добавлен, "M" - изменён, "R" - переименован); ключи:

zfs userspace имя-пула/имя-файловой-системы[@имя-снимка] # показать квоты и занимаемое место (см. свойства userused@имя-пользователя и userquota@имя-пользователя; ключи:

zfs groupspace имя-пула/имя-файловой-системы[@имя-снимка] # показать квоты и занимаемое место (см. свойства groupused@имя-группы и groupquota@имя-группы; ключи:

zfs projectspace имя-пула/имя-файловой-системы[@имя-снимка] # показать квоты и занимаемое место (см. свойства projectused@идентификатор-проекта и projectquota@идентификатор-проекта; ключи:

zfs allow и unallow позволяют передать непривилегированному пользователю (не uid 0) часть прав по администрированию файловой системы или тома. Без параметров выводит текущие права.

zfs hold [-r] метка имя-пула/имя-файловой-системы@имя-снимка ... # именованная блокировка не позволяет удалить снимок, каждый снимок имеет своё пространство имён. Этот механизм используется в send/receive. Клоны используют другой механизм.

zfs holds [-rHp] имя-пула/имя-файловой-системы@имя-снимка ... # вывести список блокировок.

zfs release [-r] метка имя-пула/имя-файловой-системы@имя-снимка ... # снять поименованную блокировку.

zfs upgrade [-v] # показать список файловых систем (не пулов!), которые можно улучшить. В настоящее время нет ничего кроме версии 5.

zfs upgrade {-a | имя-пула/имя-файловой-системы} # обновить версию файловой системы (не пула!); ключи:

zfs jail и unjail # только для FreeBSD.

zfs load-key и unload-key и change-key # манипуляции с ключами шифрования.

zfs zone файл-пространства-имён имя-пула/имя-файловой-системы # подключить файловую систему в пространство имён пользователя; требуется свойство zoned; определяется файлом /proc/номер-процесса/ns/user; в пользовательском пространстве имён требуется доступ к /dev/zfs; подчинённые файловые системы нельзя подключить к другому пользователю; нельзя поменять квоту.

zfs unzone файл-пространства-имён имя-пула/имя-файловой-системы # отключить файловую систему из пространства имён пользователя.

zfs wait [-t тип,...] # дождаться завершения указанной фоновой активности; пока только deleteq (дожидается завершения процессов с указателями на удалённые файлы).

zfs project # управление привязкой файлов к проектам.

zfs program имя-пула имя-скрипта-LUA [параметры] # запуск скрипта на LUA 5.2; выполнение атомарное; ключи:

Для InnoDB необходимо установить параметр zfs_nocacheflush модуля zfs и создать отдельную файловую систему со свойствами recordsize=16K, primarycache=metadata, logbias=throughput, atime=off, sync=disabled.

Для MyISAM необходимо установить параметр zfs_nocacheflush модуля zfs и создать отдельную файловую систему со свойствами recordsize=8K, primarycache=metadata, logbias=throughput, atime=off, sync=disabled.

А лучше не использовать CoW файловую систему для работы с СУБД, под swap, блочные устройства виртуальных машин и т.п..

Кроме предварительного чтения на уровне устройств ZFS предлагает механизм предварительного чтения на уровне файлов - zfetch. Этот механизм отслеживает шаблоны чтения файлов и при обнаружении потока последовательного чтения (вперёд или назад, сплошного или интервального, 8 потоков на файл - на dnode, а не на file handler) заранее загружает данные в кеш ARC. Статистику можно получить в /proc/spl/kstat/zfs/zfetchstats или с помощью утилиты arc_summary.py. Управлять можно с помощью параметров zfs_prefetch_disable, zfetch_array_rd_sz, zfetch_block_cap, zfs_read_chunk_size модуля zfs.

Для обработки ситуации с удалением использумых в настоящий момент файлов (pending delete) применяется такой внутренний объект ZFS как очередь удаления, которая хранит ссылки на все временно не удалённые объекты (отдельная очередь для каждой файловой системы и снимка, таким образом место не освободится пока не будет удалён последний снимок). Эта очередь передаётся в операциях send/receive и в момент монтирования по завершению передачи файлы удаляются, порождая расхождение между текущим состоянием файловой системы и только что переданных снимком (но место не осовободится!), при следующей инкрементальной передаче придётся использовать ключ "-F" для откатки этого изменения. Поиск объектов очереди удаления (не нашёл):

zdb -dddd имя-файловой-системы 1

найти в выводе "DELETE_QUEUE = номер-объекта"

zdb -dddd имя-файловой-системы номер-объекта
...
ZAP entries: количество объектов в очереди на удаление

Тестирование производительности сжатия

Тестирование производительности сжатия проводилось в основном на сервере с 2 Intel Xeon CPU E5-2637 v2 @ 3.50GHz, по 4 ядра.

Дедупликация

ZFS использует синхронную дедупликацию, которая производится после сжатия (не надо менять сжатие на ходу!) на блочном уровне. Дедупликация воздействует на весь пул - дедуплицированные файлы могут ссылаться на записи в других файловых системах этого пула, производится дополнительная работа со всеми файлами пула, размер DDT определяется всем пулом, даже свойство dedupratio относится к пулу, а не файловой системе. Метаданные и каталоги не участвуют в дедупликации.

Для работы дедупликации необходимо ведение на ходу таблицы дедупликации (DDT), которая хранит хеш блока (sha256) и количество блоков, имеющих этот хеш. Каждый указатель на блок данных имеет флаг дедупликации, который взводится при записи при наличия дубля с таким же хешем. DDT не используется при чтении данных (если не произошло ошибки чтения и не пришлось читать запасную копию), DDT изменяется при записи, при удалении блока проверяется флаг дедупликации указателя на блок и при необходимости изменяется счётчик использования в DDT. Если счётчик уменьшается до нуля, то удаляется сама запись из DDT. DDT всегда есть, возможно пустая. На каждый пул заводится отдельная DDT (одна на весь пул; похоже, что заводится отдельная таблица на блоки с 1 ссылкой?). DDT относится к метаданным и пишется в режиме CoW. На каждый блок данных требуется 320 байт на диске ("zdb -L -D" сообщает, что требуется 449 байт для уникальных блоков и 476 байт для всех дублей с одним хешем на диске и 153/145 байт в памяти). Если грубо, то на каждый ТБ ёмкости хранилища необходимо от 1 до 5ГБ под DDT, для более точного подсчёта текущих потребностей необходимо получить количество блоков в пуле - bp count ("zdb -L -b имя-пула" - очень долго и нужно очень много памяти) и умножить на 320 (449 для уникальных блоков и 476 для каждой группы одинаковых). Занимаемое место отражается в USEDCHILD. При необходимости (?) регенерируется из метаданных.

Выключение дедупликации не отменяет необходимости вносить изменения в DDT при удалении блока.

При проверке и лечении DDT используется как источник ссылок, по которым надо пробежаться.

Для обеспечения нормальной скорости DDT должна быть в ARC, в крайнем случае - в L2ARC. При недостатке ARC и L2ARC удаление снимка может потребовать сутки (и его нельзя прервать даже перезагрузкой). Кроме DDT в ARC должно остаться место под прочие метаданные (в среднем 1% от ёмкости хранилища) и данные (3/4 от ARC, параметр zfs_arc_meta_limit модуля zfs?) с учётом максимального размера самого ARC и уровня фрагментации памяти (как узнать?). Кстати, записи DDT в L2ARC (300-500 байт?) требуют места под ссылки на них в ARC (180 байт?).

Если ожидается большой средний размер файла, то можно увеличить recordsize файловой системы с 128 КиБ до 1 МиБ, таким образом уменьшив потребности в памяти в 8 раз (в предельно оптимистичном случае). У меня средний размер блока получился равным 338 КБ до сжатия и 114 КБ после оного.

При выборе SSD под L2ARC необходимо учитывать большую и непрерывную нагрузку, так что надо не хуже Intel DC S3600 (S3500?). Предполагаемая производительность DDR3 в этом режиме - 100-150k IOPS.

Встречаются самые разные рекомендации от необходимости вынесения всех дедуплицированных файловых систем в отдельный пул до категорического неприятия дедупликации как таковой. Важной информацией для решения является степень дедупликации dedupratio, предсказать её можно командой "zdb -S имя-пула" (очень долго, строится временная DDT - заодно узнаете достаточно ли у Вас памяти ;).

Офлайновую дедупликацию сделать не получится, т.к. отсутствует механизм прозрачной для пользователя перезаписи блоков данных и метаданных. Этот же механизм (BPR - Block Pointer Rewrite, ожидается с 2008) позволит сделать дефрагментацию, ребалансировку, уменьшение пула или vdev и т.д..

Утилита zdb

Утилита zdb позволяет узнать полезную информацию о текущем состоянии ZFS, базовые ключи ("-L" - не делать проверок):

zdb не согласует свои действия с модулем ядра, при активном использовании может показывать и делать всякое.

zfs_ids_to_path имя-пула идентификатор-набора идентификатор-объекта - преобразовать идентификаторы в имя файла и путь.

zinject - создаёт искусственные проблемы в пуле ZFS симулируя повреждение данных и сбой устройств.

Утилиты сбора статистики

arc_summary (ранее arc_summary.py) - статистика использования ARC. Ключи:

arcstat интервал количество (ранее arcstat.py) - iostat для кеша. Ключи:

dbufstat (ранее dbufstat.py) - статистика (ключ "-t") и содержимое объектов в памяти. Ключи:

zilstat - скрипт на python. Ключи:

Прочие утилиты

Заглушка fsck.zfs. Некоторые дистрибутивы хотят утилиту fsck для каждого типа файловой системы, но имеющийся в ZFS scrub работает для всего пула и довольно долго, поэтому предоставляется заглушка в виде fsck.zfs, которая запрашивает текущий статус пула и может вернуть 4 (пул деградировал) и 8 (пул неисправен).

mount.zfs имя точка-монтирования - вспомогательная утилита для монтирования снимков или файловой системы в режиме mountpoint=legacy (/etc/fstab). Рекомендуется использовать mount или "zfs mount". Ключи:

zgenhostid - создать файл /etc/hostid и записать в него идентификатор хоста (бинарные случайные данные). Идентификатор хоста требуется для экспорта и импорта пула. См. параметры модуля spl: spl_hostid (0 - не использовать или случайное число?) и spl_hostid_path (/etc/hostid). Пакет initscripts имеет утилиту genhostid, которая делает тоже самое и утилиту hostid, которая выводит идентификатор хоста в виде IP адреса с переставленными байтами.

zpios - стресс-тестирование DMU.

zstream (она же zstreamdump) позволяет манипулировать потоком, создаваемым "zfs send", на стандартном вводе:

ztest - тесты регрессии для ZFS.

raidz_test - тест RAID-Z.

zvol_wait - ожидание появления блочных устройств в /dev/zvol после импорта пула.

udev и vdev

Видимо, в Solaris нет udev и пришлось делать своё. vdev_id (vdev_id.8) используя /etc/zfs/vdev_id.conf (vdev_id.conf.5) создаёт "правильные" имена для устройств хранения в /dev/disk/by-vdev. Предлагаются примеры для multipath, sas_direct, sas_switch и scsi.

Используется в Linux подсистемой udev, для которой предоставляются правила udev в /usr/lib/udev/rules.d/: 60-zvol.rules (имена томов для блочных устройств в /dev/zvol/), 69-vdev.rules (слоты корзины) и 90-zfs.rules (загрузка модуля zfs).

Система извещений

Модули ядра генерируют сообщения (zpool-events.8) при наступлении событий. Сообщения обрабатываются сервисом zed (zed.8, ZFS Event Daemon), вызывает скрипты (bash), которые хранятся в /etc/zfs/zed.d/ (ссылки на /usr/libexec/zfs/zed.d/). Настройки: /etc/zfs/zed.d/zed.rc. Сигнал SIGHUP вызывает реконфигурацию сервиса. Мешает выгружать модуль zfs.

Настройки systemd

Службы (/usr/lib/systemd/system/) systemd (настройки в /usr/lib/systemd/system-preset/50-zfs.preset):

Цели: zfs.target (из multi-user.target), zfs-import.target (из zfs.target), zfs-volumes.target (из zfs.target, после zfs-volume-wait.service).

zfs-mount-generator - генератор юнитов systemd.mount(5) исходя из свойств наборов данных (mountpoint не legacy или none, canmount не off), обрабатывает noauto, atime=, relatime=, devices=, exec=, readonly=, setuid=, nbmand=. Хранит кеш в /etc/zfs/zfs-list.cache/poolname (не обнаружил). Тестовый пример не пройден.

Выделенный сервер архива без дедупликации

Выделенный сервер архива без дедупликации: 8 ядер по 3.5GHz, 64 ГиБ ОП, сеть 10Gbps, большой локальный массив (LSI MEGARAID 2xRAID-6 of 18 SATA HDD LFF 2000GB 7200 rpm (старые больные диски) + lvmcache на SSD Intel DC S3500).

Параметры модуля spl (/etc/modprobe.d/spl.conf): отсутствуют.

Параметры модуля zfs (/etc/modprobe.d/zfs.conf): отсутствуют.

Создание пула (надо было xattr=sa и без utf8only, выше gzip-7 не тянет, вместе с relatime надо включать atime, checksum лучше делать sha256):

zpool create -f -m /time_machine -o ashift=12 -o listsnapshots=on \
-d -o feature@async_destroy=enabled -o feature@empty_bpobj=enabled -o feature@lz4_compress=enabled -o feature@spacemap_histogram=enabled -o feature@extensible_dataset=enabled -o feature@bookmarks=enabled -o feature@enabled_txg=enabled -o feature@embedded_data=enabled -o feature@large_blocks=enabled \
-O utf8only=on \
-O compression=gzip-7 \
-O atime=off -O relatime=on \
-O acltype=posixacl -O xattr=on \
-O dedup=off \
-O redundant_metadata=most \
-O sync=disabled -O logbias=throughput \
-O snapdir=visible \
time_machine dm-name-x136all36-share 

Наполнение архива с помощью rsync (40 потоков, "--max-size=100GB -vas --inplace --numeric-ids --ignore-errors --delete").

Статистика после заполнения первого дня, в 1.5 раза дольше btrfs поверх того же аппаратного RAID и LVM cache, примерно тот же объём (но 3.5% - 2 ТБ - заблокировано):

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   61778751MB 11329313MB 50449439MB  19% /time_machine

zpool list
NAME           SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  10.3T  47.7T         -    14%    17%  1.00x  ONLINE  -

zfs  list -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbyrefreservation,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDREFRESERV  USEDSNAP
  gzip-7  2.56x     2.56x      56.0M   10.3T              0         0

zfs list
NAME           USED  AVAIL  REFER  MOUNTPOINT
time_machine  10.3T  45.9T  10.3T  /time_machine

Статистика блоков после заполнения первого дня

zdb -b time_machine
Traversing all blocks to verify nothing leaked ...

loading space map for vdev 0 of 1, metaslab 64 of 116 ...
10.3T completed (1421MB/s) estimated time remaining: 0hr 00min 00sec
        No leaks (block sum matches space maps exactly)

        bp count:       291107412
        ganged count:           0
        bp logical:    28883875873792      avg:  99220
        bp physical:   11236123043328      avg:  38597     compression:   2.57
        bp allocated:  11329371234304      avg:  38918     compression:   2.55
        bp deduped:             0    ref>1:      0   deduplication:   1.00
        SPA allocated: 11329371234304     used: 17.77%

        additional, non-pointer bps of type 0:   24469613
        Dittoed blocks on same vdev: 5579261 

Статистика после заполнения 23-го дня:

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
time_machine   93362015349 78754757 93283260592    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   60204402MB 12443373MB 47761030MB  21% /time_machine

zpool list
NAME           SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  12.7T  45.3T         -    14%    21%  1.00x  ONLINE  -

zfs  list time_machine -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbyrefreservation,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDREFRESERV  USEDSNAP
  gzip-7  2.78x     2.64x      1.36G   11.3T              0     1.43T

zfs list|head -4;zfs list |tail -4
NAME                    USED  AVAIL  REFER  MOUNTPOINT
time_machine           12.7T  43.4T  11.3T  /time_machine
time_machine@20140801  16.3G      -  10.3T  -
time_machine@20140802  3.52G      -  10.9T  -
time_machine@20140820  13.9G      -  11.1T  -
time_machine@20140821  6.93G      -  11.2T  -
time_machine@20140822  2.80G      -  11.2T  -
time_machine@20140823  1.87G      -  11.3T  - 

Статистика после заполнения 96-го дня (фрагментация свободного пространства всё ещё приличная):

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
time_machine   86838204271 81602375 86756601896    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   58034215MB 13614834MB 44419381MB  24% /time_machine

zpool list
NAME           SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  15.8T  42.2T         -    19%    27%  1.00x  ONLINE  -

zfs  list time_machine -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-7  2.89x     2.65x      3.41G   12.4T     3.40T

zfs list|head -4;zfs list |tail -4
NAME                    USED  AVAIL  REFER  MOUNTPOINT
time_machine           15.8T  40.4T  12.4T  /time_machine
time_machine@20140801  16.3G      -  10.3T  -
time_machine@20140802  3.52G      -  10.9T  -
time_machine@20141031  1.41G      -  12.3T  -
time_machine@20141101  2.47G      -  12.4T  -
time_machine@20141102  1.34G      -  12.4T  -
time_machine@20141103   298M      -  12.4T  - 

zdb -L -b time_machine

Traversing all blocks ...

16.4T completed ( 671MB/s) estimated time remaining: 0hr 00min 04sec         
	bp count:       500483120
	ganged count:           0
	bp logical:    52499166426624      avg: 104896
	bp physical:   17887185559552      avg:  35739     compression:   2.94
	bp allocated:  18031836352512      avg:  36028     compression:   2.91
	bp deduped:             0    ref>1:      0   deduplication:   1.00
	SPA allocated: 18031836352512     used: 28.28%

	additional, non-pointer bps of type 0:   29943472
	Dittoed blocks on same vdev: 12402758

Статистика L2ARC:

L2 ARC Size: (Adaptive)				254.89	GiB
	Compressed:			49.48%	126.12	GiB
	Header Size:			0.23%	598.29	MiB

L2 ARC Breakdown:				2.54b
	Hit Ratio:			3.19%	81.03m
	Miss Ratio:			96.81%	2.46b
	Feeds:					228.49k

zfs set secondarycache=metadata time_machine
zpool remove time_machine /dev/system/l2arc
zpool add time_machine cache /dev/system/l2arc # статистика общая

Попытался выполнить "zdb -S" на системе с 64ГиБ ОП и распределённым пулом 21 ТиБ (из 58 ТиБ). После 3 часов молчаливой работы система начала тупить (трешинг свопа? вплоть до "сервер недоступен" в мониторинге), при этом zdb потребил почти 19 ГиБ, top показывал наличие свободной памяти.

Статистика после заполнения 236-го дня (фрагментация свободного пространства всё ещё приличная, средний прирост - 70 ГБ в день):

df -i /time_machine
Filesystem          Inodes     IUsed       IFree IUse% Mounted on
time_machine   66644509563 108181763 66536327800    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   47971509MB 13904913MB 34066597MB  29% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  25.2T  32.8T         -    32%    43%  1.00x  ONLINE  -
  dm-name-x136all36-share    58T  25.2T  32.8T         -    32%    43%
cache      -      -      -         -      -      -
  l2arc   145G  12.5G   132G         -     0%     8%

zfs list time_machine -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-7  3.01x     2.64x      11.7G   12.6T     12.5T

Статистика после заполнения 300-го дня:

df -i /time_machine
Filesystem          Inodes     IUsed       IFree IUse% Mounted on
time_machine   59961056654 114028446 59847028208    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   44739499MB 14097821MB 30641679MB  32% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  28.3T  29.7T         -    36%    48%  1.00x  ONLINE  -
  dm-name-x136all36-share    58T  28.3T  29.7T         -    36%    48%
cache      -      -      -         -      -      -
  l2arc   145G  13.7G   131G         -     0%     9%

zfs list time_machine -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-7  3.05x     2.56x      14.6G   12.8T     15.5T

Статистика после заполнения 365-го дня:

df -i /time_machine
Filesystem          Inodes     IUsed       IFree IUse% Mounted on
time_machine   52350051528 118689584 52231361944    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   42062128MB 15319671MB 26742458MB  37% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  31.9T  26.1T         -    41%    54%  1.00x  ONLINE  -
  dm-name-x136all36-share    58T  31.9T  26.1T         -    41%    54%
cache      -      -      -         -      -      -
  l2arc   145G  14.7G   130G         -     0%    10%

zfs list time_machine -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-7  3.05x     2.54x      17.1G   13.9T     17.9T

Статистика после заполнения 512-го дня:

df -i /time_machine
Filesystem          Inodes     IUsed       IFree IUse% Mounted on
time_machine   31871545123 123555195 31747989928    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
time_machine   31505671MB 15250700MB 16254971MB  49% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
time_machine    58T  41.4T  16.6T         -    54%    71%  1.00x  ONLINE  -
  dm-name-x136all36-share    58T  41.4T  16.6T         -    54%    71%
cache      -      -      -         -      -      -
  l2arc   145G  16.0G   129G         -     0%    11%

zfs list time_machine -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-7  3.10x     2.58x      25.2G   13.9T     27.5T

Предварительный итог: zfs без дедупликации ненастроенный со сжатием gzip-7, без файлов копирования файлов размером более 100ГБ, rsync в режиме --inplace, с 20140801 по 20151217 (503 дня)

Несколько часов что-то делал без видимого результата (не было ввода/вывода, rngd + txg_sync + z_null_iss + txg_quiesce + rsync). Убийство rsync не помогло, второй rsync не убился. Неожиданно помогла попытка размонтировать файловую систему ("zfs unmount time_machine", не "umount /time_machine"): размонтировать отказался, но "плохое место" проскочил (а может просто совпало? дважды, но на третий раз пришлось убить rsync, размонтировать, смонтировать и перезапустить задачи вручную). На следующем витке не повторилось, т.е. проблема возникает из-за сочетания обстоятельств.

Выделенный сервер архива с дедупликацией

Выделенный сервер архива с дедупликацией: 12 ядер по 3.5GHz, 80 ГиБ ОП, сеть 1Gbps, локальный массив среднего размера (LSI MEGARAID RAID-6 of 15 HDD SFF 1800GB 10k rpm).

Параметры модуля spl (/etc/modprobe.d/spl.conf): отсутствуют.

Параметры модуля zfs (/etc/modprobe.d/zfs.conf): отсутствуют.

Создание пула (надо было xattr=sa и без utf8only, выше gzip-8 не тянет, вместе с relatime надо включать atime, checksum лучше делать sha256):

zpool create -f -m /time_machine -o ashift=12 \
-d -o feature@async_destroy=enabled -o feature@empty_bpobj=enabled -o feature@lz4_compress=enabled -o feature@spacemap_histogram=enabled -o feature@extensible_dataset=enabled -o feature@bookmarks=enabled -o feature@enabled_txg=enabled -o feature@embedded_data=enabled -o feature@large_blocks=enabled \
-O utf8only=on \
-O compression=gzip-8 \
-O atime=off -O relatime=on \
-O acltype=posixacl -O xattr=on \
-O dedup=on \
-O redundant_metadata=most \
-O sync=disabled -O logbias=throughput \
-O snapdir=visible \
-O recordsize=1048576 \
tm_small scsi-3600605b008ca05c01fc0c51340366923 cache /dev/system/l2arc

Наполнение архива с помощью rsync (40 потоков, "--max-size=100GB -vas --inplace --numeric-ids --ignore-errors --delete").

Статистика блоков (в самом начале):

zdb -L -b tm_small

3.74T completed (1014MB/s) estimated time remaining: 46259hr 54min 49sec        4294967241sec
        bp count:       113034474
        ganged count:           0
        bp logical:    9842270394880      avg:  87073
        bp physical:   3968674195968      avg:  35110     compression:   2.48
        bp allocated:  4115137540096      avg:  36406     compression:   2.39
        bp deduped:    953664348160    ref>1: 8947494   deduplication:   1.23
        SPA allocated: 3161473191936     used: 13.53%

        additional, non-pointer bps of type 0:    5667515
        Dittoed blocks on same vdev: 5681636

Статистика после заполнения первого дня (большая фрагментация свободного пространства):

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       26910345944 76876211 26833469733    1% /time_machine

df -B G /time_machine
Filesystem     1G-blocks   Used Available Use% Mounted on
tm_small          23363G 10568G    12796G  46% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  8.02T  13.2T         -    44%    37%  1.30x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  8.02T  13.2T         -    44%    37%
cache      -      -      -         -      -      -
  l2arc   300G   202G  97.8G         -     0%    67%

zfs  list -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbyrefreservation,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDREFRESERV  USEDSNAP
  gzip-8  2.56x     2.56x      79.4G   10.3T              0         0

zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
tm_small  10.4T  12.5T  10.3T  /time_machine

Статистика после заполнения 6-го дня:

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       25355323516 77948660 25277374856    1% /time_machine

df -B G /time_machine
Filesystem     1G-blocks   Used Available Use% Mounted on
tm_small          23334G 11281G    12054G  49% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  8.74T  12.5T         -    48%    41%  1.29x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  8.74T  12.5T         -    48%    41%
cache      -      -      -         -      -      -
  l2arc   300G   143G   157G         -     0%    47%

zfs  list -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbyrefreservation,usedbysnapshots tm_small
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDREFRESERV  USEDSNAP
  gzip-8  2.66x     2.63x      91.8G   11.0T              0      157G

zfs list
NAME                USED  AVAIL  REFER  MOUNTPOINT
tm_small           11.3T  11.8T  11.0T  /time_machine
tm_small@20140801  15.8G      -  10.3T  -
tm_small@20140802  3.50G      -  10.9T  -
tm_small@20140803  2.44G      -  10.9T  -
tm_small@20140804   623M      -  10.9T  -
tm_small@20140805  43.1G      -  11.1T  -

Статистика дедупликации:

zpool status -D

dedup: DDT entries 188783133, size 458 on disk, 148 in core

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1     148M   17.3T   7.61T   7.63T     148M   17.3T   7.61T   7.63T
     2    25.5M   2.89T    954G    958G    55.6M   6.26T   2.01T   2.02T
     4    4.95M    528G    144G    145G    23.7M   2.45T    669G    676G
     8    1.21M    110G   25.2G   25.9G    12.4M   1.11T    256G    262G
    16     437K   37.7G   8.54G   8.77G    9.26M    822G    188G    192G
    32     141K   11.5G   2.18G   2.27G    5.90M    487G   92.0G   96.0G
    64    45.2K   2.69G    600M    644M    3.80M    227G   50.6G   54.4G
   128    19.8K    841M    282M    304M    3.37M    144G   47.9G   51.6G
   256    14.7K    744M    456M    471M    4.94M    247G    153G    158G
   512    5.57K    198M   57.3M   62.9M    3.68M    128G   34.6G   38.5G
    1K    1.93K    127M   35.7M   37.4M    2.44M    151G   43.3G   45.5G
    2K      584   44.5M   21.0M   21.5M    1.84M    156G   77.8G   79.3G
    4K      291   3.59M    370K   1.14M    1.68M   19.1G   2.00G   6.73G
    8K       79   2.40M    148K    316K     935K   34.1G   1.87G   3.65G
   16K       35   1.65M     73K    140K     710K   28.6G   1.31G   2.77G
   32K       37   2.29M     98K    148K    1.68M    118G   4.80G   6.71G
   64K       10    337K   29.5K     40K     889K   28.2G   2.66G   3.47G
  128K       24   2.50M     82K     96K    4.65M    516G   16.4G   18.6G
  256K        4      2K      2K     16K    1.58M    811M    811M   6.34G
  512K        1     512     512      4K     649K    324M    324M   2.53G
    1M        1    128K      4K      4K    1.35M    173G   5.40G   5.40G
    2M        1     512     512      4K    2.76M   1.38G   1.38G   11.1G
 Total     180M   20.9T   8.72T   8.74T     291M   30.3T   11.2T   11.3T

Статистика после заполнения 33-го дня (чудовищная фрагментация свободного места):

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       21932741784 79019953 21853721831    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       23833665MB 12644559MB 11189106MB  54% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  10.3T  10.9T         -    58%    48%  1.30x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  10.3T  10.9T         -    58%    48%
cache      -      -      -         -      -      -
  l2arc   300G   182G   118G         -     0%    60%

zfs list tm_small -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-8  2.79x     2.66x       129G   11.5T     1.74T

zfs list|head -4;zfs list |tail -4
NAME                USED  AVAIL  REFER  MOUNTPOINT
tm_small           13.4T  10.2T  11.5T  /time_machine
tm_small@20140801  15.8G      -  10.3T  -
tm_small@20140802  3.50G      -  10.9T  -
tm_small@20140831   174M      -  11.5T  -
tm_small@20140901  2.74G      -  11.5T  -
tm_small@20140902  20.9G      -  11.5T  -
tm_small@20140903   216M      -  11.5T  -

Тест прерван в пользу улучшенного варианта.

Выделенный сервер архива с дедупликацией настроенный

Выделенный сервер архива с дедупликацией: 12 ядер по 3.5GHz, 80 ГиБ ОП, сеть 1Gbps, локальный массив среднего размера (LSI MEGARAID RAID-6 of 15 HDD SFF 1800GB 10k rpm).

2048 в /proc/sys/kernel/random/read_wakeup_threshold (или "kernel.random.read_wakeup_threshold = 2048" в /etc/sysctl.conf).

Параметры модуля spl (/etc/modprobe.d/spl.conf): отсутствуют.

Параметры модуля zfs (/etc/modprobe.d/zfs.conf):

options zfs zfs_autoimport_disable=0
options zfs spa_asize_inflation=3 # нет зеркал/raid и никаких дополнительных копий, кроме метаданных (most)
#options zfs spa_slop_shift=6
options zfs metaslab_lba_weighting_enabled=0
options zfs zio_taskq_batch_pct=85 # больше не надо
options zfs_txg_timeout=30
options zfs zfs_nocacheflush=1
options zfs zfs_arc_max=60000000000
#options zfs zfs_arc_max=77309411328
#options zfs zfs_arc_meta_limit=?
options zfs zfs_arc_average_blocksize=32768 # можно 65536
#options zfs zfs_arc_lotsfree_percent=5
#options zfs zvol_inhibit_dev=1
#options zfs zfs_admin_snapshot=1

Создание пула (bin/zfsdedup.sh, вместе с relatime надо включать atime, checksum лучше делать sha256, составное LVM устройство в режиме RAID-0 разобрать):

zpool create -f -m /time_machine -o ashift=12 \
-d -o feature@async_destroy=enabled -o feature@empty_bpobj=enabled -o feature@lz4_compress=enabled -o feature@spacemap_histogram=enabled -o feature@extensible_dataset=enabled -o feature@bookmarks=enabled -o feature@enabled_txg=enabled -o feature@embedded_data=enabled -o feature@large_blocks=enabled \
-O compression=gzip-8 \
-O atime=off -O relatime=off \
-O acltype=posixacl -O xattr=sa \
-O dedup=on \
-O redundant_metadata=most \
-O sync=disabled -O logbias=throughput \
-O snapdir=visible \
-O recordsize=1048576 \
-O secondarycache=metadata \
tm_small scsi-3600605b008ca05c01fc0c51340366923 cache /dev/system/l2arc

mkdir /time_machine/{colddata,raid,share4h,share4s,share4x,share5c,xeon01,xeon04}

Наполнение архива с помощью rsync (20 потоков, "--max-size=100GB -vas --inplace --numeric-ids --ignore-errors --delete").

Статистика после начального заполнения первого дня:

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       27371887339 76877617 27295009722    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       24948903MB 10973859MB 13975045MB  44% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  7.81T  13.4T         -    30%    36%  1.28x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  7.81T  13.4T         -    30%    36%
cache      -      -      -         -      -      -
  l2arc   300G   240G  60.5G         -     0%    79%

zfs list tm_small -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-8  2.70x     2.70x      19.0G   9.98T         0

zfs list|head -4;zfs list |tail -4
NAME       USED  AVAIL  REFER  MOUNTPOINT
tm_small  10.0T  12.7T  9.98T  /time_machine

Статистика дедупликации после начального заполнения первого дня:

zpool status -D
 dedup: DDT entries 34317141, size 481 on disk, 155 in core

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1    25.6M   15.4T   6.80T   6.82T    25.6M   15.4T   6.80T   6.82T
     2    5.04M   2.38T    785G    789G    11.1M   5.15T   1.66T   1.66T
     4    1.37M    477G    125G    127G    6.72M   2.22T    582G    589G
     8     480K    104G   21.2G   21.8G    4.79M   1.05T    216G    222G
    16     179K   34.6G   7.16G   7.37G    3.77M    757G    158G    162G
    32    62.2K   10.2G   1.79G   1.88G    2.65M    433G   75.6G   79.5G
    64    28.6K   2.12G    507M    551M    2.45M    187G   43.1G   46.9G
   128    14.7K    762M    213M    233M    2.53M    129G   34.2G   37.8G
   256    9.93K    731M    447M    462M    3.39M    245G    149G    155G
   512    4.51K    194M   53.6M   59.1M    2.98M    123G   31.9G   35.7G
    1K    1.06K    119M   32.7M   34.3M    1.41M    152G   39.5G   41.7G
    2K      279   48.2M   20.3M   20.9M     800K    159G   75.5G   77.0G
    4K      283   18.4M    344K   1.11M    1.64M    107G   1.89G   6.59G
    8K       59   2.13M     76K    236K     660K   25.9G    886M   2.58G
   16K       35   12.0M   69.5K    140K     712K    219G   1.28G   2.78G
   32K       25   7.04M   53.5K    100K     997K    250G   2.10G   3.89G
   64K        9   1.08M   25.5K     36K     848K    133G   2.50G   3.31G
  128K        5   2.50K   2.50K     20K     880K    440M    440M   3.44G
  256K        3   1.50K   1.50K     12K    1.31M    670M    670M   5.24G
  512K        1     512     512      4K     642K    321M    321M   2.51G
    2M        1     512     512      4K    2.72M   1.36G   1.36G   10.9G
 Total    32.7M   18.3T   7.72T   7.74T    78.5M   26.6T   9.84T   9.93T

Статистика блоков после начального заполнения первого дня:

zdb -L -b tm_small

Traversing all blocks ...

10.1T completed (2399MB/s) estimated time remaining: 4294617589hr 00min 4294967252sec
        bp count:       103252048
        ganged count:           0
        bp logical:    29739547317760      avg: 288028
        bp physical:   10967514414592      avg: 106220     compression:   2.71
        bp allocated:  11117812854784      avg: 107676     compression:   2.67
        bp deduped:    2427436392448    ref>1: 7569740   deduplication:   1.22
        SPA allocated: 8690376462336     used: 37.19%

        additional, non-pointer bps of type 0:   11884845
        Dittoed blocks on same vdev: 7125171

Статистика после заполнения 33-го дня (по сравнению с первым вариантом: дедупликация меньше и сжатие больше - места на 3% меньше, фрагментация значительно лучше):

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       22709829244 79029191 22630800053    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       23801210MB 12214241MB 11586970MB  52% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  9.96T  11.3T         -    38%    46%  1.28x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  9.96T  11.3T         -    38%    46%
cache      -      -      -         -      -      -
  l2arc   300G   200G  99.7G         -     0%    66%

zfs list tm_small -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-8  2.95x     2.79x      23.3G   11.1T     1.63T

zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
tm_small  12.8T  10.5T  11.1T  /time_machine

zfs list -t snapshot|head -4;zfs list -t snapshot |tail -4
NAME                USED  AVAIL  REFER  MOUNTPOINT
tm_small@20140801  15.1G      -  9.98T  -
tm_small@20140802  3.15G      -  10.5T  -
tm_small@20140803  2.24G      -  10.6T  -
tm_small@20140831   164M      -  11.1T  -
tm_small@20140901  2.70G      -  11.1T  -
tm_small@20140902  19.4G      -  11.1T  -
tm_small@20140903  37.2M      -  11.1T  -

Статистика дедупликации после заполнения 33-го дня:

zpool status -D

 dedup: DDT entries 43561002, size 440 on disk, 142 in core

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1    32.8M   21.5T   8.63T   8.65T    32.8M   21.5T   8.63T   8.65T
     2    6.26M   3.47T   1.04T   1.04T    13.8M   7.61T   2.25T   2.26T
     4    1.62M    663G    158G    160G    7.99M   3.09T    742G    750G
     8     544K    136G   26.7G   27.4G    5.44M   1.36T    275G    282G
    16     206K   50.8G   9.77G   10.0G    4.32M   1.07T    212G    218G
    32    69.9K   13.3G   2.13G   2.23G    2.94M    562G   89.6G   93.9G
    64    31.7K   3.22G    578M    623M    2.64M    261G   46.5G   50.3G
   128    16.2K   1.07G    273M    295M    2.85M    185G   46.1G   50.0G
   256    10.2K    838M    435M    450M    3.54M    288G    156G    161G
   512    5.76K    238M   75.0M   82.5M    3.84M    157G   46.3G   51.4G
    1K    1.22K    125M   34.5M   36.4M    1.62M    162G   42.7G   45.2G
    2K      317   49.0M   20.4M   21.0M     892K    161G   75.7G   77.3G
    4K      282   18.6M    383K   1.16M    1.70M    110G   2.08G   7.03G
    8K       83   2.21M    134K    332K     905K   27.9G   1.45G   3.53G
   16K       32   12.0M   71.5K    128K     678K    265G   1.49G   2.65G
   32K       30   7.04M     56K    120K    1.26M    300G   2.47G   5.04G
   64K        7     77K   17.5K     28K     641K   8.68G   1.65G   2.50G
  128K        6   1.01M     10K     24K    1.03M    234G   1.78G   4.12G
  256K        3   1.50K   1.50K     12K    1.17M    601M    601M   4.69G
  512K        2      1K      1K      8K    1.19M    608M    608M   4.75G
    2M        1     512     512      4K    2.87M   1.43G   1.43G   11.5G
 Total    41.5M   25.8T   9.86T   9.88T    94.1M   37.3T   12.6T   12.7T

Статистика блоков после заполнения 33-го дня:

zdb -L -b tm_small

Traversing all blocks ...

12.8T completed (2008MB/s) estimated time remaining: 46981hr 05min 41sec        4294967256sec
        bp count:       121664603
        ganged count:           0
        bp logical:    41122740267008      avg: 338000
        bp physical:   13873447785984      avg: 114030     compression:   2.96
        bp allocated:  14041409785856      avg: 115410     compression:   2.93
        bp deduped:    3083509776384    ref>1: 9173591   deduplication:   1.22
        SPA allocated: 10957900009472     used: 46.90%

        additional, non-pointer bps of type 0:   12900459
        Dittoed blocks on same vdev: 8499054

Статистика после заполнения 105-го дня (фрагментация свободного места ещё терпимая, коэффициент сжатия поражает):

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       17950274179 83943603 17866330576    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       22458963MB 13311402MB 9147562MB  60% /time_machine

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  12.2T  9.09T         -    47%    57%  1.28x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  12.2T  9.09T         -    47%    57%
cache      -      -      -         -      -      -
  l2arc   300G   202G  97.9G         -     0%    67%

zfs list tm_small -o compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
  gzip-8  3.10x     2.81x      33.1G   12.1T     3.47T

zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
tm_small  15.6T  8.32T  12.1T  /time_machine

Тестирование чтения привычным tarnull_all_common.sh базового снимка в момент 120 снимка:

Тестирование чтения привычным tarnull_all_common.sh снимка 120 (20141130):

Передача накопленного (gzip-1 для скорости - 1.23 TB/час - 342 MB/s, постепенно снижается до 300 MB/s):

# осторожно с памятью!
zfs set primarycache=metadata tm_small
zfs set secondarycache=metadata tm_small
zpool remove tm_small /dev/system/l2arc

zpool create -f -m /tm_tiny -o ashift=12 \
-d -o feature@async_destroy=enabled -o feature@empty_bpobj=enabled -o feature@lz4_compress=enabled -o feature@spacemap_histogram=enabled -o feature@extensible_dataset=enabled -o feature@bookmarks=enabled -o feature@enabled_txg=enabled -o feature@embedded_data=enabled -o feature@large_blocks=enabled \
-O compression=gzip-1 \
-O atime=off -O relatime=off \
-O acltype=posixacl -O xattr=sa \
-O dedup=on \
-O redundant_metadata=most \
-O sync=disabled -O logbias=throughput \
-O snapdir=visible \
-O recordsize=1048576 \
-O secondarycache=metadata \
tm_tiny wwn-1 wwn-2 cache /dev/system/l2arc

zfs set primarycache=metadata tm_tiny
zfs set secondarycache=metadata tm_tiny

zfs send -R -Le -v tm_small@20140815 | zfs receive -vd -F tm_tiny

send from @ to tm_small@20140801 estimated size is 26.6T
send from @20140801 to tm_small@20140802 estimated size is 2.22T
...
send from @20140814 to tm_small@20140815 estimated size is 368G
total estimated size is 33.3T

receiving full stream of tm_small@20140801 into tm_tiny@20140801
TIME        SENT   SNAPSHOT
22:42:31    614K   tm_small@20140801 # исходных до сжатия?
...

zpool list -v

NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  13.2T  8.04T         -    51%    62%  1.28x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  13.2T  8.04T         -    51%    62%
tm_tiny  9.88T  4.85T  5.03T         -    43%    49%  1.33x  ONLINE  -
  wwn-0x600605b008ca0500ff00978d08a70a6a  4.91T  2.42T  2.49T         -    42%    49%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  2.43T  2.54T         -    44%    48%
cache      -      -      -         -      -      -
  l2arc   300G  6.09G   294G         -     0%     2%

zfs list tm_small tm_tiny -o name,compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots

NAME      COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_small    gzip-8  3.12x     2.83x      37.5G   11.8T     5.10T
tm_tiny     gzip-1  2.40x     1.00x      6.46T     96K         0

zfs list

NAME       USED  AVAIL  REFER  MOUNTPOINT
tm_small  16.9T  7.26T  11.8T  /time_machine
tm_tiny   6.46T  4.67T    96K  /tm_tiny

В процессе тестирования попытался подключить ("zpool add -o ashift=12 tm_tiny dm-name-mpaths209") старенький iSCSI SAN HP StorageWorks MSA 2012i (при сжатии lz4 не хватило места), получил завал по записи и (igb - драйвер сетевой карты):

Jan 25 03:27:03 x142 kernel: BUG: Bad page state in process swapper/4  pfn:117940c
Jan 25 03:27:03 x142 kernel: page:ffffea0045e50300 count:0 mapcount:-1 mapping:          (null) index:0x0
Jan 25 03:27:03 x142 kernel: page flags: 0x6fffff00008000(tail)
Jan 25 03:27:03 x142 kernel: page dumped because: nonzero mapcount
Jan 25 03:27:03 x142 kernel: Call Trace:
Jan 25 03:27:03 x142 kernel:   [] dump_stack+0x19/0x1b
Jan 25 03:27:03 x142 kernel: [] bad_page.part.59+0xdf/0xfc
Jan 25 03:27:03 x142 kernel: [] free_pages_prepare+0x16d/0x190
Jan 25 03:27:03 x142 kernel: [] free_compound_page+0x29/0x40
Jan 25 03:27:03 x142 kernel: [] __put_compound_page+0x1f/0x30
Jan 25 03:27:03 x142 kernel: [] put_compound_page+0x145/0x170 
...
Jan 25 03:32:15 x142 kernel: BUG: Bad page state in process z_rd_int_6  pfn:faca0c
Jan 25 03:32:15 x142 kernel: page:ffffea003eb28300 count:0 mapcount:-1 mapping:          (null) index:0x0
Jan 25 03:32:15 x142 kernel: page flags: 0x6fffff00008000(tail)
Jan 25 03:32:15 x142 kernel: page dumped because: nonzero mapcount
Jan 25 03:32:15 x142 kernel:   [] dump_stack+0x19/0x1b
Jan 25 03:32:15 x142 kernel: [] bad_page.part.59+0xdf/0xfc
Jan 25 03:32:15 x142 kernel: [] free_pages_prepare+0x16d/0x190
Jan 25 03:32:15 x142 kernel: [] free_compound_page+0x29/0x40
Jan 25 03:32:15 x142 kernel: [] __put_compound_page+0x1f/0x30
Jan 25 03:32:15 x142 kernel: [] put_compound_page+0x145/0x170
Jan 25 03:32:15 x142 kernel: [] put_page+0x2c/0x40
Jan 25 03:32:15 x142 kernel: [] skb_release_data+0x88/0x110
Jan 25 03:32:15 x142 kernel: [] skb_release_all+0x24/0x30
Jan 25 03:32:15 x142 kernel: [] consume_skb+0x2c/0x80
Jan 25 03:32:15 x142 kernel: [] __dev_kfree_skb_any+0x3d/0x50
Jan 25 03:32:15 x142 kernel: [] igb_poll+0xe6/0x770 [igb] 
При этом счётчик переданных байт застыл на 4.33TB, mpaths209 имеет 100% загрузки на случайной записи, "zpool destroy tm_tiny" не остановил случайную запись.

Оказалось, что приёмник нельзя трогать до окончания передачи. Запустил заново с gzip-2 (примерно 1 ТБ/час или 293 МБ/сек).

zfs send -R -Le -v tm_small@20140811 | zfs receive -vd -F tm_tiny
send from @ to tm_small@20140801 estimated size is 26.6T
send from @20140801 to tm_small@20140802 estimated size is 2.22T
send from @20140802 to tm_small@20140803 estimated size is 176G
send from @20140803 to tm_small@20140804 estimated size is 72.9G
send from @20140804 to tm_small@20140805 estimated size is 742G
send from @20140805 to tm_small@20140806 estimated size is 295G
send from @20140806 to tm_small@20140807 estimated size is 204G
send from @20140807 to tm_small@20140808 estimated size is 387G
send from @20140808 to tm_small@20140809 estimated size is 920G
send from @20140809 to tm_small@20140810 estimated size is 47.3G
send from @20140810 to tm_small@20140811 estimated size is 50.6G
total estimated size is 31.7T
...
zfs send -Le -v  -I tm_small@20140811 tm_small@20140813 | zfs receive -vd -F tm_tiny
send from @20140811 to tm_small@20140812 estimated size is 238G
send from @20140812 to tm_small@20140813 estimated size is 725G
total estimated size is 963G
would receive incremental stream of tm_small@20140812 into tm_tiny@20140812
TIME        SENT   SNAPSHOT
16:51:12   1013M   tm_small@20140812
...
received 725GB stream in 2971 seconds (250MB/sec)

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  21.2T  13.2T  8.04T         -    51%    62%  1.28x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  13.2T  8.04T         -    51%    62%
tm_tiny  9.88T  9.43T   456G         -    81%    95%  1.28x  ONLINE  -
  wwn-0x600605b008ca0500ff00978d08a70a6a  4.91T  4.69T   220G         -    83%    95%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  4.74T   236G         -    80%    95%
cache      -      -      -         -      -      -
  l2arc   300G  8.73G   291G         -     0%     2%

zfs list tm_small tm_tiny -o name,used,avail,refer,compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
NAME       USED  AVAIL  REFER  COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_small  16.9T  7.65T  11.8T    gzip-8  3.12x     2.83x      37.5G   11.8T     5.10T
tm_tiny   12.1T   255G  11.3T    gzip-2  2.72x     2.67x      20.2G   11.3T      808G

zfs send -Le -v  -I tm_small@20140813 tm_small@20140814 | zfs receive  -vd -F tm_tiny
...
received 306GB stream in 1667 seconds (188MB/sec)

zfs send -Le -v  -I tm_small@20140814 tm_small@20140815 | zfs receive  -vd -F tm_tiny
send from @20140814 to tm_small@20140815 estimated size is 368G
total estimated size is 368G
receiving incremental stream of tm_small@20140815 into tm_tiny@20140815
...
received 368GB stream in 1277 seconds (295MB/sec)

zfs send -Le -v  -I tm_small@20140815 tm_small@20140816 | zfs receive  -vd -F tm_tiny
send from @20140815 to tm_small@20140816 estimated size is 560G
total estimated size is 560G
receiving incremental stream of tm_small@20140816 into tm_tiny@20140816
...
21:48:17    492G   tm_small@20140816
cannot receive incremental stream: out of space
warning: cannot send 'tm_small@20140816': Broken pipe

автоматический откат на последний успешный снимок

Попробовал писать в переполненный пул

NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_tiny  9.88T  9.56T   326G         -    71%    96%  1.28x  ONLINE  -
  wwn-0x600605b008ca0500ff00978d08a70a6a  4.91T  4.75T   157G         -    73%    96%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  4.80T   170G         -    70%    96%

NAME       USED  AVAIL  REFER  COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_tiny   12.3T      0  11.4T    gzip-2  2.72x     2.68x      42.3G   11.4T      799G

dd if=/dev/sda bs=1k of=/tm_tiny/share4h/test
^C

не пишет и не снимается

ls -ld /tm_tiny/share4h
^C^C

kill -9 не помогает

zfs umount -f /tm_tiny
umount: /tm_tiny: target is busy.

отвисла, когда прекратил активную работу с другим пулом 

На одном из тестовых серверов (на котором меньше ОП - 64ГиБ, но больше пул - 64ТБ) проявилась проблема - жёсткая нехватка памяти (80% в cache), arc_reclaim потребляет 100% CPU, но не успевает освободить (фрагментированность?), попытки понять и попбороть:

В порыве борьбы за память: metadata в primarycache и secondarycache. Добавил ещё 1 виртуальный диск.

Статистика после заполнения 215-го дня:

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       17584992388 106959602 17478032786    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       22770856MB 13822104MB 8948753MB  61% /time_machine

zpool list -v
tm_small  26.2T  17.1T  9.15T         -    52%    65%  1.36x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  17.0T  4.22T         -    65%    80%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  37.2G  4.93T         -     0%     0%
cache      -      -      -         -      -      -
  l2arc   300G  14.2G   286G         -     0%     4%

zfs list tm_small -o name,used,avail,refer,compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
NAME       USED  AVAIL  REFER  COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_small  23.2T  8.14T  12.6T    gzip-8  3.19x     2.82x      51.7G   12.6T     10.6T

Статистика после заполнения 301-го дня:

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       20124719802 114330347 20010389455    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       23955499MB 13710181MB 10245319MB  58% /time_machine

zpool list -v
tm_small  30.3T  19.8T  10.5T         -    54%    65%  1.37x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  18.0T  3.22T         -    69%    84%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  1.16T  3.81T         -    25%    23%
  wwn-0x600605b008ca0500202630e6fda1c4eb  4.06T   607G  3.47T         -    13%    14%
cache      -      -      -         -      -      -
  l2arc   300G  19.2G   281G         -     0%     6%

zfs list tm_small -o name,used,avail,refer,compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
NAME       USED  AVAIL  REFER  COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_small  27.2T  9.32T  12.5T    gzip-8  3.26x     2.70x      63.3G   12.5T     14.6T

Статистика после заполнения 361-го дня:

df -i /time_machine
Filesystem          Inodes    IUsed       IFree IUse% Mounted on
tm_small       15406945432 118602991 15288342441    1% /time_machine

df -B MB /time_machine
Filesystem     1MB-blocks       Used  Available Use% Mounted on
tm_small       22466955MB 14639324MB 7827631MB  66% /time_machine

zpool list -v
tm_small  30.3T  22.0T  8.32T         -    60%    72%  1.37x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  18.7T  2.52T         -    71%    88%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  1.92T  3.05T         -    41%    38%
  wwn-0x600605b008ca0500202630e6fda1c4eb  4.06T  1.31T  2.75T         -    30%    32%
cache      -      -      -         -      -      -
  l2arc   300G  22.1G   278G         -     0%     7%

zfs list tm_small -o name,used,avail,refer,compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
NAME       USED  AVAIL  REFER  COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_small  30.1T  7.12T  13.3T    gzip-8  3.27x     2.69x      74.0G   13.3T     16.7T

Статистика после заполнения 518-го дня (место кончилось):

zpool list -v
NAME   SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tm_small  30.3T  28.9T  1.35T         -    59%    95%  1.37x  ONLINE  -
  scsi-3600605b008ca05c01fc0c51340366923  21.2T  20.8T   445G         -    56%    97%
  wwn-0x600605b008ca052020111fe9d78370c6  4.97T  4.44T   538G         -    69%    89%
  wwn-0x600605b008ca0500202630e6fda1c4eb  4.06T  3.67T   405G         -    67%    90%
cache      -      -      -         -      -      -
  l2arc   300G  26.7G   273G         -     0%     8%

zfs list tm_small -o name,used,avail,refer,compress,compressratio,refcompressratio,usedbychildren,usedbydataset,usedbysnapshots
NAME       USED  AVAIL  REFER  COMPRESS  RATIO  REFRATIO  USEDCHILD  USEDDS  USEDSNAP
tm_small  39.7T  74.5G  13.9T    gzip-8  3.33x     2.75x      86.1G   13.9T     25.7T

Статистика блоков после заполнения 518-го дня (7 часов):

zdb -L -bb tm_small
        bp count:       403056102
        ganged count:           0
        bp logical:    143683750113792      avg: 356485
        bp physical:   42932481053696      avg: 106517     compression:   3.35
        bp allocated:  43624229873152      avg: 108233     compression:   3.29
        bp deduped:    11819060480512    ref>1: 32743371   deduplication:   1.27
        SPA allocated: 31805169392640     used: 95.53%

        additional, non-pointer bps of type 0:   34730385
        Dittoed blocks on same vdev: 15595207

Blocks  LSIZE   PSIZE   ASIZE     avg    comp   %Total  Type
  284K  34.7G   8.09G   25.1G   90.5K    4.29     0.06  bpobj
 17.4M   278G   56.3G    137G   7.92K    4.94     0.34  DMU dnode
  317M   130T   39.0T   39.4T    127K    3.34    99.26  ZFS plain file
 43.4M  45.8G   12.3G   77.3G   1.78K    3.74     0.19  ZFS directory
 5.45M  21.8G   14.2G   57.8G   10.6K    1.54     0.14  DDT ZAP algorithm

Статистика дедупликации после заполнения 518-го дня (быстро)

zdb -L -DD tm_small
DDT-sha256-zap-duplicate: 32743371 entries, size 414 on disk, 150 in core
DDT-sha256-zap-unique: 110802556 entries, size 437 on disk, 160 in core

DDT histogram (aggregated over all DDTs):

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1     106M   71.3T   23.5T   23.6T     106M   71.3T   23.5T   23.6T
     2    23.6M   13.2T   4.27T   4.30T    52.0M   28.8T   9.31T   9.37T
     4    4.97M   2.17T    602G    608G    24.3M   10.4T   2.78T   2.81T
     8    1.51M    508G    120G    122G    15.3M   4.99T   1.18T   1.21T
    16     640K    140G   28.9G   29.9G    13.3M   2.94T    625G    646G
    32     249K   60.5G   9.48G   9.90G    10.4M   2.55T    402G    420G
    64     101K   17.1G   2.07G   2.21G    8.75M   1.43T    176G    189G
   128    63.5K   10.7G   1020M   1.08G    11.0M   1.90T    186G    200G
   256    48.2K   4.20G    824M    881M    17.0M   1.47T    308G    329G
   512    17.4K   2.65G    354M    388M    12.8M   1.82T    252G    277G
    1K    7.69K    468M    112M    124M    10.1M    609G    149G    166G
    2K    1.56K    167M   36.8M   40.3M    4.12M    489G    120G    129G
    4K      353   7.22M   1.67M   2.57M    1.79M   40.9G   8.43G   13.1G
    8K      401   41.9M    590K   1.61M    4.59M    509G   6.45G   18.7G
   16K      128   14.3M    216K    506K    2.73M    324G   4.56G   10.8G
   32K       57   9.10M   72.5K    228K    2.49M    457G   3.27G   9.97G
   64K       21   41.5K     29K     84K    1.69M   3.20G   2.27G   6.75G
  128K       11    112K     16K     44K    1.92M   19.1G   2.96G   7.70G
  256K        5   1.00M      6K     20K    1.75M    259G   1.75G   6.98G
  512K        4      2K      2K     16K    2.78M   1.39G   1.39G   11.1G
    1M        2      1K      1K      8K    2.69M   1.35G   1.35G   10.8G
    4M        1     512     512      4K    4.96M   2.48G   2.48G   19.8G
 Total     137M   87.4T   28.5T   28.6T     312M    130T   38.9T   39.4T

dedup = 1.38, compress = 3.34, copies = 1.01, dedup * compress / copies = 4.55

Тестирование чтения привычным tarnull_all_common.sh базового снимка в момент 518 снимка (l2arc_noprefetch=1, zfs_prefetch_disable=0, primarycache=metadata, secondarycache=metadata - для чтения это оказалось плохо):

Тестирование чтения привычным tarnull_all_common.sh базового снимка в момент 518 снимка (l2arc_noprefetch=0, zfs_dedup_prefetch=1, primarycache=all, secondarycache=all)

Тестирование чтения привычным tarnull_all_common.sh последнего снимка (20151231) (l2arc_noprefetch=0, zfs_dedup_prefetch=1, primarycache=all, secondarycache=all, задействованы 3 vdev)

Итог тестирования компактности: zfs с дедупликацией настроенный со сжатием gzip-8, без копирования файлов размером более 100ГБ, rsync в режиме --inplace, с 1 августа 2014 по 31 декабря 2015 (518 день)

Передача по сети (предусмотреть - screen, iptables):

Измерение скорости send в /dev/null (разжимается перед передачей):

time zfs send -R -Le  tm_small@20151231 | dd bs=1024k > /dev/null # статистика zfs двоичная, dd - десятичная
send from @ to tm_small@20140801 estimated size is 26.6T
send from @20140801 to tm_small@20140802 estimated size is 2.22T
send from @20140802 to tm_small@20140803 estimated size is 176G
...
send from @20151230 to tm_small@20151231 estimated size is 163G
total estimated size is 130T

143709025174440 bytes (144 TB) copied, 139968 s, 1.0 GB/s

Измерение скорости send в /dev/null без разжимания (0.7.0-rc3, возврат на 0.6.9 прошёл без проблем)

time zfs send -R -Le -c tm_small@20151231 | dd bs=1024k > /dev/null # статистика zfs двоичная, dd - десятичная
full send of tm_small@20140801 estimated size is 9.86T
send from @20140801 to tm_small@20140802 estimated size is 590G
...
send from @20151230 to tm_small@20151231 estimated size is 33.9G
total estimated size is 39.0T

43369814706360 bytes (43 TB) copied, 92704.8 s, 468 MB/s

Реальная пересылка без разжимания:

# разведка
time zfs send -n -v -R -p -Le -c time_machine@20170326
full send of time_machine@20140901 estimated size is 11.1T
send from @20140901 to time_machine@20140902 estimated size is 49.0G
...
send from @20170325 to time_machine@20170326 estimated size is 12.7G
total estimated size is 82.0T

# оценка
time zfs send -R -p -Le -c time_machine@20170326 | dd bs=1024k > /dev/null # статистика zfs двоичная, dd - десятичная
670009514760 bytes (670 GB) copied, 1302.84 s, 514 MB/s

ncat -l порт | dd bs=1024k | zfs receive -vd -F time_machine
time zfs send -R -p -Le -c time_machine@20170326 | ncat хост порт

receiving incremental stream of time_machine@20170326 into time_machine@20170326
91080262204792 bytes (91 TB) copied, 371889 s, 245 MB/s

# накопившиеся за время пересылки остатки
zfs send -p  -Le -c -I time_machine@20170326  time_machine@20170331 | ncat хост порт

Сравнение сжатия на подмножестве share4x/[a-c]* 20160101-20160304 (~10% по файлам, объёму и времени):

В связи с проблемами в реализации дельта алгоритма в rsync в режиме "--inplace" попробовал отключить его ("--whole-file --inplace") и оценить разницу на небольшом подмножестве (share4x/a[a-l]*:20160101-20160131, 1.5TB), gzip-1, итог: в 1.5 раза быстрее, место примерно столько же за счёт увеличения коэффициента дедупликации ("--whole-file" отличается от "--whole-file --inplace"):

--inplace, 10 часов на изменения

   tm_tiny  dedupratio                  1.38x
   tm_tiny  allocated                   401313722368
   tm_tiny           used                  552812175360
   tm_tiny           referenced            426534752256
   tm_tiny           compressratio         3.85x
   tm_tiny           usedbysnapshots       125003440128           -
   tm_tiny           usedbydataset         426534752256           -
   tm_tiny           usedbychildren        1273982976             -

zfs rollback -R tm_tiny@20160101
--whole-file --inplace, 6.5 часов на изменения

   tm_tiny  dedupratio                  1.43x                       -
   tm_tiny  allocated                   401376501760                -
   tm_tiny           used                  573943959552           -
   tm_tiny           referenced            426534752256           -
   tm_tiny           compressratio         4.18x                  -
   tm_tiny           usedbysnapshots       146084622336           -
   tm_tiny           usedbydataset         426534752256           -
   tm_tiny           usedbychildren        1324584960   

Попробовал rsync 3.1.1 на том же подмножестве, gzip-1, итог: стало быстрее чем в 3.0, но медленнее, чем с --whole-file, --preallocate выигрыша в месте не даёт:

--preallocate и --inplace без --whole-file, 7 часов 45 мин
   tm_tiny  dedupratio                  1.38x
   tm_tiny  allocated                   401245483008
   tm_tiny           used                  552747048960
   tm_tiny           referenced            426536271872
   tm_tiny           compressratio         3.85x
   tm_tiny           usedbysnapshots       125001945088           -
   tm_tiny           usedbydataset         426536271872           -
   tm_tiny           usedbychildren        1208832000  

zdb -L -b tm_tiny
        bp count:         6923504
        ganged count:           0
        bp logical:    2094598171136      avg: 302534
        bp physical:   542733561344      avg:  78390     compression:   3.86
        bp allocated:  552747257856      avg:  79836     compression:   3.79
        bp deduped:    151501774848    ref>1: 372618   deduplication:   1.27
        SPA allocated: 401245483008     used:  4.05%

        additional, non-pointer bps of type 0:     892290
        Dittoed blocks on same vdev: 622766

Статистика по [почти] всему массиву данных при тестовом восстановлении (compression=lz4, dedup=on):

zfs get compressratio,logicalused;zpool get dedupratio restore
NAME     PROPERTY       VALUE  SOURCE
restore  compressratio  2.32x  -
restore  logicalused    67.9T  -
NAME     PROPERTY    VALUE  SOURCE
restore  dedupratio  1.38x  -

Статистика по time_machine (compression=gzip-6, dedup=on, 1691 снимок):

NAME                   PROPERTY       VALUE  SOURCE
time_machine           compressratio  3.30x  -
time_machine           logicalused    696T
NAME          PROPERTY    VALUE  SOURCE
time_machine  dedupratio  1.49x  -

Выделенный сервер архива с дедупликацией, версия 3

Время идёт, появляются новые возможности, выявляются недостатки. Например, нельзя исключить "вредные" файлы из экспорта потребителям. Выделенный сервер архива с дедупликацией: CentOS 7.9, zfs 2.1.7, 8 ядер по 3.5GHz, 128 ГиБ ОП, сеть 2x10 Gbps, локальный массив среднего размера (LSI MEGARAID RAID-6 of 18 HDD LFF 10 TB 7200 rpm и RAID-6 of 8 HDD LFF 10 TB 7200 rpm).

Параметры модуля spl (/etc/modprobe.d/spl.conf): отсутствуют.

Параметры модуля zfs (/etc/modprobe.d/zfs.conf):

# большой архив (300ТБ) с дедупликацией

options zfs zfs_max_recordsize=16777216

# пусть импортирует из кеша
options zfs zfs_autoimport_disable=1
# для исследования
options zfs spa_load_print_vdev_tree=1
# от греха подальше
options zfs ignore_hole_birth=1
# выделение свободного места
options zfs metaslab_lba_weighting_enabled=0
options zfs spa_asize_inflation=3
#options zfs spa_slop_shift=6
options zfs spa_slop_shift=7
# архиву больше заняться нечем
options zfs zio_taskq_batch_pct=85
# потеря части наливаемых данных не страшна
options zfs zfs_txg_timeout=30
options zfs zfs_nocacheflush=1
options zfs zil_nocacheflush=1
# глубина очереди на MegaRAID и SSD может быть больше
options zfs zfs_vdev_async_write_max_active=16
options zfs zfs_vdev_async_write_min_active=4
# всю память под кеш!
#options zfs zfs_arc_max=80000000000
options zfs zfs_arc_max=40000000000
options zfs zfs_arc_meta_limit_percent=100
options zfs zfs_arc_average_blocksize=65536
options zfs zfs_arc_grow_retry=5
# и агрессивно чистить кеш
options zfs zfs_arc_lotsfree_percent=5
options zfs zfs_arc_meta_prune=100000

options zfs zfs_scan_strict_mem_lim=1

Создание пула (оглавление на SSD, bin/zfs_tm.sh)

zpool create -f -o ashift=12 -o autoexpand=on \
-d \
-o feature@allocation_classes=enabled \
-o feature@async_destroy=enabled \
-o feature@bookmarks=enabled -o feature@bookmark_v2=enabled -o feature@bookmark_written=enabled \
-o feature@device_rebuild=enabled -o feature@device_removal=enabled \
-o feature@edonr=enabled -o feature@sha512=enabled -o feature@skein=enabled \
-o feature@embedded_data=enabled \
-o feature@empty_bpobj=enabled \
-o feature@enabled_txg=enabled -o feature@extensible_dataset=enabled \
-o feature@encryption=enabled \
-o feature@large_blocks=enabled \
-o feature@large_dnode=enabled \
-o feature@livelist=enabled \
-o feature@log_spacemap=enabled \
-o feature@lz4_compress=enabled -o feature@zstd_compress=enabled \
-o feature@redacted_datasets=enabled -o feature@redaction_bookmarks=enabled \
-o feature@resilver_defer=enabled \
-o feature@spacemap_histogram=enabled -o feature@spacemap_v2=enabled \
-o feature@zpool_checkpoint=enabled \
-O aclinherit=passthrough -O aclmode=passthrough -O acltype=posix -O xattr=sa \
-O atime=off -O relatime=off \
-O checksum=sha256 \
-O compression=zstd-12 \
-O dedup=sha256 \
-O dnodesize=legacy \
-O devices=off \
-O overlay=off \
-O primarycache=metadata -O secondarycache=metadata \
-O recordsize=16777216 \
-O redundant_metadata=none \
-O sharenfs=off -O sharesmb=off \
-O snapdir=visible \
-O special_small_blocks=0 \
-O sync=disabled -O logbias=throughput \
-O mountpoint=none \
bigpool /dev/data/tm /dev/data/tm2 special /dev/disk/by-id/ata-INTEL_SSDSC2KB038T8_PHYF020300AY3P8EGN

zfs create bigpool/time_machine \
-o aclinherit=passthrough -o aclmode=passthrough -o acltype=posix -o xattr=sa \
-o atime=off -o relatime=off \
-o checksum=sha256 \
-o compression=zstd-12 \
-o dedup=sha256 \
-o dnodesize=legacy \
-o devices=off \
-o overlay=off \
-o primarycache=metadata -o secondarycache=metadata \
-o recordsize=16777216 \
-o redundant_metadata=none \
-o sharenfs=off -o sharesmb=off \
-o snapdir=visible \
-o special_small_blocks=0 \
-o sync=disabled -o logbias=throughput \
-o mountpoint=/time_machine

mkdir /time_machine/{colddata,raid,share4h,share4s,share4x,share5c,share5d,share5e,share5f,xeon01,xeon04}

Наполнение архива с помощью rsync каталогами в параллель из предыдущего архива, дневная часть, делается клон (его можно почистить и экспортировать), полный суточный архив getall_snapshot.sh:

#!/bin/bash

DATE=$1
echo $DATE

snap=`ssh старый-архив ls -1d '/time_machine/.zfs/snapshot/'$DATE 2>&1`
if [ "$snap" = "/time_machine/.zfs/snapshot/$DATE" ]
then
  ls -1d /time_machine/*/*|awk -F/ '{print  $3 "/" $4}' |LANG= sort > /tmp/getall.current.list
  (ssh старый-архив ls -1d '/time_machine/.zfs/snapshot/'$DATE'/*/*';)|awk -F/ '{print  $6 "/" $7}'|LANG= sort > /tmp/getall.new.list
  LANG= comm -23 /tmp/getall.current.list /tmp/getall.new.list | awk '{print "/time_machine/" $1}' | xargs --verbose --no-run-if-empty --max-args=1 --max-procs=1 rm -r 2>&1 | cat --squeeze-blank > /root/rsync/rsync.$DATE.deleted.log
  rm /tmp/getall.current.list /tmp/getall.new.list
  if [ ! -s /root/rsync/rsync.$DATE.deleted.log ]
  then
   rm /root/rsync/rsync.$DATE.deleted.log
  fi

  (ssh старый-архив ls -d '/time_machine/.zfs/snapshot/'$DATE'/*/*'; )|awk -F/ '{print $5 "/" $6 "/" $7}' | xargs --verbose --max-args=1 --max-procs=20 getdir_snapshot.sh 2>&1 | xz  > /root/rsync/rsync.$DATE.log.xz
fi
zfs snapshot bigpool/time_machine@$DATE
zfs clone -o mountpoint=/clones/$DATE -p bigpool/time_machine@$DATE bigpool/clones/$DATE

копирование каталога getdir_snapshot.sh:

#!/bin/bash

if [ -z "$1" ]
then
  echo empty
  exit
else
  DATE=`echo $1|awk -F/ '{print $1}'`
  DIR=`echo $1|awk -F/ '{print $2 "/" $3}'`
  FILESYSTEM=`echo $1|awk -F/ '{print $2}'`

  if [ -z `ssh старый-архив ls -ld /time_machine/.zfs/snapshot/$DATE/$DIR|grep '^d.*'|awk '{print $1}'` ]; 
  then   
     echo $DIR is nodir
     rm -rf /time_machine/$DIR
  else
     rsync --password-file=/root/rsync.password -vas -HAX --inplace --ignore-errors --delete --max-size=100G --exclude '*.da_vinci_code' --exclude '.mozilla/**/Cache' --exclude .Trash --exclude .local/share/Trash --exclude /temp/ --exclude .local/share/gvfs-metadata --exclude ... --delete-excluded --stats --whole-file --numeric-ids  btrfs@старый-архив::time_machine_copy/$DATE/$DIR/ /time_machine/$DIR/
  fi

fi

Выделенный сервер архива с дедупликацией, версия 4

Выделенный сервер архива с дедупликацией: CentOS 7.9 (8.9?), zfs 2.2.2, 36 ядер по 3.0GHz, 512 ГиБ ОП, сеть 2x40 Gbps, локальный массив большого размера (2 x LSI/Broadcom MegaRAID RAID-6 of 17 HDD SAS LFF 16 TB 7200 rpm) и зеркало из частей INTEL D7-P5620.

Сборка сервера SuperMicro SSG-640P-E1CR36L.

Настройка BIOS/UEFI SuperMicro X12DPi-NT6

Настройка контроллера LSI/Broadcom MegaRAID 9560-8i (суперконденсатор CV на месте):

/opt/MegaRAID/storcli/storcli64 /c0 set bios Mode=SOE # стоять, если что не так
/opt/MegaRAID/storcli/storcli64 /c0 set coercion=0 # были проблемы с вычислениями
/opt/MegaRAID/storcli/storcli64 /c0 set copyback=off type=all # без неожиданностей
/opt/MegaRAID/storcli/storcli64 /c0 set dimmerswitch=off type=4 # не спать!
/opt/MegaRAID/storcli/storcli64 /c0 start dpm # сбор статистики
/opt/MegaRAID/storcli/storcli64 /c0 set foreignautoimport=off # без неожиданностей
/opt/MegaRAID/storcli/storcli64 /c0 set loadbalancemode=on # хотя тут 1 порт
/opt/MegaRAID/storcli/storcli64 /c0 set patrolread=off # везде CC
/opt/MegaRAID/storcli/storcli64 /c0 set perfmode=1 # не поддерживается, но Support Perf Tuning = Yes

Создание массива

/opt/MegaRAID/storcli/storcli64 /c0 add vd type=raid6 size=all name=first drives=250:0-11,251:0-4 pdcache=off wb nora direct Strip=64
/opt/MegaRAID/storcli/storcli64 /c0 add vd type=raid6 size=all name=second drives=251:5-15,18-23 pdcache=off wb nora direct Strip=64
# и немедленно
/opt/MegaRAID/storcli/storcli64 /c0/vall set autobgi=off
/opt/MegaRAID/storcli/storcli64 /c0/vall start init full

pvcreate /dev/sdc
pvcreate /dev/sdd
vgcreate data /dev/sdc /dev/sdd
lvcreate -n tm --stripes 2 --stripesize 64K -l +100%FREE data

Раздел зеркала под special vdev на частях INTEL D7-P5620 (SSDPF2KE064T1, U.2, PCIe 4 x4, 3D TLC, 3DWPD - 35PBW, конденсаторы для защиты от пропадания питания на месте)

mdadm --create /dev/md/SSD --verbose --raid-devices=2 --level=raid1 --name=zfsmeta /dev/nvme0n1 /dev/nvme1n1
pvcreate /dev/md/SSD
vgcreate SSD /dev/md/SSD
lvcreate -n zfsmeta -L 2T SSD

Настройки системы:

Параметры модуля spl (/etc/modprobe.d/spl.conf): отсутствуют.

Параметры модуля zfs (/etc/modprobe.d/zfs.conf):

# у нас большие батальоны
options zfs zfs_max_recordsize=16777216

# всё вручную
options zfs zfs_autoimport_disable=1

# от греха подальше
options zfs zfs_bclone_enabled=0
options zfs ignore_hole_birth=1

# для совместимости DDT с исходным архивом
options zfs zstd_earlyabort_pass=0

# выделение свободного места
options zfs metaslab_lba_weighting_enabled=0
options zfs spa_asize_inflation=3
options zfs spa_slop_shift=7
options zfs zfs_fallocate_reserve_percent=100

# архиву больше заняться нечем
options zfs zio_taskq_batch_pct=85

# потеря части наливаемых в архив данных не страшна
options zfs zfs_txg_timeout=30
options zfs zfs_nocacheflush=1
options zfs zil_nocacheflush=1

# глубина очереди на MegaRAID и SSD моожет быть больше
options zfs zfs_vdev_async_write_max_active=16
options zfs zfs_vdev_async_write_min_active=4
options zfs zfs_vdev_sync_read_max_active=40

# всю память под кеш! ну не совсем
options zfs zfs_arc_max=80000000000
options zfs zfs_arc_average_blocksize=65536
options zfs zfs_arc_grow_retry=5

# и агрессивно чистить кеш
options zfs zfs_vdev_async_write_active_min_dirty_percent=10

# если интенсивное чтение (параллельный rsync)
#options zfs zfs_prefetch_disable=1

options zfs zfs_scan_strict_mem_lim=1

Свойства пула:

-d \
-o feature@allocation_classes=enabled \
-o feature@async_destroy=enabled \
-o feature@device_removal=enabled \
-o feature@embedded_data=enabled \
-o feature@empty_bpobj=enabled \
-o feature@enabled_txg=enabled -o feature@extensible_dataset=enabled \
-o feature@head_errlog=enabled \
-o feature@large_blocks=enabled \
-o feature@large_dnode=enabled \
-o feature@livelist=enabled \
-o feature@log_spacemap=enabled \
-o feature@lz4_compress=enabled -o feature@zstd_compress=enabled \
-o feature@resilver_defer=enabled \
-o feature@spacemap_histogram=enabled -o feature@spacemap_v2=enabled \
-o feature@userobj_accounting=enabled \
-o feature@zpool_checkpoint=enabled \
-o ashift=12 -o autoexpand=on \
bigpool /dev/data/tm special /dev/SSD/zfsmeta

Свойства набора данных:

-O aclinherit=passthrough -O aclmode=passthrough -O acltype=posix -O xattr=sa \
-O atime=off -O relatime=off \
-O checksum=sha256 \
-O compression=zstd-12 \
-O dedup=sha256 \
-O dnodesize=legacy \
-O devices=off \
-O overlay=off \
-O primarycache=metadata -O secondarycache=none \
-O recordsize=16777216 \
-O redundant_metadata=none \
-O sharenfs=off -O sharesmb=off \
-O snapdir=visible \
-O special_small_blocks=0 \
-O sync=disabled -O logbias=throughput \
-O mountpoint=none \

Заливка копии по частям - цепочки снимков (основанные на снимках клоны не копируются):

имеются снимки и клоны с 20150101 по 20240131
zfs send -R -Lec bigpool/time_machine@20240131| mbuffer -O приёмник:7777 -m 1G -s 1048576

пул bigpool создан, а файловая система нет
mbuffer -I 7777 -m 1G -s 1048576| zfs receive -vd -F -o aclinherit=passthrough -o aclmode=passthrough -o acltype=posix -o xattr=sa \
  -o atime=off -o relatime=off -o checksum=sha256 -o compression=zstd-12 -o dedup=sha256 -o dnodesize=legacy -o devices=off \
  -o overlay=off -o primarycache=metadata -o secondarycache=none -o recordsize=16777216 -o redundant_metadata=none\
  -o sharenfs=off -o sharesmb=off -o snapdir=visible -o special_small_blocks=0 -o sync=disabled -o logbias=throughput \
  -o mountpoint=/time_machine bigpool

receiving full stream of bigpool/time_machine@20150101 into bigpool/time_machine@20150101
in @ 28.0 MiB/s, out @ 28.0 MiB/s, 11.2 TiB total, buffer   0% fullreceived 11.2T stream in 113336.17 seconds (104M/sec)
receiving incremental stream of bigpool/time_machine@20150102 into bigpool/time_machine@20150102
in @ 53.9 MiB/s, out @ 49.9 MiB/s, 11.3 TiB total, buffer   0% fullreceived 29.1G stream in 145.54 seconds (205M/sec)
...

summary:  374 TiByte in 464h 34min 55.0sec - average of  234 MiB/s
# повторно с правильными настройками приёмника
summary:  374 TiByte in 395h 20min 46.6sec - average of  275 MiB/s

for DATE in `ls /time_machine/.zfs/snapshot/`; do zfs clone -o mountpoint=/clones/$DATE -p bigpool/time_machine@$DATE bigpool/clones/$DATE; done

Конечный результат

NAME            SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
bigpool         439T   244T   195T        -         -     0%    55%  1.53x    ONLINE  -
  data/tm       437T   243T   194T        -         -     0%  55.6%      -    ONLINE
special            -      -      -        -         -      -      -      -         -
  SSD/zfsmeta     2T   941G  1.07T        -         -    39%  46.3%      -    ONLINE
COMPRESS        RATIO   USED  LUSED  AVAIL
zstd-12         3.42x   374T  1.24P   193T
DDT ~40GB в памяти
zdb -L -bb bigpool

 374T completed (18186MB/s)

        bp count:            1428006631
        ganged count:                 0
        bp logical:      1401826123974656      avg: 981666
        bp physical:     408889790567424      avg: 286336     compression:   3.43
        bp allocated:    411025536360448      avg: 287831     compression:   3.41
        bp deduped:                   0    ref>1:      0   deduplication:   1.00
        bp cloned:                    0    count:      0
        Normal class:    266855525736448     used: 55.60%
        Special class     1011439149056     used: 46.36%
        Embedded log class              0     used:  0.00%

        additional, non-pointer bps of type 0:  155840545
        Dittoed blocks on same vdev: 3253922

средний размер блока 287831

Blocks  LSIZE   PSIZE   ASIZE     avg    comp   %Total  Type
     -      -       -       -       -       -        -  unallocated
     2    32K      8K     24K     12K    4.00     0.00  object directory
   440   348K    248K   5.23M   12.2K    1.40     0.00  object array
     1    16K      4K     12K     12K    4.00     0.00  packed nvlist
     -      -       -       -       -       -        -  packed nvlist size
 1.79M   229G   40.1G    120G   67.3K    5.70     0.03  bpobj
     -      -       -       -       -       -        -  bpobj header
     -      -       -       -       -       -        -  SPA space map header
 28.3K  3.52G    187M    561M   19.8K   19.30     0.00  SPA space map
     -      -       -       -       -       -        -  ZIL intent log
 86.6M  1.68T    433G    433G   5.00K    3.99     0.11  DMU dnode
 3.23K  12.9M   12.9M   12.9M   4.00K    1.00     0.00  DMU objset
     -      -       -       -       -       -        -  DSL directory
 3.27K  2.09M    176K    540K     165   12.13     0.00  DSL directory child map
 3.27K  2.09M    176K    528K     161   12.16     0.00  DSL dataset snap map
 6.49K   104M   25.9M   77.8M   12.0K    4.00     0.00  DSL props
     -      -       -       -       -       -        -  DSL dataset
     -      -       -       -       -       -        -  ZFS znode
     -      -       -       -       -       -        -  ZFS V0 ACL
 1.03G  1.24P    371T    373T    363K    3.43    99.76  ZFS plain file
  196M   451G   90.4G    207G   1.05K    4.99     0.05  ZFS directory
     3  1.50K   1.50K     16K   5.33K    1.00     0.00  ZFS master node
     -      -       -       -       -       -        -  ZFS delete queue
     -      -       -       -       -       -        -  zvol object
     -      -       -       -       -       -        -  zvol prop
     -      -       -       -       -       -        -  other uint8[]
     -      -       -       -       -       -        -  other uint64[]
     -      -       -       -       -       -        -  other ZAP
     -      -       -       -       -       -        -  persistent error log
   294  36.8M   2.47M   7.41M   25.8K   14.89     0.00  SPA history
     -      -       -       -       -       -        -  SPA history offsets
     -      -       -       -       -       -        -  Pool properties
     -      -       -       -       -       -        -  DSL permissions
     -      -       -       -       -       -        -  ZFS ACL
     -      -       -       -       -       -        -  ZFS SYSACL
     -      -       -       -       -       -        -  FUID table
     -      -       -       -       -       -        -  FUID table size
     -      -       -       -       -       -        -  DSL dataset next clones
     -      -       -       -       -       -        -  scan work queue
 6.45K   119M   38.7M   38.7M   6.00K    3.08     0.00  ZFS user/group/project used
     -      -       -       -       -       -        -  ZFS user/group/project quota
     -      -       -       -       -       -        -  snapshot refcount tags
 1.17M  37.3G   22.3G   66.9G   57.4K    1.67     0.02  DDT ZAP algorithm
     2    32K     12K     36K     18K    2.67     0.00  DDT statistics
 23.2M  11.6G   11.6G   92.7G   4.00K    1.00     0.02  System attributes
     -      -       -       -       -       -        -  SA master node
     3  4.50K   4.50K     16K   5.33K    1.00     0.00  SA attr registration
     8   128K     32K     40K      5K    4.00     0.00  SA attr layouts
     -      -       -       -       -       -        -  scan translations
     -      -       -       -       -       -        -  deduplicated block
 53.7K  1.25G    389M   1.14G   21.8K    3.29     0.00  DSL deadlist map
     -      -       -       -       -       -        -  DSL deadlist map hdr
    23   464K    168K    504K   21.9K    2.76     0.00  DSL dir clones
     -      -       -       -       -       -        -  bpobj subobj
     -      -       -       -       -       -        -  deferred free
     -      -       -       -       -       -        -  dedup ditto
 9.74K  5.47M   51.5K    180K      18   108.71    0.00  other
 1.33G  1.25P    372T    374T    281K    3.43   100.00  Total
  314M  2.97T    618G    942G   3.00K    4.93     0.25  Metadata Total

Block Size Histogram

  block   psize                lsize                asize
   size   Count   Size   Cum.  Count   Size   Cum.  Count   Size   Cum.
    512:   335M   167G   167G   335M   167G   167G      0      0      0
     1K:   165M   201G   368G   165M   201G   368G      0      0      0
     2K:   124M   331G   699G   124M   331G   699G      0      0      0
     4K:   343M  1.36T  2.04T   116M   624G  1.29T   955M  3.73T  3.73T
     8K:  89.5M   821G  2.84T  93.8M  1.03T  2.32T  97.7M   882G  4.59T
    16K:  35.8M   736G  3.56T   159M  2.90T  5.22T  36.4M   738G  5.31T
    32K:  20.6M   874G  4.41T  52.3M  2.19T  7.41T  21.4M   912G  6.20T
    64K:  12.8M  1.10T  5.52T  29.7M  2.61T  10.0T  13.8M  1.18T  7.38T
   128K:  10.2M  1.81T  7.32T  28.6M  4.43T  14.4T  10.6M  1.87T  9.25T
   256K:  11.1M  4.02T  11.3T  10.5M  3.73T  18.2T  11.2M  4.02T  13.3T
   512K:  14.9M  10.9T  22.2T  7.89M  5.71T  23.9T  14.9M  10.9T  24.2T
     1M:  15.1M  22.6T  44.8T  6.44M  9.08T  33.0T  15.1M  22.6T  46.7T
     2M:  12.2M  32.6T  77.4T  5.49M  14.8T  47.7T  12.2M  32.7T  79.4T
     4M:  7.09M  41.9T   119T  3.22M  18.5T  66.3T  7.09M  41.9T   121T
     8M:  5.83M  66.2T   186T  2.36M  26.5T  92.7T  5.83M  66.2T   187T
    16M:  11.6M   186T   372T  73.9M  1.15P  1.25P  11.6M   186T   374T

zdb -L -MM bigpool
        vdev          0         metaslabs27940          fragmentation  0%
                         30:   4103 *******
                         31:     57 *
                         32:  23779 ****************************************
        vdev          1         metaslabs  127          fragmentation 39%
                         12: 924926 *************
                         13: 737630 **********
                         14: 2954248 ****************************************
                         15: 1775606 *************************
                         16: 1223379 *****************
                         17: 724551 **********
                         18: 437028 ******
                         19: 274588 ****
                         20: 143446 **
                         21:  49990 *
                         22:  10918 *
                         23:   1209 *
                         24:      8 *

Основные изменения в версиях

Ссылки

@ Карта сайта News Автора!

Bog BOS: Файловая система ZFS

Последние изменения:
2024.11.11: sysadmin: Linux: пространства имён
2024.11.06: sysadmin: настройка TCP/IP в Linux: виртуальный интерфейс и виртуальный мост
2024.10.25: sysadmin: Linux VFS, атрибуты, расширенные атрибуты, ACL
2024.10.22: sysadmin: Монтирование файловых систем: bind, shared и OverlayFS



Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru