Linux overlay что это

Обновлено: 04.07.2024

Для полного понимания процедур крайне желательно ознакомится с темами приведенными ниже:

This article relies on the following:

Так же необходимо отметить что механизм конфигурирования extroot существенно зависит от версии OpwnWrt и в меньшей степени зависит от типа вашего устройства. Данная русскоязычная версия документации будет отталкиваться от версии OpwnWrt 18.06. В качестве аппаратной платформы будет использоваться роутер TP-LINK TL-WDR4300/3600.

У многих роутеров существенно ограничено размер дискового пространства для хранения файлов и данных (встроенная flash-память). Но, в тоже время, роутеры могут быть оборудованы портами USB или SATA, что позволяет подключить к ним внешние устройства хранения, такие, как диски USB-flash и USB-HDD. В более экзотических случаях могут быть подключены даже mini PCI-E или сетевые диски. Подключение подобных устройств позволяет расширить “дисковую” память роутера, в том числе и его корневую файловую систему, rootfs для хранения как дополнительного программного обеспечения, так и дополнительных настроек. В большинстве поддерживаемых устройств OpenWrt разбивает внутреннее хранилище на разделы rootfs и rootfs_data , которые объединяются в одну перезаписываемую файловую систему наложения overlay .

Partition(раздел) Mount point(точка монтирования) Compression(сжатие) Writable(записываемый)
rootfs /rom Yes(Да) No(Нет)
rootfs_data /overlay No(Нет) Yes(Да)
overlay / Unmodified files(Не модифицированные файлы) Yes(Да)

Таким образом, OpenWrt помещается даже в крошечные объемы внутренней памяти (всего 4 МБ), но все же позволяет записывать настройки и устанавливать некоторые пакеты в доступный для записи раздел без изменения всех используемых программ Linux.
Extroot работает, устанавливая другой overlay раздел на внешнем устройстве хранения, и во время загрузки этот новый overlay раздел будет смонтирован поверх overlay раздела внутреннего хранилища. Этот подход позволяет легко откатиться в случае удаления внешнего устройства хранения, поскольку ваше устройство по-прежнему будет иметь свой собственный overlay раздел и, следовательно, будет загружать всю конфигурацию оттуда.
Это означает, что он будет вести себя точно так же, как и перед настройкой extroot.

Инструкции

1.1. Для устройств менее чем с 4 МБ флеш памяти

В образах прошивки OpenWrt по умолчанию нет инструментов для создание extroot, так как система сборки в настоящее время создает только barebone-образы.
Единственный способ использовать эти устройства - перестроить образ прошивки с нужными пакетами с помощью Image Builder.
Image Builder может работать только в 64-битной операционной системе Linux, поэтому, если у вас нет системы Linux, посмотрите инструкции по установке Ubuntu 64bit в VirtualBox.
Затем перейдите на ту же страницу загрузки, где вы можете загрузить прошивку для своего устройства, и прокручивать вниз, пока не найдете файл, начинающийся с “ OpenWrt-imagebuilder ”.
Загрузите его и распакуйте в папку в системе Linux.

Откройте терминал в этой папке и напишите:

Это выведет на экран все возможные имена профилей для устройств, поддерживаемых этим Image Builder, чтобы мы могли создать образ для нужного устройства. Каждая запись будет выглядеть так:

Первая строка - это имя профиля, вторая строка - полное имя вашего устройства, третья строка - список пакетов по умолчанию для этого устройства, и в нем должны быть перечислены некоторые пакеты с USB или Sata или любым другим устройством хранения.

В нашем случаи это TP-LINK TL-WR1043N/ND v1, поэтому имя профиля этого устройства tl-wr1043nd-v1 Теперь нам нужно написать команду, чтобы начать сборку образа (обратите внимание, что имя после PROFILE= является именем профиля данного устройства, обязательно используйте имя профиля для своего устройства):

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

К сожалению, пакет e2fsprogs с инструментами для файловой системы ext4 слишком велик, чтобы поместиться в 4 МБ. Если кто-то может отделить mke2fs и инструменты проверки файловой системы от него, то можно сделать отделенные инструкции по использованию файловой системы ext4.

После этого откройте папку bin внутри папки Image Builder, затем откройте папку target, затем папку, в которой вы ее найдете (она имеет имя, зависящее от типа устройства), а затем внутри папки. называется generic , и вы должны добраться образа для прошивки. Выберите правильный образ (factory или sysupgrade) и установите его.

Затем вам нужно будет отформатировать USB-накопитель в файловую систему ext4, и для этого вам потребуется использовать Linux LiveCD или gparted диск.
К сожалению, это неудобно, но, как сказано выше, мы не можем разместить инструменты форматирования на устройствах с 4 МБ флэш-памяти.

1.2. Устройства более чем с 8 МБ флеш памяти

На этих устройствах должно быть достаточно места для установки необходимых нам пакетов. Удалите все пакеты, которые вы установили, чтобы добавить функциональность, так как они теперь только используют место во встроенной флеш памяти. После того, как вы сделаете extroot, у вас будет все необходимое пространство.

Из интерфейса командной строки напишите (в одну строку):

Это установит пакеты, необходимые для раздела с файловой системой ext4.

Пользователи, подверженные риску, могут захотеть создать собственный образ (как описано в предыдущем разделе), содержащий эти инструменты и особенно модули ядра, которые соответствуют ядру прошивки, чтобы они были доступны в отказоустойчивом режиме(failsafe mode).

2. Настройка rootfs_data

Подключитесь через ssh к устройству.

Сконфигурируйте /etc/config/fstab для монтирования rootfs_data в другой каталог на тот случай, если вам понадобится получить доступ к исходному оверлею root для изменения настроек extroot:

Или вы можете определить раздел rootfs_data вручную:

Каталог /rwm будет содержать исходный корневой overlay, который используется в качестве основного корневого overlay до тех пор, пока extroot не будет поднят и запущен. Позже вы можете отредактировать /rwm/upper/etc/config/fstab , чтобы изменить вашу конфигурацию extroot (или временно отключить ее), если вам это когда-либо понадобится.

3. Настройка extroot

Посмотрите, какие есть у вас разделы:

Здесь мы видим mtdblock устройства (разделы во внутренней флеш памяти), и раздел /dev/sda1 это ваш USB флеш диск.

Отформатируйте раздел /dev/sda1 в ext4 если это необходимо:

Сейчас мы от конфигурируем /dev/sda1 как новый overlay через подсистему fstab uci:

Если у вас есть раздел подкачки, он также будет распознан и добавлен автоматически.

4. Перенос данных

Теперь мы перенесем содержимое текущего оверлея на наш новый оверлей на внешнем диске:

Проверка

Через Web интерфейс

LuCI → System → Mount Points должен быть показан раздел на внешнем USB устройстве подмонтированный как overlay . LuCI → System → Software должно быть показано большее свободное пространство на overlay разделе.

Через командную строку

Раздел на внешнем USB устройстве должен быть подмонтирован как overlay Свободное пространство в корневом разделе / должно быть равно пространству на /overlay .

Сохранение списков программных пакетов при загрузке

Сохранение статуса установленных пакетов opkg в /usr/lib/opkg/lists хранящемся в extroot, а не в RAM, экономит некоторую оперативную память и сохраняет списки пакетов доступными после перезагрузки.

Через Web интерфейс

1. LuCI → System → Software → Configuration

это должно выглядеть примерно так:

2. LuCI → System → Software → Actions → Update lists производит первоначальное обновление списка пакетов на extroot

———–Перевод и обновление статьи продолжается! ———— далее идет старая версия!

Troubleshooting

Add option force_space in /etc/opkg.conf to allow installation of packets bigger than your /rom partitions free space: Do not use vfat (FAT/FAT32); it does not work. If you have a FAT preformatted USB drive, you cannot use it for extroot without reformatting. Use e.g. ext4 (install e2fsprogs, then format your FAT formatted USB drive using mkfs.ext4 /dev/sda1 as per the example, also see storage). On Barrier Breaker, block-mount will create a file /etc/.extroot-uuid on extroot filled with uuid of mtd partition rootfs . At boot time when trying to do extroot, block-mount would try to check the actual uuid with the content of .extroot-uuid . If they did not match, extroot would fail. So if you want to continue use extroot after flashing a new firmwre, /etc/.extroot-uuid needs to be deleted first.

Дополнительные сведения

Extroot на карту памяти в слоте USB-модема

В статье Использование 3g/UMTS USB модема для WAN соединений рекомендуют добавить в образ прошивки утилиту usb-modeswitch .
Использование данной утилиты имеет особенности: если /overlay расположить на карте памяти, находящейся в слоте USB-модема, то даже при совершенно правильных настройках внешнего overlay , работоспособных при любом другом размещении оверлея, в данном случае будут наблюдаться неполадки файловой системы, возникающие на завершающей стадии загрузки ОС. Неполадки вызваны тем, что утилита usb-modeswitch , отключая CDROM и подключая модем, попутно на некоторое время отключает и считыватель карт памяти, нарушая работу файловой системы.
Избежать этого можно заранее настроив USB-модем так, чтобы usb-modeswitch не потребовался вообще: устройство должно сразу представляться ОС как модем или сетевой адаптер со считывателем карт памяти включенными по-умолчанию.

Подключите USB-модем к компьютеру и с помощью терминала отправьте на модем соответствующие AT-команды.
Проверяем исходную конфигурацию USB-модема:

Расшифровать данный ответ модема можно с помощью следующей команды:

В данном примере у нас USB-модем, в котором в первой конфигурации (слева от символа ; ) включены CDROM и считыватель карт, во второй конфигурации (справа от символа ; ) включен модем, управляющий и диагностический интерфейсы, и считыватель карт памяти. Именно между двумя этими конфигурациями утилита usb-modeswitch переключает USB-модем на роутере.

Ваша цель - оставить только одну конфигурацию, в которой по-умолчанию включен модем (см. 1 выше) или сетевой адаптер (см. 16 выше), присутствует считыватель карт памяти (см. A2 выше), но при этом выключен CDROM.
ВНИМАНИЕ: Нельзя отключать интерфейс PCUI (см. 2 выше) - вы потеряете возможность управлять USB-модемом!

Данная последовательность команд выключила CDROM и оставила единственную конфигурацию, в которой по-умолчанию присутствуют модем, интерфейсы и считыватель карт памяти - без необходимости пользоваться утилитой usb-modeswitch на роутере. Обратите внимание на символ ; - слева от него пусто.

Не закончен, так как не хватает знаний. По мере изучения, постараюсь дополнить.

Данная файловая системы используется, например, в Docker. Часто её можно наблюдать на роутерах или других подобных устройствах, где оперативная запись информации ведётся во временную наложенную ФС, доступную до момента выключения устройства.

С помощью OverlayFS я объединяю домашние фото и видео каталоги для удобного просмотра. Так как архивы исходных фотографий доступны только для чтения, наложением рабочей папки, для сохранения временных или промежуточных файлов обработки, я добиваюсь удобства в обработке фоток.

Каталог = Директория = Папка

Перед пониманием темы Overlay Filesystem, мне необходимо провентилировать Linux Virtual File System.

Overlay Filesystem

Этот документ описывает прототип нового подхода к обеспечению функциональности overlay filesystem (наложенная файловая система) в Линукс (некоторые предпочитают называть union-filesystems объединённая файловая система). Overlay filesystem пытается показать файловую систему так, как результат наложения одной ФС поверх другой ФС.

Overlay объекты

Метод наложения файловой системы является смешанным, так как объекты, которые видны в этой ФС не всегда ей принадлежат. Во многих случаях, доступ к объекту в объединении будет неразличимым от доступа к соответствующему объекту из обычной файловой системы. Это наиболее очевидно из поля 'st_dev' возвращаемого системным вызовом stat ( man 2 stat ).

Почитав stat(2), я выяснил, что поле 'st_dev' описывает устройство на котором находится файл. 'st_ino' — номер inode.

В то время как директории будут сообщать 'st_dev' из наложенной файловой системы, объекты, не являющиеся каталогами, могут сообщать 'st_dev' из нижней или верхней файловой системы, которая предоставляет объект. Аналогично 'st_ino' будет уникальным только в сочетании с 'st_dev', и оба они могут изменяться в течение всего времени жизни объекта не-каталога. Многие приложения и инструменты игнорируют эти значения.

В особом случае, когда все наложенные слои принадлежат одной подлежащей файловой системе, то все объекты будут сообщать 'st_dev' из наложенной файловой системы, а 'st_ino' из подлежащей файловой системы. Это делает монтирование наложения более совместимым со сканерами файловой системы, и оверлей-объекты будут отличаться от соответствующих объектов в оригинальной файловой системе.

On 64bit systems, even if all overlay layers are not on the same underlying filesystem, the same compliant behavior could be achieved with the "xino" feature. The "xino" feature composes a unique object identifier from the real object st_ino and an underlying fsid index. If all underlying filesystems support NFS file handles and export file handles with 32bit inode number encoding (e.g. ext4), overlay filesystem will use the high inode number bits for fsid. Even when the underlying filesystem uses 64bit inode numbers, users can still enable the "xino" feature with the "-o xino=on" overlay mount option. That is useful for the case of underlying filesystems like xfs and tmpfs, which use 64bit inode numbers, but are very unlikely to use the high inode number bit.

Верхний и нижний слои

Наложенная файловая система комбинируется из двух ФС - верхней и нижней. Когда имя объекта существует в обеих ФС, тогда объект из верхней ФС виден, а объект из нижней ФС скрыт. В случае с совпадением имён каталогов, их содержимое будет объединено.

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

Нижняя файловая система может быть любой файловой системой, поддерживаемой Linux, и для неё не требуется прав на запись. Нижняя файловая система может быть даже другим оверлеем. Верхняя файловая система обычно доступна для записи, и в таком случае она должна поддерживать создание расширенных атрибутов "trusted.*", и также должна предоставлять допустимый 'd_type' в 'readdir' ответах, так что NFS не подходит.

readdir — чтение директории
описание поля "d_type".


"d_type" Это поле содержит значение, обозначающее тип файла, что позволяет избежать затрат на вызов lstat(2), если дальнейшие действия зависят от типа файла.

When a suitable feature test macro is defined (_DEFAULT_SOURCE on glibc versions since 2.19, or _BSD_SOURCE on glibc versions 2.19 and earlier), glibc defines the following macro constants for the value returned in d_type:
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory.
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file.
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type could not be determined.

На данный момент только некоторые файловые системы (среди них, такие как: Btrfs, ext2, ext3, and ext4) умеют возвращать правильное значение типа файла в поде "d_type". Все приложения обязаны должным образом обрабатывать возвращаемое значение DT_UNKNOWN.

Только в варианте, когда наложенная ФС имеет атрибут "только для чтения" и составлена из двух "только для чтения" файловых систем, могут использоваться любые типы ФС.

Каталоги

В оверлее, в основном, участвуют каталоги. Если имя объекта ссылается не на каталог, и объект проявляется как в верхней, так и в нижней файловых системах, то нижний объект скрыт и имя относится только к верхнему объекту.

Если верхний и нижний объекты являются каталогами, то формируется объединенный каталог.

В момент монтирования две директории, указанные в опциях как "upperdir" и "lowerdir", соединяются в одну объединённую директорию:

Опция "workdir" должна указывать на пустой каталог в той же файловой системе, где находится "upperdir".

dentry — объект VFS, содержащий информацию о директориях ФС и существующий только в памяти файловой системы и не хранится на диске. Если я правильно понял, то предназначен для уменьшения обращений к ФС при перечитывании содержимого каталогов.

Тогда всякий раз, когда поиск запрашивается в такой объединенной директории, просмотр выполняется в каждой фактической директории и объединенный результат кэшируется в dentry, принадлежащем наложенной файловой системе. Если оба актуальных поиска находят каталоги, оба сохраняются и создается объединенный каталог, в противном случае сохраняется только один: верхний, если он существует, иначе нижний.

Объединяются только списки имён из директорий. Другое содержимое, такое как метаданные и расширенные атрибуты, отображается только для директорий из верхней ФС. Эти атрибуты для директории из нижней ФС скрыты.

"Выбеленные" и "непрозрачные" каталоги

Не уверен, что подобрал правильный перевод для "whiteouts and opaque directories".

Чтобы выполнять rm и rmdir без изменения нижней файловой системы, наложенная файловая система должна записать в верхнюю файловую систему информацию о том, что файлы были удалены. Это делается с помощью "выбеленных" и "непрозрачных" каталогов (объекты не-каталоги всегда непрозрачны).

"Выбеленная" директория создаётся как символьное устройство с номером устройства 0/0. Когда в верхнем слое объединенного каталога обнаруживается "выбеленная" директория, любое совпадающее имя на нижнем уровне игнорируется, и сама "выбеленная" директория также скрывается.

Каталог объявляется "непрозрачным" установкой расширенного атрибута "trust.overlay.opaque" в значение "y". Если верхний слой содержит "непрозрачный" каталог с именем совпадающим с именем каталога из нижнего слоя, тогда соответствующий каталог в нижнем слое игнорируется.

Системный запрос readdir (Чтение каталога)

Когда readdir запрашивается в объединенном каталоге, то каждый верхний и нижний каталог читается, а списки имён объединяются очевидным образом (сначала читается верхний, затем нижний, уже существующие имена не добавляются повторно). Этот объединенный список имён кэшируется в 'struct file' и таким остаётся так долго, пока файл остаётся открытым. Если директория открыта и одновременно читается двумя процессами, то каждый из них будет иметь отдельный кэш. A seekdir to the start of the directory (offset 0) followed by a readdir will cause the cache to be discarded and rebuilt.

Это означает, что изменения в объединённой директории не проявятся пока каталог читается. Вряд ли это будет замечено каким-либо программами.

seek offsets are assigned sequentially when the directories are read.
Thus if

  • read part of a directory
  • remember an offset, and close the directory
  • re-open the directory some time later
  • seek to the remembered offset

there may be little correlation between the old and new locations in the list of filenames, particularly if anything has changed in the directory.

Readdir on directories that are not merged is simply handled by the underlying directory (upper or lower).

Переименование каталога

Когда переименовывается каталог, который является нижним или объединённым (то есть этот каталог не был создан на верхнем слое до начала операции), overlayfs может обработать его двумя различными способами:

  1. возврат EXDEV ошибки: эта ошибка возвращается вызовом rename , когда при попытке перемещения файла или директории нарушаются границы файловой системы. Приложение обычно готово обработать эту ошибку ( mv , для примера, рекурсивно копирует дерево директорий). Это поведение по умолчанию.
  2. Если свойство "redirect_dir" включено, тогда директория будет скопирована (без своего содержимого). Потом будет установлен расширенный атрибут "trusted.overlay.redirect" на путь оригинального местоположения от корня наложения. В заключении директория перемещается в новое место.

Есть несколько способов настроить "redirect_dir" свойство.

Kernel config options:

  • OVERLAY_FS_REDIRECT_DIR:
    • If this is enabled, then redirect_dir is turned on by default.
    • If this is enabled, then redirects are always followed by default. Enabling this results in a less secure configuration. Enable this option only when worried about backward compatibility with kernels that have the redirect_dir feature and follow redirects even if turned off.

    Module options (can also be changed through /sys/module/overlay/parameters/* ) :

    • "redirect_dir=BOOL":
      • See OVERLAY_FS_REDIRECT_DIR kernel config option above.
      • See OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW kernel config option above.
      • The maximum number of bytes in an absolute redirect (default is 256)
      • "redirect_dir=on":
        Redirects are enabled.
      • "redirect_dir=follow":
        Redirects are not created, but followed.
      • "redirect_dir=off":
        Redirects are not created and only followed if "redirect_always_follow"
        feature is enabled in the kernel/module config.
      • "redirect_dir=nofollow":
        Redirects are not created and not followed (equivalent to "redirect_dir=off"
        if "redirect_always_follow" feature is not enabled).

      When the NFS export feature is enabled, every copied up directory is indexed by the file handle of the lower inode and a file handle of the upper directory is stored in a "trusted.overlay.upper" extended attribute on the index entry. On lookup of a merged directory, if the upper directory does not match the file handle stores in the index, that is an indication that multiple upper directories may be redirected to the same lower directory. In that case, lookup returns an error and warns about a possible inconsistency.

      Because lower layer redirects cannot be verified with the index, enabling NFS export support on an overlay filesystem with no upper layer requires turning off redirect follow (e.g. "redirect_dir=nofollow").

      Прочие объекты не-Каталоги

      Объекты, не являющиеся каталогами (файлы, симлинки, device-special files, и т.д.), представлены в объединённой ФС из верхней, либо из нижней файловой системы, по обстоятельствам. Когда требуется доступ на запись к файлу, представленному в нижней файловой системе, то сначала файл копируется из нижней ФС в верхнюю (copy_up). Обратите внимание, что создание жёсткой ссылки также требует copy_up, тогда как создание симлинка такой операции конечно не требует.

      Если файл, открытый на запись, не был изменён, то операция copy_up выполнена не будет.

      Процесс copy_up начинается с проверки наличия в верхней ФС соответствующих каталогов, которые создаются при необходимости. После чего в существующий или созданный каталог копируется объект с такими же метаданными (owner, mode, mtime, symlink-target etc.). Далее, в случае если объект это файл, то копируется содержимое нижнего файла в только что созданный файл в верхней ФС. В заключении копируются расширенные атрибуты.

      После завершения процесса copy_up, overlay ФС предоставит прямой доступ к только что созданному файлу из верхней файловой системы. Последующие операции над файлом будут едва заметны для overlay ФС (тогда как операции над именем файла, вроде переименования или unlink, конечно будут замечены и обработаны).

      Множество нижних слоёв

      Множество нижних слоёв можно задать с помощью символа двоеточие (":"), используя его как разделитель между именами каталогово. Для примера:

      Как видно в примере, опции "upperdir=" и "workdir ro-ro-overlay.jpg" src="https://debuntu.ru/a/opisanie-failovoi-sistemy-overlayfs/ro-ro-overlay.jpg" title="ro-ro-overlay.jpg" />

      В пустом каталоге RawArchive , после монтирования доступном только для чтения, мы увидим объединённое отображение двух папок c исходниками фото- и видеоматериалов. Все каталоги, задействованные в этой схеме, могут находиться, как на одном носителе, так и на разных (даже сетевых?).

      Копирование только метаданных

      Когда включена опция копирования только метаданных, overlayfs скопирует только метаданные (в отличие от всего файла), в том случае когда выполняется определённая операция, типа chown/chmod . Полностью файл будет скопирован после того, как файл будет открыт для записи.

      Другими словами, это операция с задержкой копирования данных. Данные будут скопированы в том случае, если понадобится их изменение.

      Есть несколько способов включения/отключния этой опции. Опция CONFIG_OVERLAY_FS_METACOPY может быть установлена/снята для включения/отключения этой функции по умолчанию. Или можно включить/отключить эту опцию во время загрузки модуля с параметром metacopy=on/off. И наконец, использовать опцию metacopy=on/off во время монтирования.

      Не стоит использовать metacopy=on с ненадёжными верхним/нижним каталогом. Otherwise it is possible that an attacker can create a handcrafted file with appropriate REDIRECT and METACOPY xattrs, and gain access to file on lower pointed by REDIRECT. This should not be possible on local system as setting "trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible for untrusted layers like from a pen drive.

      Note: redirect_dir= conflicts with metacopy=on, and results in an error.

      (*) redirect_dir=follow only conflicts with metacopy=on if upperdir=. is given.

      Расшаривание и копирование слоёв

      Нижние слои могут совместно использоваться при монтировании нескольких разных overlay-стеков, и это обычная практика. При монтировании какой-нибудь Overlay может использовать тот же путь до каталога нижнего слоя, что и другой overlay mount.

      Что такое файловая система? Согласно высказыванию одного из первых мэйнтейнеров Linux и автора популярных книг - Роберта Лава, файловая система - это иерархическое хранилище данных, придерживающиеся определённой структуры.

      Однако, это описание одинаково хорошо подходит как для VFAT (Virtual File Allocation Table), так и для Git, Cassandra и других баз данных. Так что же отличает файловую систему? В этой статье мы попытаемся ответить на этот вопрос, а также разобраться что такое виртуальные файловые системы.

      Основы файловых систем

      Ядро Linux требует, чтобы во всём, что считается файловой системой были реализованы методы open(), read(), и write() для постоянных объектов, у которых есть имена. С точки зрения объективно ориентированного программирования, ядро считает файловую систему абстрактным интерфейсом, в котором определены эти виртуальные функции без реализации. Таким образом реализация файловой системы на уровне ядра называется VFS (Virtual Filesystem).


      Мы можем открыть, прочитать и записать в файл.

      Термин VFS лежит в основе всем известного утверждения о том, что в Unix-подобных системах всё является файлом. Подумайте о том, насколько странно, что приведенная выше последовательность действий с файлом /dev/console работает. На снимке показан интерактивный сеанс Bash в виртуальном терминале TTY. При отправке строки устройству виртуальной консоли, она появляется на виртуальном экране. VFS имеет и другие, даже более странные свойства. Например, в таких файлах можно выполнять поиск.

      В таких популярных файловых системах как Ext4, NFS и даже в подсистеме /proc реализованы три основные функции в структуре данных на языке Си, которая называется file_operations. Кроме того, некоторые файловые системы расширяют и переопределяют функции VFS подобным объективно ориентированным способом. Как утверждает Роберт Лав, абстракция VFS позволяет пользователям Linux копировать файлы из других операционных систем или абстрактных объектов, таких как каналы не беспокоясь об их внутреннем формате данных. В пространстве пользователя с помощью системного вызова read() процессы могут копировать содержимое файла в структуры ядра из одной файловой системы, а затем использовать системный вызов write() в другой файловой системе, чтобы записать полученные данные в файл.

      Определения функций, относящиеся к VFS находятся в файлах fs/*.c в исходном коде ядра. Подкаталоги fs/ же содержат различные файловые системы. Ядро также содержит объекты, похожие на файловые системы, это cgroups, /dev и tmpfs, которые нужны на раннем этапе загрузки системы и поэтому определены в подкаталоге исходников init/. Обратите внимание, что они не вызывают функции большой тройки из file_operations, зато они могут непосредственно читать и записывать в память.

      На схеме ниже наглядно показано, как из пространства пользователя можно получить доступ к большинству файловых систем. На рисунке нет каналов, таймера POSIX и dmesg, но они тоже используют методы из структуры file_operations и работают через VFS:


      Существование VFS способствует повторному использованию кода, поскольку основные методы для работы с файловыми системами не переопределяются в каждой файловой системе. Это широко используемая практика, однако если в таком коде есть ошибки, то от них страдают все реализации, использующие общие методы.

      Самый простой способ вывести все виртуальные файловые системы, это выполнить такую команду:

      mount | grep -v sd | grep -v :/

      Она выведет все смонтированные файловые системы, которые не связанны с физическим или сетевым диском. Оной из первых точек монтирования виртуальных файловых систем будет /tmp. Так почему не рекомендуется хранить содержимое /tmp на диске? Потому что файлы из /tmp временные, а постоянные хранилища намного медленнее памяти, где находится tmpfs. Кроме того, физические устройства более подвержены износу от частой записи, в отличие от оперативной памяти. И наконец, файлы в /tmp могут содержать конфиденциальную информацию, поэтому их лучше удалять при каждой перезагрузке.

      /proc и /sys

      Помимо /tmp, виртуальные файловые системы, с которыми знакомо большинство пользователей Linux - это /proc и /sys (/dev полагается на общую память и не поддерживает file_operations). Но зачем аж две? Давайте разбираться.

      Файловая система procfs предоставляет моментальный снимок состояния ядра и процессов, которые оно контролирует в пространстве пользователя. Кроме того, в /proc ядро делает доступной информацию о прерываниях, виртуальной памяти и планировщике. А ещё в /proc/sys размещены параметры, которые можно настроить из пространства пользователя с помощью команды sysctl. Состояние и статистика по каждому процессу находятся в директориях /proc/<PID>.


      /proc/meminfo - пустой файл, но тем не менее, он содержит информацию о памяти

      Поведение файлов в /proc показывает, насколько виртуальные файловые системы могут отличаться от, тех, у которых есть файлы на диске. С одной стороны, файл /etc/meminfo содержит информацию, выводимую командой free. Но с другой стороны, он пустой! Как такое может быть. Ситуация напоминает знаменитую статью, написанную физиком Корнельского университета Дэвидом Мермином в 1985 году под названием Есть ли Луна когда никто не смотрит? На самом деле ядро собирает статистику о памяти, когда процесс запрашивает её из /proc. И на самом деле в файлах из /proc ничего нет, когда никто не смотрит. Как сказал Мермин, "Фундаментальная квантовая доктрина состоит в том, что измерение, как правило, не выявляет ранее существовавшее значение измеряемого свойства.

      Кажущаяся пустота /proc имеет смысл, поскольку доступная информация динамическая и актуальная на момент получения. Ситуация с файловой системой /sys. Давайте сравним сколько файлов, размером хотя бы один байт, находятся в /proc и /sys:


      В procfs такой файл только один - это конфигурация ядра, которую надо генерировать только один раз во время загрузки. С другой стороны в каталоге /sys содержится много файлов большого размера, но большинство из них составляют одну страницу памяти. Обычно файлы из sysfs содержат одно число или строку, в отличие от таблиц информации, например, из /proc/meminfo.

      Цель sysfs - предоставить доступ для чтения и записи свойств так называемых объектов kobjects в пользовательском пространстве. Единственная цель kobject - подсчёт ссылок, когда последняя ссылка на kobject будет удалена, система освободит ресурсы, связанные с ним. К тому же, /sys/ составляет основную часть стабильного ABI ядра для пользовательского пространства, которую никто и ни при каких обстоятельствах не может сломать. Но это не значит, что файлы в sysfs статичны. Это бы противоречило подсчёту ссылок.

      Стабильность ABI ограничивает то, что может появится в /sys, а не то, что на самом деле есть в любой конкретный момент. Перечисление разрешений на файлы в sysfs дает представление о том, что настраиваемые параметры устройств, модулей и файловых систем можно прочитать и изменить. По логике procfs тоже должна быть частью стабильного ABI ядра, однако в документации об этом ничего не сказано.


      Файлы в sysfs можно читать или записывать или всё вместе. Здесь 0 означает, что SSD не извлекаем.

      Слежение за VFS

      Самый простой способ узнать как ядро управляет файлами в sysfs - это посмотреть на это всё в действии. А самый простой способ это сделать на ARM64 или x86_64 - это использование eBPF. eBPF (extended Berkeley Packet Filter) - состоит из виртуальной машины, работающей на уровне ядра, к которой привилегированные пользователи могут обращаться из командной строки. Исходный код ядра показывает читателю как ядро может что-то сделать. Инструменты eBPF показывают как на самом деле всё происходит.

      К счастью, начать работу с eBPF довольно просто с помощью инструментов bcc, для которых доступны пакеты в множестве дистрибутивов. Инструменты bcc - это скрипты на Python с небольшими фрагментами кода на Си, а это значит, что любой кто знаком с этим языком может их модифицировать. На данный момент существует около 80 скриптов на Python в bcc, поэтому каждый найдёт то, что ему надо.

      Чтобы получить общее представление о работе VFS в работающей системе используйте простые скрипты vfscount и vfsstat, которые покажут, что каждую секунду выполняются десятки вызовов vfs_open() и подобных функций:

      В качестве менее общего примера, давайте посмотрим что происходит, когда к работающей системе подключается USB накопитель:


      Когда USB-накопитель вставлен, появляется трассировка вызовов ядра, показывающая что один из потоков kworker с PID 7711 создал файл с именем events в sysfs. При попытке отслеживать вызов sysfs_remove_files() вы увидите, что извлечение флешки приводит к удалению файла events в соответствии с идеей отслеживания ссылок. Отслеживание sysfs_create_link() во время подключения USB накопителя показывает что создается не менее 48 ссылок.

      Зачем же нужен файл events? Используя инструмент cscope можно найти функцию __device_add_disk(), которая вызывает функцию disk_add_events(). А та в свою очередь может записать в файл "media_change" или "eject request". Здесь ядро сообщает в пользовательское пространство о появлении или исчезновении диска. Это намного информативнее, чем просто анализ исходников.

      Файловые системы только для чтения

      Никто не выключает сервер или компьютер, просто отключив питание. Почему? Потому что примонтированные файловые системы на физических устройствах могут выполнять запись и структуры данных файловой системы могут быть не полностью перенесены на диск. Когда такое происходит, вам придется при следующей загрузке подождать восстановления файловой системы с помощью fsck, а в худшем случае вы даже можете потерять данные.

      Тем не менее, вы наверное слышали, что многие встраиваемые устройства, такие как маршрутизаторы, термостаты и даже автомобили работают под Linux. У многих из этих устройств нет пользовательского интерфейса и их невозможно корректно выключить. Представьте автомобиль, основной компьютер которого полностью отключается, когда разряжается батарея. Как тогда быстро включить компьютер, когда двигатель снова заработает и батарея восстановит заряд? Ответ прост. IoT устройства используют корневую систему в режиме только для чтения или коротко ro-rootfs.

      Такой подход даёт несколько преимуществ, которые менее очевидны чем неповреждаемость. Одна из них - вирусы не могут выполнять запись в /user или /lib если ни один процесс Linux не может выполнять туда запись. Во вторых это обеспечивает удобную поддержку удалённых устройств, поскольку они имеют такую же файловую систему как и тестовые образцы. Самое важное обстоятельство такого подхода - разработчикам приходится решать на этапе проектирования какие компоненты системы должны быть неизменяемыми. Работа с ro-rootfs иногда может быть очень сложной, но преимущества компенсируют недостатки.

      Создания таких файловых систем требует дополнительных усилий от разработчиков и здесь снова на помощь приходит VFS. Linux требует, чтобы файлы в /var были доступны для записи, кроме того, множество приложений будут пытаться создавать скрытые файлы в домашней папке. Решением для файлов конфигурации в домашнем каталоге моет быть их предварительное создание. В каталог /var можно монтировать отдельный раздел, доступный для записи, тогда как корень будет все ещё доступен только для чтения. Другая же альтернатива - использование bind и overlay монтирования.

      Bind и overlay монтирование

      Лучше всего про монтирование файловых систем и про bind монтирование в частности можно узнать выполнив такую команду:

      Bind и overlay монтирование позволяет разработчикам встраиваемых систем и системным администраторам создавать файловую систему, доступную по определённому пути, а потом делать её доступной приложениям по совсем другому пути. Для встраиваемых систем подразумевается что можно хранить файлы из /var на устройстве доступном только для чтения, но наложить на /var tmpfs, так чтобы приложения могли туда писать если им это надо. При перезагрузке все изменения в /var будут утеряны. Overlay монтирование позволяет объединить tmpfs и обычную файловую систему так, чтобы в ней можно было изменять файлы, а bind монтирование позволяет сделать доступными для записи пустые папки с tmpfs в ro-rootfs. Хотя overlayfs - это отдельная файловая система, bind монтирование выполняется с помощью VFS.

      Исходя из всего этого, не удивительно, что контейнеры Linux активно используют overlay и bind монтирование. Давайте посмотрим что происходит, когда мы запускаем контейнер с помощью systemd-nspawn. Будем использовать инструмент mountsnoop из набора bcc:


      Осталось посмотреть что произошло:


      Здесь systemd-nspawn размещает нужные файлы из procfs и sysfs хоста в контейнер. Здесь помимо флага MS_BIND, означающего bind-монтирование есть флаги, которые настраивают связь при изменениях файлов процессами контейнера или хоста. Например, файловая система может автоматически отображать изменения в контейнере или скрывать их.

      Выводы

      Понимание внутреннего устройства Linux может показаться невыполнимой задачей, поскольку само ядро содержит огромный объем кода и это не считая приложений пространства пользователя и библиотеки glibc. Один из способов достичь прогресса - прочитать исходный код одной из подсистем ядра, обращая внимание на системные вызовы, которые используются пространством пользователя, а также на основные внутренние интерфейсы ядра, вроде структуры file_operations.

      Структура file_operations - это то, что делает концепцию "Всё есть файл" работающей, поэтому изучение информации о ней особенно интересно. Исходные файлы ядра в каталоге fs/ представляют собой реализацию виртуальных файловых систем, которые представляют из себя слой прокладки для взаимодействия между физическими устройствами и популярными файловыми системами. Bind и overlay монтирование - это магия VFS, которая делает возможным использование Linux на IoT устройствах и контейнеры. Инструменты eBPF вместе с изучением исходного кода ядра, делают исследование ядра проще чем когда либо.

      Как мне это использовать? Где его документация?

      4 ответа

      Верхний и Нижний

      Наложение Файловая система объединяет две файловые системы - «верхнюю» файловую систему и «нижнюю» файловую систему. Когда имя существует в обеих файловых системах, объект в «верхней» файловой системе виден, в то время как объект в «нижней» файловой системе либо скрыт, либо, в случае каталогов, объединяется с «верхним» объектом.

      Было бы более правильно сослаться на верхнее и нижнее «дерево каталогов», а не на «файловую систему», поскольку вполне возможно, что оба дерева каталогов находятся в одной и той же файловой системе, и не требуется, чтобы корень файловой системы быть дано для верхнего или нижнего.

      Нижняя файловая система может быть любой файловой системой, поддерживаемой Linux, и не требует записи. Нижняя файловая система может быть даже другим оверлеем. Верхняя файловая система обычно доступна для записи, и если она есть, она должна поддерживать создание расширенных атрибутов доверенных. * И должна предоставлять допустимый d_type в ответах readdir, поэтому NFS не подходит.

      Только для чтения наложение двух файловых систем только для чтения может использовать любой тип файловой системы.

      Каталоги

      Наложение в основном включает каталоги. Если данное имя появляется как в верхней, так и в нижней файловых системах и ссылается на не каталог в любом из них, то нижний объект скрыт - имя относится только к верхнему объекту.

      Если верхний и нижний объекты являются каталогами, создается объединенный каталог.

      Во время монтирования две директории, указанные как опции монтирования «lowerdir» и «upperdir», объединяются в объединенную директорию:

      «Рабочий каталог» должен быть пустым каталогом в одной и той же директории. файловая система как upperdir.

      Затем всякий раз, когда поиск запрашивается в таком объединенном каталоге, поиск выполняется в каждом фактическом каталоге, и объединенный результат кэшируется в dentry, принадлежащем оверлейной файловой системе. Если оба фактических поиска находят каталоги, оба сохраняются и создается объединенный каталог, в противном случае сохраняется только один: верхний, если он существует, иначе нижний.

      Объединяются только списки имен из каталогов. Другое содержимое, такое как метаданные и расширенные атрибуты, сообщается только для верхнего каталога. Эти атрибуты нижнего каталога скрыты.

      Я расширил эти статьи, добавив в них скрипт для оверлеев, который устанавливает корень fs только для чтения.

      Надеюсь, это поможет.

      Минимальный выполнимый пример

      Вывод первого ls с монтированием:

      Вывод второго ls без монтирования:

      • ниже: было неизменно после записи в наложение
      • верхний: полученный модификация для накладывания
      • наложение: выставочные файлы и от верхнего и от ниже
      • работа: содержит некоторое случайное содержание (a work/ каталог) мы не должны заботиться о

      Протестированный на Ubuntu 18.04, ядро Linux 4.15.0.

      ответ дан Ciro Santilli 新疆改造中心996ICU六四事件 13 October 2017 в 07:08

      Редактировать: После написания этого ответа некоторые вещи изменились в оверлеях, а именно добавление обязательного параметра workdir , подробное описание этого нового параметра см. В ответе totti ниже.

      Поскольку настоящая справочная документация - это скорее «как она работает», а не «как монтировать ее», вот краткое изложение (в документации по ядру есть один пример):

      Где [опции монтирования] могут быть:

      • lowerdir = somedir: lowerdir - каталог, над которым вы собираетесь заложить свою новую файловую систему, если есть дубликаты, эти get перезаписывается (на самом деле, скрыто в пользу) версии upperdir
      • upperdir = somedir: upperdir - это каталог, с которым вы хотите наложить lowerdir. Если дублирующие имена файлов существуют в lowerdir и upperdir, версия upperdir имеет приоритет.
      • Стандартные варианты монтажа. Единственное, что я видел из кода, это ro / rw, но вы можете поэкспериментировать.

      Одна вещь, которая поначалу меня смутила, поэтому я должен пояснить, что монтирование overlayfs фактически не монтирует файловую систему. Я пытался смонтировать файловую систему squashfs с помощью монтирования overlayfs, но это не так. Сначала вы должны смонтировать (в моем случае squashfs) файловую систему в произвольный каталог, а затем использовать overlayfs для объединения точки монтирования (каталога) и другого каталога в третичный каталог (точку монтирования overlayfs) (edit: этот «третичный» каталог) на самом деле может быть каталогу upperdir =). Третичный каталог - это место, где вы увидите объединенные файловые системы (или деревья каталогов - это гибко).

      Пример 1, наложение корневой файловой системы

      Я работал на гибридном загрузочном диске Ubuntu, где базовая система Ubuntu существует как filesystem.squashfs, и у меня есть файлы с именем ubuntu.overlay kubuntu.overlay xubuntu. наложение и lubuntu.overlay. Файлы .overlay - это базовые установки указанных систем с сокращением содержимого filesystem.squashfs (для экономии места). Затем я изменил сценарии инициализации так, чтобы они перекрывали файл .overlay правильного дистрибутива (из параметра загрузки), используя overlayfs и вышеуказанные параметры, и он работает как шарм!

      Это строки, которые я использовал в моих сценариях инициализации. (как только все переменные переведены):

      Обратите внимание, что файл filesystem.squashfs выше - это каталог , созданный casper, а не файл.

      Эти три оператора создают каталог /overlay , монтируют файловую систему squashfs в каталог /overlay и затем используют OverlayFS для существенного объединения содержимого /overlay с / .

      Пример 2, прозрачное объединение двух каталогов

      В процессе перестройки моего живого USB для каждого выпуска я использую OverlayFS, чтобы сэкономить кучу времени. Я начну с каталога под названием ubuntu-base, который содержит содержимое образа ядра ubuntu, который является самой базовой установкой. Затем я создам каталоги с именами ubuntu, kubuntu, lubuntu и xubuntu.

      Затем я использую OverlayFS, чтобы файлы из базы ubuntu отображались в отдельных каталогах. Я бы использовал что-то вроде этого:

      Это заставит файлы из ubuntu-base появляться в папке kubuntu. Затем я могу chroot перейти в папку kubuntu и сделать что-то вроде apt-get install kubuntu-desktop . Любые изменения, сделанные во время этого монтирования OverlayFS, останутся в верхнем каталоге, в этом случае в папке kubuntu. Затем, когда я размонтирую OverlayFS, смонтируйте файлы, которые действительно существуют в ubuntu-base, но «зеркально отражаются» в папке kubuntu, исчезают, если они не были изменены. Это избавляет меня от необходимости иметь несколько копий файлов в Ubuntu-Base, но при этом я могу использовать их, как если бы они физически существовали в каждом месте.

      Читайте также: