Как findmnt может составить список привязок?

11

Многие люди продолжают утверждать, что Linux не хранит информацию о bind mounts, поэтому нет способа получить их список и их источники. Вот некоторые примеры:

  • из одного из комментариев здесь :

    IIRC эта информация нигде не хранится: после того mount --bind, как две копии эквивалентны, нет ни одной, которая более «оригинальна», чем другая. Ведь не может быть оригинала, если вы уже разобрались /mnt.

  • из ответа на этом сайте :

    Таким образом, единственный способ запомнить, какие монтирования были bind mounts - это журнал оставленных в нем команд монтирования /etc/mtab. Операция монтирования связывания указывается с помощью опции монтирования связывания (которая приводит к игнорированию типа файловой системы). Но mount не имеет возможности перечислять только файловые системы, смонтированные с определенным набором опций.

  • из отчета об ошибке Debian :

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

Выше чепуха, хотя. Инструмент findmntможет перечислять исходные пути монтируемых привязок (в форме device[source-path]; я также пытаюсь заставить его перечислять только исходный путь, а не устройство). Если ядро ​​Linux должно поддерживать монтирование, тогда эта информация должна храниться где-то , иначе она не может знать, с чем /homeона связана /users. Так где эти данные? Хранится ли он в какой-то непонятной области в ОЗУ? Есть ли findmntсмотреть в /procгде - нибудь?

MELAB
источник
Какую версию findmntвы используете и какие варианты вы ей предоставляете? Мой не распечатывает это так, и смотрит на исходный код, который, похоже, использует, _PATH_PROC_MOUNTINFOкоторый выглядит так, /proc/self/mountinfoчто в нем тоже нет этой информации.
Братчли
ОК, я думаю, что /proc/self/mountinfoсравнительно недавно была реструктурирована. Я был на моей машине RHEL6, у которой раньше не было информации о пути, но моя машина RHEL7 делает, и, как упоминалось в вашей ссылке, Wheezy также делает.
Братчли
Это не чепуха: это было верно с более старыми ядрами, но более новые ядра отслеживают информацию.
Жиль "ТАК - перестань быть злым"
@Gilles Тогда как может сохраняться привязка, если информация о том, что один каталог смонтирован в другом, не отслеживается?
Мелаб
@Melab На самом деле, для привязки монтирования легче сохраняться, если вы не отслеживаете, что это привязка монтирования. Когда /dev/Aмонтируется в, /Bи вы делаете mount --bind /B /C, старые ядра помнят только /B → /dev/Aи /C → /dev/A, они не помнят никакой связи между /Bи /C. Таким образом, размонтирование, /Bестественно, не влияет на /C. Более новые ядра помнят, что это /Cбыла привязка /B, но таким образом, который не мешает /Cпродолжать работать, если /Bон отключен, я не знаю точно, как.
Жиль "ТАК - перестань быть злым"

Ответы:

12

Вы неправильно поняли; две точки монтирования равны с точки зрения разрешений, флагов и т. д., поскольку привязка эффективно перенаправляет доступ с одного пути на другой. Но они все еще различны .

Если вы посмотрите на это, /proc/self/mountinfoто увидите представление ядра для мира монтирования для этого процесса (пространства имен усложняют ситуацию; не существует только одного представления таблицы монтирования).

man 5 procобъяснит формат этого файла, но вы увидите древовидную иерархию и то, где у bind mounts есть «родитель». Это файл, который findmntанализирует.

Стивен Харрис
источник
9

Linux не хранит информацию о том, какое монтирование было монтируемым . Он хранит информацию обо всех креплениях, включая привязные .

Это очень похоже на жесткие ссылки. Монтирует ссылки на файловые системы, например, имена файлов ссылаются на inode. Единственное отличие состоит в том, что монтирование также имеет флаги для каждой точки монтирования и может ссылаться на подкаталог целевой файловой системы вместо корня файловой системы.

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

Назад к bind mounts: ядро ​​хранит таблицу, которая содержит файловую систему (определяемую парой старший: младший номер), точку монтирования, путь относительно корня файловой системы и некоторые флаги. Вы можете получить доступ к этому списку, посмотрев на /proc/self/mountinfo. (Это становится более сложным, когда задействованы пространства имен, как упомянул @ stephen-harris). findmntразбирает этот список.

Если ваш корень /dev/sda1с major: minor, 8:1и вы запустите, он mount --bind /a /b /proc/self/mountinfoбудет содержать строки, подобные этой:

1 0 8:1 / / rw - ext4 /dev/sda1 rw,errors=remount-ro
2 1 8:1 /a /b rw - ext4 /dev/sda1 rw,errors=remount-ro

Если ваш /homeесть /dev/sda2с главным: несовершеннолетним 8:2и запустить mount --bind /home /usersэто будет выглядеть следующим образом :

1 0 8:1 / / rw - ext4 /dev/sda1 rw,errors=remount-ro
2 1 8:2 / /home rw - ext4 /dev/sda2 rw
3 1 8:2 / /users rw - ext4 /dev/sda2 rw

Соответствующие столбцы для вашего вопроса - третий, четвертый и пятый. Это идентификатор файловой системы (для реальных файловых систем он такой же, как у основного устройства: minor; для виртуальных файловых систем, таких как tmpfs, это [0: counter ]), путь относительно корня файловой системы, который привязан к точке монтирования (обычно / для обычной mounts, может быть что угодно для bind mounts) и точка монтирования.
Значение остальных столбцов смотрите в документации ядра Linux .

findmntвызывает исходный путь относительно корня файловой системы "FSROOT". Вы можете использовать, findmnt -o TARGET,FSROOTчтобы получить это. Если вам нужен абсолютный путь к исходному коду, вам, вероятно, нужно проанализировать /proc/self/mountinfoсамостоятельно и объединить информацию о монтировании для одной и той же файловой системы.

Для получения дополнительной информации см. Мой ответ на «Список только привязывать крепления» .

cg909
источник
Если /proc/self/mountinfoможет содержать такие строки 2 1 8:1 /a /b rw - ext4 /dev/sda1 rw,errors=remount-ro, то Linux, безусловно , делает держать некоторую информацию о связываемых креплениях.
Мелаб
Посмотри на мой второй пример. Он хранит информацию о том, какая файловая система была смонтирована и какой путь относительно корня файловой системы был смонтирован . Таким образом , для mount --bind /home/melab /mntрезультирующей строки может выглядеть любой из следующих в зависимости от того, какой из /homeи /home/melabявляется точкой монтирования: 3 1 8:1 /home/melab /mnt rw - ext4 /dev/sda1 rw, 3 1 8:2 /melab /mnt rw - ext4 /dev/sda2 rw,3 1 8:3 / /mnt rw - ext4 /dev/sda3 rw
cg909
Это правда, что что-то отличное /от четвертого столбца часто указывает на привязку. Но это также может быть подраздел Btrfs.
cg909
Является ли /dev/sda3должен быть установлен в /home/melab?
Мелаб
Да. В моем примере я использовал /dev/sda1как /, /dev/sda2как /homeи /dev/sda3как/home/melab
cg909