3.2. kbdus API reference

This page contains reference documentation for the entire user-space API of kbdus, which is exported by the kbdus.h header file.

Summary

  • Driver life cycle:

    • struct kbdus_device_config

    • struct kbdus_fd_config

    • struct kbdus_device_and_fd_config

    • KBDUS_IOCTL_CREATE_DEVICE

    • KBDUS_IOCTL_ATTACH_TO_DEVICE

    • KBDUS_IOCTL_TERMINATE

    • KBDUS_IOCTL_MARK_AS_SUCCESSFUL

  • Items and replies:

    • enum kbdus_item_type

    • struct kbdus_item

    • struct kbdus_reply

    • struct kbdus_reply_or_item_common

    • union kbdus_reply_or_item

    • KBDUS_IOCTL_RECEIVE_ITEM

    • KBDUS_IOCTL_SEND_REPLY

    • KBDUS_IOCTL_SEND_REPLY_AND_RECEIVE_ITEM

  • Device management:

    • KBDUS_IOCTL_DEVICE_PATH_TO_ID

    • KBDUS_IOCTL_GET_DEVICE_CONFIG

    • KBDUS_IOCTL_FLUSH_DEVICE

    • KBDUS_IOCTL_TRIGGER_DEVICE_DESTRUCTION

    • KBDUS_IOCTL_WAIT_UNTIL_DEVICE_IS_DESTROYED

  • Versions:

    • struct kbdus_version

    • KBDUS_IOCTL_GET_VERSION

    • KBDUS_HEADER_VERSION_{MAJOR,MINOR,PATCH}

  • Miscellaneous:

    • KBDUS_IOCTL_TYPE

Driver life cycle

struct kbdus_device_config

Configuration for a device.

The documentation for each field specifies its directionality, i.e., whether it is read by kbdus (IN), written by kbdus (OUT), or both (IN/OUT), when the configuration is part of the argument for ioctl command KBDUS_IOCTL_CREATE_DEVICE.

When the configuration is instead part of the argument for ioctl command KBDUS_IOCTL_ATTACH_TO_DEVICE, then field id has directionality IN and all other fields have directionality OUT.

Note that the restrictions documented for each field apply only if it is under a directionality of IN or IN/OUT. Similarly, the documentation for how each field is modified applies only if they are under a directionality of IN/OUT.

Public Members

uint64_t id

The device’s numerical identifier, unique for every device since module load.

Directionality: OUT on create.

uint64_t size

The size of the device, in bytes.

Directionality: IN on create.

Restrictions: Must be a positive multiple of physical_block_size, or of logical_block_size if the former is 0.

uint32_t logical_block_size

The device’s logical block size, in bytes.

Directionality: IN on create.

Restrictions: Must be a power of two greater than or equal to 512 and less than or equal to the system’s page size.

uint32_t physical_block_size

The device’s physical block size, in bytes.

Directionality: IN/OUT on create.

Restrictions: Must be 0 or a power of two greater than or equal to logical_block_size and less than or equal to the system’s page size.

How this value is modified:

  • If this value is 0, it is set to the value of logical_block_size.

  • Otherwise, this value is left unchanged.

uint32_t max_read_write_size

The maximum size for read, write, and FUA write requests, in bytes.

Note that this does not impose a limit on operations performed by clients of the device, but ensures that requests violating this limit are split into requests that satisfy it.

Directionality: IN/OUT on create.

Requirements: Must be 0 or a value greater than or equal to the system’s page size.

How this value is modified:

  • If supports_read, supports_write, and supports_fua_write are all false, this value is set to 0;

  • Otherwise, if this value is 0, it is set to an unspecified positive multiple of logical_block_size that is greater than or equal to the system’s page size;

  • Otherwise, this value is either left unchanged or decreased to an unspecified positive multiple of logical_block_size that is greater than or equal to the system’s page size (but never increased).

uint32_t max_write_same_size

The maximum size for write same requests, in bytes.

Note that this does not impose a limit on operations performed by clients of the device, but ensures that requests violating this limit are split into requests that satisfy it.

Directionality: IN/OUT on create.

Requirements: Must be 0 or a value greater than or equal to logical_block_size.

How this value is modified:

  • If supports_write_same is false, this value is set to 0;

  • Otherwise, if this value is 0, it is set to an unspecified positive multiple of logical_block_size;

  • Otherwise, this value is either left unchanged or decreased to an unspecified positive multiple of logical_block_size (but never increased).

uint32_t max_write_zeros_size

The maximum size for write zeros requests, in bytes.

Note that this does not impose a limit on operations performed by clients of the device, but ensures that requests violating this limit are split into requests that satisfy it.

Directionality: IN/OUT on create.

Requirements: Must be 0 or a value greater than or equal to logical_block_size.

How this value is modified:

  • If supports_write_zeros is false, this value is set to 0;

  • Otherwise, if this value is 0, it is set to an unspecified positive multiple of logical_block_size;

  • Otherwise, this value is either left unchanged or decreased to an unspecified positive multiple of logical_block_size (but never increased).

uint32_t max_discard_erase_size

The maximum size for discard and secure erase requests, in bytes.

Note that this does not impose a limit on operations performed by clients of the device, but ensures that requests violating this limit are split into requests that satisfy it.

Directionality: IN/OUT on create.

Requirements: Must be 0 or a value greater than or equal to logical_block_size.

How this value is modified:

  • If supports_discard and supports_secure_erase are both false, this value is set to 0;

  • Otherwise, if this value is 0, it is set to an unspecified positive multiple of logical_block_size;

  • Otherwise, this value is either left unchanged or decreased to an unspecified positive multiple of logical_block_size (but never increased).

uint32_t max_outstanding_reqs

The maximum number of simultaneously outstanding requests.

An outstanding request is one that has been received through a file description but not yet replied to.

Directionality: IN/OUT on create.

Requirements: Must be positive.

How this value is modified: This value is either left unchanged or decreased to an unspecified positive value (but never increased).

uint8_t supports_read

Whether the device supports read requests.

Directionality: IN on create.

uint8_t supports_write

Whether the device supports write requests.

Directionality: IN on create.

uint8_t supports_write_same

Whether the device supports write same requests.

Directionality: IN on create.

uint8_t supports_write_zeros

Whether the device supports write zeros requests (both allowing and disallowing unmapping).

Directionality: IN on create.

uint8_t supports_fua_write

Whether the device supports FUA write requests.

Directionality: IN on create.

uint8_t supports_flush

Whether the device supports flush requests.

Directionality: IN on create.

uint8_t supports_discard

Whether the device supports discard requests.

Directionality: IN on create.

uint8_t supports_secure_erase

Whether the device supports secure erase requests.

Directionality: IN on create.

uint8_t supports_ioctl

Whether the device supports ioctl requests.

Directionality: IN on create.

uint8_t rotational

Whether to mark the device as being rotational.

This may have an effect on the behavior of the scheduler for the device, and thus its performance.

Directionality: IN on create.

uint8_t merge_requests

Whether request merging should occur.

Directionality: IN on create.

uint8_t enable_partition_scanning

Whether to enable partition scanning for the device.

Directionality: IN on create.

uint8_t recoverable

Whether the device is recoverable.

If a non-recoverable device is left without an attached file description, it is automatically destroyed. A recoverable device, on the other hand, is not (unless it is left without an attached file description before becoming available to clients), and can only be destroyed using the KBDUS_IOCTL_TRIGGER_DEVICE_DESTRUCTION ioctl command.

Note that KBDUS_IOCTL_ATTACH_TO_DEVICE can be used on a device regardless of whether it is recoverable.

Directionality: IN on create.

uint32_t major

The device’s major number.

Directionality: OUT on create.

uint32_t minor

The device’s minor number.

Directionality: OUT on create.

struct kbdus_fd_config

Configuration for a file description.

The documentation for each field specifies its directionality, i.e., whether it is read by kbdus but not written (IN), or both read and written (OUT), regardless of whether the configuration is part of the argument for ioctl command KBDUS_IOCTL_CREATE_DEVICE (“on create”) or KBDUS_IOCTL_ATTACH_TO_DEVICE (“on attach”).

Public Members

uint32_t num_preallocated_buffers

How many user-mappable request payload buffers to allocate.

Directionality: IN/OUT.

How this value is modified: If it is greater than the adjusted value of max_outstanding_reqs, then it is set to that value.

struct kbdus_device_and_fd_config

Configuration for both a device and a file description.

Public Members

struct kbdus_device_config device

Configuration for the device.

struct kbdus_fd_config fd

Configuration for the file description.

KBDUS_IOCTL_CREATE_DEVICE _IOWR(KBDUS_IOCTL_TYPE, 1, struct kbdus_device_and_fd_config)

Creates a device and attaches the file description to that device.

Note that the only way to detach a file description from a device is to close that file description (i.e., close all file descriptors pointing to that file description).

If the file description fails to attach to the device, then the device is unconditionally destroyed before the ioctl returns.

The given configuration is adjusted as specified in the documentation for struct kbdus_device_config and struct kbdus_fd_config.

If this ioctl fails with errno = EINTR, its argument is left unmodified. If this ioctl fails with any other errno, its argument is left in an unspecified state.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from/to user space fails.

  • Fails with errno = EINVAL if the file description is concurrently attaching or is already attached to a device.

  • Fails with errno = EINVAL if the given configuration is invalid.

  • Fails with errno = ENOSPC if the maximum number of BDUS devices currently exist.

  • Fails with errno = EINTR if interrupted.

  • May fail due to other unspecified reasons with other errno values as well.

  • Returns 0 on success.

KBDUS_IOCTL_ATTACH_TO_DEVICE _IOWR(KBDUS_IOCTL_TYPE, 2, struct kbdus_device_and_fd_config)

Attaches the file description to a given device.

Note that the only way to detach a file description from a device is to close that file description (i.e., close all file descriptors pointing to that file description).

The id of the device is taken from the device.id field of the configuration given as the ioctl argument. Other fields of device are not inspected, and the device field is overwritten with the existing device’s configuration. *The configuration of the existing device is not modified in any way.

The fd field of the configuration given as the ioctl argument can be completely different of that of file descriptions previously attached to the existing device.

A file description can only be attached to devices that are already available to clients. Nevertheless, the first request received through the file description is always a “device available” notification.

The device may or may not already have a file description attached to it. If it does, (1) a single “flush+terminate” message, followed by “terminate” messages ad infinitum, will be sent to that file description, (2) this ioctl will block until that file description is closed, and (3) only then the new file description will be attached to the device. However, in this case, if the previous file description was not marked as successful prior to being closed, or if this ioctl fails and the device is non-recoverable, it will be destroyed.

If this ioctl fails with errno = EINTR, its argument is left unmodified. If this ioctl fails with any other errno, its argument is left in an unspecified state.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from/to user space fails.

  • Fails with errno = EINVAL if the file description is concurrently attaching or is already attached to a device.

  • Fails with errno = EINVAL if no device with the given id ever existed.

  • Fails with errno = ENODEV if the device with the given id doesn’t exist anymore.

  • Fails with errno = EBUSY if the device is not yet available to clients.

  • Fails with errno = EINPROGRESS if another file description is trying to attach to the device.

  • Fails with errno = EINTR if interrupted while waiting for already-attached file description to be closed. (Note that if the device is non-recoverable, it may then happen to be destroyed before the caller has a chance to retry this ioctl.)

  • May fail due to other unspecified reasons with other errno values as well.

  • Returns 0 on success.

KBDUS_IOCTL_TERMINATE _IO(KBDUS_IOCTL_TYPE, 3)

Terminates the file description.

After this command is issued, “terminate” messages will be sent to the file description ad infinitum.

Errors and return values:

  • Fails with errno = EINVAL if the file description is not attached to a device.

  • Returns 0 on success.

KBDUS_IOCTL_MARK_AS_SUCCESSFUL _IO(KBDUS_IOCTL_TYPE, 4)

Marks the file description as successful.

Whether or not a file description attached to a device was marked as successful prior to being closed is relevant if the device is non-recoverable and another file description is attaching to it. In that case, the device is destroyed and the new file description will consequently fail to attach to it.

Errors and return values:

  • Fails with errno = EINVAL if the file description is not attached to a device.

  • Returns 0 on success.

Items and replies

enum kbdus_item_type

Item types.

Values:

enumerator KBDUS_ITEM_TYPE_DEVICE_AVAILABLE

Indicates that the device has become available to clients.

Items of this type are not requests and should not be replied to.

enumerator KBDUS_ITEM_TYPE_TERMINATE

Indicates that the file description should be closed.

Items of this type are not requests and should not be replied to.

enumerator KBDUS_ITEM_TYPE_FLUSH_AND_TERMINATE

Indicates that the file description should be closed right after performing a flush request.

Items of this type are not requests and should not be replied to.

enumerator KBDUS_ITEM_TYPE_READ

Read request.

  • 64-bit argument: read offset;

  • 32-bit argument: number of bytes to be read;

  • Request payload: (none);

  • Reply payload: the read data, if the operation was successful;

  • Reply payload size: the 32-bit argument.

enumerator KBDUS_ITEM_TYPE_WRITE

Write request.

  • 64-bit argument: write offset;

  • 32-bit argument: number of bytes to be written;

  • Request payload: the data to be written;

  • Request payload size: the 32-bit argument;

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_WRITE_SAME

Write same request.

  • 64-bit argument: write offset;

  • 32-bit argument: number of bytes to be written;

  • Request payload: the data to be written;

  • Request payload size: the device’s logical block size;

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_WRITE_ZEROS_NO_UNMAP

Write zeros request that must not deallocate space.

  • 64-bit argument: write offset;

  • 32-bit argument: number of bytes to be zeroed;

  • Request payload: (none);

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_WRITE_ZEROS_MAY_UNMAP

Write zeros request that may deallocate space.

  • 64-bit argument: write offset;

  • 32-bit argument: number of bytes to be zeroed;

  • Request payload: (none);

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_FUA_WRITE

FUA write request.

  • 64-bit argument: write offset;

  • 32-bit argument: number of bytes to be written;

  • Request payload: the data to be written;

  • Request payload size: the 32-bit argument;

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_FLUSH

Flush request.

  • 64-bit argument: (unused);

  • 32-bit argument: (unused);

  • Request payload: (none);

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_DISCARD

Discard request.

  • 64-bit argument: discard offset;

  • 32-bit argument: number of bytes to be discarded;

  • Request payload: (none);

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_SECURE_ERASE

Secure erase request.

  • 64-bit argument: secure erase offset;

  • 32-bit argument: number of bytes to be securely erased;

  • Request payload: (none);

  • Reply payload: (none).

enumerator KBDUS_ITEM_TYPE_IOCTL

ioctl request.

  • 64-bit argument: (unused);

  • 32-bit argument: ioctl command;

  • Request payload: the argument data, if the ioctl command’s direction has the _IOC_READ bit set;

  • Request payload size: given by the ioctl command, if the ioctl command’s direction has the _IOC_READ bit set;

  • Reply payload: the argument data, if the ioctl command’s direction has the _IOC_WRITE bit set;

  • Reply payload size: given by the ioctl command, if the ioctl command’s direction has the _IOC_WRITE bit set.

struct kbdus_item

An item.

Public Members

uint64_t user_ptr_or_buffer_index

Pointer to process memory or index of preallocated buffer.

The meaning of this field depends on use_preallocated_buffer.

uint64_t handle_seqnum

The seqnum portion of the handle that identifies this item.

uint16_t handle_index

The index portion of the handle that identifies this item.

uint8_t use_preallocated_buffer

Whether the payload for this item (if any) should be stored in a preallocated buffer or in a region of process memory.

uint8_t type

The type of this item.

uint32_t arg32

The 32-bit argument for this item (if applicable).

uint64_t arg64

The 64-bit argument for this item (if applicable).

struct kbdus_reply

A reply to a request.

Public Members

uint64_t user_ptr_or_buffer_index

Pointer to process memory or index of preallocated buffer.

The meaning of this field depends on use_preallocated_buffer.

uint64_t handle_seqnum

The seqnum portion of the handle that identifies the item to which this reply pertains.

uint16_t handle_index

The index portion of the handle that identifies the item to which this reply pertains.

uint8_t use_preallocated_buffer

Whether the payload for this reply (if any) should be stored in a preallocated buffer or in a region of process memory.

int32_t error

0 if the operation succeeded, errno value otherwise.

For non-ioctl requests, values other than 0, ENOLINK, ENOSPC, and ETIMEDOUT are converted into EIO.

For ioctl requests, negative values and values greater than 133 are converted into EIO.

struct kbdus_reply_or_item_common

The common prefix of struct kbdus_reply and struct kbdus_item.

Public Members

uint64_t user_ptr_or_buffer_index

An alias for the kbdus_reply.user_ptr_or_buffer_index and kbdus_item.user_ptr_or_buffer_index fields.

uint64_t handle_seqnum

An alias for the kbdus_reply.handle_seqnum and kbdus_item.handle_seqnum fields.

uint16_t handle_index

An alias for the kbdus_reply.handle_index and kbdus_item.handle_index fields.

uint8_t use_preallocated_buffer

An alias for the kbdus_reply.use_preallocated_buffer and kbdus_item.use_preallocated_buffer fields.

union kbdus_reply_or_item
#include <kbdus.h>

A reply or an item.

Public Members

struct kbdus_reply reply

The reply.

struct kbdus_item item

The item.

struct kbdus_reply_or_item_common common

Aliases the common prefix of reply and item.

KBDUS_IOCTL_RECEIVE_ITEM _IO(KBDUS_IOCTL_TYPE, 10)

Blocks until an item is ready to be consumed.

The argument is the index of the union kbdus_reply_or_item to which to write the item.

If this ioctl fails with errno = EINTR, the struct kbdus_reply_or_item is left unmodified. If this ioctl fails with any other errno, the struct kbdus_reply_or_item is left in an unspecified state.

KBDUS_IOCTL_SEND_REPLY _IO(KBDUS_IOCTL_TYPE, 11)

Sends a reply to a (request) item.

The argument is the index of the union kbdus_reply_or_item serving as the reply.

If the reply’s handle_index field is 0, this has no effect.

The struct kbdus_reply_or_item is always left unmodified.

KBDUS_IOCTL_SEND_REPLY_AND_RECEIVE_ITEM _IO(KBDUS_IOCTL_TYPE, 12)

Sends a reply to a request and then blocks until an item is ready to be consumed.

If the reply’s handle_index field is 0, no reply is sent.

This may only fail with EINTR after the reply was successfully sent, so when retrying the handle might first be set to 0, but it’s not strictly necessary since attempts to complete an already completed request are ignored.

If this ioctl fails with errno = EINTR, the struct kbdus_reply_or_item is left unmodified. If this ioctl fails with any other errno, the struct kbdus_reply_or_item is left in an unspecified state.

Device management

KBDUS_IOCTL_DEVICE_PATH_TO_ID _IOWR(KBDUS_IOCTL_TYPE, 5, uint64_t)

Obtains the numerical identifier of the device referred by a block special file.

The argument is interpreted as the result of converting to a uint64_t a pointer to a character buffer containing the path to the block special file. Upon success, the argument is replaced with the device’s numerical identifier.

If this ioctl fails with errno = EINTR, its argument is left unmodified. If this ioctl fails with any other errno, its argument is left in an unspecified state.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from/to user space fails.

  • Fails with errno = EACCES, ELOOP, ENOENT, or ENOTDIR due to the same reasons as stat() does.

  • Fails with errno = ENOTBLK if not a block special file.

  • Fails with errno = EINVAL if the given dev_t can never correspond to a BDUS device or partition thereof.

  • Fails with errno = ENODEV if the given dev_t is not in the minor space for an existing BDUS device.

  • Fails with errno = ECHILD if the given dev_t is in the minor space of an existing BDUS device but it does not correspond to the whole device (i.e., corresponds to a partition of that device that may or may not exist).

  • May fail due to other unspecified reasons with other errno values as well.

  • Returns 0 on success.

KBDUS_IOCTL_GET_DEVICE_CONFIG _IOWR(KBDUS_IOCTL_TYPE, 6, struct kbdus_device_config)

Retrieves the configuration of a device.

The id of the device whose configuration to retrieve must be specified in the id field of the argument. The entire argument is then overwritten with the device’s configuration.

If this ioctl fails with errno = EINTR, its argument is left unmodified. If this ioctl fails with any other errno, its argument is left in an unspecified state.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from/to user space fails.

  • Fails with errno = EINVAL if no device with the given id ever existed.

  • Fails with errno = ENODEV if the device with the given id no longer exists.

  • Fails with errno = EINTR if interrupted.

  • Returns 0 on success.

KBDUS_IOCTL_FLUSH_DEVICE _IOR(KBDUS_IOCTL_TYPE, 7, uint64_t)

Submits a flush request to the device with the given id and awaits its completion.

This command has the effect of ensuring (if not interrupted) that all data written to the device with the given id is persistently stored, as if fsync() or fdatasync() were called on it.

This command works even if the device is already open with O_EXCL.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from user space fails.

  • Fails with errno = EINVAL if no device with the given id ever existed.

  • Fails with errno = ENODEV if the device with the given id no longer exists.

  • Fails with errno = EINTR if interrupted.

  • May fail due to other unspecified reasons with other errno values as well.

  • Returns 0 on success.

KBDUS_IOCTL_TRIGGER_DEVICE_DESTRUCTION _IOR(KBDUS_IOCTL_TYPE, 8, uint64_t)

Triggers the destruction of the device with the given id.

If the device has a file description attached to it, this will cause “terminate” messages to be sent to it ad infinitum. After it is closed, or if the device does not have a file description attached, the device will be destroyed (even if the device is recoverable).

This command only triggers the above procedure, returning immediately without waiting for any file description to be closed or for the device to be destroyed.

If the device with the given id no longer exists, this command has no effect.

This does not flush the device.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from user space fails.

  • Fails with errno = EINVAL if no device with the given id ever existed.

  • May fail due to other unspecified reasons with other errno values as well.

  • Returns 0 on success.

KBDUS_IOCTL_WAIT_UNTIL_DEVICE_IS_DESTROYED _IOR(KBDUS_IOCTL_TYPE, 9, uint64_t)

Blocks until the device with the given id is destroyed.

If the device with the given id no longer exists, this command returns immediately.

Errors and return values:

  • Fails with errno = EFAULT if memory copy from user space fails.

  • Fails with errno = EINVAL if no device with the given id ever existed.

  • Fails with errno = EINTR if interrupted.

  • May fail due to other unspecified reasons with other errno values as well.

  • Returns 0 on success.

Versions

struct kbdus_version

A version number.

Public Members

uint32_t major

The major version.

uint32_t minor

The minor version.

uint32_t patch

The patch version.

KBDUS_IOCTL_GET_VERSION _IOW(KBDUS_IOCTL_TYPE, 0, struct kbdus_version)

Writes kbdus’ version into the argument.

If this ioctl fails, its argument is left in an unspecified state.

Errors and return values:

  • Fails with errno = EFAULT if memory copy to user space fails.

  • Fails with errno = EINTR if interrupted.

  • Returns 0 on success.

KBDUS_HEADER_VERSION_MAJOR 0
KBDUS_HEADER_VERSION_MINOR 1
KBDUS_HEADER_VERSION_PATCH 2

The three components of the version of the kbdus.h header file that was included.

Miscellaneous

KBDUS_IOCTL_TYPE 0xbd

The “type” of all kbdus-specific ioctl commands.