Perché il montaggio avviene su una directory esistente?


52

È necessaria una directory esistente come punto di montaggio .

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

Lo trovo confuso poiché si sovrappone ai contenuti esistenti della directory. Esistono due possibili contenuti della directory del punto di montaggio che possono essere commutati in modo imprevisto (per un utente che non sta eseguendo il montaggio).

Perché non mountaccade in una directory appena creata? Questo è il modo in cui i sistemi operativi grafici visualizzano i supporti rimovibili. Sarebbe chiaro se la directory è montata (esiste) o non montata (non esiste). Sono abbastanza sicuro che ci sia una buona ragione, ma non sono stato ancora in grado di scoprirlo.


1
Se vuoi quel comportamento, usa udisksctl. Perché l'uso mount?
Muru,

1
Perché è il modo di Unix. Perché in questo modo è più flessibile e puoi montarlo ovunque. Perché il loro montaggio ovunque ti consente di estendere i tuoi server di cui hai bisogno, ad esempio, ottenere un nuovo disco per la partizione del database, spostare i dati nella partizione DB sul nuovo disco e montarlo nel posto giusto per consentire i dati DB per crescere di più.
Rui F Ribeiro,

8
Come nota storica, prima che Windows e LInux distruggessero essenzialmente tutti gli altri sistemi operativi, c'era una società chiamata Apollo. Hanno scritto un sistema operativo unix-like (design migliore rispetto a Unix!). Ha creato le directory su cui sono state montate automaticamente le esportazioni NFS. In effetti, non è possibile montare su una directory preesistente. HP acquistò Apollo, buttò via il sistema operativo e usò la CPU a 64 bit di Apollo come HP-PA. Il sistema di chiamate di procedura remote di Apollo è diventato il DCE dell'OSF, che apparentemente vive all'interno di Windows. Sapere è metà della battaglia!
Bruce Ediger,

in qualche modo questo accade sul mio sistema Ubuntu 14.04,3. non ho ancora indagato. quando la mia scheda SD viene montata, finisce in un percorso che non ha nulla sotto. se lo smonto e provo a rimontarlo manualmente, l'errore che ottengo è che non vi è alcuna directory nel punto di montaggio.
Skaperen,

2
@BruceEdiger better design than Unix![citazione necessaria]
Ruslan il

Risposte:


51

Questo è il caso di un dettaglio di implementazione che è trapelato.

In un sistema UNIX, ogni directory è composta da un elenco di nomi associati a numeri di inode . Un inode contiene metadati che indicano al sistema se si tratta di un file, una directory, un dispositivo speciale, una pipe denominata, ecc. Se si tratta di un file o di una directory, indica anche al sistema dove trovare il contenuto del file o della directory sul disco. La maggior parte degli inode sono file o directory. L' -iopzione per lselencare i numeri di inode.

Montare un filesystem prende un inode di directory e imposta un flag sulla copia in memoria del kernel per dire "in realtà, quando cerchi il contenuto di questa directory guarda invece questo altro filesystem" (vedi slide 10 di questa presentazione ). Questo è relativamente semplice in quanto sta cambiando un singolo elemento di dati.

Perché non crea invece una voce di directory che punta al nuovo inode? Esistono due modi per implementarlo, entrambi i quali presentano degli svantaggi. Uno è scrivere fisicamente una nuova directory nel filesystem - ma ciò fallisce se il filesystem è di sola lettura! L'altro è quello di aggiungere a ogni processo di elenco delle directory un elenco di cose "extra" che non sono realmente presenti. Questo è complicato e potenzialmente comporta un piccolo calo delle prestazioni su ogni operazione di file.

Se desideri punti di montaggio creati dinamicamente, il automountsistema può farlo. Filesystem non-disco speciali possono anche creare directory a piacere, ad esempio proc, sys, devfse così via.

Modifica: vedi anche la risposta a Cosa succede quando 'monti' una cartella esistente con contenuti?


Solo che non imposta un flag sull'inode. sudo mount --bind / /mnt ; ls /mnt/proc-> vuoto. Mi chiedo come funzioni.
FonteJedi

L'operazione esatta è in fs/namespace.c, penso; Non ho familiarità con la fonte e non volevo dedicare troppo tempo alla perforazione dei dettagli. La "bandiera sull'inode" che ho ottenuto dalla presentazione collegata.
pjc50,

2
@sourcejedi: monta bind monta solo il filesystem a cui effettivamente fai riferimento. Non vincolano ricorsivamente altri filesystem montati sotto di esso. Questo è un modo pratico per trovare la spazzatura nascosta dai supporti. (ad es. se alcune cose finiscono sul root FS in /var/cachequalche momento quando /varnon si riesce a montare.) Vedi anche path_resolution(7). (Le vecchie manpage di linux avevano quella pagina man nella sezione 2, come die.net) IDK su come Linux effettivamente funziona internamente, per ottimizzare il controllo di ogni componente della directory come possibile mount. Forse aggiungi quella voce VFS nella cache?
Peter Cordes,

2
Bene, questo è il mio punto ... Quindi fs/namei.c(path -> inode lookup) chiama però namespace.c lookup_mnt(). C'è un flag sull'odontoiatria (voce cache directory). Ma questa è solo un'ottimizzazione nota anche come dettaglio di implementazione. Non ti dice quale filesystem è montato lì; devi guardare nella tabella di montaggio. (Vedi m_hash (), per maggiori dettagli sull'implementazione. Linux, almeno, evita ulteriori confronti di stringhe, e AFAICS allo stesso tempo riesce a riutilizzare i dentisti attraverso ad esempio i montaggi di bind, perché è scritto dai maghi).
sourcejedi,

1
@PeterCordes man 8 mount:: mount --bind foo foo. La mountchiamata di bind allega solo (parte di) un singolo filesystem, non possibili submount. L'intera gerarchia dei file, inclusi i sub-mount, viene allegata in una seconda posizione utilizzando :mount --rbind olddir newdir
mikeserv,

19

Se è mount(2) richiesta la creazione di una nuova directory come punto di montaggio, non è possibile montare nulla in un file system di sola lettura. Sarebbe stupido, quindi possiamo escluderlo.

Se mount opzionalmente creasse una nuova directory come mountpoint, sarebbe strano. Non è come montare / smontare avvenga continuamente, quindi inserire una logica aggiuntiva nel kernel per eseguire questi due passaggi con una singola chiamata di sistema non sarebbe un importante aumento di velocità. Lascialo allo spazio utente per effettuare una mkdir(2)chiamata di sistema se ne desidera una. La risposta di Dmitry sottolinea che mount(2)fare entrambe le cose lo renderebbe non atomico. E che ci si vuole un argomento in più per mount(2)con le bandiere del modo come open(2)avviene, per O_CREAT, O_EXCLecc sarebbe solo stupido paragonato a lasciare user-space farlo.

O forse ti stavi chiedendo di fare mount(8)(il tradizionale programma che effettua mount(2)chiamate di sistema)? Ciò sarebbe possibile, ma esiste già un ottimo strumento mkdir(1)per il lavoro e il design di Unix è incentrato su buoni piccoli strumenti che possono essere combinati. Se vuoi uno strumento che fa entrambe le cose, è facile scrivere uno script di shell per costruire quello strumento con due strumenti più semplici. (O, come ha commentato Muru, lo udisksctlfa già, quindi non è necessario scriverlo.) Inoltre, il normale Linux mount(8)da util-linux supporta l' mount -o x-mount.mkdir[=mode]utilizzo della sua x-sintassi per le opzioni per userspace, piuttosto che le opzioni da passare al filesystem.


Ora la domanda più interessante: perché ci deve essere una directory sul filesystem genitore?

Come sottolinea la risposta di pjc50 (nessuna relazione, anche se ha le mie iniziali!), Avere punti di mount mostrati negli elenchi delle directory richiederebbe un controllo extra su ogni readdir().

Avere punti di mount esistono come directory nella directory che li contiene (sul FS padre) è un bel trucco. readdir()non è necessario notare che si tratta di un mount point. Ciò accade solo se il punto di montaggio viene utilizzato come componente del percorso. Naturalmente la risoluzione del percorso deve controllare la tabella di montaggio per ogni componente della directory di un percorso.


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- Direi che è più intelligente: dal punto di vista dell'utente, un filesystem di sola lettura non dovrebbe cambiare, ma consentire i montaggi significa che può
Izkata,

2
@Izkata: Creare un filesystem in sola lettura non significa che l'intera sottostruttura di VFS sia bloccata. Potrebbe avere collegamenti simbolici che puntano a directory di lettura-scrittura o già avere punti di montaggio di lettura-scrittura sotto di essa quando il fs genitore è stato rimontato ro. Esistono molti casi d'uso per filesystem di sola lettura in cui il tuo argomento non ha senso.
Peter Cordes,

2
man 8 mount: x-mount.mkdir[=mode] Consente di creare una directory di destinazione (mountpoint). La modalità argomento opzionale specifica la modalità di accesso al filesystem utilizzata mkdir(2)nella notazione ottale. La modalità predefinita è 0755. Questa funzionalità è supportata solo per gli utenti root.
Mikeserv,

Non vedo alcun caso d'uso importante di filesystem di sola lettura con filesystem di lettura-scrittura montati, specialmente non nei primi Unix. @PeterCordes
kubanczyk il

@kubanczyk: filesystem di root di sola lettura, con un read-write /tmpe /home. O di sola lettura montato su NFS /usrcon un locale /usr/localmontato su di esso. O più in generale, qualsiasi immagine di sola lettura condivisa con una parte modificabile montata su di essa. (Le modifiche locali a un'immagine di sola lettura possono anche essere eseguite su una base per file con filesystem personalizzati come overlayfs o altri filesystem union per Linux, usati su immagini di avvio di LiveCD.) Inizialmente pensavo al root RO inizialmente montato su avvio, ma farlo rw può avvenire prima di altri montaggi.
Peter Cordes,

12

Il montaggio su una directory esistente fa una chiamata mountpraticamente atomica: ha successo o fallisce, almeno dal punto di vista dell'utente. Se mountdovesse creare il mountpoint stesso, avrebbe due punti di errore, rendendo impossibile garantire un rollback pulito. Immagina il seguente scenario:

  1. mount crea correttamente il mountpoint
  2. mount tenta di montare un nuovo file system in quella directory, ma non riesce
  3. mount tenta di rimuovere il mountpoint, ma non riesce

Il sistema finisce con un effetto collaterale di un fallimento mount.

Eccone un altro:

  1. umount smonta correttamente un file system
  2. umount tenta di rimuovere il mountpoint, ma non riesce

Ora, dovrebbe umountrestituire successo o fallimento?


5
mountha 8 diversi codici di ritorno per errori che possono anche essere combinati. Potrebbe semplicemente aggiungerne un altro quando la rimozione della directory non riesce. man7.org/linux/man-pages/man8/mount.8.html#RETURN_CODES
caos

8
Penso che l'OP stia chiedendo perché il mountpoint debba essere una directory esistente, non perché la mountchiamata di sistema non lo crei. Anche se forse era solo la mia interpretazione / aspettativa di ciò che pensavo volesse chiedere l'OP, o cosa avrei chiesto se stessi chiedendo.
Peter Cordes,

3

Un altro caso che può verificarsi:

All'avvio, un'immagine di sola lettura di base viene caricata nella directory principale. Quindi ti piacerebbe scavalcarlo quando vorresti montare la vera radice. Quindi puoi immaginare che mount syscall cambi semplicemente il romountpoint a rw.

Qui, immaginiamo di avere un problema con il filesystem sul mountpoint di root, vorresti poter provare a ripararlo. Con mount overlap, è possibile smontare il filesystem e utilizzare fsckl'immagine fornita di base per risolverlo.

Questa funzionalità può essere utile anche nei sistemi che richiedono una sicurezza elevata per tenere traccia delle modifiche tra una ropartizione e una rw.


1
Non sono sicuro di come questo risponda alla domanda. Stai sottolineando che, se mount necessario, creando una nuova directory nella posizione del mountpoint che non puoi montare nulla su un filesystem di sola lettura? Il paragrafo di apertura è confuso: non è così che funziona initrd Linux. Usa la pivot_rootchiamata di sistema per cambiare il root fs, non solo per montare più cose su di esso. Ciò ha reso difficile seguire la tua logica nei prossimi paragrafi, perché pensavo che stavi parlando pivot_root(2).
Peter Cordes,

2
@PeterCordes - Linux non usa un initrd da molti anni : quando si cambia un altro dispositivo root, initrd lo farebbe pivot_roote poi umountil ramdisk. Ma initramfs è rootfs: non puoi né pivot_rootrootfs né smontarlo . Invece elimina tutto da rootfs per liberare spazio ( find -xdev / -exec rm {} \;), monta rootfs con il nuovo root ( cd /newmount; mount --move . /; chroot .), collega stdin / stdout / stderr al nuovo / dev / console e execil nuovoinit
mikeserv il

@mikeserv: pulito! Non mi ero reso conto che il meccanismo di base per il cambio delle radici è cambiato quando abbiamo iniziato a usare initramfs anziché initrd. Dal punto di vista amministrativo "assicurati che i moduli del kernel giusti finiscano in esso", sono identici>. <. Penso ancora che questo non risponda molto bene alla domanda . Sembra supporre che l'interpretazione "montare sotto un rofs è impossibile", e fornisce un caso molto specifico (il che sembra improbabile perché initramfs non è montato in sola lettura all'avvio. E anche se lo è, può semplicemente essere rimontato leggi -write senza influenzare l'immagine cpio.gz.)
Peter Cordes il

@PeterCordes - non capisco davvero questa risposta. ho appena visto il tuo commento - initramfs è un file system - non può mai essere di sola lettura - la sua cache fs si incarna.
Mikeserv,

2

Mi sono sempre chiesto anche questo.

Un semplice wrapper come:

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

salvato come uno script eseguibile chiamato mountin una directory che ha la precedenza /binsul tuo PERCORSO dovrebbe occupartene se ti dà troppo fastidio

(Prima di eseguire il file mountbinario effettivo , crea una directory denominata dopo l'ultimo argomento mount, se tale directory non esiste già.)


In alternativa, se non si desidera invocazioni non riuscite del mountwrapper per creare directory, è possibile effettuare:

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

Il mountcomando non dovrebbe quindi utilizzare la directory così creata?
Muru,

1
@muru Ecco cosa fa l'ultima riga.
PSkocik,

Oh, quindi vuoi dire che dovrebbe essere usato così mount /dev/foo /some/path:? Ho pensato che avrebbe funzionato come udisksctlfa, quindi avresti corso mount /dev/foo.
muru,

4
Puoi ottenere l'ultimo cmdline arg senza evalespanderlo $#, usando "${@:-1}". Ho provato questo con DASH, poiché penso che non supporti nulla oltre a ciò che è richiesto POSIX sh per supportare. /bin/dash -c 'echo ${@:-1}' foo barstampe bar.
Peter Cordes,

1
puoi usare man -o x-mount.mkdir...
mikeserv il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.