Mengapa mount terjadi pada direktori yang ada?

52

Direktori yang ada diperlukan sebagai titik pemasangan .

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

Saya merasa ini membingungkan karena overlay isi direktori yang ada. Ada dua kemungkinan isi dari direktori titik mount yang dapat diaktifkan secara tidak terduga (untuk pengguna yang tidak melakukan mount).

Mengapa tidak mountterjadi pada direktori yang baru dibuat? Ini adalah cara bagaimana sistem operasi grafis menampilkan media yang dapat dilepas. Akan menjadi jelas jika direktori di-mount (ada) atau tidak di-mount (tidak ada). Saya cukup yakin ada alasan bagus tapi saya belum bisa menemukannya.

Melebius
sumber
1
Jika Anda menginginkan perilaku itu, gunakan udisksctl. Mengapa menggunakan mount?
muru
1
Karena itu adalah cara Unix. Karena cara ini lebih fleksibel, dan Anda dapat memasang kemudian di mana saja. Karena memasang mereka di mana saja memungkinkan Anda untuk memperluas server Anda seperti yang Anda butuhkan, misalnya, mendapatkan disk baru untuk partisi database, memindahkan data dalam partisi DB ke disk baru, dan memasangnya di tempat yang tepat untuk memungkinkan data DB untuk tumbuh lebih banyak.
Rui F Ribeiro
8
Sebagai catatan sejarah, sebelum Windows dan LInux pada dasarnya menghancurkan semua OS lainnya, ada sebuah perusahaan bernama Apollo. Mereka menulis sistem operasi unix-alike (desain yang lebih baik daripada Unix!). Itu menciptakan direktori di mana NFS ekspor dipasang secara otomatis. Bahkan, Anda tidak bisa memasang pada direktori yang sudah ada sebelumnya. HP membeli Apollo, membuang sistem operasi, dan menggunakan CPU 64-bit Apollo sebagai HP-PA. Sistem panggilan prosedur jarak jauh Apollo menjadi DCE OSF, yang tampaknya tinggal di dalam Windows. Mengetahui adalah setengah dari pertempuran!
Bruce Ediger
entah bagaimana ini terjadi di sistem ubuntu 14.04,3 ​​saya. saya belum menginvestigasi. ketika kartu SD saya dipasang, itu berakhir di jalan yang tidak memiliki apa pun di bawahnya. jika saya umount dan mencoba me-mount kembali secara manual, kesalahan yang saya dapatkan adalah tidak ada direktori pada titik mount.
Skaperen
2
@BruceEdiger better design than Unix![rujukan?]
Ruslan

Jawaban:

51

Ini adalah kasus detail implementasi yang bocor.

Dalam sistem UNIX, setiap direktori terdiri dari daftar nama yang dipetakan ke nomor inode . Inode menyimpan metadata yang memberi tahu sistem apakah itu file, direktori, perangkat khusus, bernama pipe, dll. Jika itu adalah file atau direktori, ia juga memberi tahu sistem tempat menemukan file atau isi direktori pada disk. Kebanyakan inode adalah file atau direktori. The -ipilihan untuk lsnomor inode daftar keinginan.

Memasang sistem file membutuhkan inode direktori dan menetapkan tanda pada salinan dalam-memori kernel untuk mengatakan "sebenarnya, ketika mencari isi direktori ini, lihat sistem file lain ini sebagai gantinya" (lihat slide 10 dari presentasi ini ). Ini relatif mudah karena itu mengubah item data tunggal.

Mengapa tidak membuat entri direktori untuk Anda yang menunjuk pada inode baru? Ada dua cara Anda bisa mengimplementasikannya, yang keduanya memiliki kelemahan. Pertama adalah secara fisik menulis direktori baru ke sistem file - tetapi itu gagal jika sistem file hanya dibaca! Yang lain adalah menambahkan ke setiap proses daftar direktori daftar hal-hal "ekstra" yang tidak benar-benar ada. Ini fiddly dan berpotensi menimbulkan hit kinerja kecil pada setiap operasi file.

Jika Anda ingin titik pemasangan yang dibuat secara dinamis, automountsistem dapat melakukan ini. Sistem file non-disk khusus juga dapat membuat direktori sesuka hati, mis proc. sys, devfsDan sebagainya.

Sunting: lihat juga jawaban untuk Apa yang terjadi ketika Anda 'me-mount' folder yang ada dengan konten?

pjc50
sumber
Kecuali itu tidak menetapkan bendera pada inode. sudo mount --bind / /mnt ; ls /mnt/proc-> kosong Saya bertanya-tanya bagaimana cara kerjanya.
sourcejedi
Operasi tepatnya fs/namespace.c, saya pikir; Saya tidak terbiasa dengan sumbernya dan tidak ingin menghabiskan waktu terlalu lama untuk menggali detailnya. "Bendera di inode" saya dapatkan dari presentasi yang ditautkan.
pjc50
2
@sourcejedi: bind mounts hanya mengikat filesystem yang sebenarnya Anda lihat. Mereka tidak secara mengikat mengikat sistem file lain yang terpasang di bawahnya. Ini adalah cara praktis untuk menemukan sampah yang disembunyikan oleh tunggangan. (mis. jika beberapa hal berakhir pada root FS dalam /var/cachebeberapa waktu ketika /vargagal dipasang.) Lihat juga path_resolution(7). (Linux-manpages lama memiliki halaman manual di bagian 2, seperti die.net) IDK bagaimana Linux sebenarnya bekerja secara internal, untuk mengoptimalkan memeriksa setiap komponen direktori sebagai kemungkinan mount. Mungkin pin entri VFS di cache?
Peter Cordes
2
Benar, itu maksud saya ... Jadi fs/namei.c(path -> inode lookup) memanggil namespace.c lookup_mnt(). Ada bendera di dentry (entri cache direktori). Tapi itu hanya optimasi alias detail implementasi. Itu tidak memberi tahu Anda sistem file mana yang dipasang di sana; Anda harus melihat di tabel mount. (Lihat m_hash (), untuk detail implementasi lebih lanjut. Linux, setidaknya, menghindari perbandingan string tambahan, dan AFAICS pada saat yang sama berhasil menggunakan kembali dentry's di mis. Bind mounts, karena ditulis oleh penyihir).
sourcejedi
1
@PeterCordes man 8 mount:: mount --bind foo foo. Mengikat mountpanggilan menempel saja (bagian dari) filesystem tunggal, tidak mungkin submounts. Seluruh hierarki file termasuk sub-mount dilampirkan di tempat kedua dengan menggunakan :mount --rbind olddir newdir
mikeserv
19

Jika mount(2) diperlukan pembuatan direktori baru sebagai titik mount, Anda tidak bisa me-mount apa pun di bawah sistem file read-only. Itu akan bodoh, jadi kita bisa mengesampingkan itu.

Jika mount secara opsional membuat direktori baru untuk menjadi mountpoint, itu akan aneh. Ini tidak seperti me-mount / unmount yang terjadi setiap saat, jadi menempatkan logika ekstra di kernel untuk melakukan dua langkah ini dengan satu pemanggilan sistem tidak akan menjadi sebuah speedup yang penting. Serahkan saja pada ruang pengguna untuk melakukan mkdir(2)panggilan sistem jika menginginkannya. Jawaban Dmitry menunjukkan bahwa setelah mount(2)melakukan kedua hal itu akan membuatnya menjadi non-atom. Dan Anda ingin argumen ekstra untuk mount(2)dengan modus bendera seperti open(2)mengambil, untuk O_CREAT, O_EXCL, dll hanya akan konyol dibandingkan dengan membiarkan user-space melakukannya.

Atau mungkin Anda bertanya tentang memiliki mount(8)(program tradisional yang membuat mount(2)panggilan sistem) melakukan ini? Itu mungkin, tetapi sudah ada yang sangat baik mkdir(1)untuk pekerjaan itu, dan desain Unix adalah tentang alat kecil yang baik yang dapat digabungkan. Jika Anda menginginkan alat yang melakukan keduanya, mudah untuk menulis skrip shell untuk membangun alat itu dari dua alat yang lebih sederhana. (Atau, seperti komentar muru, udisksctlsudah melakukan ini, jadi Anda tidak perlu menulisnya.) Selain itu, normal Linux mount(8)dari util-linux mendukung mount -o x-mount.mkdir[=mode]penggunaan x-sintaksnya untuk opsi untuk userspace, daripada opsi untuk diteruskan ke sistem file.


Sekarang pertanyaan yang lebih menarik: mengapa harus ada direktori di sistem berkas induk?

Seperti yang ditunjukkan oleh jawaban pjc50 (tidak ada relasi, meskipun ia memiliki inisial saya!), Memiliki mount poin muncul di daftar direktori akan memerlukan pemeriksaan tambahan pada setiap readdir().

Memiliki mount point ada sebagai direktori dalam direktori yang berisi mereka (pada induk FS) adalah trik yang bagus. readdir()tidak perlu memperhatikan bahwa itu adalah titik pemasangan sama sekali. Itu hanya terjadi jika titik mount digunakan sebagai komponen jalur. Resolusi path tentu saja harus memeriksa tabel mount untuk setiap komponen direktori dari sebuah path.

Peter Cordes
sumber
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- Saya berpendapat lebih pintar: Dari perspektif pengguna, sistem file read-only tidak boleh berubah, tetapi memungkinkan mounts berarti itu bisa
Izkata
2
@Izkata: Membuat filesystem read-only tidak berarti seluruh subtree dari VFS dibekukan. Itu bisa memiliki symlink yang menunjuk ke direktori read-write, atau sudah memiliki mount-point read-write di bawahnya ketika parent fs di-remount ro. Ada banyak kasus penggunaan untuk sistem file read-only di mana argumen Anda tidak masuk akal.
Peter Cordes
2
man 8 mount: x-mount.mkdir[=mode] Izinkan untuk membuat direktori target (mountpoint). Mode argumen opsional menentukan mode akses sistem file yang digunakan mkdir(2)dalam notasi oktal. Mode standar adalah 0755. Fungsi ini hanya didukung untuk pengguna root.
mikeserv
Saya tidak melihat kasus penggunaan yang penting dari sistem file read-only dengan filesystem read-write yang terpasang, terutama di Unix awal. @PeterCordes
kubanczyk
@kubanczyk: sistem file root read-only, dengan read-write /tmpdan /home. Atau read-only NFS-mount /usrdengan lokal yang /usr/localterpasang di atasnya. Atau lebih umum, gambar read-only yang dibagikan dengan bagian yang dapat dimodifikasi dipasang di atasnya. (mods lokal untuk gambar read-only juga bisa dilakukan pada basis per-file tersebut dengan filesystem kustom seperti overlayfs atau filesystem serikat lainnya untuk Linux, yang digunakan pada LiveCD gambar bootable.) Saya awalnya berpikir akar FS awalnya dipasang RO di boot, tetapi membuatnya bisa terjadi sebelum tunggangan lainnya.
Peter Cordes
12

Pemasangan ke direktori yang ada membuat panggilan ke mountatom praktis: itu berhasil atau gagal, setidaknya dari perspektif pengguna. Jika mountharus membuat mountpoint itu sendiri, itu akan memiliki dua titik kegagalan, sehingga tidak mungkin untuk menjamin roll kembali yang bersih. Bayangkan skenario berikut:

  1. mount berhasil membuat mountpoint
  2. mount mencoba memasang sistem file baru ke direktori itu, tetapi gagal
  3. mount mencoba menghapus titik mount, tetapi gagal

Sistem berakhir dengan efek samping yang gagal mount.

Ini satu lagi:

  1. umount berhasil meng-unmount sistem file
  2. umount mencoba menghapus titik mount, tetapi gagal

Sekarang, haruskah umountmengembalikan keberhasilan atau kegagalan?

Dmitry Grigoryev
sumber
5
mountmemiliki 8 kode pengembalian berbeda untuk kesalahan yang juga dapat digabungkan. Itu bisa saja menambahkan yang lain ketika penghapusan direktori gagal. man7.org/linux/man-pages/man8/mount.8.html#RETURN_CODES
chaos
8
Saya pikir OP bertanya mengapa mountpoint perlu menjadi direktori yang sudah ada, bukan mengapa mountsystem call tidak membuatnya. Meskipun mungkin itu hanya interpretasi / harapan saya tentang apa yang saya pikir ingin ditanyakan oleh OP, atau apa yang akan saya tanyakan jika saya bertanya.
Peter Cordes
3

Kasus lain yang dapat terjadi:

Saat Anda boot, gambar hanya baca dasar dimuat di direktori root. Jadi, Anda ingin menimpanya ketika ingin membuat gundukan root asli. Jadi Anda dapat membayangkan bahwa mount syscall cukup menukar romountpoint ke rw.

Di sini, mari kita bayangkan Anda memiliki masalah sistem file pada mountpoint root, Anda ingin dapat mencoba memperbaikinya. Dengan mount overlap, Anda dapat meng-unmount sistem file dan menggunakan fsckgambar dasar yang disediakan untuk menyelesaikannya.

Fitur ini juga dapat berguna dalam sistem yang membutuhkan keamanan yang kuat untuk melacak perubahan antara ropartisi dan partisi rw.

alexises
sumber
1
Saya tidak yakin bagaimana ini menjawab pertanyaan. Apakah Anda menunjukkan bahwa jika mount diperlukan membuat direktori baru di lokasi mountpoint yang Anda tidak bisa memasang apa pun di atas sistem file read-only? Paragraf pembuka membingungkan: itu bukan cara kerja initrd Linux. Ia menggunakan pivot_rootsystem call untuk mengubah root fs, tidak hanya me-mount lebih banyak barang di atasnya. Itu membuatnya sulit untuk mengikuti logika Anda di paragraf berikutnya, karena saya pikir Anda bicarakan pivot_root(2).
Peter Cordes
2
@PeterCordes - linux tidak menggunakan initrd selama bertahun-tahun : Ketika berpindah perangkat root, initrd akan pivot_rootdan kemudian umountramdisk. Tetapi initramfs adalah rootfs: Anda tidak dapat pivot_rootrootfs, maupun unmount . Alih-alih hapus semuanya dari rootfs untuk mengosongkan spasi ( find -xdev / -exec rm {} \;), overmount rootfs dengan root baru ( cd /newmount; mount --move . /; chroot .), lampirkan stdin / stdout / stderr ke konsol / dev / baru, danexecinit
mikeserv
@mikeserv: Rapi! Saya tidak menyadari bahwa mekanisme dasar untuk berganti root berubah ketika kami mulai menggunakan initramfs alih-alih initrd. Dari sudut pandang admin "pastikan modul kernel yang tepat ada di dalamnya", semuanya identik>. <. Saya masih berpikir ini tidak benar-benar menjawab pertanyaan dengan sangat baik . Tampaknya menganggap interpretasi "mount di bawah rofs is nothing", dan memberikan kasus masalah yang sangat spesifik (yang tampaknya tidak mungkin karena initramfs tidak dipasang hanya baca saat boot. Dan bahkan jika itu, ia dapat dengan mudah dipasang kembali dibaca -write tanpa mempengaruhi gambar cpio.gz.)
Peter Cordes
@PeterCordes - saya tidak begitu mengerti jawaban ini. Saya baru saja melihat komentar Anda - initramfs adalah sistem file - itu tidak bisa benar-benar hanya baca-saja - fs cache menjelma.
mikeserv
2

Saya selalu bertanya-tanya itu juga.

Pembungkus sederhana seperti:

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

disimpan sebagai skrip yang dapat dieksekusi bernama mountdalam direktori yang menimpa /bindi PATH Anda harus mengurus ini jika itu mengganggu Anda terlalu banyak

(Sebelum menjalankan mountbiner yang sebenarnya , ia membuat direktori bernama setelah argumen terakhir mount, jika direktori tersebut belum ada.)


Sebagai alternatif, jika Anda tidak ingin undangan mountpembungkus yang gagal untuk membuat direktori, Anda dapat melakukan:

#!/bin/sh
set -e
eval "lastArg=\"\$$#\""
test -d "$lastArg" || { mkdir "$lastArg"; madeDir=1; }
/bin/mount "$@"  ||  {  test -z "$madeDir" || rmdir "$lastArg"; }
PSkocik
sumber
Bukankah seharusnya mountperintah kemudian menggunakan direktori yang dibuat?
muru
1
@uru Itulah yang dilakukan baris terakhir.
PSkocik
Oh, jadi Anda berarti itu harus digunakan sehingga: mount /dev/foo /some/path? Saya menganggap itu akan berfungsi seperti udisksctlhalnya, sehingga Anda akan lari mount /dev/foo.
muru
4
Anda bisa mendapatkan cmdline arg terakhir tanpa evalmemperluas $#, menggunakan "${@:-1}". Saya menguji ini dengan DASH, karena saya pikir itu tidak mendukung apa pun di luar apa yang POSIX sh diperlukan untuk mendukung. /bin/dash -c 'echo ${@:-1}' foo barcetakan bar.
Peter Cordes
1
Anda dapat menggunakan man -o x-mount.mkdir...
mikeserv