¿Por qué el montaje ocurre sobre un directorio existente?

52

Se necesita un directorio existente como punto de montaje .

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

Me resulta confuso ya que superpone los contenidos existentes del directorio. Hay dos posibles contenidos del directorio del punto de montaje que pueden cambiarse inesperadamente (para un usuario que no está realizando el montaje).

¿Por qué no mountsucede en un directorio recién creado? Así es como los sistemas operativos gráficos muestran los medios extraíbles. Sería claro si el directorio está montado (existe) o no está montado (no existe). Estoy bastante seguro de que hay una buena razón, pero aún no he podido descubrirlo.

Melebio
fuente
1
Si quieres ese comportamiento, úsalo udisksctl. ¿Por qué usar mount?
muru
1
Porque es el camino de Unix. Porque de esta manera es más flexible y puedes montarlo en cualquier lugar. Debido a que montarlos en cualquier lugar le permite extender sus servidores según lo necesite, por ejemplo, obtener un nuevo disco para la partición de la base de datos, mover los datos en la partición DB al nuevo disco y montarlo en el lugar correcto para permitir los datos DB para crecer más.
Rui F Ribeiro
8
Como nota histórica, antes de que Windows y Linux destruyeran esencialmente todos los demás sistemas operativos, había una compañía llamada Apollo. Escribieron un sistema operativo similar a Unix (¡mejor diseño que Unix!). Creó los directorios en los que las exportaciones NFS se montaron automáticamente. De hecho, no podría montar en un directorio preexistente. HP compró Apollo, tiró el sistema operativo y usó la CPU de 64 bits de Apollo como HP-PA. El sistema de llamadas de procedimiento remoto de Apollo se convirtió en el DCE de OSF, que aparentemente vive dentro de Windows. ¡Saber es la mitad de la batalla!
Bruce Ediger
de alguna manera esto sucede en mi sistema ubuntu 14.04,3. No he investigado, todavía. cuando mi tarjeta SD se monta, termina en un camino que no tiene nada debajo. si lo desmonto e intento volver a montarlo manualmente, el error que obtengo es que no hay un directorio en el punto de montaje.
Skaperen
2
@BruceEdiger better design than Unix![cita requerida]
Ruslan

Respuestas:

51

Este es un caso de un detalle de implementación que se ha filtrado.

En un sistema UNIX, cada directorio consta de una lista de nombres asignados a números de inodo . Un inodo contiene metadatos que le dicen al sistema si es un archivo, directorio, dispositivo especial, canalización con nombre, etc. Si es un archivo o directorio, también le dice al sistema dónde encontrar el contenido del archivo o directorio en el disco. La mayoría de los inodos son archivos o directorios. La -iopción para lslistará los números de inodo.

El montaje de un sistema de archivos toma un inodo de directorio y establece un indicador en la copia en memoria del núcleo para decir "en realidad, cuando busque el contenido de este directorio, mire este otro sistema de archivos" (vea la diapositiva 10 de esta presentación ). Esto es relativamente fácil ya que está cambiando un solo elemento de datos.

¿Por qué no crea una entrada de directorio para que apunte al nuevo inodo? Hay dos formas de implementarlo, las cuales tienen desventajas. Una es escribir físicamente un nuevo directorio en el sistema de archivos, ¡pero eso falla si el sistema de archivos es de solo lectura! La otra es agregar a cada proceso de listado de directorio una lista de cosas "adicionales" que realmente no están allí. Esto es incómodo y potencialmente incurre en un pequeño impacto en el rendimiento en cada operación de archivo.

Si desea puntos de montaje creados dinámicamente, el automountsistema puede hacer esto. Sistemas de archivos no son de disco especiales también pueden crear directorios a voluntad, por ejemplo proc, sys, devfsy así sucesivamente.

Editar: vea también la respuesta a ¿Qué sucede cuando 'monta sobre' una carpeta existente con contenido?

pjc50
fuente
Excepto que no establece una bandera en el inodo. sudo mount --bind / /mnt ; ls /mnt/proc-> vacío. Me pregunto cómo funciona.
sourcejedi
La operación exacta está en fs/namespace.c, creo; No estoy familiarizado con la fuente y no quería pasar demasiado tiempo perforando los detalles. La "bandera en el inodo" que obtuve de la presentación vinculada.
pjc50
2
@sourcejedi: los montajes de enlace solo vinculan el sistema de archivos al que realmente se refiere. No enlazan recursivamente otros sistemas de archivos montados debajo de él. Esta es una forma práctica de encontrar basura oculta por monturas. (por ejemplo, si algunas cosas terminaron en el FS raíz en /var/cachealgún momento cuando /varno se pudo montar). Consulte también path_resolution(7). (Las páginas de manual de Linux anteriores tenían esa página de manual en la sección 2, como die.net). Identifique cómo Linux funciona realmente internamente, para optimizar la comprobación de cada componente del directorio como un posible montaje. ¿Quizás anclar esa entrada VFS en caché?
Peter Cordes
2
Bien, ese es mi punto ... Entonces fs/namei.c(ruta -> búsqueda de inodo) llama a namespace.c sin embargo lookup_mnt(). Hay una bandera en la dentry (entrada de caché de directorio). Pero eso es solo una optimización, también conocida como detalle de implementación. No le dice qué sistema de archivos está montado allí; tienes que mirar en la mesa de montaje. (Consulte m_hash (), para obtener más detalles sobre la implementación. Linux, al menos, evita comparaciones de cadenas adicionales, y AFAICS al mismo tiempo se las arregla para reutilizar dentry en, por ejemplo, monturas de enlace, porque está escrito por asistentes).
sourcejedi
1
@PeterCordes man 8 mount:: mount --bind foo foo. La mountllamada de enlace solo adjunta (parte de) un solo sistema de archivos, no es posible submontar. Toda la jerarquía de archivos, incluidos los submontajes, se adjunta un segundo lugar mediante :mount --rbind olddir newdir
mikeserv
19

Si se mount(2) requiere la creación de un nuevo directorio para ser el punto de montaje, no podría montar nada bajo un sistema de archivos de solo lectura. Eso sería tonto, por lo que podemos descartarlo.

Si mount creara opcionalmente un nuevo directorio para ser el punto de montaje, sería extraño. No es como montar / desmontar todo el tiempo, por lo que poner lógica adicional en el núcleo para realizar estos dos pasos con una sola llamada al sistema no sería una aceleración importante. Simplemente déjelo al espacio del usuario para hacer una mkdir(2)llamada al sistema si lo desea. La respuesta de Dmitry señala que mount(2)hacer ambas cosas lo haría no atómico. Y te gustaría un argumento adicional para mount(2)con banderas modo como open(2)se lleva, para O_CREAT, O_EXCL, etc. Sólo sería tonto en comparación con dejar el espacio de usuario hacerlo.

¿O tal vez estabas preguntando sobre cómo hacer esto mount(8)(el programa tradicional que hace mount(2)llamadas al sistema)? Eso sería posible, pero ya hay un producto perfectamente bueno mkdir(1)para el trabajo, y el diseño de Unix se trata de buenas herramientas pequeñas que se pueden combinar. Si desea una herramienta que haga ambas cosas, es fácil escribir un script de shell para construir esa herramienta a partir de dos herramientas más simples. (O, como comentó muru, udisksctlya lo hace, por lo que no tiene que escribirlo). Además, Linux es normal mount(8)desde util-linux admite el mount -o x-mount.mkdir[=mode]uso de su x-sintaxis para las opciones de espacio de usuario, en lugar de las opciones que se pasan al sistema de archivos.


Ahora la pregunta más interesante: ¿por qué tiene que haber un directorio en el sistema de archivos principal?

Como señala la respuesta de pjc50 (¡sin relación, a pesar de que tiene mis iniciales!), Hacer que los puntos de montaje aparezcan en los listados del directorio requeriría una verificación adicional en cada uno readdir().

Tener puntos de montaje como directorios en el directorio que los contiene (en el FS primario) es un buen truco. readdir()no tiene que notar que es un punto de montaje en absoluto. Eso solo sucede si el punto de montaje se usa como un componente de ruta. La resolución de ruta, por supuesto, tiene que verificar la tabla de montaje para cada componente de directorio de una ruta.

Peter Cordes
fuente
1
If mount(2) required the creation of a new directory to be the mount point, you couldn't mount anything under a read-only filesystem. That would be dumb- Yo diría que es más inteligente: desde la perspectiva del usuario, un sistema de archivos de solo lectura no debería cambiar, pero permitir montajes significa que puede
Izkata
2
@Izkata: Hacer un sistema de archivos de solo lectura no significa que todo el subárbol del VFS esté congelado. Podría tener enlaces simbólicos que apuntan a directorios de lectura-escritura, o ya tener puntos de montaje de lectura-escritura debajo cuando se montó el fs principal ro. Hay muchos casos de uso para sistemas de archivos de solo lectura donde su argumento no tiene sentido.
Peter Cordes
2
man 8 mount: x-mount.mkdir[=mode] Permitir hacer un directorio de destino (punto de montaje). El modo de argumento opcional especifica el modo de acceso al sistema de archivos utilizado para la mkdir(2)notación octal. El modo predeterminado es 0755. Esta funcionalidad solo es compatible con usuarios root.
mikeserv
No veo ningún caso de uso importante de sistemas de archivos de solo lectura con sistemas de archivos de lectura y escritura montados, especialmente no en los primeros Unix. @PeterCordes
kubanczyk
@kubanczyk: sistema de archivos raíz de solo lectura, con lectura y escritura /tmpy /home. O montado en NFS de solo lectura /usrcon un local /usr/localmontado en él. O, más generalmente, cualquier imagen compartida de solo lectura con una parte modificable montada sobre ella. (Las modificaciones locales a una imagen de solo lectura también se pueden hacer por archivo con sistemas de archivos personalizados como overlayfs u otros sistemas de archivos de unión para Linux, utilizados en imágenes de arranque LiveCD). Inicialmente estaba pensando en el RO raíz montado inicialmente en RO arranque, pero hacer que rw pueda suceder antes de otras monturas.
Peter Cordes
12

El montaje en el directorio existente hace una llamada a mountprácticamente atómica: tiene éxito o falla, al menos desde la perspectiva del usuario. Si mounttuviera que crear el punto de montaje en sí, tendría dos puntos de falla, lo que haría imposible garantizar un retroceso limpio. Imagine el siguiente escenario:

  1. mount crea con éxito el punto de montaje
  2. mount intenta montar un nuevo sistema de archivos en ese directorio, pero falla
  3. mount intenta eliminar el punto de montaje, pero falla

El sistema termina con un efecto secundario de un error mount.

Aqui hay otro más:

  1. umount desmonta con éxito un sistema de archivos
  2. umount intenta eliminar el punto de montaje, pero falla

Ahora, ¿debería umountdevolver el éxito o el fracaso?

Dmitry Grigoryev
fuente
55
mounttiene 8 códigos de retorno diferentes para errores que también se pueden combinar. Simplemente podría agregar otro cuando falla la eliminación del directorio. man7.org/linux/man-pages/man8/mount.8.html#RETURN_CODES
caos
8
Creo que el OP pregunta por qué el punto de montaje debe ser un directorio existente, no por qué el mountsistema no lo crea. Aunque tal vez eso fue solo mi interpretación / expectativa de lo que pensé que el OP quería preguntar, o lo que hubiera preguntado si hubiera preguntado.
Peter Cordes
3

Otro caso que puede ocurrir:

Cuando inicia, una imagen básica de solo lectura se carga en el directorio raíz. Por lo tanto, le gustaría anularlo cuando desee amontonar la raíz real. Entonces puede imaginar que mount syscall simplemente cambie el punto de romontaje a rw.

Aquí, imaginemos que tiene un problema con el sistema de archivos en el punto de montaje raíz, le gustaría intentar repararlo. Con la superposición de montaje, puede desmontar el sistema de archivos y usarlo fscken la imagen básica para resolverlo.

Esta característica también puede ser útil en sistemas que necesitan una seguridad sólida para realizar un seguimiento del cambio entre una ropartición y una rw.

alexises
fuente
1
No estoy seguro de cómo esto responde la pregunta. ¿Está señalando que, si fuera mount necesario, crear un nuevo directorio en la ubicación del punto de montaje que no podría montar nada encima de un sistema de archivos de solo lectura? El primer párrafo es confuso: no es así como funciona Linux initrd. Utiliza la pivot_rootllamada del sistema para cambiar la raíz fs, no solo montar más cosas sobre ella. Eso hizo difícil seguir tu lógica en los siguientes párrafos, porque pensé que estabas hablando pivot_root(2).
Peter Cordes
2
@PeterCordes: Linux no ha usado un initrd durante muchos años : cuando se cambia otro dispositivo raíz, initrd lo haría pivot_rooty luego umountel disco ram. Pero initramfs es rootfs: no puedes ni pivot_rootrootfs ni desmontarlo . En su lugar, elimine todo de rootfs para liberar el espacio ( find -xdev / -exec rm {} \;), supere rootfs con la nueva raíz ( cd /newmount; mount --move . /; chroot .), adjunte stdin / stdout / stderr a la nueva / dev / console y execla nuevainit
mikeserv
@mikeserv: ¡Genial! No me había dado cuenta de que el mecanismo básico para cambiar de raíz cambió cuando comenzamos a usar initramfs en lugar de initrd. Desde una perspectiva administrativa de "asegúrese de que los módulos de kernel correctos terminen en él", son idénticos>. <. Sigo pensando que esto realmente no responde muy bien la pregunta . Parece suponer que la interpretación de "montar bajo un rofs es imposible", y da un caso de problema muy específico (lo que parece poco probable porque initramfs no está montado de solo lectura en el arranque. E incluso si lo es, simplemente se puede volver a montar leer -escribir sin afectar la imagen cpio.gz.)
Peter Cordes
@ PeterCordes - Realmente no entiendo esta respuesta. Acabo de ver su comentario: el initramfs es un sistema de archivos, realmente nunca puede ser de solo lectura, su caché fs encarnado.
mikeserv
2

Siempre me he preguntado eso también.

Un contenedor simple como:

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

guardado como un script ejecutable nombrado mounten un directorio que sobrescribe /binen su RUTA debe ocuparse de esto si le molesta demasiado

(Antes de ejecutar el mountbinario real , crea un directorio con el nombre del último argumento mount, si dicho directorio ya no existe).


Alternativamente, si no desea invocaciones fallidas del mountcontenedor para crear directorios, puede hacer:

#!/bin/sh
set -e
eval "lastArg=\"\$$#\""
test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; }
/bin/mount "$@"  ||  {  test -z "$madeDir" || rmdir "$lastArg"; }
PSkocik
fuente
¿No debería el mountcomando usar el directorio así creado?
muru
1
@muru Eso es lo que hace la última línea.
PSkocik
Ah, entonces quieres decir que debería usarse así mount /dev/foo /some/path:? Supuse que funcionaría como lo udisksctlhace, así que correría mount /dev/foo.
muru
44
Puede obtener el último cmdline arg sin evalexpandir $#, utilizando "${@:-1}". Probé esto con DASH, ya que creo que no admite nada más allá de lo que POSIX sh debe admitir. /bin/dash -c 'echo ${@:-1}' foo barimpresiones bar.
Peter Cordes
1
puedes usar man -o x-mount.mkdir...
mikeserv