Кратко

  • В NFSv2 изменяющая операция возвращалась после стабильного хранения. Это упрощало восстановление stateless-сервера, но заставляло каждый WRITE ждать постоянный носитель.
  • NFSv3 ввёл UNSTABLE, DATA_SYNC и FILE_SYNC; ответ сообщал фактическую длину, достигнутый уровень и непрозрачный write verifier.
  • До COMMIT или достаточно сильного результата клиент хранил данные. Смена verifier требовала считать нестабильные диапазоны прежнего экземпляра потенциально утраченными и повторить их.

Успешный вызов с незакрытым долгом

Удалённый WRITE получает NFS3_OK, но поле committed может равняться UNSTABLE. Процедура завершилась, сервер принял некоторый диапазон, однако байты ещё могут не пережить исчезновение его volatile memory.

RFC 1094 описывал синхронные изменения NFSv2. После ответа клиент мог предположить stable storage и выбросить свою копию. Это поддерживало простое восстановление сервера без состояния, одновременно помещая задержку носителя в каждый запрос.

RFC 1813 назвал такое ожидание ограничением throughput. Безопасная асинхронная запись NFSv3 была безопасна не потому, что ранний ответ стал долговечным, а потому, что клиент сохранял данные и правила восстановления.

Запрошенный уровень не подменял полученный

Запрос выбирает UNSTABLE, DATA_SYNC или FILE_SYNC. Последний требует устойчивых данных и всех метаданных; DATA_SYNC — данных и метаданных, достаточных для их извлечения; UNSTABLE позволяет ответить, сохранив всё, часть или ничего.

Ответ committed показывает реальный уровень и может быть сильнее запроса. count сообщает реальное число записанных байтов: успешный short write оставляет хвост для следующего вызова. Поэтому общий статус не доказывает ни полный размер, ни долговечность принятого диапазона.

Поле verf — непрозрачный cookie, постоянный внутри значимого экземпляра сервера и новый после события, которое могло уничтожить uncommitted data. Обычно это reboot. Его смысл — непрерывность временного хранения.

Verifier не является хешем файла. Совпадение не доказывает правильность содержимого, отсутствие конкурента или полный диапазон. Изменение не доказывает потерю каждого байта; оно лишает клиента основания доверять старому volatile состоянию.

COMMIT сравнивал две эпохи

После нестабильного ответа клиент оставляет buffer. RFC 1813 выделяет dirty, done but needs to be committed и done. Среднее состояние показывает, куда переместилась цена быстрого ответа.

COMMIT выталкивает ранее нестабильные изменения в stable storage и может охватывать диапазон. Успех возвращает verifier. При совпадении две стадии принадлежат одному экземпляру. При различии клиент должен считать старые UNSTABLE-диапазоны возможно потерянными и записать их снова по известным offsets.

Это осторожная презумпция, а не измерение ущерба. Часть данных могла попасть на диск до сбоя, но клиент не умеет надёжно отделить её. Повторяемая запись восстанавливает состояние без выдуманной точности.

Граница стабильного хранения

RFC 1813 относит к stable storage переживание повторных отключений питания, некоторых аппаратных отказов, программных сбоев и reboot. Отказ самого модуля хранения исключён. Термин не обещает backup, replication или логическую правильность.

Строгая согласованность client caches тоже не следует из COMMIT. Долговечность отвечает, сохранятся ли байты после определённых сбоев; согласованность — какая версия должна считаться верной.

Механизм сохранился в RFC 3530 и RFC 7530. RFC 8881 прямо требует при смене write verifier предположить потерю старых данных с результатом UNSTABLE4 и восстановить их.

Производительность сменила владельца работы

Сервер получил возможность группировать flush и раньше отвечать. Клиент оплатил это памятью, картой диапазонов и способностью replay. После смены экземпляра накопленный объём нестабильных записей превращается в восстановительный трафик. Работа не исчезла, а была перенесена с обычного пути на условный.