Memantau direktori untuk perubahan dengan Linux dimungkinkan melalui mekanisme terkenal inotify. Dengan inotify, Anda dapat mengatur jam tangan di direktori, mengonfigurasinya untuk menonton acara di konten, dan Anda akan menerima pesan di deskriptor file ketika sesuatu terjadi. Ini berfungsi dengan baik ketika direktori berada di penyimpanan lokal, seperti hard drive, SSD, atau drive USB, Tetapi itu tidak cukup ketika direktori berada di sistem file jaringan ketika penyimpanan ada di komputer lain. Pengguna lain yang bekerja di direktori yang sama, terhubung melalui sistem file yang sama atau lainnya, dapat menghapus file dan jam tangan yang Anda atur tidak akan mendapatkan pemberitahuan.
Mengapa ini?
Secara desain, inotify mendapatkan hasil dari suatu operasi (seperti mkdir atau chmod) tetapi jenis filesystem apa yang digunakan jam tangan tidak diketahui (kotak hitam) untuk inotify. Sistem file tidak "tahu" jam tangan telah disetel, dan karenanya tidak dapat mengambil tindakan yang tepat, seperti memberi tahu host jarak jauh bahwa seseorang ingin menonton direktori.
Selama Anda adalah satu-satunya pengguna, tidak ada masalah. Ini menjadi masalah ketika ada lebih banyak pengguna yang bekerja di direktori yang ingin Anda tonton.
Anda dapat membandingkan perilaku ini dengan perpustakaan umum. Ketika Anda adalah satu-satunya pengguna, Anda dapat mengetahui buku mana yang tersedia dan mana yang tidak seperti Anda mengetahui buku mana yang telah Anda pinjam. Ini tidak mungkin lagi bila Anda bukan satu-satunya pengguna, ada lebih banyak pengguna yang meminjam buku.
Dalam hal ini, seseorang di perpustakaan harus mengelola apa yang dipinjam oleh pengguna mana pun (yang merupakan kasus biasa), dan Anda harus menghubungi orang ini untuk mengetahui apakah buku tersedia atau tidak. Itu seperti meminta seseorang untuk memberi tahu Anda ketika sebuah buku, yang saat ini tidak ada, tersedia lagi.
Sekarang menghubungi perpustakaan untuk menginformasikan bahwa Anda tidak bekerja dengan Linux, di mana tentu saja perpustakaan adalah penyimpanan jarak jauh, dan server adalah "seseorang" yang bekerja di perpustakaan.
Untuk membuat ini berfungsi dengan Linux berarti membuat server jarak jauh mendapat pemberitahuan bahwa jam tangan telah disetel.
Sebenarnya, sistem file seperti CIFS dan versi NFS terbaru berisi dukungan pengiriman arloji ke server:untuk CIFS pada baris 6438 dari fs/cifs/cifssmb.c dari kernel 4.1.2 pesan SMB untuk ini (NT_TRANSACT_NOTIFY_CHANGE) dikomentari tapi tetap hadir. Alasan untuk mengomentari ini adalah karena ini bekerja dengan dnotify, yang sudah lama bukan sistem fsnotify default untuk Linux.
Membuat penerusan jam tangan berfungsi di Linux dengan sistem file jaringan dan FUSE dimungkinkan melalui ruang kernel.
Baru-baru ini saya mencoba menerapkan "penerusan arloji ke server" ini dengan FUSE. Saya harus menambal:
Subsistem kernel fsnotify, untuk memberi tahu modul kernel FUSE bahwa jam tangan telah disetel atau dihapus pada sebuah inode.
Modul kernel FUSE untuk mengambil tindakan setelah diinformasikan oleh fsnotify. Saya memperkenalkan kode operasi baru
FUSE_FSNOTIFY yang dikirim modul kernel ke daemon userspace bersama dengan inodenumber dan mask.
Library FUSE untuk menerima dan memproses panggilan FUSE_FSNOTIFY dengan memanggil fungsi yang tepat dari sistem file userspace.
Pustaka FUSE untuk menerima dan memproses kejadian fs dan melaporkannya kembali ke VFS.
Melihat lebih dekat bagaimana segala sesuatunya bekerja, ketika jam tangan telah disetel oleh sistem file ruang pengguna di backendnya dengan sukses (perhatikan juga mungkin untuk membalas ENOSYS), backend dapat mengirim acara di jam tangan kapan saja, hingga jam tangan dilepas. Apa yang harus dilakukan dengan acara ini?
Skenario yang mungkin:
Perkenalkan opcode FUSE ekstra FUSE_FSNOTIFY_EVENT, terjemahkan topeng jika diterima dari protokol backend dalam sesuatu yang dipahami fsnotify, dan kirimkan kembali ke modul FUSE menggunakan opcode baru, inode arloji, nama entri, dan topeng yang diterjemahkan. Modul FUSE pada gilirannya mengirimkannya ke subsistem fsnotify, yang menginformasikan kepada pendengar (notify dan atau fanotify), di mana informasi disediakan bahwa acara tersebut ada di backend. (tanda peristiwa tambahan diperlukan, misalnya untuk memberi tahu topeng peristiwa IN_REMOTE, untuk mem-fanotifikasi FAN_REMOTE). Terserah pendengar apa yang harus dilakukan dengan informasi ini. VFS lokal mungkin sudah atau belum diperbarui.
Catatan:
Menerjemahkan topeng dari backend menjadi sesuatu yang dipahami fsnotify bisa sangat mudah dan tidak mudah, tergantung pada acaranya. Peristiwa dasar seperti membuat (atau menghapus) entri dalam direktori yang ditonton sederhana (FS_CREATE dan FS_DELETE resp.), mengubah pemiliknya juga tidak terlalu sulit (FS_ATTRIB), tetapi sesuatu seperti atribut yang diperluas (SMB menggunakan itu banyak) hanya dapat diterjemahkan ke dalam sesuatu yang umum seperti FS_ATTRIB.
Modul FUSE harus memeriksa apakah arloji dan/atau inode masih valid, dan apakah mask jam tangan berlaku untuk eventmask.
Bit topeng ekstra IN_REMOTE (untuk inotify) dan FAN_REMOTE (untuk fanotify) diperlukan.
Informasi ganda harus dihindari. Ini rumit. Misalnya, pembuatan file di direktori yang ditonton di host yang sama dengan jam tangan aktif. Ketika operasi ini berhasil, ini akan menyebabkan acara fsnotify FS_CREATE, dan juga akan membuat FS_CREATE | FS_REMOTE event, karena operasi berhasil dilakukan di backend, menghasilkan pesan ini (dari backend→fuse library→FUSE kernel module→fsnotify subsystem→notify dan/atau fanotify).
Salah satu cara untuk mengatasi ini adalah dengan meminta backend untuk hanya mengirim acara yang diprakarsai oleh orang lain. Untuk backend, cukup mudah untuk membandingkan inisiator (host) dari event FS dengan host yang membuat koneksi.
Solusi lain adalah membandingkan kejadian yang dilaporkan dengan cache lokal di pustaka fuse dan modul FUSE. Dengan contoh membuat file, perpustakaan (dan modul FUSE) harus memeriksa apakah entri sudah ada di direktori yang diawasi. Jika tidak, itu tidak diprakarsai oleh host ini. Untuk menghapus, ini serupa.
Untuk acara lain, seperti file yang ditulis, atau pemilik diubah, metode ini tidak cukup, informasi tambahan tentang apa yang telah diubah jarak jauh (seperti ukuran baru, pemilik baru) harus ada di pesan yang dikirim oleh host jarak jauh.
Jika informasi tersebut tidak disediakan oleh backend, solusi lain adalah membuat daemon yang bertanggung jawab untuk menonton acara FS atas nama klien memelihara cache acara lokal terbaru. Jika peristiwa jarak jauh dilaporkan, dan dalam cache tidak ditemukan padanan lokal, itu diprakarsai oleh host lain. Ini bisa menjadi rumit karena peristiwa dilaporkan menggunakan koneksi untuk pengguna tertentu, pengguna lain mungkin atau mungkin tidak diizinkan untuk menerima peristiwa. Dan seberapa besar cache ini?
Saya telah menggunakan FUSE di atas, saya pikir itu mirip untuk sistem file lain seperti CIFS dan NFS.
Oh ya, masih ada pilihan lain:cukup polling setiap 5 detik atau lebih.
Stef Bon