Когда действует O_SYNC?

Я изучал проблему, которая возникла у меня с Мендер, из-за которой ход установки (то есть копирование файла на блочное устройство) не отображается правильно.

Я чувствую, что речь идет о кеше страниц ядра: индикатор выполнения показывает «100%», когда код прочитал все изображение, но это не означает, что ядро ​​закончило его запись.

Более конкретно, Mender вызывает n, err := io.Copy(dev, image), который возвращается после завершения записи ядра. Но индикатор выполнения связан с «изображением» Reader, которое полностью считывается за десятки секунд до возврата io.Copy.

Поскольку файл открывается с флагами здесь, я наивно думал, что надо просто поставить flag |= O_SYNC, чтобы io.Copy(dev, image) не читал image быстрее, чем пишет в dev.

Но установка O_SYNC не имеет значения.

Мне не ясно, является ли O_SYNC просто подсказкой (поэтому я не могу на это рассчитывать), может ли быть так, что я что-то упускаю на своем устройстве (например, я забыл параметр ядра на своем Raspberry Pi и поэтому O_SYNC бесполезен ), или если я просто неправильно понял, что делает O_SYNC?

Обновлено: я также пытался установить O_SYNC | O_DIRECT (хотя O_DIRECT, по-видимому, не отображается в Go, и поэтому я сделал O_SYNC | 0o40000), но при открытии блочного устройства я получил следующую ошибку:

Opening device: /dev/mmcblk0p2 for writing with flag: 1069058
Failed to open the device: "/dev/mmcblk0p2": open /dev/mmcblk0p2: not a directory

Вы знать или предполагать, который image полностью прочитан до того, как io.Copy вернется? В первом случае, как вы это проверили?

Yotam Salmon 04.05.2022 18:40

Я добавил тег линукс, так как это действительно внутренний вопрос Linux. Я не думаю, что O_SYNC много для вас делает здесь. Он предназначен для синхронной записи, но если он не передан в драйвер устройства и драйвер не подчиняется ему, а аппаратное обеспечение не взаимодействует, это буквально не мочь поможет вам. O_DIRECT для обхода буферного кеша. больше здесь

torek 04.05.2022 18:56

Спасибо @torek! Я также попробовал O_DIRECT, а потом подумал, что это неправильный путь (также из-за этого: svetlinmladenov.wordpress.com/2013/01/20/on-o_direct). Я отредактировал свой вопрос тем, что пробовал. Должен ли O_DIRECT работать с блочным устройством? Я не понимаю, почему написано: «не каталог», но, может быть, 0o40000 неправильно...?

JonasVautherin 04.05.2022 19:18

@YotamSalmon: Судя по коду (но я его не проверял), индикатор выполнения — это своего рода «декоратор» (не уверен, что это правильное слово) вокруг Reader изображения. Таким образом, индикатор выполнения обновляется напрямую, когда читается Reader. Следовательно, я достаточно уверен, что «100%» означает, что Reader прочитал все байты. Если только где-то в коде не работает какой-то странный прокси, который я пропустил, то есть :-).

JonasVautherin 04.05.2022 19:21
040000 (0o40000 для Go) — это По умолчанию из linux/bits/fcntl-linux.h, но ваша архитектура может иметь другое (зависящее от архитектуры) значение. Похоже, что RPi (рука) имеет этот бит как O_DIRECTORY и O_DIRECT, определенный как 0200000: см. github.com/raspberrypi/tools/blob/master/arm-bcm2708/…
torek 04.05.2022 19:32

Между тем, если индикатор выполнения украшает только часть io.Reader, это, вероятно, будет частью проблемы...

torek 04.05.2022 19:34

@torek: вы правы, в логике завершения индикатора выполнения была ошибка -_-. Не могли бы вы написать свои комментарии об O_SYNC и O_DIRECT (также о части Raspberry Pi) в качестве ответа, который я могу принять? Я немного отредактирую свой вопрос, чтобы сосредоточиться на части O_SYNC (если вам это подходит)

JonasVautherin 04.05.2022 22:29

@YotamSalmon: Итак, вы были правы, это было на стороне индикатора выполнения. Благодаря вам я познакомилась с ним поближе! Большое спасибо :)

JonasVautherin 04.05.2022 22:35

Синхронизация не имела бы значения. Если установщик думал, что запись завершена (но на самом деле она ожидалась), то же самое сделает и остальная часть системы, и установка будет «завершена». Объяснение декоратора io.Reader имеет гораздо больше смысла.

Daniel Farrell 05.05.2022 02:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Резюмируя комментарии:

  1. Основная проблема заключается в том, что индикатор выполнения украшает средство чтения (как Йотам Салмон отметил), а не средство записи; задержка на стороне автора.

  2. В большинстве систем Linux O_DIRECT действительно 0o40000, но на ARM (включая Raspberry Pi) это 0o200000, а 0o40000 — это O_DIRECTORY. Это объясняет ошибку «не каталог».

  3. O_SYNC на самом деле является тем битом, который вам нужен, или вы можете просто выполнить системный вызов fsync (используйте Flush, если это уместно, а затем Sync, как указано в Когда сбрасывать файл в Go?). Бит O_SYNC подразумевает fsync системный вызов как часть каждого write системного вызова.

Полностью синхронный ввод-вывод — это своего рода минное поле: некоторые устройства лгут о том, записывали ли они данные в энергонезависимую память. Тем не менее, O_SYNC или fsync — это наибольшая гарантия, которую вы здесь получите. O_DIRECT, скорее всего, не имеет значения, поскольку вы переходите непосредственно к файлу раздела устройства /dev. O_SYNC или fsyncмая передается драйверу устройства, который мая что-то с ним делает, а мая заставляет устройство записывать в энергонезависимую память. Подробнее об этом читайте в Что на самом деле означает O_DIRECT?.

Другие вопросы по теме