Submission queue io_uring dapat memuat banyak operasi sekaligus, tetapi setiap operasi tidak harus independen. Menetapkan IOSQE_IO_LINK pada sebuah submission queue entry mengikatnya ke entry berikutnya, membentuk rantai dengan urutan eksekusi dan propagasi kegagalan sebagai bagian dari struktur request yang terlihat oleh kernel.

Kontrak ini berbeda dari dua SQE independen yang koordinasinya baru dilakukan setelah completion. Rantai terhubung menyatakan dependensi sebelum kernel mulai memproses operasi. Perbedaan tersebut penting saat request berikutnya hanya valid setelah request sebelumnya selesai, atau saat kegagalan satu tahap harus mencegah tahap yang tersisa dijalankan.

IOSQE_IO_LINK tidak menandai sebuah SQE sebagai child yang bergantung pada entry lain. Flag tersebut menyatakan bahwa SQE saat ini terhubung ke SQE sesudahnya.

Rantai tiga operasi menempatkan flag pada dua entry pertama:

SQE 0: operation A + IOSQE_IO_LINK
SQE 1: operation B + IOSQE_IO_LINK
SQE 2: operation C

Tidak adanya flag pada entry terakhir mengakhiri rantai. SQE lain yang disubmit setelah C bersifat independen kecuali relasi link baru dibuat.

Representasi ini menjadikan batas rantai sebagai properti metadata submission, bukan state aplikasi di sisi completion. Kode pembentuk SQE harus mempertahankan urutan sekaligus flag-nya. Mengubah urutan entry yang tampak independen pada call site dapat mengubah dependency graph secara diam-diam.

Completion menjadi gerbang request berikutnya

Pada rantai link normal, request berikutnya tidak diterbitkan sampai request sebelumnya selesai dengan sukses menurut semantik link io_uring. Jaminan ini lebih kuat daripada urutan submission saja.

Urutan submission secara umum tidak berarti urutan completion bagi request asinkron yang tidak saling terkait. Kernel dapat memiliki beberapa request yang sedang berjalan, sedangkan completion dapat tiba dalam urutan yang ditentukan operasi dan subsistem di bawahnya. Link menambahkan batas sequencing eksplisit di antara anggota rantai yang bersebelahan.

Pertimbangkan operasi file yang diikuti timeout dan dimaksudkan sebagai bagian dari satu aksi gabungan. Jika keduanya disubmit secara independen, keduanya dapat aktif tanpa dependensi. Menghubungkannya mengubah relasi tersebut: anggota kedua diatur oleh status completion anggota pertama dan aturan rantai.

Aplikasi tetap menerima completion queue entry untuk setiap operasi. Link tidak mengubah beberapa SQE menjadi satu CQE atau menghapus hasil per request. Link mengubah relasi scheduling dan pembatalan sambil mempertahankan pelaporan completion individual.

Kegagalan dapat menghentikan sisa rantai

Link normal membawa propagasi kegagalan. Jika sebuah request terhubung gagal, request berikutnya dalam rantai dibatalkan alih-alih diterbitkan seolah tahap sebelumnya sukses. Anggota yang dibatalkan biasanya melaporkan -ECANCELED pada hasil completion.

Kondisi pemutus rantai lebih luas daripada hasil negatif bergaya errno. Untuk IOSQE_IO_LINK, io_uring dapat memperlakukan hasil yang tidak sesuai ekspektasi sebagai error bagi chaining; short read merupakan contoh terdokumentasi yang dapat menghentikan sisa rantai. Karena itu, kode harus memperhitungkan semantik hasil yang spesifik untuk setiap opcode, bukan menyederhanakan aturan menjadi cqe->res < 0.

Request terhubung mengurangi sebagian orkestrasi di sisi completion, tetapi tidak menggantikan validasi domain. Kernel dapat menegakkan aturan hasil request miliknya; kernel tidak dapat menentukan apakah sebuah hasil memenuhi invariant aplikasi di luar aturan tersebut.

Batas pembatalan juga hanya berlaku pada rantai tersebut. SQE independen dalam batch submission yang sama tidak ikut dibatalkan hanya karena rantai terhubung di dekatnya gagal.

IOSQE_IO_HARDLINK mempertahankan urutan di antara request yang bersebelahan, tetapi mengubah perilaku setelah kegagalan. Kegagalan satu anggota tidak otomatis membatalkan sisa rantai.

Perbedaan tersebut memisahkan dua kontrak:

IOSQE_IO_LINK
A gagal -> anggota terhubung berikutnya dibatalkan

IOSQE_IO_HARDLINK
A gagal -> urutan rantai tetap berlaku, anggota berikutnya dapat berlanjut

Hard link tepat digunakan hanya saat operasi berikutnya tetap valid setelah operasi sebelumnya gagal. Cleanup merupakan salah satu bentuk kebutuhan ini: aplikasi mungkin perlu menjalankan aksi berikutnya walaupun operasi sebelumnya mengembalikan error.

Menggunakan hard link hanya untuk menghindari pembatalan akan melemahkan kontrak dependensi. Operasi berikutnya harus aman untuk setiap hasil yang dapat diproduksi anggota sebelumnya, termasuk error. Jika tidak, rantai mempertahankan urutan tetapi mengizinkan transisi state yang tidak valid.

Rantai bukan transaksi

Rantai terhubung dapat tampak seperti transaksi kecil karena mengelompokkan pekerjaan berurutan dan dapat menahan operasi berikutnya setelah kegagalan. Rantai tersebut tidak menyediakan rollback transaksional.

Jika operasi A mengubah state eksternal lalu operasi B gagal, link tidak membatalkan efek A. Operasi pertama sudah selesai. Mutasi filesystem, byte yang telah dikirim ke socket, atau efek eksternal lain tetap mengikuti semantik operasinya masing-masing.

Kondisi ini menghasilkan model kegagalan asimetris:

A sukses -> efek A mungkin sudah terlihat
B gagal  -> C dapat dibatalkan
            efek A tidak di-rollback

Atomicity harus berasal dari API yang mendasarinya jika memang diperlukan. Rantai dapat mengatur urutan penerbitan dan propagasi kegagalan, tetapi tidak dapat menggabungkan operasi kernel yang terpisah menjadi commit all-or-nothing.

Batas ini sangat penting untuk state persisten. Mengurutkan dua write melalui link tidak dengan sendirinya menghasilkan crash consistency, durable commit, atau atomic replacement. Properti tersebut bergantung pada semantik filesystem dan storage serta operasi sinkronisasi yang digunakan aplikasi.

Rantai juga menciptakan dependensi lifetime resource

Sebuah SQE dapat merujuk ke memory, file descriptor, fixed resource, socket address, atau struktur khusus operasi. Menghubungkan request tidak melonggarkan persyaratan lifetime objek tersebut.

Jika request terhubung yang berada di belakang merujuk ke buffer, buffer itu harus tetap valid selama periode yang diwajibkan kontrak operasi io_uring terkait. Fakta bahwa request menunggu di belakang anggota lain tidak membuat reuse lebih awal menjadi aman. Eksekusinya ditunda, bukan dibuang.

Masalah serupa berlaku pada file descriptor ketika descriptor biasa digunakan. Kode aplikasi harus memperhitungkan lifetime dan reuse descriptor sesuai aturan API. Registered resource dapat mengubah mekanismenya, tetapi juga membawa kontrak registration dan update tersendiri.

Konsekuensi desainnya jelas: rantai mengodekan dependensi operasi di sisi kernel, sedangkan ownership resource user space tetap menjadi tanggung jawab aplikasi.

Penanganan completion tetap memerlukan identitas request

Karena setiap anggota menghasilkan completion sendiri, aplikasi tetap perlu mengaitkan CQE dengan operasi logis. Field user_data tetap menjadi mekanisme umum untuk membawa identitas yang ditentukan aplikasi dari submission ke completion.

Rantai tidak menjamin bahwa penanganan completion dapat mengabaikan hasil individual. Setiap CQE dapat membawa informasi yang diperlukan untuk pelepasan resource, klasifikasi error, accounting, atau state protokol.

Hal ini juga mencegah kekeliruan abstraksi: merepresentasikan seluruh rantai hanya dengan satu record state aplikasi sambil membuang identitas setiap anggota. Pendekatan itu dapat bekerja pada wrapper yang sangat terbatas, tetapi wrapper tetap harus mengonsumsi setiap CQE serta memetakan pembatalan dan progress parsial ke state machine miliknya secara tepat.

Dependensi tepat ditempatkan saat semantik kegagalannya eksplisit

SQE terhubung paling tepat saat dependensi sudah diketahui pada waktu submission dan perilaku kegagalan yang diinginkan cocok dengan kontrak kernel. Mekanisme ini dapat mengurangi race yang muncul saat operasi kedua baru disubmit setelah user space menerima CQE pertama, sebab dependensi sudah ada sebelum salah satu tahap selesai.

Mekanisme ini kurang cocok ketika operasi berikutnya bergantung pada pemeriksaan data tingkat aplikasi dari hasil sebelumnya. Dalam kondisi tersebut, user space harus menerima dan mengklasifikasikan hasil sebelum membentuk aksi berikutnya. Membuat rantai lebih awal berarti menetapkan transisi sebelum aplikasi memiliki informasi yang diperlukan untuk memilihnya.

Batasnya bukan sekadar kontrol sinkron dibanding asinkron. Batas tersebut berada pada lokasi pengambilan keputusan. IOSQE_IO_LINK memindahkan relasi sequencing dan pembatalan yang sudah ditentukan ke request graph yang disubmit. Keputusan yang bergantung pada interpretasi hasil tingkat aplikasi tetap berada di luar graph tersebut.