АйТи Фреш
Главная / Статьи / Серверы и хостинг
Серверы и хостинг

Почему ZFS не отдаёт место после удаления файлов и не даёт снести нужный снимок

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~25 мин чтения
Почему ZFS не отдаёт место после удаления файлов и не даёт снести нужный снимок
Иллюстрация к статье «Почему ZFS не отдаёт место после удаления файлов и не даёт снести нужный снимок».

Пул забит на 94 %, вы удалили полтерабайта логов и старых бэкапов, а свободного места не прибавилось ни на гигабайт. Дальше вы пробуете снести самый жирный снимок — и получаете «dataset is busy». Ниже — как я разбираю такие случаи: какие три числа смотреть первыми, почему сумма USED всех снимков врёт, чем hold отличается от зависимости клона, и как удалить снимки так, чтобы не потерять нужные версии данных и не убить работающий клон.

«Удалили 400 ГБ, а место не появилось»

Классический звонок в пятницу вечером: на хранилище кончается место, дежурный админ вычистил старые дампы и архивы, df -h показывает ровно то же самое. Дальше начинается самое вредное — человек начинает удалять что-то ещё, потом ещё, и в какой-то момент сносит то, что было нужно. Хотя причина почти всегда одна и та же и никакого отношения к «багу ZFS» не имеет.

ZFS — copy-on-write. Удаление файла не освобождает блоки, если на эти блоки ссылается хотя бы один снимок. Снимок — это не «копия», это набор ссылок на блоки, зафиксированный в момент создания. Пока снимок жив, блоки живы. Поэтому rm -rf внутри датасета, у которого есть ночной снимок, не освобождает ничего вообще: данные просто переезжают из «активной» части в «снимочную». Место вернётся только когда уйдёт последний снимок, который эти блоки удерживает.

Первое, что я делаю, — смотрю не df, а собственную арифметику ZFS. df на ZFS показывает производную величину и на пуле со снимками и refreservation врёт систематически. Нужны три-четыре числа, и все они берутся одной командой:

zfs list -o space -r tank/data
# NAME  AVAIL  USED  USEDSNAP  USEDDS  USEDREFRESERV  USEDCHILD

zfs get -Hp -o property,value used,referenced,usedbysnapshots,written tank/data
zpool get freeing,leaked,fragmentation,capacity tank

-o space — это, по документации, шорткат для name,avail,used,usedsnap,usedds,usedrefreserv,usedchild. Из этих колонок сразу видно, куда ушло место: в сами данные (USEDDS), в снимки (USEDSNAP), в детей (USEDCHILD) или в резервирование тома (USEDREFRESERV). В 90 % случаев виновник — USEDSNAP, и тогда дальше вопрос только один: какие именно снимки и что их держит.

Есть ещё два честных отложенных фактора, о которых забывают. Первый — свойство пула freeing: после уничтожения датасета или снимка «space it was using is returned to the pool asynchronously», то есть освобождение идёт фоном, порциями по транзакционным группам. На большом снимке freeing может крутиться десятки минут, и всё это время zpool list показывает старую цифру. Второй — обычные для любой ФС удалённые, но открытые файлы: процесс держит дескриптор, инод не освобождается. Проверяется lsof +L1. К снимкам это отношения не имеет, но в разборе полётов стоит исключить сразу.

df и du на ZFS — не источник истины. Любой разбор начинайте с zfs list -o space и zpool get freeing. Если freeing больше нуля — просто подождите, ничего дополнительно удалять не нужно.
Памятка: «Удалили 400 ГБ, а место не появилось» — схема
Памятка: «Удалили 400 ГБ, а место не появилось». Открыть схему в полном размере

Почему сумма USED всех снимков обманывает

Самая частая логическая ловушка. Админ делает zfs list -t snapshot -r tank/data, видит 40 снимков по 1–2 ГБ в колонке USED, складывает — получает 60 ГБ — и делает вывод: «снимки тут ни при чём, они занимают копейки». А usedbysnapshots при этом 1,2 ТБ. И это не противоречие, это ровно то, что написано в мануале.

Дословно из zfsprops(7): «The used space of a snapshot is space that is referenced exclusively by this snapshot. If this snapshot is destroyed, the amount of used space will be freed. Space that is shared by multiple snapshots isn't accounted for in this metric.» То есть USED отдельного снимка — это только его эксклюзивные блоки. Всё, что разделяют между собой хотя бы два снимка, не попадает ни в один из USED. А usedbysnapshots — «the amount of space that would be freed if all of this dataset's snapshots were destroyed», то есть эксклюзив снимков как группы относительно активного датасета.

Отсюда следствие, которое ловит людей врасплох: удаление одного снимка может увеличить USED соседнего. Мануал прямо это оговаривает: «When a snapshot is destroyed, space that was previously shared with this snapshot can become unique to snapshots adjacent to it, thus changing the used space of those snapshots». Практически это выглядит так: снесли снимок с USED 3 ГБ, ожидали минус 3 ГБ, получили минус 3 ГБ, а у соседа USED вырос с 1 ГБ до 380 ГБ. Никакого места вы не выиграли, просто перетасовали учёт.

Поэтому единственный честный способ узнать, сколько вернёт удаление конкретной группы снимков, — спросить об этом саму ZFS. Для этого есть сухой прогон и диапазонный синтаксис. Диапазон задаётся знаком процента: «An inclusive range of snapshots may be specified by separating the first and last snapshots with a percent sign», причём начало или конец можно опустить — тогда подставится самый старый или самый новый снимок датасета.

# сколько вернёт снос всего, что старше апреля (человекочитаемо)
zfs destroy -nv tank/data@auto-2025-01-01%auto-2026-03-31
# would destroy tank/data@auto-2025-01-01
# ...
# would reclaim 412G

# то же для скрипта: строки destroy/reclaim, объём в байтах
zfs destroy -np tank/data@auto-2025-01-01%auto-2026-03-31

# сколько вернёт снос вообще всех снимков датасета
zfs destroy -nv tank/data@%

-n — это «Do a dry-run ("No-op") deletion. No data will be deleted», -v печатает, что именно будет удалено, -p даёт машиночитаемый вывод (объём в байтах), который удобно скармливать в скрипт. Я почти никогда не запускаю zfs destroy на диапазоне без предварительного -nvp. Это не перестраховка: диапазон легко расширить на один символ и снести полугодовую глубину ретеншена вместо недельной.

Никогда не планируйте чистку по сумме колонки USED. Планируйте по выводу zfs destroy -nvp на том самом диапазоне, который собираетесь удалять.
Почему ZFS не отдаёт место после удаления файлов и не даёт снести нужный снимок — схема
Схема к статье. Открыть схему в полном размере

Кто держит снимок: holds, клоны, checkpoint, refreservation

Вторая половина проблемы — когда вы уже поняли, какие снимки жрут место, но zfs destroy отказывается их сносить. Формулировка в мануале однозначная: команда «will fail if any clones of the snapshot exist or if the snapshot is held». То есть держателей ровно два класса: пользовательские holds и клоны. Плюс два пулевых фактора, которые к снимкам отношения не имеют, но выглядят как «место не вернулось»: checkpoint и refreservation.

Hold — это именованный персистентный замок на снимке. Ставится zfs hold tag snapshot, снимается zfs release tag snapshot, обе команды умеют -r для рекурсии по потомкам. Попытка снести удерживаемый снимок возвращает EBUSY. Количество холдов лежит в свойстве userrefs, а сами теги показывает zfs holds -rHp. Ключевое: холды ставят не только люди. Их массово ставят системы репликации. zrepl в режиме guarantee_resumability вешает step-holds вида zrepl_STEP_J_<имя_джобы> — и если джобу переименовали или удалили, эти холды остаются висеть годами и тихо блокируют весь пруннинг.

Клон — это отдельная зависимость. Свойство clones у снимка — «comma-separated list of filesystems or volumes which are clones of this snapshot». Пока клон существует, снимок-родитель неудаляем, и обратная ссылка живёт в свойстве origin у самого клона. Типичный источник — тестовое восстановление, которое сделали через zfs clone, проверили и забыли снести. Клон на диске почти ничего не занимает, но удерживает всю историю блоков за собой. При попытке снести такой снимок zfs destroy не пишет «busy», а прямо сообщает, что у снимка есть зависимые клоны, и предлагает -R — вот этот совет выполнять не спешите.

# все снимки пула, у которых есть холды или клоны
zfs list -H -t snapshot -o name,userrefs,clones,defer_destroy -r tank | awk -F'\t' '$2!=0 || $3!="-"'

# кто именно держит
zfs holds -rHp tank/data@2026-01-14

# все клоны в пуле и их origin
zfs get -H -r -t filesystem,volume -o name,value origin tank | awk -F'\t' '$2!="-"'

# checkpoint пула — колонка CKPOINT
zpool list -v tank

Про checkpoint отдельно. zpool checkpoint фиксирует состояние всего пула, и пространство, освобождённое после его создания, продолжает удерживаться, чтобы был возможен откат. Занятый объём видно в колонке CKPOINT вывода zpool list. Чекпойнт обычно ставят перед рискованным апгрейдом и забывают снять — и потом полгода удивляются, почему пул не худеет ни от каких удалений. Снимается zpool checkpoint -d tank, освобождение идёт фоном.

И refreservation. У zvol (виртуальные диски в Proxmox, iSCSI-таргеты) по умолчанию стоит refreservation, равный объёму тома. Это гарантия, что тому хватит места на полную перезапись. В zfs list -o space оно светится в USEDREFRESERV, и никакие удаления внутри гостевой ОС на него не влияют. Это не проблема и не утечка — это ровно то, за что вы платите, когда используете толстые тома.

Прежде чем ломать зависимость, выясните, кто её поставил. Холд с тегом zrepl_STEP_J_* или похожим — это не мусор, а страховка резервного копирования. Снимать его вслепую значит порвать инкрементальную цепочку репликации.

Разбор из практики: пул на 94 % в театральной школе на 42 рабочих места

Условно — театральная школа «Дебютная роль»: 42 рабочих места (администрация, бухгалтерия, педагоги, монтажёр), один сервер виртуализации в собственной серверной. Стенд: Proxmox VE 8.4, ZFS из штатного репозитория ветки 2.2, пул tank из шести дисков по 4 ТБ в raidz2 — полезно около 14,5 ТБ. На пуле — 11 виртуалок, из них две тяжёлые: 1С с бухгалтерией и зарплатой и файловый архив видеозаписей спектаклей и репетиций, который пополняется после каждого показа. Обращение банальное: «места нет, бэкапы падают, чистили — не помогает».

На момент захода: capacity 94 %, free около 900 ГБ, fragmentation 41 %. Снимков в пуле — 960 штук, три источника вперемешку: zfs-auto-snapshot, встроенная репликация PVE со своими __replicate_* и поверх всего zrepl на резервный узел. Никто не мог сказать, кто за что отвечает, потому что настраивали это трое разных подрядчиков за четыре года. Первый же zfs list -o space показал по диску видеоархива: USEDDS 2,1 ТБ, USEDSNAP 1,26 ТБ. При этом сумма колонки USED по 214 снимкам этого датасета — 41 ГБ: монтажёр перегонял и удалял исходники, и почти всё удалённое осело в блоках, общих для нескольких снимков сразу. Вот та самая ловушка из второго раздела в чистом виде.

Дальше по чек-листу. zfs list -t snapshot -o name,userrefs,clones дал 37 снимков с userrefs=1. zfs holds -rHp показал тег zrepl_STEP_J_prod_to_backup, а в конфиге zrepl джоба уже называлась иначе — её переименовали в марте, а старые step-holds никто не подобрал: zrepl управляет холдами только своих текущих джоб. Отдельно нашёлся клон tank/test-restore с origin = tank/vm-105-disk-1@2026-01-14: тестовое восстановление архива, сделанное восемь месяцев назад «на пару дней». Клон занимал 4 ГБ и удерживал 640 ГБ истории. И вишенка — zpool list -v показал CKPOINT 310 ГБ: чекпойнт, поставленный перед обновлением PVE год назад.

# 1. сухой прогон: сколько реально вернёт чистка
zfs destroy -nv tank/vm-105-disk-1@auto-2024-09-01%auto-2026-03-31
# would destroy ...
# would reclaim 980G

# 2. осиротевшие step-holds zrepl: сверили со списком zrepl и сняли адресно
zrepl zfs-abstraction list
zfs list -H -r -t snapshot -o name tank | xargs zfs holds -H | awk -F'\t' '$2=="zrepl_STEP_J_prod_to_backup" {print $1}' \
  | xargs -n1 zfs release zrepl_STEP_J_prod_to_backup

# 3. клон тестового восстановления — после сверки просто удалить
zfs list -o name,origin,used,creation tank/test-restore
zfs destroy -nv tank/test-restore
zfs destroy tank/test-restore

# 4. снять чекпойнт и дождаться окончания
zpool checkpoint -d -w tank

Отдельно про шаг 3. Соблазн был снести клон через zfs destroy -R на снимке-родителе — эта опция «recursively destroy all clones of these snapshots, including the clones, snapshots, and children». Я так не делаю почти никогда: -R уносит вместе с зависимостью всё, что на ней выросло, и в момент запуска вы редко на 100 % знаете, что там висит. Правильнее адресно: выписать клоны из свойства clones, по каждому решить судьбу и удалить только его. А вот zfs promote здесь был бы ошибкой, хотя его часто советуют «чтобы развязать». Promote разворачивает связь: снимок-origin и все более ранние снимки переходят во владение клона, «no new space is consumed by this operation, but the space accounting is adjusted», а исходный диск архива сам становится клоном. Зависимость никуда не исчезает, просто меняет направление, и удалить после этого нельзя уже клон — он стал родителем боевого диска. Promote нужен в обратной ситуации: когда жить должен клон, а исходный датасет — уйти. Здесь клон был мусором, поэтому его сверили с методистом по архиву, убедились, что нужных файлов в нём нет, и удалили.

Итог: за один вечер вернули 2,9 ТБ, capacity упал с 94 % до 74 %. Само удаление отработало минут за двадцать, ещё около сорока минут zpool get freeing tank показывал остаток — за это время директор и завхоз успели трижды спросить, «почему место не появилось». Плюс переписали ретеншен: один источник снимков вместо трёх, глубина 14 дней на ежедневных и 6 месяцев на месячных, и алерт в Telegram на два условия — capacity > 80 % и «есть снимок старше 200 дней». За полгода после этого повторных обращений по месту не было.

Если в инфраструктуре больше одного механизма снапшотинга — считайте, что ретеншена у вас нет. Это самая частая первопричина забитого пула, которую я вижу.
Цифры и версии: Разбор из практики: пул на 94 % в театральной школе на 42 рабочих места — схема
Цифры и версии: Разбор из практики: пул на 94 % в театральной школе на 42 рабочих места. Открыть схему в полном размере

Как удалять снимки, чтобы не отстрелить себе ногу

Порядок, которого я придерживаюсь и которого требую от инженеров. Он скучный, но за годы ни разу не привёл к потере данных, а вот отклонения от него — приводили.

Сначала измеряем: zfs destroy -nvp на предполагаемом диапазоне. Если ожидаемый выигрыш меньше, чем вы рассчитывали, — не расширяйте диапазон рефлекторно, а сначала поймите, кто ещё держит блоки. Затем инвентаризируем зависимости: userrefs, clones, defer_destroy по всем снимкам пула одной командой. Затем разбираемся с каждой зависимостью адресно: холд — найти хозяина и сверить с его конфигурацией (для zrepl — zrepl zfs-abstraction list: холды активных джоб не трогаем, осиротевшие снимаем zfs release с точным тегом); клон — выяснить, кто им пользуется, и либо удалить сам клон, либо, если жить должен именно он, сделать zfs promote и удалять уже исходный датасет. И только потом удаляем.

Про zfs destroy -d. Это полезная штука в узком сценарии: «rather than returning error if the given snapshot is ineligible for immediate destruction, mark it for deferred, automatic destruction once it becomes eligible». То есть вы помечаете снимок, и он уйдёт сам, как только пропадёт последний холд или клон. Свойство defer_destroy при этом переключается в on. Важная деталь из мануала: помеченный снимок остаётся видимым, на него можно поставить новый холд и сделать с него новый клон — то есть -d не гарантирует, что снимок вообще когда-нибудь уйдёт. Я использую -d только там, где точно знаю, что зависимость временная: например, снимок держит идущая прямо сейчас репликация.

# правильный порядок
zfs destroy -nv tank/data@old-first%old-last            # 1. измерили
zfs list -t snapshot -o name,userrefs,clones -r tank    # 2. инвентаризировали
zfs release <tag> tank/data@snap                        # 3. сняли осиротевший холд адресно
zfs destroy tank/test-clone                             # 4. удалили ненужный клон (не -R!)
zfs destroy -v tank/data@old-first%old-last             # 5. удалили снимки
watch -n5 zpool get freeing tank                        # 6. дождались фонового освобождения

Чего делать не надо. Не запускать zfs destroy -R на снимке, пока не выписали список его клонов на бумажку — эта опция унесёт их все вместе с их снимками и потомками. Не снимать холды в цикле по всему пулу «чтобы почистить» — вы гарантированно порвёте инкрементальную цепочку репликации, и следующий инкремент превратится в полный сенд на несколько терабайт. Не удалять снимок, чтобы «посмотреть, сколько вернётся» — снимок обратно не возвращается, это необратимая операция без корзины.

И про порог. На пуле, забитом выше 90 %, ZFS заметно деградирует по скорости записи и по фрагментации. Удаление снимков тоже требует записи метаданных; на такой случай ZFS держит небольшой служебный запас (slop space, по умолчанию около 1/32 пула), поэтому zfs destroy на полном пуле обычно всё же проходит — но обычные записи и создание новых снимков к этому моменту уже падают с «out of space». Если пул на 98 % и работа встала, быстрый способ получить манёвр — временно снять refreservation с крупного толстого zvol (zfs set refreservation=none tank/vm-XXX-disk-0): зарезервированное, но не записанное место сразу вернётся в пул. Помните, что пока резерва нет, гостевая ОС этого тома может упереться в нехватку места, поэтому после чистки refreservation обязательно вернуть.

zfs destroy необратим: снапшот-корзины в ZFS нет. Единственная «отмена» — восстановление из репликации или бэкапа, и именно поэтому холды репликации нельзя снимать пачкой.

Что настроить один раз, чтобы больше не разбираться

Разовая чистка — это лечение симптома. Настоящая причина забитого пула почти всегда организационная: снимки создаёт кто-то, кто не отвечает за их удаление. Поэтому у себя и у клиентов я закрываю вопрос четырьмя вещами, и они дают эффект на годы.

Первое — один источник снимков. Не zfs-auto-snapshot плюс sanoid плюс встроенная репликация гипервизора плюс ручные снимки инженеров. Один инструмент, один конфиг, один ретеншен, всё остальное — выключить, старые артефакты — вычистить. Если гипервизор делает свои служебные снимки под репликацию (как PVE с префиксом __replicate_), их трогать нельзя, но и путать с бэкапными не нужно: они живут по своим правилам и удаляются самой репликацией.

Второе — мониторинг не только по свободному месту, но и по возрасту снимков. Порог capacity > 80 % даёт вам недели, а не часы, на реакцию. Отдельный алерт «есть снимок старше N дней» ловит ровно те случаи, что были в театральной школе: осиротевший холд, забытый клон, зависшая джоба репликации. Оба чека тривиально снимаются с хоста в Zabbix или в скрипт с отправкой в Telegram.

# самый старый снимок в пуле, в днях (systime есть в gawk и современном mawk)
zfs list -Hp -r -t snapshot -o name,creation -s creation tank | head -1 | \
  awk '{print $1, int((systime()-$2)/86400)" days"}'

# топ-10 датасетов по месту, занятому снимками
zfs list -Hp -o name,usedbysnapshots -r tank | sort -k2 -n -r | head -10

Третье — бук-марки вместо снимков там, где снимок нужен только как точка отсчёта для инкрементального zfs send. Бук-марка «marks the point in time when the snapshot was created, and can be used as the incremental source for a zfs send» — то есть даёт вам возможность продолжить инкремент, но не удерживает блоки данных. Это прямой способ разорвать связку «нужна инкрементальная репликация — значит, нужно вечно хранить старые снимки». Оговорюсь честно: сценарий рабочий не везде, часть инструментов репликации бук-марки поддерживает частично, конфигурацию надо проверять под конкретный стек. И важное ограничение: закладка годится только как источник инкремента на отправляющей стороне — откатиться на неё или смонтировать её содержимое нельзя, данных в ней нет.

Четвёртое — регламент на тестовые восстановления. Любой zfs clone, созданный для проверки бэкапа, получает имя с датой и владельцем и живёт максимум неделю. У нас это просто строчка в чек-листе восстановления и еженедельная проверка zfs get -r origin. Стоит пять минут, экономит терабайты.

Самый недооценённый чек — «самый старый снимок в пуле». Он ловит и осиротевшие холды, и забытые клоны, и молча упавшую репликацию, потому что во всех трёх случаях снимки перестают ротироваться.

Что из этого действительно опасно, а на что можно забить

Раз уж обещал честность — расставлю приоритеты, потому что паники вокруг «места в ZFS» обычно больше, чем оснований.

Действительно опасно ровно три вещи. Пул выше 90 % занятости — это уже деградация записи, а на 95+ % вы рискуете не суметь провести операции, которые сами требуют записи. Слепое снятие холдов репликации — вы не потеряете данные прямо сейчас, но следующий инкремент превратится в полный сенд, и на канале в 100 Мбит/с копирование 3 ТБ займёт вам трое суток, в течение которых резервной копии фактически нет. И zfs destroy -R без предварительной инвентаризации клонов — единственный сценарий в этой статье, где вы можете за одну команду потерять живые продакшен-данные.

А вот на что я предлагаю не тратить нервы. Ненулевой freeing — это норма, просто подождите; лезть туда не надо, крутить тюнинги ради пары минут — тоже. Расхождение между df и zfs list — тоже норма, df на ZFS никогда не будет точным, ориентируйтесь на zfs list -o space и не пытайтесь их «примирить». Большой USEDREFRESERV на zvol — не утечка, а осознанная плата за толстый том; менять его на sparse-том стоит только если вы понимаете, что берёте на себя риск переподписки пула. Фрагментация в 40–50 % на пуле с виртуалками — обычное дело и сама по себе не повод для аврала.

И отдельно про спорное. Единого мнения в сообществе нет по двум вопросам: агрессивность ретеншена и sparse против толстых томов. Я держу консервативно — 14 дней ежедневных плюс полгода месячных, толстые тома с refreservation на всём, что связано с 1С и SQL. Аргумент простой: место дешевле, чем ночь восстановления и объяснение директору, почему версии за прошлый вторник больше нет. Но это позиция, а не истина; на стенде разработки я сам делаю ровно наоборот. Главное — чтобы решение было принято осознанно и записано, а не сложилось само из четырёх слоёв чужих настроек.

Если пул уже за 95 % и работа встала — не паникуйте и не сносите снимки наугад. Временно снимите refreservation с крупного толстого zvol, чтобы получить манёвр, дальше действуйте по порядку, а после чистки верните резерв обратно.
Цифры и версии: Что из этого действительно опасно, а на что можно забить — схема
Цифры и версии: Что из этого действительно опасно, а на что можно забить. Открыть схему в полном размере

Частые вопросы

Удалил файлы в датасете, место не вернулось. Это точно из-за снимков?

В подавляющем большинстве случаев да. Проверяется одной командой: zfs list -o space -r <датасет> — если колонка USEDSNAP заметно больше нуля, блоки удерживают снимки. Дополнительно исключите два фактора: zpool get freeing <пул> (асинхронное освобождение ещё идёт) и lsof +L1 (удалённые, но открытые процессами файлы).

Почему сумма USED всех снимков намного меньше usedbysnapshots?

Потому что USED отдельного снимка по документации учитывает только блоки, на которые ссылается исключительно этот снимок. Всё, что разделяют между собой два и более снимка, не попадает ни в один USED. usedbysnapshots — это то, что освободится при удалении всех снимков датасета сразу, и оно может быть в десятки раз больше суммы. Реальный выигрыш конкретной чистки показывает только zfs destroy -nv (или -np для скриптов) на нужном диапазоне.

zfs destroy пишет «dataset is busy». Что смотреть?

Сначала два свойства снимка: userrefs (число пользовательских holds) и clones (список зависимых файловых систем и томов). Если userrefs > 0 — смотрите zfs holds -rHp и ищите, кто поставил тег; часто это система репликации. Если clones не пустое, zfs destroy обычно прямо пишет про зависимые клоны: ненужный клон удаляют отдельно, а zfs promote делают, только если жить должен клон, а исходный датасет — уйти.

Чем hold отличается от зависимости клона?

Hold — это именованный замок, метка «не удалять»: её ставит человек или скрипт, снимается она командой zfs release с тем же тегом. Клон — реальная зависимость данных: файловая система или том, построенные поверх снимка. Снять hold безопасно для данных, но опасно для цепочки репликации. Клон же развязывается только удалением. zfs promote зависимость не убирает, а разворачивает: снимок переходит к клону, и уже исходный датасет становится зависимым.

Что делает zfs destroy -d и когда его применять?

Флаг -d вместо ошибки помечает снимок на отложенное автоматическое удаление, которое произойдёт, как только снимок станет удаляемым. Свойство defer_destroy переключается в on. Нюанс: помеченный снимок остаётся видимым, на него можно поставить новый hold или сделать клон, поэтому -d не гарантирует, что он вообще уйдёт. Применять стоит только когда зависимость заведомо временная.

Можно ли удалить сразу диапазон снимков?

Да, через знак процента: zfs destroy tank/data@first%last, причём начало или конец можно опустить — подставится самый старый или самый новый снимок. Обязательно прогоняйте сначала с -nvp: ошибка в одном символе имени расширяет диапазон на месяцы истории, и откатить это нечем.

Место не вернулось даже после удаления всех снимков. Где искать?

Три типовых места. Первое — zpool get freeing: асинхронное освобождение ещё не закончилось, подождите. Второе — колонка CKPOINT в zpool list -v: висит забытый zpool checkpoint, который удерживает всё освобождённое с момента его создания. Третье — USEDREFRESERV в zfs list -o space: это резервирование под толстый zvol, и оно не освободится от удалений внутри гостевой ОС.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи