Dlaczego montuje się w istniejącym katalogu?

52

Istniejący katalog jest potrzebny jako punkt podłączenia .

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

Uważam to za mylące, ponieważ nakłada się na istniejącą zawartość katalogu. Istnieją dwie możliwe treści katalogu punktu podłączenia, które mogą zostać nieoczekiwanie przełączone (dla użytkownika, który nie wykonuje montowania).

Dlaczego nie mountdzieje się w nowo utworzonym katalogu? W ten sposób graficzne systemy operacyjne wyświetlają nośniki wymienne. Byłoby jasne, czy katalog jest podłączony (istnieje), czy nie został podłączony (nie istnieje). Jestem pewien, że istnieje dobry powód, ale jeszcze go nie odkryłem.

Melebius
źródło
1
Jeśli chcesz tego zachowania, użyj udisksctl. Dlaczego warto korzystać mount?
muru
1
Ponieważ jest to droga Uniksa. Ponieważ w ten sposób jest bardziej elastyczny i można go zamontować w dowolnym miejscu. Ponieważ zamontowanie ich w dowolnym miejscu pozwala na rozszerzenie serwerów w razie potrzeby, na przykład uzyskanie nowego dysku dla partycji bazy danych, przeniesienie danych z partycji DB na nowy dysk i zamontowanie go we właściwym miejscu, aby umożliwić dane DB rosnąć więcej.
Rui F Ribeiro,
8
Historycznie rzecz biorąc, zanim Windows i LInux zasadniczo zniszczyły wszystkie inne systemy operacyjne, istniała firma o nazwie Apollo. Napisali system operacyjny podobny do Unixa (lepszy design niż Unix!). Stworzył katalogi, w których eksportowane przez NFS pliki były montowane automatycznie. W rzeczywistości nie można zamontować w istniejącym katalogu. HP kupił Apollo, wyrzucił system operacyjny i użył 64-bitowego procesora Apollo jako HP-PA. System zdalnego wywoływania procedur Apollo stał się DCE OSF, który najwyraźniej działa w systemie Windows. Wiedza to połowa sukcesu!
Bruce Ediger,
jakoś tak się dzieje na moim systemie Ubuntu 14.04,3. jeszcze nie zbadałem. kiedy moja karta SD zostanie zamontowana, kończy się to ścieżką, która nie ma nic pod spodem. jeśli go umountuję i spróbuję ręcznie zamontować z powrotem, pojawia się błąd, że nie ma katalogu w punkcie montowania.
Skaperen
2
@BruceEdiger better design than Unix![potrzebne źródło]
Ruslan

Odpowiedzi:

51

Jest to przypadek szczegółu implementacji, który wyciekł.

W systemie UNIX każdy katalog składa się z listy nazw odwzorowanych na numery i- węzłów . I-węzeł przechowuje metadane, które informują system, czy jest to plik, katalog, urządzenie specjalne, nazwany potok itp. Jeśli jest to plik lub katalog, informuje również system, gdzie znaleźć zawartość pliku lub katalogu na dysku. Większość i-węzłów to pliki lub katalogi. -iOpcja lsbędzie lista numerów węzłów.

Montowanie systemu plików zajmuje i-węzeł katalogu i ustawia flagę na kopii w pamięci jądra, aby powiedzieć „tak naprawdę, patrząc na zawartość tego katalogu, spójrz zamiast tego na inny system plików” (patrz slajd 10 tej prezentacji ). Jest to stosunkowo łatwe, ponieważ zmienia pojedynczy element danych.

Dlaczego zamiast tego nie tworzy pozycji katalogu wskazującej na nowy i-węzeł? Istnieją dwa sposoby, aby to zaimplementować, oba mają wady. Jednym z nich jest fizyczne zapisanie nowego katalogu w systemie plików - ale to się nie powiedzie, jeśli system plików jest tylko do odczytu! Drugim jest dodanie do każdego procesu wyświetlania katalogu listy „dodatkowych” rzeczy, których tak naprawdę nie ma. Jest to kłopotliwe i potencjalnie powoduje niewielki spadek wydajności przy każdej operacji na pliku.

Jeśli chcesz dynamicznie tworzone punkty montowania, automountsystem może to zrobić. Specjalne systemy plików inne niż dyskowe mogą również tworzyć katalogi na woli, na przykład proc, sys, devfsi tak dalej.

Edycja: zobacz także odpowiedź na Co się stanie, gdy „zamontujesz” istniejący folder z zawartością?

pjc50
źródło
Tyle że nie ustawia flagi na i-węzle. sudo mount --bind / /mnt ; ls /mnt/proc-> pusty. Zastanawiam się, jak to działa.
sourcejedi
fs/namespace.cMyślę, że dokładna operacja się rozpoczęła ; Nie znam źródła i nie chciałem spędzać zbyt dużo czasu na wierceniu szczegółów. „Flaga na i-węźle” pochodzi z połączonej prezentacji.
pjc50,
2
@sourcejedi: bind mounts wiąże tylko system plików, do którego się odwołujesz. Nie wiążą rekurencyjnie innych systemów plików zamontowanych pod nim. Jest to przydatny sposób na znalezienie śmieci ukrytych przez wierzchowce. (np. jeśli jakieś rzeczy trafiły do ​​root FS w /var/cachepewnym momencie, gdy /varnie udało się zamontować.) Zobacz także path_resolution(7). (Starsze strony linux-man miały tę stronę podręcznika w sekcji 2, np. Die.net) IDK jak Linux faktycznie działa wewnętrznie, aby zoptymalizować sprawdzenie każdego komponentu katalogu jako możliwego montowania. Może przypiąć ten wpis VFS do pamięci podręcznej?
Peter Cordes,
2
Właśnie, o to mi chodzi ... Więc fs/namei.c(ścieżka -> wyszukiwanie i-węzłów) wywołuje jednak plik namespace.c lookup_mnt(). Na zębatce znajduje się flaga (pozycja w pamięci podręcznej katalogu). Ale to tylko optymalizacja aka szczegóły implementacji. Nie mówi ci, który system plików jest tam zamontowany; musisz zajrzeć do tabeli montażu. (Zobacz m_hash (), aby uzyskać więcej informacji na temat implementacji. Linux przynajmniej unika dodatkowych porównań łańcuchów, a AFAICS w tym samym czasie udaje się ponownie użyć dentry między np. Oprawami łączenia, ponieważ jest napisany przez kreatorów).
sourcejedi
1
@PeterCordes man 8 mount:: mount --bind foo foo. mountWywołanie wiązania dołącza tylko (część) jednego systemu plików, nie jest możliwe podliczanie. Cała hierarchia plików, w tymmount --rbind olddir newdir
podpięcia,
19

Jeśli mount(2) wymagane jest utworzenie nowego katalogu, który będzie punktem podłączenia, nie można zamontować niczego w systemie plików tylko do odczytu. To byłoby głupie, więc możemy to wykluczyć.

Gdyby mount opcjonalnie utworzył nowy katalog jako punkt podłączenia, byłoby to dziwne. Nie jest tak, że montowanie / odmontowywanie odbywa się cały czas, więc umieszczenie dodatkowej logiki w jądrze, aby wykonać te dwa kroki za pomocą jednego wywołania systemowego, nie byłoby ważnym przyspieszeniem. Wystarczy pozostawić przestrzeń użytkownika, aby wykonać mkdir(2)połączenie systemowe, jeśli chce. Odpowiedź Dmitry'ego wskazuje, że mount(2)zrobienie obu rzeczy sprawiłoby, że nie byłby to atom. A ty chcesz dodatkowy argument mount(2)z flagi trybu podoba open(2)trwa, dla O_CREAT, O_EXCLitp byłoby to po prostu głupie porównaniu do przestrzeni użytkownika pozwalając zrobić.

A może pytałeś o to, czy mount(8)(tradycyjny program, który wykonuje mount(2)wywołania systemowe) to robi? Byłoby to możliwe, ale już doskonale nadaje się mkdir(1)do tego zadania, a konstrukcja Uniksa polega na dobrych małych narzędziach, które można łączyć. Jeśli potrzebujesz narzędzia, które spełnia oba te warunki, łatwo jest napisać skrypt powłoki, aby zbudować to narzędzie z dwóch prostszych narzędzi. (Lub, jak skomentował Muru, udisksctljuż to robi, więc nie musisz tego pisać). Ponadto, normalny Linux mount(8)z util-linux obsługuje mount -o x-mount.mkdir[=mode]używanie jego x-składni dla opcji przestrzeni użytkownika, a nie opcji, które mają być przekazywane do systemu plików.


Teraz bardziej interesujące pytanie: dlaczego w ogóle nadrzędny system plików musi mieć katalog?

Jak wskazuje odpowiedź pjc50 (brak relacji, nawet jeśli ma moje inicjały!), Posiadanie punktów montowania wyświetlanych na listach katalogów wymagałoby wtedy dodatkowej kontroli każdego readdir().

Posiadanie punktów montowania, ponieważ katalogi w katalogu je zawierającym (na nadrzędnym FS) to niezła sztuczka. readdir()wcale nie musi zauważać, że jest to punkt montowania. Dzieje się tak tylko wtedy, gdy punkt montowania jest używany jako komponent ścieżki. Rozdzielczość ścieżki oczywiście musi sprawdzać tabelę montowania dla każdego elementu katalogu ścieżki.

Peter Cordes
źródło
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- Twierdzę, że jest mądrzejszy: z punktu widzenia użytkownika system plików tylko do odczytu nie powinien się zmieniać, ale zezwolenie na montowanie oznacza, że ​​może
Izkata
2
@Izkata: Utworzenie systemu plików tylko do odczytu nie oznacza, że ​​całe poddrzewo VFS jest zamrożone. Może mieć dowiązania symboliczne wskazujące katalogi do odczytu i zapisu lub mieć pod nim punkty montowania do odczytu i zapisu, gdy nadrzędny fs został ponownie zamontowany ro. Istnieje wiele przypadków użycia systemów plików tylko do odczytu, w których argument nie ma sensu.
Peter Cordes,
2
man 8 mount: x-mount.mkdir[=mode] Zezwól na utworzenie katalogu docelowego (mountpoint). Opcjonalny tryb argumentów określa tryb dostępu do systemu plików używany mkdir(2)w notacji ósemkowej. Domyślnym trybem jest 0755. Ta funkcja jest obsługiwana tylko dla użytkowników root.
mikeserv
Nie widzę żadnych ważnych przypadków użycia systemów plików tylko do odczytu z zamontowanymi systemami plików do odczytu i zapisu, szczególnie nie we wczesnym Uniksie. @PeterCordes
kubańczyk
@kubanczyk: główny system plików tylko do odczytu, z możliwością odczytu i zapisu /tmporaz /home. Lub montowany tylko do odczytu NFS /usrz /usr/localzamontowanym na nim lokalnym . Lub bardziej ogólnie, każdy wspólny obraz tylko do odczytu z zamontowaną modyfikowalną częścią. (lokalne modyfikacje obrazu tylko do odczytu można również wykonać dla poszczególnych plików za pomocą niestandardowych systemów plików, takich jak overlayfs lub inne unijne systemy plików dla systemu Linux, używanych w obrazach rozruchowych LiveCD.) Początkowo myślałem o root FS początkowo zamontowanym RO w boot, ale sprawienie, by rw mogło się zdarzyć przed innymi montowaniami.
Peter Cordes,
12

Montowanie do istniejącego katalogu powoduje wywołanie mountpraktycznie atomowej: albo kończy się niepowodzeniem, przynajmniej z perspektywy użytkownika. Gdyby mountmusiał sam utworzyć punkt montowania, miałby dwa punkty awarii, co uniemożliwiłoby zagwarantowanie czystego wycofania. Wyobraź sobie następujący scenariusz:

  1. mount pomyślnie tworzy punkt montowania
  2. mount próbuje zamontować nowy system plików w tym katalogu, ale kończy się niepowodzeniem
  3. mount próbuje usunąć punkt montowania, ale kończy się niepowodzeniem

System kończy się efektem ubocznym niepowodzenia mount.

Oto kolejny:

  1. umount pomyślnie odmontowuje system plików
  2. umount próbuje usunąć punkt montowania, ale kończy się niepowodzeniem

A teraz, czy umountpowróci sukces czy porażka?

Dmitrij Grigoriew
źródło
5
mountma 8 różnych kodów powrotu dla błędów, które można również łączyć. Może po prostu dodać kolejny, gdy usunięcie katalogu nie powiedzie się. man7.org/linux/man-pages/man8/mount.8.html#RETURN_CODES
chaos
8
Myślę, że OP pyta, dlaczego punkt montowania musi być w ogóle istniejącym katalogiem, a nie dlaczego mountwywołanie systemowe go nie tworzy. Chociaż może to była tylko moja interpretacja / oczekiwanie tego, o co myślałem, że OP chciał zapytać, lub o co zapytałbym, gdybym pytał.
Peter Cordes,
3

Kolejny przypadek, który może wystąpić:

Podczas uruchamiania podstawowy obraz tylko do odczytu jest ładowany do katalogu głównego. Więc chcesz to zmienić, jeśli chcesz kopać prawdziwy root. Możesz więc sobie wyobrazić, że mount syscall po prostu zamienia punkt romontowania na rw.

Tutaj wyobraźmy sobie, że masz problem z systemem plików w głównym punkcie montowania. Chciałbyś móc spróbować go naprawić. Dzięki nakładaniu się montowania możesz odmontować system plików i użyć fsckdostarczonego obrazu podstawowego do jego rozwiązania.

Ta funkcja może być również przydatna w systemach wymagających silnych zabezpieczeń, aby śledzić zmiany między ropartycją a rwjedną.

alexises
źródło
1
Nie jestem pewien, jak to odpowiada na pytanie. Czy wskazujesz, że w razie mount potrzeby utworzenia nowego katalogu w miejscu punktu montowania nie można zamontować niczego na systemie plików tylko do odczytu? Pierwszy akapit jest mylący: nie tak działa Linux initrd. Używa pivot_rootwywołania systemowego, aby zmienić root fs, a nie tylko montować na nim więcej rzeczy. Utrudniało to przestrzeganie logiki w następnych akapitach, ponieważ myślałem, że mówisz pivot_root(2).
Peter Cordes,
2
@PeterCordes - linux nie używał initrd od wielu lat : Podczas przełączania innego urządzenia root, initrd pivot_rooti następnie umountramdysk. Ale initramfs to rootfs: nie możesz ani pivot_rootrootfs, ani odmontować go . Zamiast tego usuń wszystko z rootfów, aby zwolnić miejsce ( find -xdev / -exec rm {} \;), zamontuj rootfsy za pomocą nowego roota ( cd /newmount; mount --move . /; chroot .), dołącz stdin / stdout / stderr do nowego / dev / console i execnowegoinit
mikeserv
@mikeserv: Neat! Nie zdawałem sobie sprawy, że podstawowy mechanizm przełączania rootów zmienił się, kiedy zaczęliśmy używać initramfs zamiast initrd. Z perspektywy administracyjnej „upewnij się, że trafiają do niego odpowiednie moduły jądra”, są one identyczne>. <. Nadal uważam, że to nie bardzo odpowiada na pytanie . Wydaje się, że zakłada interpretację „zamontowanie pod rofs jest niemożliwe” i podaje bardzo konkretny przypadek problemu (co wydaje się mało prawdopodobne, ponieważ initramfs nie jest montowany tylko do odczytu podczas rozruchu. A nawet jeśli tak, to można go po prostu ponownie zamontować jako odczyt -pisz bez wpływu na obraz cpio.gz.)
Peter Cordes,
@PeterCordes - naprawdę nie rozumiem tej odpowiedzi. właśnie widziałem twój komentarz - initramfs to system plików - naprawdę nigdy nie może być tylko do odczytu - wcielona pamięć podręczna fs.
mikeserv
2

Zawsze też się nad tym zastanawiałem.

Proste opakowanie, takie jak:

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

zapisany jako skrypt wykonywalny o nazwie mountw katalogu nadpisującym /binw ŚCIEŻCE powinien się tym zająć, jeśli zbytnio Ci to przeszkadza

(Przed uruchomieniem rzeczywistego mountpliku binarnego tworzy katalog nazwany na podstawie ostatniego argumentu mount, jeśli taki katalog jeszcze nie istnieje).


Alternatywnie, jeśli nie chcesz, aby nieudane wywołania mountopakowania tworzyły katalogi, możesz:

#!/bin/sh
set -e
eval "lastArg=\"\$$#\""
test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; }
/bin/mount "$@"  ||  {  test -z "$madeDir" || rmdir "$lastArg"; }
PSkocik
źródło
Czy mountpolecenie nie powinno zatem używać utworzonego katalogu?
muru
1
@muru Tak właśnie działa ostatnia linia.
PSkocik,
Och, masz na myśli, że należy go użyć w ten sposób mount /dev/foo /some/path:? Zakładałem, że to zadziała tak jak udisksctldziała, więc uciekniesz mount /dev/foo.
muru
4
Możesz pobrać ostatni argument cmdline bez evalrozwijania $#, używając "${@:-1}". Testowałem to z DASH, ponieważ myślę, że nie obsługuje on niczego poza tym, co jest wymagane do obsługi POSIX sh. /bin/dash -c 'echo ${@:-1}' foo barodbitki bar.
Peter Cordes,
1
możesz użyć man -o x-mount.mkdir...
Mikeserv