---
name: "io_submit"
section: "2"
platform: "linux"
package: "man-pages"
version: "6.19-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/io_submit"
---

# io\_submit(2)

submit asynchronous I/O blocks for processing

## NAME

io\_submit - submit asynchronous I/O blocks for processing

## LIBRARY

Standard C library (*libc*, *-lc*)

## SYNOPSIS

```
#include <linux/aio_abi.h>
#include <sys/syscall.h>    /* Definition of SYS_* constants */
#include <unistd.h>
```

**int syscall(SYS\_io\_submit, aio\_context\_t** *ctx\_id***,**             **long** *n***, struct iocb \****iocbpp***\[***n***\]);**

## DESCRIPTION

*Note*: you probably want to use the [**io\_setup**(3)](/io_setup/3.md) wrapper function provided by *libaio*; see VERSIONS.

The **io\_submit**() system call queues *n* I/O request blocks for processing in the AIO context *ctx\_id*. The *iocbpp* argument should be an array of *n* AIO control blocks, which will be submitted to context *ctx\_id*.

The *iocb* (I/O control block) structure defined in *linux/aio\_abi.h* defines the parameters that control the I/O operation.

```
#include <linux/aio_abi.h>
struct iocb {
    __u64   aio_data;
    __u32   PADDED(aio_key, aio_rw_flags);
    __u16   aio_lio_opcode;
    __s16   aio_reqprio;
    __u32   aio_fildes;
    __u64   aio_buf;
    __u64   aio_nbytes;
    __s64   aio_offset;
    __u64   aio_reserved2;
    __u32   aio_flags;
    __u32   aio_resfd;
};
```

The fields of this structure are as follows:

- *aio\_data*

  This data is copied into the *data* field of the *io\_event* structure upon I/O completion (see [**io\_getevents**(2)](/io_getevents/2.md)).

- *aio\_key*

  This is an internal field used by the kernel. Do not modify this field after an **io\_submit**() call.

- *aio\_rw\_flags*

  This defines the R/W flags passed with structure. The valid values are:

  - **RWF\_APPEND** (since Linux 4.16)

    Append data to the end of the file. See the description of the flag of the same name in [**pwritev2**(2)](/pwritev2/2.md) as well as the description of **O\_APPEND** in [**open**(2)](/open/2.md). The *aio\_offset* field is ignored. The file offset is not changed.

  - **RWF\_DSYNC** (since Linux 4.13)

    Write operation complete according to requirement of synchronized I/O data integrity. See the description of the flag of the same name in [**pwritev2**(2)](/pwritev2/2.md) as well the description of **O\_DSYNC** in [**open**(2)](/open/2.md).

  - **RWF\_HIPRI** (since Linux 4.13)

    High priority request, poll if possible

  - **RWF\_NOWAIT** (since Linux 4.14)

    Don't wait if the I/O will block for operations such as file block allocations, dirty page flush, mutex locks, or a congested block device inside the kernel. If any of these conditions are met, the control block is returned immediately with a return value of **-EAGAIN** in the *res* field of the *io\_event* structure (see [**io\_getevents**(2)](/io_getevents/2.md)).

  - **RWF\_SYNC** (since Linux 4.13)

    Write operation complete according to requirement of synchronized I/O file integrity. See the description of the flag of the same name in [**pwritev2**(2)](/pwritev2/2.md) as well the description of **O\_SYNC** in [**open**(2)](/open/2.md).

  - **RWF\_NOAPPEND** (since Linux 6.9)

    Do not honor **O\_APPEND** [**open**(2)](/open/2.md) flag. See the description of **RWF\_NOAPPEND** in [**pwritev2**(2)](/pwritev2/2.md).

  - **RWF\_ATOMIC** (since Linux 6.11)

    Write a block of data such that a write will never be torn from power fail or similar. See the description of **RWF\_ATOMIC** in [**pwritev2**(2)](/pwritev2/2.md). For usage with **IOCB\_CMD\_PWRITEV**, the upper vector limit is *stx\_atomic\_write\_segments\_max.* See **STATX\_WRITE\_ATOMIC** and *stx\_atomic\_write\_segments\_max* description in [**statx**(2)](/statx/2.md).

- *aio\_lio\_opcode*

  This defines the type of I/O to be performed by the *iocb* structure. The valid values are defined by the enum defined in *linux/aio\_abi.h*:

-

  ```
  enum {
      IOCB_CMD_PREAD = 0,
      IOCB_CMD_PWRITE = 1,
      IOCB_CMD_FSYNC = 2,
      IOCB_CMD_FDSYNC = 3,
      IOCB_CMD_POLL = 5,
      IOCB_CMD_NOOP = 6,
      IOCB_CMD_PREADV = 7,
      IOCB_CMD_PWRITEV = 8,
  };
  ```

- *aio\_reqprio*

  This defines the requests priority.

- *aio\_fildes*

  The file descriptor on which the I/O operation is to be performed.

- *aio\_buf*

  This is the buffer used to transfer data for a read or write operation.

- *aio\_nbytes*

  This is the size of the buffer pointed to by *aio\_buf*.

- *aio\_offset*

  This is the file offset at which the I/O operation is to be performed.

- *aio\_flags*

  This is the set of flags associated with the *iocb* structure. The valid values are:

  - **IOCB\_FLAG\_RESFD**

    Asynchronous I/O control must signal the file descriptor mentioned in *aio\_resfd* upon completion.

  - **IOCB\_FLAG\_IOPRIO** (since Linux 4.18)

    Interpret the *aio\_reqprio* field as an **IOPRIO\_VALUE** as defined by *linux/ioprio.h*.

- *aio\_resfd*

  The file descriptor to signal in the event of asynchronous I/O completion.

## RETURN VALUE

On success, **io\_submit**() returns the number of *iocb*s submitted (which may be less than *n*, or 0 if *n* is zero).

On error, -1 is returned, and *errno* is set to indicate the error.

## ERRORS

- **EAGAIN**

  Insufficient resources are available to queue any *iocb*s.

- **EBADF**

  The file descriptor specified in the first *iocb* is invalid.

- **EFAULT**

  One of the data structures points to invalid data.

- **EINVAL**

  The AIO context specified by *ctx\_id* is invalid.

- **EINVAL**

  *n* is less than 0.

- **EINVAL**

  The *iocb* at *\*iocbpp\[0\]* is not properly initialized.

- **EINVAL**

  The operation specified is invalid for the file descriptor in the *iocb*.

- **EINVAL**

  The value in the *aio\_reqprio* field is invalid.

- **ENOSYS**

  **io\_submit**() is not implemented on this architecture.

- **EPERM**

  The *aio\_reqprio* field is set with the class **IOPRIO\_CLASS\_RT**, but the submitting context does not have the **CAP\_SYS\_ADMIN** capability.

## VERSIONS

*libaio* ⟨https://pagure.io/libaio⟩ provides a wrapper function with the same name, but different prototype and return value. You probably want to use that wrapper.

## STANDARDS

Linux.

## HISTORY

Linux 2.5.

## SEE ALSO

[**io\_cancel**(2)](/io_cancel/2.md), [**io\_destroy**(2)](/io_destroy/2.md), [**io\_getevents**(2)](/io_getevents/2.md), [**io\_setup**(2)](/io_setup/2.md), [**io\_submit**(3)](/io_submit/3.md), [**aio**(7)](/aio/7.md)
