unvme - user NVME command interface
#include <sys/nvme/unvme.h> ioctl(int fildes, int request, unvme_cmd_t *cmd);
The unvme command is very powerful and somewhat dangerous, therefore it has some permission restrictions. See WARNINGS for more details.
The nvme(7D) driver supporting this ioctl(2) provides a general interface allowing user-level applications to cause individual NVMe commands to be directed to a particular NVMe controller under control of that driver.
The NVMe command may include a data transfer to or from that device, if appropriate for that command. Upon completion of the command, the user application can determine the command status through NVMe command completion queue entry returned by the interface.
The fildes argument is an open file descriptor that refers to an NVMe controller minor node.
The unvme_cmd structure is defined in <sys/nvme/unvme.h> and includes the following members:
int unvme_flags; /* read, write, etc. see below */ int unvme_timeout; /* command timeout */ caddr_t unvme_comp; /* nvme command completion queue entry */ caddr_t unvme_cmdp; /* nvme command */ caddr_t unvme_bufaddr; /* i/o source/destination */ size_t unvme_buflen; /* size of i/o to take place */ void *unvme_rsvd; /* reserved field for future use */
The fields of the unvme_cmd structure have the following meanings:
The I/O direction and other details of how to carry out the NVMe command. Possible values are described below.
Time in seconds to allow for completion of the command.
The 16 bytes NVMe Completion Queue Entry for this NVMe command. Only the Command Specific and Status Field are valid. Other fields will be cleared to zero.
A pointer to the 64 bytes NVMe command to be transferred to the device. The caller can set Opcode, NSID and DW10 to DW15. All other fields must be set to zero by the caller.
The user buffer containing the data to be read from or written to the device.
The length of unvme_bufaddr.
Reserved for future use.
The unvme_flags field defines the following:
UNVME_READ /* Get data from device */ UNVME_WRITE /* Write data to device */ UNVME_ADMIN /* Admin command flag */ UNVME_NVM /* NVM command flag */ UNVME_RESET /* Reset controller */ UNVME_FAILFAST /* Don't retry if fail */
The unvme_flags bits have the following interpretation:
Data will be read from device to host.
Data will be written from the host to the device.
Indicating that the command being sent is an Admin command.
Indicating that the command being sent is a NVM command.
Issuing a controller level reset.
If this command fails, do not retry or reset controller. Just return fail.
The ioctl supported by drivers providing the unvme interface is:
The argument is a pointer to a unvme_cmd structure. The NVMe device addressed by NVMe driver is selected, and given the NVMe command addressed by unvme_cmdp. If this command requires a data transfer, the unvme_buflen and unvme_bufaddr fields must be set appropriately; The status of the command, as returned by the device, is returned in the unvme_comp field.
A parameter has an incorrect, or unsupported value.
An error occurred during the execution of the command.
The unvme_cmd itself, the unvme_cmdp, the unvme_comp, or the unvme_bufaddr points to an invalid address.
See attributes(5) for descriptions of the following attributes:
The unvme command is very powerful, but somewhat dangerous, so its use is restricted to processes running as root, regardless of the file permissions on the device node. The device driver code expects to own the device state, and unvme commands can change the state of the device and confuse the device driver. It is best to send unvme commands only with no side effects, and avoid commands such as Create/Delete Submission/Completion Queue, Format, Set Feature, Asynchronous Event, etc. as they may cause damage to data stored on the drive or system panics. Also, as the commands are not checked in any way by the device driver, any block may be overwritten.
The unvme interface is not recommended for very large data transfers (not exceeding the maximum transfer size reported by NVMe controller). If the requested transfer size exceeds the maximum transfer size supported by the controller, it will not be broken up into multiple transfers and EINVAL will be returned.