Почему монтирование происходит через существующий каталог?

В качестве точки монтирования требуется существующий каталог.

$ ls $ sudo mount /dev/sdb2 ./datadisk mount: mount point ./datadisk does not exist $ mkdir datadisk $ sudo mount /dev/sdb2 ./datadisk $ 

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

Почему mount не происходит во вновь созданный каталог? Именно так отображаются графические операционные системы сменных носителей. Было бы ясно, если каталог установлен (существует) или не установлен (не существует). Я уверен, что есть веская причина, но я еще не смог ее обнаружить.

Это случай детализации реализации, который просочился.

В системе UNIX каждый каталог состоит из списка имен, сопоставленных с номерами inode . Индекс содержит метаданные, которые сообщают системе, является ли это файлом, каталогом, специальным устройством, именованным каналом и т. Д. Если это файл или каталог, он также сообщает системе, где можно найти содержимое файла или каталога на диске. Большинство индексных дескрипторов – файлы или каталоги. Параметр -i для ls будет перечислять номера inode.

Установка файловой системы принимает индекс inode и устанавливает флаг в копии ядра в памяти, чтобы сказать «фактически, при поиске содержимого этой директории вместо этой другой файловой системы» (см. Слайд 10 этой презентации ). Это относительно просто, поскольку он меняет единый элемент данных.

Почему он не создает запись в каталоге, указывающую на новый индекс? Есть два способа реализовать это, оба из которых имеют недостатки. Один из них – физически написать новый каталог в файловой системе, но это не удается, если файловая система только для чтения! Другой заключается в том, чтобы добавить к каждому каталогу процесс списка список «лишних» вещей, которые на самом деле не существуют. Это неудобно и потенциально может привести к небольшому результативному результату при каждой операции с файлами.

Если вам нужны динамически созданные точки automount система automount может это сделать. Специальные файловые системы без диска также могут создавать каталоги по желанию, например proc , sys , devfs и т. Д.

Изменить: см. Также ответ на вопрос Что происходит, когда вы монтируете существующую папку с содержимым?

Если mount(2) потребовал, чтобы создание нового каталога являлось точкой монтирования, вы не могли монтировать ничего в файловой системе только для чтения. Это было бы глупо, поэтому мы можем это исключить.

Если mount, возможно, создал новый каталог для точки монтирования, это было бы странно. Это не похоже на то, что mount / unmount происходит все время, поэтому добавление дополнительной логики в ядро ​​для выполнения этих двух шагов с помощью единого системного вызова не будет важным ускорением. Просто оставьте это до пользовательского пространства, чтобы сделать системный вызов mkdir(2) если он этого захочет. Ответ Дмитрия указывает, что с mount(2) обе эти вещи сделают его неатомным. И вам нужен дополнительный аргумент для mount(2) с такими флагами режима, как open(2) , для O_CREAT , O_EXCL и т. Д. Было бы просто глупо сравнивать с тем, чтобы позволить пользователю делать это.

Или, может быть, вы спрашивали о том, как mount(8) (традиционная программа, которая делает системные вызовы mount(2) )? Это было бы возможно, но для работы уже есть неплохой mkdir(1) , а дизайн Unix – это хорошие инструменты, которые можно комбинировать. Если вам нужен инструмент, который делает оба, легко написать сценарий оболочки для создания этого инструмента из двух более простых инструментов. (Или, как прокомментировал муру, udisksctl уже делает это, поэтому вам не нужно его писать.) Кроме того, обычное mount(8) от Linux-linux поддерживает mount -o x-mount.mkdir[=mode] используя его x- синтаксис для параметров для пользовательского пространства, а не параметры, которые необходимо передать в файловую систему.


Теперь более интересный вопрос: почему вообще должен быть каталог в родительской файловой системе?

Как и в ответах на вопрос pjc50 (никакого отношения, хотя у него есть мои инициалы!), Наличие точек монтирования, отображаемых в списках каталогов, потребует дополнительной проверки для каждого readdir() .

Наличие точек монтирования существует, поскольку каталоги в каталоге, содержащем их (на родительском FS), являются хорошим трюком. readdir() не должен заметить, что это точка монтирования вообще. Это происходит только в том случае, если точка монтирования используется как компонент пути. Конечно, разрешение пути должно проверять таблицу монтирования для каждого компонента каталога пути.

Подключение к существующему каталогу делает вызов для mount практически атомарным: он либо преуспевает, либо не работает, по крайней мере, с точки зрения пользователя. Если mount должен был создать точку монтирования, она имела бы две точки отказа, что сделало бы невозможным гарантировать чистый откат. Представьте себе следующий сценарий:

  1. mount успешно создает точку монтирования
  2. mount пытается подключить новую файловую систему к этому каталогу, но не работает
  3. mount пытается удалить точку монтирования, но не работает

Система заканчивается побочным эффектом отказавшего mount .

Вот еще один:

  1. umount успешно размонтирует файловую систему
  2. umount пытается удалить точку монтирования, но не работает

Теперь, следует ли возвращать успех или неудачу?

Другой случай, который может произойти:

Когда вы загружаете, основное изображение только для чтения – это загрузка в корневой каталог. Таким образом, вы хотели бы переопределить его, если захотите вырезать настоящий корень. Таким образом, вы можете себе представить, что mount syscall просто заменяет точку монтирования ro на rw .

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

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

Я всегда это задавался.

Простая обертка, такая как:

 #!/bin/sh eval "mkdir -p \"\$$#\"" /bin/mount "$@" 

сохраненный как исполняемый скрипт с именем mount в директории, переопределяющей /bin в вашем PATH, должен позаботиться об этом, если это вас слишком беспокоит

(Перед запуском фактического бинарного файла mount он создает каталог с именем после последнего аргумента для mount , если такой каталог уже не существует).


Кроме того, если вы не хотите, чтобы вызванные вызовы оболочки mount создавали каталоги, вы можете:

 #!/bin/sh set -e eval "lastArg=\"\$$#\"" test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; } /bin/mount "$@" || { test -z "$madeDir" || rmdir "$lastArg"; }