Completions
bash
tokunori@tokunori-desktop:~/nvme-cli$ source completions/bash-nvme-completion.sh && source ~/.bashrc
zsh
tokunori@tokunori-desktop:~/nvme-cli$ sudo apt install zsh
...
tokunori@tokunori-desktop:~/nvme-cli$ zsh
if your working shell is zsh...
-------------------------------
create the zsh completions directory if you don't have it
#if [ ! -e "~/.zsh" ]; then
# mkdir ~/.zsh
# mkdir ~/.zsh/completion
#fi
#cp `pwd`/_nvme ~/.zsh/completion/_nvme
add compinit if you don't have it in your .zshrc
#echo "autoload -Uz compinit && compinit" >> ~/.zshrc
add nvme autocompletions to your .zshrc
#echo "# source for tab autocompletions" >> ~/.zshrc
#echo "fpath=(~/.zsh/completion $fpath)" >> ~/.zshrc
#echo "source ~/.zsh/completion/_nvme" >> ~/.zshrc
make sure this zsh knows where everything is
#source ~/.zsh/completion/_nvme && source ~/.zshrc
You should be able to autocomplete with the nvme utility now (single TAB press
should get you a completion with descriptions -- sadly, bash doesn't support
descriptions within completions). If autocompletes disappear, just re-source
_nvme and .zshrc. Also, make sure your .zshrc is ordered correctly: we want to
source _nvme before updating our fpath. Both of these should occur before
compinit is loaded.
tokunori-desktop% cp completions/_nvme ~/.zsh/completion/_nvme
tokunori-desktop% source ~/.zsh/completion/_nvme && source ~/.zshrc
.zshrc
tokunori-desktop% nano ~/.zshrc
autoload -Uz compinit && compinit
# source for tab autocompletions
fpath=(~/.zsh/completion /usr/local/share/zsh/site-functions /usr/share/zsh/vendor-functions /usr/share/zsh/vendor-c>
source ~/.zsh/completion/_nvme
setopt interactivecomments
bindkey "^[[3~" delete-char
bindkey "^[[1~" beginning-of-line
bindkey "^[[4~" end-of-line
read
master: nvme version 2.4 (git 2.4-50-g4e7b9fd+) / libnvme version 1.4 (git 1.4-13-gc90eeff)
if (cfg.metadata_size) {
err = nvme_cli_identify_ns(dev, cfg.namespace_id, &ns);
if (err > 0) {
nvme_show_status(err);
goto free_buffer;
} else if (err < 0) {
nvme_show_error("identify namespace: %s", nvme_strerror(errno));
goto free_buffer;
}
struct nvme_io_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.nsid = cfg.namespace_id,
.slba = cfg.start_block,
.nlb = nblocks,
.control = control,
.dsm = cfg.dsmgmt,
.sts = sts,
.pif = pif,
.dspec = cfg.dspec,
.reftag_u64 = cfg.ref_tag,
.apptag = cfg.app_tag,
.appmask = cfg.app_tag_mask,
.storage_tag = cfg.storage_tag,
.data_len = buffer_size,
.data = buffer,
.metadata_len = cfg.metadata_size,
.metadata = mbuffer,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
struct nvme_passthru_cmd {
__u8 opcode;
__u8 flags;
__u16 rsvd1;
__u32 nsid;
__u32 cdw2;
__u32 cdw3;
__u64 metadata;
__u64 addr;
__u32 metadata_len;
__u32 data_len;
__u32 cdw10;
__u32 cdw11;
__u32 cdw12;
__u32 cdw13;
__u32 cdw14;
__u32 cdw15;
__u32 timeout_ms;
__u32 result;
};
struct nvme_passthru_cmd cmd = {
.opcode = opcode,
.nsid = args->nsid,
.cdw2 = cdw2,
.cdw3 = cdw3,
.cdw10 = cdw10,
.cdw11 = cdw11,
.cdw12 = cdw12,
.cdw13 = cdw13,
.cdw14 = cdw14,
.cdw15 = cdw15,
.data_len = args->data_len,
.metadata_len = args->metadata_len,
.addr = (__u64)(uintptr_t)args->data,
.metadata = (__u64)(uintptr_t)args->metadata,
.timeout_ms = args->timeout,
};
return nvme_submit_passthru(fd, NVME_IOCTL_IO_CMD, cmd, result);
1.8
if (cfg.metadata_size) {
mbuffer = malloc(cfg.metadata_size);
if (!mbuffer) {
fprintf(stderr, "can not allocate io metadata "
"payload: %s\n", strerror(errno));
err = ENOMEM;
goto free_buffer;
}
}
struct nvme_user_io {
__u8 opcode;
__u8 flags;
__u16 control;
__u16 nblocks;
__u16 rsvd;
__u64 metadata;
__u64 addr;
__u64 slba;
__u32 dsmgmt;
__u32 reftag;
__u16 apptag;
__u16 appmask;
};
struct nvme_user_io io = {
.opcode = opcode,
.flags = 0,
.control = control,
.nblocks = nblocks,
.rsvd = 0,
.metadata = (__u64)(uintptr_t) metadata,
.addr = (__u64)(uintptr_t) data,
.slba = slba,
.dsmgmt = dsmgmt,
.reftag = reftag,
.appmask = appmask,
.apptag = apptag,
};
return ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io);
v1.16: nvme version 1.16
if (cfg.metadata_size) {
err = nsid = nvme_get_nsid(fd);
if (err < 0) {
perror("get-namespace-id");
goto close_mfd;
}
struct nvme_passthru_cmd {
__u8 opcode;
__u8 flags;
__u16 rsvd1;
__u32 nsid;
__u32 cdw2;
__u32 cdw3;
__u64 metadata;
__u64 addr;
__u32 metadata_len;
__u32 data_len;
__u32 cdw10;
__u32 cdw11;
__u32 cdw12;
__u32 cdw13;
__u32 cdw14;
__u32 cdw15;
__u32 timeout_ms;
__u32 result;
};
struct nvme_passthru_cmd cmd = {
.opcode = opcode,
.nsid = nsid,
.metadata = (__u64)(uintptr_t) metadata,
.addr = (__u64)(uintptr_t) data,
.cdw2 = storage_tag & 0xffffffff,
.cdw3 = (storage_tag >> 32) & 0xffff,
.cdw10 = slba & 0xffffffff,
.cdw11 = slba >> 32,
.cdw12 = nblocks | (control << 16),
.cdw13 = dsmgmt,
.cdw14 = reftag,
.cdw15 = apptag | (appmask << 16),
.data_len = buffer_size,
.metadata_len = mbuffer_size,
};
return ioctl(fd, NVME_IOCTL_IO_CMD, cmd);
kernel: master
static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd,
void __user *argp, unsigned int flags, fmode_t mode)
{
switch (cmd) {
case NVME_IOCTL_ID:
force_successful_syscall_return();
return ns->head->ns_id;
case NVME_IOCTL_IO_CMD:
return nvme_user_cmd(ns->ctrl, ns, argp, flags, mode);
/*
* struct nvme_user_io can have different padding on some 32-bit ABIs.
* Just accept the compat version as all fields that are used are the
* same size and at the same offset.
*/
#ifdef COMPAT_FOR_U64_ALIGNMENT
case NVME_IOCTL_SUBMIT_IO32:
#endif
case NVME_IOCTL_SUBMIT_IO:
return nvme_submit_io(ns, argp);
struct nvme_user_io {
__u8 opcode;
__u8 flags;
__u16 control;
__u16 nblocks;
__u16 rsvd;
__u64 metadata;
__u64 addr;
__u64 slba;
__u32 dsmgmt;
__u32 reftag;
__u16 apptag;
__u16 appmask;
};
static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
{
struct nvme_user_io io;
struct nvme_command c;
unsigned length, meta_len;
void __user *metadata;
if (copy_from_user(&io, uio, sizeof(io)))
return -EFAULT;
struct nvme_passthru_cmd {
__u8 opcode;
__u8 flags;
__u16 rsvd1;
__u32 nsid;
__u32 cdw2;
__u32 cdw3;
__u64 metadata;
__u64 addr;
__u32 metadata_len;
__u32 data_len;
__u32 cdw10;
__u32 cdw11;
__u32 cdw12;
__u32 cdw13;
__u32 cdw14;
__u32 cdw15;
__u32 timeout_ms;
__u32 result;
};
static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
struct nvme_passthru_cmd __user *ucmd, unsigned int flags,
fmode_t mode)
{
struct nvme_passthru_cmd cmd;
struct nvme_command c;
unsigned timeout = 0;
u64 result;
int status;
if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
return -EFAULT;