Разработчики KDE подготовили исправление ошибки, из-за которой индикатор копирования на USB-накопитель мог завершаться раньше фактической записи данных. Проблему зарегистрировали в сентябре 2011 года, и она сохранялась около 15 лет. Изменения уже включены в код библиотеки KIO и должны войти в KDE Frameworks 6.32, выпуск которого запланирован на 13 ноября 2026 года. Обновление также изменит перемещение файлов: исходники будут удаляться после успешной синхронизации записи на съёмный накопитель.
Почему файлы ещё записывались после завершения копирования

Разработчик KDE Мевен Кар (Méven Car) рассказал об исправлении 27 октября. Причина ошибки связана с кешированием: успешный вызов write() означает, что система приняла данные в оперативную память, но их запись на устройство может продолжаться позже. Прежний индикатор отражал передачу в кеш и поэтому опережал накопитель.
Кеш отложенной записи – область оперативной памяти, в которой система временно хранит данные перед записью на накопитель. Завершение передачи в этот кеш ещё не означает завершения записи на устройство.
На быстром локальном SSD разница могла оставаться незаметной. Медленная флешка продолжала записывать данные после того, как Dolphin уже считал копирование завершённым. Если пользователь отключал её в этот момент, скопированные файлы могли оказаться повреждены или потеряны.
Особенно опасным было перемещение: KIO удаляла исходные файлы после копирования, хотя их содержимое ещё могло оставаться только в памяти. При преждевременном отключении накопителя пользователь рисковал потерять и оригинал, и пригодную для использования копию.
Почему исправление заняло 15 лет


Сообщение об ошибке № 281270 появилось 3 сентября 2011 года и относилось к KDE 4.7. Уже тогда обсуждался системный вызов sync_file_range(), который позволяет управлять записью отдельных диапазонов файла. Однако требовалось согласовать показания индикатора с накопителем без существенного замедления копирования.
В 2021 году Нейт Грэм повысил приоритет ошибки из-за риска потери файлов при перемещении. В 2022 году доработали сообщение при извлечении устройства, чтобы оно объясняло продолжающуюся запись. В 2024 году разработчики проверяли cachestat(), появившийся в Linux 6.5, но этот вызов предоставляет сведения об отдельных файлах, а не о завершении записи всей файловой системы.
Две попытки Мевена Кара в 2024 году также не дали нужного результата. В одной реализации вызов sync_file_range() оставался закомментированным, в другой ожидание применялось к только что записанному участку, для которого обратная запись ещё не началась. Рабочее решение потребовало ожидать предыдущую порцию данных, пока следующая продолжает заполняться. Предложение полностью отключить кеширование при копировании впоследствии закрыли.
Как теперь учитывается запись на накопитель
KIO передаёт данные ограниченными порциями. Вспомогательный поток запускает их запись через sync_file_range() и ожидает её завершения, пока основной поток готовит следующую порцию. Это ограничивает объём данных, которые уже учтены копированием, но ещё остаются в памяти.
Размер порции подстраивается под измеренную скорость записи: начальное значение составляет 1 МиБ, целевая продолжительность записи – около 200 мс. За один шаг размер может увеличиться не более чем вдвое; верхний предел составляет 16 МиБ, а для CIFS – 128 МиБ. Индикатор опережает подтверждённую запись не более чем на одну такую порцию.
sync_file_range() – системный вызов Linux для управления записью диапазонов файла. Сам по себе он не синхронизирует все метаданные и не очищает аппаратный кеш накопителя, поэтому для надёжного завершения копирования нужна дополнительная синхронизация.
Для крупных файлов на съёмном устройстве KIO синхронизирует файл и его каталог через fsync(). Небольшие файлы не синхронизируются по одному: перед завершением всей операции CopyJob вызывает syncfs() для файловой системы назначения. Во время ожидания уведомление показывает сообщение Writing the copied data to the device... – о записи скопированных данных на устройство. Ошибка синхронизации считается ошибкой копирования.
При перемещении исходники сохраняются до успешной синхронизации. Если накопитель отключён во время записи или синхронизация завершилась ошибкой, оставшиеся исходники не удаляются. Файл, размер или время изменения которого поменялись за время ожидания, также сохраняется с предупреждением.
При остановке из-за ошибки KIO сначала синхронизирует уже скопированные данные. После отмены синхронизация запускается отдельно; исходники перенесённых файлов удаляются только после её успешного завершения.
Что показала проверка на USB-флешке
В опубликованных замерах разработчика разница между уведомлением и окончанием записи была особенно заметна на небольших файлах.
| Операция | До исправления: уведомление / завершение записи | После исправления |
|---|---|---|
| Один файл размером 128 МиБ | 0,06–0,13 с / 68–91 с | Оба события через 28,1 с |
| 3000 файлов по 16 КиБ | 1,2 с / 185,2 с | Оба события через 183,9 с |
Меньшее время в замере большого файла разработчик не считает доказательством ускорения: скорость этой флешки сильно менялась между запусками. Главное изменение заключается в том, что время операции теперь учитывает ожидание записи.
Какие устройства получат новое поведение
Для распознавания съёмных устройств KIO использует сведения sysfs: признаки самого диска, доступного снаружи USB-порта или слота PCIe, а также SD-карт. Проверка прослеживает связь зашифрованных томов и LVM с физическим накопителем. Если ни диск, ни его порт не определяются как съёмные, новая обработка для него не включается.
Ограничение объёма ожидающих записи данных также применяется к сетевым файловым системам, которые KIO считает медленными, включая NFS, CIFS, Ceph, GlusterFS, 9p, sshfs и некоторые другие FUSE-подключения. Обычные локальные несъёмные диски сохраняют прежнее поведение.
У исправления есть ограничения. Завершающая синхронизация затрагивает всю файловую систему назначения и может ожидать данные, записанные другими программами. Её выполняет CopyJob: отдельный вызов KIO::file_copy() для небольшого файла не получает такую же завершающую обработку. Очереди загрузки внутри FUSE-программ, например rclone, находятся вне контроля этого механизма; Ceph и FUSE с кешем обратной записи в описанных тестах не проверялись.
Исправление относится к KDE Frameworks, поэтому ориентироваться только на номер KDE Plasma недостаточно. Пользователи получат его по мере обновления соответствующих пакетов в дистрибутиве. Предыдущие сводки разработки KDE также разделяют изменения рабочего стола, Frameworks и Qt.
Вывод
Исправление делает прогресс копирования на съёмные накопители ближе к фактической записи и устраняет преждевременное удаление исходников при перемещении. Операция может дольше оставаться на экране, поскольку теперь включает ожидание накопителя. Перед физическим отключением устройства по-прежнему следует выполнять безопасное извлечение.