Menjamin Kemajuan Operasi I/O

Beberapa driver, seperti driver penyimpanan untuk perangkat paging sistem, harus melakukan setidaknya beberapa operasi I/O yang didukung tanpa kegagalan, untuk menghindari kehilangan data sistem penting. Salah satu penyebab potensial kegagalan driver adalah situasi memori rendah. Jika kerangka kerja atau driver tidak dapat mengalokasikan cukup memori untuk menangani permintaan I/O, satu atau yang lain mungkin harus gagal permintaan I/O dengan menyelesaikannya dengan nilai status kesalahan.

Dalam versi KMDF sebelum versi 1.9, kerangka kerja selalu gagal permintaan I/O jika tidak dapat mengalokasikan objek permintaan kerangka kerja untuk paket permintaan I/O (IRP) yang telah dikirim manajer I/O ke driver. Untuk memberikan kemampuan kepada driver untuk memproses permintaan I/O selama situasi memori rendah, versi 1.9 dan yang lebih baru dari kerangka kerja memberikan kemampuan kemajuan maju yang terjamin untuk antrean I/O.

Kemampuan ini memungkinkan kerangka kerja dan driver untuk mengalokasikan memori terlebih dahulu untuk serangkaian objek permintaan dan buffer konteks driver terkait permintaan. Kerangka kerja dan driver menggunakan memori yang telah dialokasikan sebelumnya ini hanya ketika jumlah memori sistem rendah.

Fitur Kemajuan Penerusan Terjamin

Dengan menggunakan kemajuan penerusan kerangka kerja yang dijamin untuk antrean I/O, driver dapat:

  • Minta kerangka kerja untuk mengalokasikan sekumpulan objek permintaan untuk digunakan dengan antrean I/O tertentu selama situasi memori rendah.

  • Berikan fungsi panggilan balik yang telah mengalokasikan sumber daya khusus permintaan yang dapat digunakan driver saat menerima objek permintaan yang telah dialokasikan sebelumnya dari kerangka kerja selama situasi memori rendah.

  • Berikan fungsi panggilan balik lain yang mengalokasikan sumber daya khusus driver untuk permintaan I/O ketika situasi memori rendah belum terdeteksi. Jika alokasi fungsi panggilan balik ini gagal karena situasi memori rendah, itu dapat menunjukkan apakah kerangka kerja harus menggunakan salah satu objek permintaan yang telah dialokasikan sebelumnya.

  • Tentukan permintaan I/O mana yang memerlukan penggunaan objek permintaan yang telah dialokasikan sebelumnya. Opsi termasuk menggunakan objek yang telah dialokasikan sebelumnya untuk semua RUN, menggunakannya hanya jika operasi I/O halaman sedang berlangsung, atau memiliki fungsi panggilan balik driver tambahan memeriksa setiap IRP untuk menentukan apakah akan menggunakan objek yang telah dialokasikan sebelumnya.

Jika driver Anda menerapkan kemajuan penerusan yang terjamin untuk satu atau beberapa antrean I/O-nya, driver akan lebih mampu memproses permintaan I/O selama situasi memori rendah. Anda dapat menerapkan kemajuan penerusan terjamin untuk antrean I/O default perangkat, dan untuk antrean I/O apa pun yang dikonfigurasi driver Anda dengan memanggil WdfDeviceConfigureRequestDispatching.

Kemampuan kemajuan maju kerangka kerja yang dijamin berfungsi untuk driver Anda hanya jika driver dan target I/O driver menerapkan kemajuan maju yang terjamin. Dengan kata lain, jika driver menerapkan kemajuan penerusan yang terjamin untuk perangkat, semua driver tingkat bawah dalam tumpukan driver perangkat juga harus menerapkan kemajuan maju yang terjamin.

Mengaktifkan Kemajuan Penerusan Terjamin untuk Antrean I/O

Untuk mengaktifkan kemajuan penerusan terjamin untuk antrean I/O, driver Anda menginisialisasi struktur WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY lalu memanggil metode WdfIoQueueAssignForwardProgressPolicy . Jika driver memanggil WdfDeviceConfigureRequestDispatching untuk mengonfigurasi antrean I/O, driver harus melakukannya sebelum memanggil WdfIoQueueAssignForwardProgressPolicy.

Ketika driver memanggil WdfIoQueueAssignForwardProgressPolicy, driver dapat menentukan tiga fungsi panggilan balik peristiwa berikut, yang semuanya opsional:

EvtIoAllocateResourcesForReservedRequest
Fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest driver mengalokasikan dan menyimpan sumber daya khusus permintaan untuk objek permintaan yang disimpan kerangka kerja untuk situasi memori rendah.

Kerangka kerja memanggil fungsi panggilan balik ini setiap kali membuat objek permintaan yang dipesan. Driver harus mengalokasikan sumber daya khusus permintaan untuk satu permintaan I/O, biasanya dengan menggunakan ruang konteks objek permintaan yang dipesan.

EvtIoAllocateRequestResources
Fungsi panggilan balik EvtIoAllocateRequestResources driver mengalokasikan sumber daya khusus permintaan untuk segera digunakan. Ini dipanggil segera setelah kerangka kerja menerima IRP dan membuat objek permintaan untuk IRP.

Jika upaya fungsi panggilan balik untuk mengalokasikan sumber daya gagal, fungsi panggilan balik mengembalikan nilai status kesalahan. Kerangka kerja kemudian menghapus objek permintaan yang baru dibuat dan menggunakan salah satu objek permintaan yang dipesan. Pada gilirannya, handler permintaan driver menggunakan sumber daya khusus permintaan yang sebelumnya dialokasikan oleh fungsi panggilan balik EvtIoAllocateRequestResources .

EvtIoWdmIrpForForwardProgress
Fungsi panggilan balik EvtIoWdmIrpForwardProgress driver memeriksa IRP dan memberi tahu kerangka kerja apakah akan menggunakan objek permintaan khusus untuk IRP atau gagal dalam permintaan I/O dengan menyelesaikannya dengan nilai status kesalahan.

Kerangka kerja memanggil fungsi panggilan balik ini hanya jika kerangka kerja tidak dapat membuat objek permintaan baru dan Anda telah menunjukkan (dengan mengatur bendera dalam struktur WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY driver) yang Anda inginkan agar driver memeriksa RUNP selama situasi memori rendah. Dengan kata lain, driver Anda dapat menilai setiap IRP dan memutuskan apakah itu adalah salah satu yang harus diproses bahkan selama situasi memori rendah.

Ketika driver Anda memanggil WdfIoQueueAssignForwardProgressPolicy, driver juga menentukan jumlah objek permintaan yang dipesan yang Anda inginkan untuk kerangka kerja yang telah dialokasikan sebelumnya untuk situasi memori rendah. Anda dapat memilih jumlah objek permintaan yang sesuai untuk perangkat dan driver Anda. Untuk mencegah penurunan performa, driver Anda biasanya harus menentukan angka yang memperhitungkan jumlah permintaan I/O yang dapat ditangani driver dan perangkat secara paralel.

Namun, jika panggilan driver Anda ke fungsi panggilan balik WdfIoQueueAssignForwardProgressPolicy dan fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest pra-alokasikan terlalu banyak objek permintaan yang dipesan atau terlalu banyak memori sumber daya khusus permintaan, driver Anda benar-benar dapat berkontribusi pada situasi memori rendah yang Anda coba tangani. Anda harus menguji performa driver dan perangkat Anda, dan menyertakan simulasi memori rendah, untuk menentukan angka terbaik yang akan dipilih.

Sebelum WdfIoQueueAssignForwardProgressPolicy kembali, kerangka kerja membuat dan mencadangkan jumlah objek permintaan yang telah ditentukan driver. Setiap kali cadangan objek permintaan, kerangka kerja segera memanggil fungsi panggilan balik EvtIoAllocateResourcesForRequest driver sehingga driver dapat mengalokasikan dan menyimpan sumber daya khusus permintaan, jika kerangka kerja benar-benar menggunakan objek permintaan yang dipesan.

Ketika salah satu penangan permintaan driver menerima permintaan I/O dari antrean I/O, ini dapat memanggil metode WdfRequestIsReserved untuk menentukan apakah objek permintaan adalah salah satu yang dialokasikan sebelumnya oleh kerangka kerja untuk situasi memori rendah. Jika metode ini mengembalikan TRUE, driver harus menggunakan sumber daya yang dicadangkan oleh fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest .

Jika kerangka kerja menggunakan salah satu objek permintaan yang dipesan, kerangka kerja mengembalikan objek ke kumpulan objek yang dipesan setelah driver menyelesaikan permintaan. Kerangka kerja menyimpan objek permintaan, dan ruang konteks apa pun yang dibuat driver dengan memanggil WdfDeviceInitSetRequestAttributes atau WdfObjectAllocateContext, untuk digunakan kembali jika situasi memori rendah lainnya terjadi.

Bagaimana Kerangka Kerja dan Dukungan Driver Dijamin Kemajuan Maju

Berikut adalah langkah-langkah yang dilakukan driver dan kerangka kerja untuk mendukung kemajuan penerusan yang terjamin untuk antrean I/O:

  1. Driver memanggil WdfIoQueueAssignForwardProgressPolicy.

    Sebagai respons, kerangka kerja mengalokasikan dan menyimpan jumlah objek permintaan yang ditentukan driver. Jika driver sebelumnya disebut WdfDeviceInitSetRequestAttributes, setiap alokasi menyertakan ruang konteks yang ditentukan WdfDeviceInitSetRequestAttributes .

    Selain itu, jika driver telah menyediakan fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest , kerangka kerja memanggil fungsi panggilan balik setiap kali mengalokasikan dan menyimpan objek permintaan.

  2. Kerangka kerja menerima paket permintaan I/O (IRP) yang dikirim manajer I/O ke driver.

    Kerangka kerja mencoba mengalokasikan objek permintaan untuk IRP. Jika antrean I/O yang dibuat driver untuk jenis permintaan mendukung kemajuan penerusan yang dijamin, langkah berikutnya tergantung pada apakah alokasi berhasil atau gagal:

    • Alokasi objek permintaan berhasil.

      Jika driver menyediakan fungsi panggilan balik EvtIoAllocateRequestResources , kerangka kerja akan memanggilnya. Jika fungsi panggilan balik mengembalikan STATUS_SUCCESS, kerangka kerja menambahkan permintaan ke antrean I/O. Jika fungsi panggilan balik mengembalikan nilai status kesalahan, kerangka kerja akan menghapus objek permintaan yang baru saja dibuat dan menggunakan salah satu objek permintaan yang telah dialokasikan sebelumnya. Ketika handler permintaan driver menerima objek permintaan, itu menentukan apakah objek permintaan telah dialokasikan sebelumnya dan oleh karena itu apakah harus menggunakan sumber daya driver yang telah dialokasikan sebelumnya.

      Jika driver tidak menyediakan fungsi panggilan balik EvtIoAllocateRequestResources , kerangka kerja menambahkan permintaan ke antrean I/O, seolah-olah driver belum mengaktifkan kemajuan penerusan yang dijamin.

    • Alokasi objek permintaan gagal.

      Apa yang dilakukan kerangka kerja selanjutnya tergantung pada nilai yang disediakan driver untuk anggota ForwardProgressReservedPolicy dari struktur WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY . Anggota ini menginformasikan kerangka kerja kapan harus menggunakan permintaan yang dipesan: selalu, hanya jika permintaan I/O adalah operasi I/O halaman, atau hanya jika fungsi panggilan balik EvtIoWdmIrpForwardProgress menunjukkan bahwa permintaan yang dipesan harus digunakan.

    Dalam semua kasus, penangan permintaan driver dapat memanggil WdfRequestIsReserved untuk menentukan apakah kerangka kerja telah menggunakan objek permintaan yang dipesan. Jika demikian, driver harus menggunakan sumber daya permintaan yang dialokasikan oleh fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest .

Skenario Kemajuan Maju Terjamin

Anda sedang menulis driver untuk perangkat penyimpanan yang mungkin berisi file halaman sistem. Penting bahwa operasi baca dari dan operasi tulis ke file halaman berhasil.

Anda memutuskan untuk membuat antrean I/O terpisah untuk operasi baca dan tulis, dan untuk mengaktifkan kemajuan penerusan yang terjamin untuk kedua antrean I/O ini. Anda memutuskan untuk membuat antrean I/O ketiga untuk semua jenis permintaan lainnya tanpa mengaktifkan kemajuan penerusan yang dijamin.

Tumpukan driver dan perangkat Anda mampu memproses empat operasi tulis secara paralel, sehingga Anda mengatur anggota TotalForwardProgressRequests dari struktur WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY ke 4 sebelum memanggil WdfIoQueueAssignForwardProgressPolicy.

Anda memutuskan bahwa menjamin kemajuan maju hanya penting jika perangkat driver Anda adalah perangkat halaman, sehingga driver Anda menetapkan anggota ForwardProgressReservedPolicy dari struktur WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY ke WdfIoForwardProgressReservedPolicyPagingIO.

Karena driver Anda memerlukan objek memori kerangka kerja untuk setiap permintaan baca dan setiap permintaan tulis, Anda memutuskan bahwa driver Anda harus mengalokasikan beberapa objek memori untuk digunakan untuk panggilannya ke WdfIoTargetFormatRequestForRead dan WdfIoTargetFormatRequestForWrite dalam situasi memori rendah.

Oleh karena itu, driver menyediakan fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest untuk antrean baca dan satu lagi untuk antrean tulis. Setiap kali kerangka kerja memanggil salah satu fungsi panggilan balik ini, fungsi panggilan balik memanggil WdfMemoryCreate dan menyimpan handel objek yang dikembalikan untuk situasi memori rendah. Karena fungsi panggilan balik menerima handel ke objek permintaan yang telah dialokasikan sebelumnya, fungsi ini dapat menginduk objek memori ke objek permintaan. (Driver untuk perangkat DMA mungkin juga mengalokasikan objek DMA kerangka kerja sebelumnya.)

Penangan permintaan untuk antrean baca dan tulis harus menentukan apakah setiap objek permintaan yang diterima adalah salah satu yang dicadangkan kerangka kerja untuk situasi memori rendah. Handler permintaan dapat memanggil WdfRequestIsReserved, atau dapat membandingkan handel objek permintaan dengan yang diterima fungsi panggilan balik EvtIoAllocateResourcesForReservedRequest sebelumnya.

Driver juga menyediakan fungsi panggilan balik EvtIoAllocateRequestResources untuk antrean baca dan satu lagi untuk antrean tulis. Kerangka kerja memanggil salah satu fungsi panggilan balik ini ketika menerima permintaan baca atau tulis dari manajer I/O dan berhasil membuat objek permintaan. Masing-masing fungsi panggilan balik ini memanggil WdfMemoryCreate untuk mengalokasikan objek memori untuk permintaan. Jika alokasi gagal, fungsi panggilan balik mengembalikan nilai status kesalahan untuk memberi tahu kerangka kerja bahwa situasi memori rendah baru saja terjadi. Kerangka kerja, mendeteksi nilai pengembalian kesalahan, menghapus objek permintaan yang baru saja dibuat dan menggunakan salah satu objek yang telah dialokasikan sebelumnya.

Driver ini tidak menyediakan fungsi panggilan balik EvtIoWdmIrpForwardProgress , karena tidak perlu memeriksa runtime integrasi baca atau tulis individu sebelum kerangka kerja menambahkannya ke antrean I/O.

Ingatlah bahwa ketika driver menerapkan kemajuan maju yang terjamin untuk perangkat, semua driver tingkat bawah di tumpukan driver perangkat juga harus menerapkan kemajuan maju yang terjamin.