Как стать автором
Обновить

Оказывается, собственные NVMe-накопители Apple невероятно быстры, только если вы не заботитесь о целостности данных

Время на прочтение3 мин
Количество просмотров12K
Всего голосов 38: ↑36 и ↓2+34
Комментарии44

Комментарии 44

Я правильно понимаю, что неожиданно лишив питания систему хранения данных, можно лишится данных? Это конечно интересно, раньше то никто об этом не знал..

А Nvme и apple в заголовке это потому что что ?

НЛО прилетело и опубликовало эту надпись здесь

А «хрен знает сколько времени» это сколько?

Я к тому что, все накопители так работают, начиная с дисков 5 размерности по 40 мегабайт (я не ошибся, 40 мегов, толстенные пластины время 286х и т.д.)

Не работают. У nvme протокола (как и у SCSI) есть конкретная вполне команда flush, которая означает согласно спецификации сброс всего из энергозависимой в энергонезависимую память. И эту команду линукс посылает в рамках fsync вызова. Эпл ведет себя иначе и об этом речь в сабже. Fsync у них, по сути, не значит ничего. А если этот flush все таки послать, то их супер быстрый ssd превращается в тыкву, которая медленнее USB флешки.

У накопителя есть ещё TRIM, которая, если не ошибаюсь, у некоторых накопителей умеет перемещать давно записанные данные (системные файлы, например) в ячейки, у которых ресурс подходит к концу, чтобы освободить для записей ячейки с меньшим числом циклов записи. И, если в этот момент выдернуть питание — система может больше не загрузиться из-за повреждения этих закэшированных, но физически не записанных файлов. У меня было что-то подобное: после горячего отключения зависшего компьютера ОС больше не загрузилась, при 100% здоровом ССД, читаемыми файлами и 2...3 ТБ записей на 1 ТБ накопитель 970ево. После переустановки ОС всё отлично работает уже почти год.

Здесь вам просто не повезло. Диск обесточило не в момент записи какого-нибудь файла, а при операции над структурой файловой системы. Такая ситуация может привести к частичной потере метаданных в том числе и давно хранящихся на диске файлов. Более подробно выяснить можно, если вспомните какой файловой системой был размечен накопитель на момент сбоя. Современные ext4, btrfs, zfs, apfs структурно сделаны довольно отказоустойчивыми. При сбоях можно потерять последние данные. Но система должна загрузиться! При загрузке системы fsck просто удалит с диска ноды, на которых не ссылается ни один файл. На большинстве ОС fsck запускается перед монтированием ФС как стандарт (например, Windows 98+), но в некоторых fsck прописывают вручную (ArchLinux, Gentoo, Slackware). Иногда бывают ситуации, когда при отключенном fsck ФС сломалась уже давно, но продолжает эксплуатироваться. Это тоже может привести к подобному эффекту потери метаданных файлов до невозможности загрузки ОС.

но в некоторых fsck прописывают вручную (ArchLinux, Gentoo, Slackware)

По поводу Gentoo и Slackware не знаю, но в Arch fsck не будет запускаться только если /etc/fstab писать вручную и соответствующим образом прописать флаги. Если его генерировать через genfstab, как советуется в Installation Guide, то проверка перед монтированием пропишется по умолчанию.

А как же добавить хук fsck в initramfs?

Он в дефолтном конфиге mkinitcpio есть.

Диск обесточило не в момент записи какого-нибудь файла, а при операции над структурой файловой системы. Такая ситуация может привести к частичной потере метаданных в том числе и давно хранящихся на диске файлов. Более подробно выяснить можно, если вспомните какой файловой системой был размечен накопитель на момент сбоя. Современные ext4, btrfs, zfs, apfs структурно сделаны довольно отказоустойчивыми.

какое-то странное у вас представление об отказоустойчивости )))
нет, всё гораздо оптимистичнее, при монтировании файловой системы просматривается журнал и фс откатывается на известное консистентное состояние (обычно это касается только метаданных, но та же ext3/ext4 умеет журналировать и данные), если при штатном использовании системы она в какой-то момент может хранить данные на диске в неподлежащем определению консистентности/откату на последнее консистентное состоянии, то это явный просчёт проектирования.


разумеется, «после лома нет приёма», журналируемость не означает, что файловую систему нельзя испортить; но в случае, если накопитель исправный и не врёт о физической записи в персистентное хранилище (как раз связанные с fsync команды протокола), то при простом нештатном выключении питания всё должно быть хорошо.

Так я и спросил, во время отказа, случаем стояла не Windows 7 с каким-нибудь старым NTFS или не дай бог FAT32. Хотя терабайт 970evo...

Была бы уверенность, что об ext3/4 идет разговор, вопросов бы не было.

И вообще, кстати, за всю жизнь, (стуча по дереву) ни один накопитель NVMe от Samsung'а ни разу не приносил даже минимальных проблем.

У накопителя есть ещё TRIM, которая, если не ошибаюсь, у некоторых накопителей умеет перемещать давно записанные данные (системные файлы, например) в ячейки, у которых ресурс подходит к концу, чтобы освободить для записей ячейки с меньшим числом циклов записи

нет, не совсем. то, про что вы пишете, называется wear leveling, а trim просто помогает работе этого механизма (накопителю сообщается содержимое каких секторов не требуется сохранять, за счёт этого у него появляется больше свободного места для «перетасовывания» данных)

Не совсем. Традиционно считается что успешное завершение fsync() гарантирует что данные попали на диск. На это например полагаются движки баз данных.


А если этой гарантии нет — то могут возникать всякие неприятные моменты, типа потери данных в тех местах, которые казалось бы защищены от этого. Например, БД переносит транзакцию их журнала в основой файл. Она уверена что запись произошла и журнал можно очищать. Но не тут то было...

Окей, давайте чуток серьезности добавим, у вас есть кластер и пара полок, fsync сказал что все в порядке, но в реальности все это лежит в кеше полок (к примеру нетапповских) и на диски оно конечно приедет, но не тогда, когда ос считает что все приехало. Возможны ли при этом проблемы? Конечно. Поэтому чуваки добавляют резервное питание как в диски так и в полки. Если у вас датацентри потеряет питание - даже тогда у полок хватит батареек сбросить кеш на диски. Неприятности будут существенно большими - дц потерял питание = сервисы в дц легли.

Проблема в том, что эпл не имеет батарейки, если мы говорим о каком-нить imac или mac mini. Поэтому после fsync мы просто теряем данные. Это в лучшем случае. В худшем еще имеем поврежденную ФС. Поэтому непонятно при чем тут хранилки, где оптимизация fsync как раз и достигается за счет обеспечения резервного питания после потери основного питания. Это любой корпоративных SSD делает так же. Поэтому их в качестве кэша записи и ставят часто.

Может означать что туда добавят маленькую батарейку?

Кто их знает. Как говорит автор всех этих находок, большая вероятность, что в прошивке эпл просто баг/кривая реализация и это все будет исправлено. Возможно это рудимент от iOS, где используется, по сути, тот же SoC и эпл продолжает использовать теже приемы, поскольку у iOS батарейка есть всегда.

Ну собственно creker правильно написал: корпоративные хранилки могут гарантировать запись кеша при обесточивании, поэтому хранилки могут не скидывать все из кеша на диск и сразу отвечать на fsync что типа записали.

В некоторых SSD есть аккумуляторы из конденсаторов, такие точно также могут работать.

Ну тут речь идет про накопители Apple, поставляемые неотъемлемо от процессора M1. Это может подразумевать, что они вряд ли будут использоваться в кластерах. Проблема с fsync очень древняя. Как пример, здесь человек рассуждает по просадке производительности mysql на процессорах G5 (пост датирован июнем 2005г). На сколько я помню, в тот момент просадка производительности mysql была около 30%. У накопителей Apple проблема не в потере данных. Проблема в чудовищно низкой скорости при доскональном контроле опустошения кэша (95-99%). Как бы, накопитель сделали довольно быстрым, а вот в прошивке контроллера где-то накосячили.

Текст частично напоминает гуглоперевод, частично фантазии. Скорость эплодисков в 600 Кб/сек - за пределами юмора, не верится как-то.

И, как вывод - кто-то добился потери данных не на всех дисках - так это потому, что другие диски хороши (?), или просто руки у вытаскивающего недостаточно прямы быстры?

В общем, на глаз: начало и заголовок об одном, тема интересна, а вывода как бы нет, есть только набор слов, странный опыт и гуглоперевод.

  • Гектор предположил, что это связано с поведением прошивки контроллера и тем, что она специально затачивалась под такое читерство с FLUSH
  • Судя по этому, скорее дело в дисках, чем в методологии. А если точнее, видимо даже в прошивках

А выводы примерно такие:


  • На макбуках всё скорее всего ОК, т.к. есть батарея, но потерю можно получить специальной командой USB-PD (теперь вредоносные зарядники угрожают ещё и ноутбукам)
  • На Mac Mini и iMac стоит использовать бесперебойник и беречь кабель питания. Это в принципе применимо и ко всем остальным компьютерам.
  • Если вам на macOS действительно нужно удостовериться в записи на диск, есть fcntl F_FULLSYNC.
  • Не стоит держать СУБД и прочий чувствительный к гарантиям и порядку записи на диск софт на маках и сомнительных SSD, если целостность данных критична.

Некоторое время назад тестировал Optane и NVM NAND диски со сбросом кеша и без. Может кому будет интересны результаты:

Ключевой вопрос: можно ли провести fio такой простой тест с параметром fsync и без, чтобы по (не)падению скорости выявить, что SSD игнорирует fsync?

А проверяли, как работает, если упереться в кэш?

Тоже интересно. По идее скорость должна падать до 600 килобайт, но как то не верится.

Так это речь про альтернативу в виде F_FULLSYNC, которая, в отличии от fsync, работает как ожидается, но очень медленно.

Чем эта альтернатива отличается от работы диска с переполненным буфером ?

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

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

Тем, что F_FULLSYNC должен сбросить на флеш еще и FTL и прочие метаданные. Тем, что даже при переполнении буфера у нас сохраняется вся та сложная логика контроллера флеша, призванного эффективно писать данные. А кэш при этом скидывается на диск явно куда более эффективно, чем обычные записи. Вполне достаточно причин, почему переполнение буфера записи должно быть менее серьезной проблемой.

Ну вы согласны что при переполнении буфера записи данные будут писаться прямо на флеш и потери данных при отключении энергии не будет?

Нет, FTL не будет писать. Он, в зависимости от реализации контроллера, останется в его оперативке. И тут уже вопрос, как контроллер переваривает потерю питания в этом месте. Плюс, DRAM кеширование никуда не девается и контроллер запросто ответить, что запись принял, хотя она еще в DRAM. Заполненность кеша, по идее, вещь с этим не связанная. F_FULLSYNC же это должна быть полная гарантия, что и FTL, и все записи записаны именно на флеш. Именно это по спеке означает nvme команда flush.

В любом случае это догадки, т.к. устройство контроллеров флеша неизвестно. Они спокойно могут и flush команду игнорировать, кто им запретит.

fsync() на маке и линуксе одинаковый, но есть дополнительные опции. На маке сделали опцию F_FULLFSYNC для гарантированной записи буфера диска (если только диск не проигнорирует эту команду, что для не-эппл дисков вполне вероятно), на линуксе есть опция монтирования barrier=1 для файловых систем ext3 (и другие опции для остальных файловых систем). Автор Sqlite Ричард Хипп регулярно это все в рассылке объясняет, потому что пользователи спрашивают и спрашивают…

"опорожнять кэш" кащенко?

Я не знаю про макось, но в линуксах fsync может вернуть управление до выполнения fsync. Зато гарантируется, что следующий fsync не будет выполнен, пока предыдущий не будет выполнен, так что простой fsync;fsync решает задачу "точно всё синкнуть".

Насчёт "супермедленных SSD". Все SSD делятся на два класса: те, которые можно принудить к крайне медленному режиму работы (400-1000 IOPS) и те, которые всё равно остаются быстрыми. Качественные - те, которые можно принудить. Волшебства не бывает, и вопрос только в том, игнорирует ли контроллер требование "писать тщательно" без участия кеша или нет.

// Мимо линуксовый админ, в маках не разбираюсь.

К какой категории относится Optane? И всякая экзотика по типу ioMemory

Качественные могут гарантировать целостность даже при использовании кэшей. У всех энтерпрайзных дисков есть большое число суперконденсаторов, чтобы успеть скинуть на флеш не только метаданные, но и in-flight записи.

Гарантировать они могут, но хорошие enterprise grade SSD уважают просьбу отключить writeback-кеш. А менее хорошие утверждают, что их алгоритмы и конденсаторы достаточны, чтобы пережить отказ по питанию, так что "и так сойдёт" и кеш не отключают.

хорошие enterprise grade SSD уважают просьбу отключить writeback-кеш

а где-то на практике это используется? и если используется, то зачем?

С ходу не скажу, но есть ожидания, что если накопитель попросили не умничать, то он должен слушаться. Иначе это writeback до самого дна, где не существует sad path.

если накопитель попросили не умничать

это если есть способ попросить )
если я правильно понимаю, за включение/отключение wb кэширования отвечает feature 6:
5.21.1.6 Volatile Write Cache (Feature Identifier 06h), (Optional)
This Feature controls the volatile write cache, if present, on the controller. If a volatile write cache is present (refer to the VWC field in Figure 247), then this feature shall be supported. The attributes are indicated in Command Dword 11.
Note: If the controller is able to guarantee that data present in a write cache is written to non-volatile media on loss of power, then that write cache is considered non-volatile and this feature does not apply to that write cache.


то есть для nvme с plp по стандарту отключение wb кэширования не предусмотрено.


проверил, действительно,


nvme get-feature -f 6 /dev/nvme0n1

на парочке dc моделей выдало ошибку, а на не-dc накопителе отработало корректно:


get-feature:0x06 (Volatile Write Cache), Current value:0x00000001

А вот это очень ценное замечание. Я говорил по опыту sas/sata SSD, в которых write cache - это write cache, но некоторые игнорят, так же как и флаг "записать" в любой форме.

В nvme, видимо, навели порядок.

fsync;fsync

это вы просто с sync путаете.


в линуксе нет необходимости вызывать sync несколько раз, из man sync(2):
According to the standard specification (e.g., POSIX.1-2001), sync() schedules the writes, but may return before the actual writing is done. However, since version 1.3.20 Linux does actually wait. (This still does not guarantee data integrity: modern disks have large caches.)


раньше было принято вызывать sync три раза, второй раз для того, чтобы точно дождать завершения первого, ну а третий на всякий случай )
вот пример обсуждения:
https://groups.google.com/g/alt.folklore.computers/c/JIFYiyMXFzs

Спасибо, перечитал. Очень ценные комментарии, обновляющие закостеневшее знание.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

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

Истории