Bagikan melalui


Meminta dan memberikan oplock

Ketika pengalih jaringan mengakses file di server jarak jauh, ia meminta oplock dari server jarak jauh. Aplikasi klien secara langsung meminta oplock hanya ketika kunci ditujukan untuk file di server lokal.

Oplocks diminta melalui FSCTL . Berikut ini adalah FSCTL yang digunakan untuk berbagai jenis oplock, yang dapat dikeluarkan oleh aplikasi mode pengguna dan driver mode kernel.

Meminta oplock dalam mode pengguna

Untuk meminta oplock Windows 7 dalam mode pengguna, panggil DeviceIoControl:

Untuk informasi selengkapnya, lihat FSCTL_REQUEST_OPLOCK.

Jika oplock yang diminta dapat diberikan, DeviceIoControl mengembalikan FALSE dan GetLastError mengembalikan ERROR_IO_PENDING. Untuk alasan ini, oplock tidak pernah diberikan untuk I/O sinkron. Operasi yang tumpang tindih tidak selesai sampai oplock rusak. Setelah operasi selesai, REQUEST_OPLOCK_OUTPUT_BUFFER akan berisi informasi tentang pemutusan oplock.

Jika oplock tidak dapat diberikan, sistem file mengembalikan kode kesalahan yang sesuai. Kode kesalahan yang paling umum dikembalikan adalah ERROR_OPLOCK_NOT_GRANTED dan ERROR_INVALID_PARAMETER.

Meminta oplock dalam mode kernel

Untuk meminta oplock Windows 7 dalam mode kernel:

Minifilter sistem file

Minifilter sistem file harus menggunakan FltAllocateCallbackData dan mengisi FLT_CALLBACK_DATA yang dialokasikan seperti:

  • Atur bidang Iopb->MajorFunction menjadi IRP_MJ_FILE_SYSTEM_CONTROL.
  • Setel bidang Iopb->MinorFunction ke IRP_MN_USER_FS_REQUEST.
  • Atur parameter Iopb->. FileSystemControl.Buffered.FsControlCode anggota menjadi FSCTL_REQUEST_OPLOCK.
  • Alokasikan buffer yang ukurannya sama dengan yang lebih besar dari REQUEST_OPLOCK_INPUT_BUFFER atau REQUEST_OPLOCK_OUTPUT_BUFFER.
    • Atur FLT_CALLBACK_DATAyang dialokasikan untuk Iopb->Parameters.FileSystemControl.Buffered.SystemBuffer agar anggotanya menunjuk ke buffer tersebut.
    • Atur parameter FLT_CALLBACK_DATAIopb->.FileSystemControl.Buffered.InputBufferLength dan Iopb->Parameters.FileSystemControl.Buffered.OutputBufferLength ke ukuran buffer tersebut.

Rujuk pada dokumentasi struktur REQUEST_OPLOCK_INPUT_BUFFER untuk informasi tentang cara memformat permintaan oplock.

Kemudian minifilter sistem file harus memanggil FltPerformAsynchronousIo, melewati FLT_CALLBACK_DATA yang dialokasikan sebagai parameter CallbackData.

Jika oplock yang diminta dapat diberikan, panggilan FltPerformAsynchronousIo mengembalikan STATUS_PENDING. Untuk alasan ini, oplock tidak pernah diberikan untuk input/output (I/O) sinkron. Operasi tidak akan selesai sampai oplock tersebut dihentikan. Setelah operasi selesai, REQUEST_OPLOCK_OUTPUT_BUFFER akan berisi informasi tentang pemutusan oplock.

Jika oplock tidak dapat diberikan, sistem file mengembalikan kode kesalahan yang sesuai. Kode kesalahan yang paling sering dikembalikan adalah STATUS_OPLOCK_NOT_GRANTED dan STATUS_INVALID_PARAMETER.

Jenis Driver Lainnya

Jenis driver lain dapat memanggil ZwFsControlFile:

Lihat dokumentasi struktur REQUEST_OPLOCK_INPUT_BUFFER untuk mengetahui cara memformat permintaan oplock.

Jika oplock yang diminta dapat diberikan, panggilan ZwFsControlFile akan mengembalikan STATUS_PENDING. Untuk alasan ini, oplock tidak pernah diberikan untuk I/O sinkron. Operasi tidak selesai sampai oplock rusak. Setelah operasi selesai, REQUEST_OPLOCK_OUTPUT_BUFFER akan berisi informasi tentang pemutusan oplock.

Jika oplock tidak dapat diberikan, sistem file mengembalikan kode kesalahan yang sesuai. Kode kesalahan yang paling umum dikembalikan adalah STATUS_OPLOCK_NOT_GRANTED dan STATUS_INVALID_PARAMETER.

Menghindari Pelanggaran Pembagian Sumber Daya Saat Meminta Oplocks

Menggunakan Metode Atomic Create-With-Oplock

Atom create-with-oplock bukan jenis oplock. Sebaliknya, ini adalah prosedur yang memungkinkan operasi terbuka untuk menghindari menyebabkan pelanggaran mode berbagi dalam rentang waktu antara membuka file dan menerima oplock. Dengan oplock warisan, memfilter oplock dan membuka dua pegangan diperlukan. Dengan oplock Windows 7, aplikasi atau driver dapat meminta segala jenis oplock menggunakan prosedur ini dan hanya perlu membuka satu pegangan.

Untuk melakukan prosedur atom create-with-oplock, Anda perlu:

  1. Gunakan FltCreateFileEx2 atau ZwCreateFile, yang sesuai, untuk membuka file. Dalam parameter CreateOptions, sisipkan flag FILE_OPEN_REQUIRING_OPLOCK. Anda dapat mengatur parameter DesiredAccess dan ShareAccess sesuai keinginan. Misalnya, dalam parameter DesiredAccess diatur GENERIC_READ sehingga Anda dapat membaca file, dan dalam parameter ShareAccess atur FILE_SHARE_READ | FILE_SHARE_DELETE bendera untuk memungkinkan orang lain membaca, mengganti nama, dan/atau menandai file untuk dihapus saat Anda membukanya.
  2. Gunakan kode kontrol FSCTL_REQUEST_OPLOCK untuk mengajukan oplock pada objek atau handle file yang dihasilkan, seperti yang dijelaskan dalam Meminta Oplock Dalam Mode Kernel.

Jangan lakukan operasi sistem file apa pun pada file antara langkah 1 dan 2. Melakukannya dapat menyebabkan kebuntuan.

Oplock yang paling umum untuk diminta menggunakan prosedur ini adalah jenis Read-Handle. Ini memungkinkan Anda untuk memberikan akses bersamaan sebanyak mungkin kepada penelepon lain, sambil tetap memberi tahu Anda jika perlu menutup handle untuk menghindari terjadinya pelanggaran berbagi yang bertentangan.

Menggunakan Filter Warisan Oplock

Oplock Filter klasik juga memungkinkan aplikasi untuk "mundur" ketika aplikasi/klien lain mencoba mengakses aliran data yang sama, tetapi kurang fleksibel daripada metode pembuatan-dengan-oplock atomik. Mekanisme ini memungkinkan aplikasi untuk mengakses aliran tanpa menyebabkan aksesor aliran lain menerima pelanggaran berbagi saat mencoba membuka aliran. Untuk menghindari pelanggaran berbagi akses, gunakan prosedur tiga langkah berikut untuk meminta Filter oplock:

  1. Buka file dengan akses FILE_READ_ATTRIBUTES yang diperlukan dan mode berbagi FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE. Handle yang dibuka dalam langkah ini tidak akan menyebabkan aplikasi lain menerima pelanggaran berbagi akses karena hanya dibuka untuk akses atribut (FILE_READ_ATTRIBUTES) dan bukan akses data (FILE_READ_DATA). Pegangan ini cocok untuk meminta oplock Filter, tetapi tidak untuk melakukan masukan/keluaran aktual pada aliran data.

  2. Minta Filter oplock (FSCTL_REQUEST_FILTER_OPLOCK) pada handle pada langkah 1. Oplock yang diberikan dalam langkah ini memungkinkan pemegang oplock untuk "keluar dari jalan" tanpa menyebabkan pelanggaran berbagi ke aplikasi lain yang mencoba mengakses aliran.

  3. Buka file lagi untuk akses baca. Pegangan yang dibuka dalam langkah ini memungkinkan pemegang oplock untuk melakukan I/O pada stream.

Sistem file NTFS menyediakan optimasi untuk prosedur ini melalui opsi pembuatan FILE_RESERVE_OPFILTER. Jika flag ini ditentukan di langkah 1 dari prosedur sebelumnya, flag ini memungkinkan sistem file untuk menolak permintaan pembuatan dengan STATUS_OPLOCK_NOT_GRANTED jika sistem file dapat menentukan bahwa langkah 2 akan gagal. Jika langkah 1 berhasil, tidak ada jaminan bahwa langkah 2 akan berhasil, bahkan jika FILE_RESERVE_OPFILTER ditentukan untuk permintaan pembuatan.

Kondisi Untuk Memberikan Oplock

Tabel berikut mengidentifikasi kondisi yang diperlukan untuk memberikan oplock.

Jenis permintaan Kondisi

Tingkat 1

Filter

Lot

Diberikan hanya jika semua kondisi berikut ini benar:

  • Permintaan adalah untuk aliran file tertentu.
    • Jika itu adalah direktori, STATUS_INVALID_PARAMETER dikembalikan.
  • Aliran data dibuka untuk akses ASINKRON.
    • Jika dibuka untuk akses SYNCHRONOUS, STATUS_OPLOCK_NOT_GRANTED dikembalikan (oplock tidak diberikan untuk permintaan I/O sinkron).
  • Tidak ada transaksi TxF pada aliran file apa pun.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada pembukaan lain pada aliran (bahkan dengan utas yang sama).
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.

Jika status oplock saat ini adalah:

  • Tidak ada oplock: Permintaan disetujui.

  • Tingkat 2: Permintaan Tingkat 2 asli rusak dengan FILE_OPLOCK_BROKEN_TO_NONE. Oplock eksklusif yang diminta kemudian diberikan.

  • Level 1, Batch, Filter, Read, Read-Handle, Read-Write, atau Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED tidak diberikan.

Tingkat 2

Diberikan hanya jika semua kondisi berikut ini benar:

  • Permintaan adalah untuk aliran file tertentu.
    • Jika itu adalah direktori, STATUS_INVALID_PARAMETER akan dikembalikan.
  • Stream dibuka untuk akses ASINKRON.
    • Jika dibuka untuk akses sinkron, STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Tidak ada transaksi TxF pada file.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada Kunci Rentang Byte yang saat ini aktif pada alur data.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
    • Sebelum Windows 7, sistem operasi memverifikasi apakah kunci rentang byte pernah ada di aliran data sejak terakhir kali dibuka, dan menolak permintaan jika demikian.

Jika status oplock saat ini adalah:

  • Tidak ada oplock: Permintaan diterima.

  • Tingkat 2 dan/atau Baca: Permintaan dikabulkan. Anda dapat memiliki beberapa oplock Tingkat 2/Baca yang diberikan pada aliran yang sama secara bersamaan. Oplock Level 2 ganda (tetapi tidak untuk membaca) bahkan dapat ada pada handle yang sama.
    • Jika Read oplock diminta pada handel yang sudah memiliki Read oplock yang diberikan kepadanya, IRP Read oplock pertama diselesaikan dengan STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE sebelum Read oplock kedua diberikan.
  • Level 1, Batch, Filter, Read-Handle, Read-Write, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED dikembalikan.

Membaca

Diberikan hanya jika semua kondisi berikut ini benar:

  • Permintaan adalah untuk aliran file tertentu.
  • Aliran data telah dibuka untuk akses asinkron.
    • Jika dibuka untuk akses sinkron, STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Tidak ada transaksi TxF pada file.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada Kunci Rentang Byte yang ada saat ini pada aliran data.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada bagian yang dapat ditulis yang dipetakan pengguna pada alur data.
    • Jika tidak, STATUS_CANNOT_GRANT_REQUESTED_OPLOCK dikembalikan. The REQUEST_OPLOCK_OUTPUT_BUFFER. bidang akan memiliki bendera REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT yang diatur.

Jika status oplock saat ini adalah:

  • Tidak ada oplock: Permintaan disetujui.

  • Tingkat 2 dan/atau Baca: Permintaan dikabulkan. Anda dapat memiliki beberapa oplock Tingkat 2/Baca yang diberikan pada aliran yang sama secara bersamaan.
    • Selain itu, jika oplock yang sudah ada memiliki kunci oplock yang sama dengan permintaan baru, maka IRP-nya akan diselesaikan dengan STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
  • Read-Handle dan oplock yang ada memiliki kunci yang berbeda dari permintaan baru: Permintaan tersebut disetujui. Beberapa oplock Baca dan Read-Handle dapat hidup berdampingan pada aliran yang sama (lihat catatan berikut tabel ini).
    • Jika tidak (kunci oplock sama) STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Level 1, Batch, Filter, Read-Write, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED dikembalikan.

Read-Handle

Diberikan hanya jika semua kondisi berikut ini benar:

  • Permintaan adalah untuk aliran file tertentu.
  • Aliran data dibuka untuk akses ASINKRON.
    • Jika dibuka untuk akses SYNCHRONOUS, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada transaksi TxF pada file.
    • Jika tidak, maka STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Tidak ada Penguncian Rentang Byte saat ini pada stream.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Tidak ada bagian yang dapat ditulis yang dipetakan pengguna dalam aliran.
    • Jika tidak, STATUS_CANNOT_GRANT_REQUESTED_OPLOCK dikembalikan. The REQUEST_OPLOCK_OUTPUT_BUFFER.Flags field akan diatur dengan bendera REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT.

Jika status oplock saat ini adalah:

  • Tidak ada oplock: permintaan diberikan.

  • Baca: permintaan diberikan.
    • Jika Read oplock yang ada memiliki kunci oplock yang sama dengan permintaan baru, IRP-nya diselesaikan dengan STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE. Hasilnya adalah bahwa oplock ditingkatkan dari Read ke Read-Handle.
    • Setiap oplock Baca yang ada yang tidak memiliki kunci oplock yang sama dengan permintaan baru tetap tidak berubah.
  • Level 2, Level 1, Batch, Filter, Read-Write, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.

Read-Write

Diberikan hanya jika semua kondisi berikut ini benar:

  • Permintaan adalah untuk aliran file tertentu.
    • Jika itu adalah direktori, STATUS_INVALID_PARAMETER akan dikembalikan.
  • Stream dibuka untuk diakses secara ASINKRON.
    • Jika dibuka untuk akses SYNCHRONOUS, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada transaksi TxF pada file.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Jika ada pembukaan lain pada aliran (bahkan dengan utas yang sama), mereka harus memiliki kunci oplock yang sama.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada bagian yang dapat ditulis yang dipetakan pengguna pada aliran.
    • Jika tidak, STATUS_CANNOT_GRANT_REQUESTED_OPLOCK dikembalikan. The REQUEST_OPLOCK_OUTPUT_BUFFER.Kolom akan memiliki bendera REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT yang diatur.

Jika status oplock saat ini adalah:

  • Tidak ada oplock: permintaan disetujui.

  • Baca atau Read-Write, dan oplock yang ada memiliki kunci oplock yang sama dengan permintaan: IRP dari oplock yang ada diselesaikan dengan STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE, dan permintaan tersebut diberikan.
    • Jika tidak, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Level 2, Level 1, Batch, Filter, Read-Handle, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED dikembalikan.

Baca-Write-Handle

Diberikan hanya jika semua hal berikut ini benar:

  • Permintaan adalah untuk aliran file tertentu.
    • Jika berupa direktori, STATUS_INVALID_PARAMETER akan dikembalikan.
  • Siaran telah dibuka untuk akses ASINKRON.
    • Jika dibuka untuk akses sinkron, STATUS_OPLOCK_NOT_GRANTED dikembalikan.
  • Tidak ada transaksi TxF pada file.
    • Jika tidak, nilai STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Jika ada permintaan terbuka lainnya pada aliran, bahkan dengan utas yang sama, mereka harus memiliki kunci oplock yang sama.
    • Jika syarat tersebut tidak dipenuhi, maka STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Tidak ada bagian yang bisa ditulis yang dipetakan pengguna pada stream.
    • Jika tidak, STATUS_CANNOT_GRANT_REQUESTED_OPLOCK dikembalikan. Bidang dalam REQUEST_OPLOCK_OUTPUT_BUFFER akan memiliki bendera REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT yang disetel.

Jika status oplock saat ini adalah:

  • Tidak ada oplock: permintaan telah disetujui.

  • Baca, Baca-Tangani, Baca-Tulis, atau Baca-Write-Handle dan oplock yang ada memiliki kunci oplock yang sama dengan permintaan: IRP oplock yang ada diselesaikan dengan STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE dan permintaan disetujui.
    • Jika tidak, maka STATUS_OPLOCK_NOT_GRANTED akan dikembalikan.
  • Tingkat 2, Tingkat 1, Batch, Filter: STATUS_OPLOCK_NOT_GRANTED dikembalikan.

Nota

Oplock Baca dan Level 2 dapat hidup berdampingan pada aliran yang sama, dan oplock Baca dan Read-Handle dapat hidup berdampingan, tetapi oplock Level 2 dan Read-Handle tidak dapat hidup berdampingan.