diff --git a/anolis/configs/L0-MANDATORY/default/CONFIG_NVME_PASS_REQFLAG b/anolis/configs/L0-MANDATORY/default/CONFIG_NVME_PASS_REQFLAG new file mode 100644 index 0000000000000000000000000000000000000000..a42eec8ec004249e50c6fe3e2febf496f61b18af --- /dev/null +++ b/anolis/configs/L0-MANDATORY/default/CONFIG_NVME_PASS_REQFLAG @@ -0,0 +1 @@ +CONFIG_NVME_PASS_REQFLAG=y diff --git a/anolis/configs/L0-MANDATORY/default/CONFIG_VIRTIO_BLK_PASS_REQFLAG b/anolis/configs/L0-MANDATORY/default/CONFIG_VIRTIO_BLK_PASS_REQFLAG new file mode 100644 index 0000000000000000000000000000000000000000..c0a932a9521e72d8793faee3b789a2dad9d4463e --- /dev/null +++ b/anolis/configs/L0-MANDATORY/default/CONFIG_VIRTIO_BLK_PASS_REQFLAG @@ -0,0 +1 @@ +CONFIG_VIRTIO_BLK_PASS_REQFLAG=y diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 9195938f67ae20726ed9b3b97160fca49d9720e5..a4cf6a1615c18b467f154a2f762ad3de521a6eb9 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -452,6 +452,24 @@ config VIRTIO_BLK_RING_PAIR If unsure, say N. +config VIRTIO_BLK_PASS_REQFLAG + bool "Virtio block device pass I/O flags" + depends on VIRTIO_BLK + help + Enable support for virtio-blk devices to pass I/O block flags + (such as REQ_META, REQ_BACKGROUND, etc.) to the backend storage. + + When enabled, the virtio-blk driver forwards per-request I/O + flags to the backend device, allowing backend to do specific + optimizations. + + Note that this feature requires both guest and backend to support + the corresponding I/O flag protocol. If the backend does not + understand the flags, they are silently ignored and there is no + functional change compared to disabling this option. + + If unsure, say N. + config BLK_DEV_RBD tristate "Rados block device (RBD)" depends on INET && BLOCK diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 17ce47c185da09303bbaaaa6a6e2cba619f1d76f..8bd9025b922dc7d7386fc6bd3bed7c5b25ec3c9a 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -841,7 +841,19 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev, vbr->out_hdr.type = cpu_to_virtio32(vdev, type); vbr->out_hdr.sector = cpu_to_virtio64(vdev, sector); +#ifdef CONFIG_VIRTIO_BLK_PASS_REQFLAG + vbr->out_hdr.rpair.ioprio = cpu_to_virtio16(vdev, (u16)req_get_ioprio(req)); + if (req_op(req) == REQ_OP_WRITE || req_op(req) == REQ_OP_READ) + /* Extract and pack request flags into ioprio high 16bit, + * bit-0 informs backend that feature is enabled + */ + vbr->out_hdr.rpair.tag = cpu_to_virtio16(vdev, + get_and_pack_req_cmd_flags(req)); + else + vbr->out_hdr.rpair.tag = cpu_to_virtio16(vdev, 0); +#else vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req)); +#endif if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) { if (virtblk_setup_discard_write_zeroes(req, unmap)) diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 494675aeaaad7957e5df634fdb5911762a92328e..7ef13c83adc48fb3a542eb91ebd8a3b1c4622c06 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -85,3 +85,21 @@ config NVME_TCP from https://github.com/linux-nvme/nvme-cli. If unsure, say N. + +config NVME_PASS_REQFLAG + bool "NVM Express block device pass I/O flags" + depends on BLK_DEV_NVME + help + Enable support for NVMe devices to pass I/O block flags + (such as REQ_META, REQ_BACKGROUND, etc.) to the backend storage. + + When enabled, the NVMe driver forwards per-request I/O flags + to the backend device, allowing backend to do specific + optimizations. + + Note that this feature requires both guest and backend to support + the corresponding I/O flag protocol. If the backend does not + understand the flags, they are silently ignored and there is no + functional change compared to disabling this option. + + If unsure, say N. \ No newline at end of file diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 1ff34199efe7aa8a412774bf5e1a4e3f603f3ae4..6866655a1a62d828feabea85aba454c944acd68e 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2852,6 +2852,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) dev_err(ctrl->device, "Identify Controller failed (%d)\n", ret); return -EIO; } +#ifdef CONFIG_NVME_PASS_REQFLAG + if (le16_to_cpu(id->vid) == PCI_VENDOR_ID_ALIBABA) + ctrl->pass_reqflag_enabled = true; +#endif if (id->lpa & NVME_CTRL_LPA_CMD_EFFECTS_LOG) { ret = nvme_get_effects_log(ctrl, NVME_CSI_NVM, &ctrl->effects); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index c6425e7f5ba33061fa2089613ac66ada4305c94f..f9ac9aae6ac222cfed7f8fa1dfc831b33b344873 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -362,6 +362,9 @@ struct nvme_ctrl { unsigned long discard_page_busy; struct nvme_fault_inject fault_inject; +#ifdef CONFIG_NVME_PASS_REQFLAG + bool pass_reqflag_enabled; +#endif }; static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 90162bfc5922279e3f464c22f3216f3c88fc9786..e769b579c9206c5216cd91755c7fc8aefbfd5a8c 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -962,6 +962,9 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx, struct nvme_iod *iod = blk_mq_rq_to_pdu(req); struct nvme_command *cmnd = &iod->cmd; blk_status_t ret; +#ifdef CONFIG_NVME_PASS_REQFLAG + u16 reqflag = 0; +#endif iod->aborted = 0; iod->npages = -1; @@ -985,6 +988,19 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx, ret = nvme_map_data(dev, req, cmnd); if (ret) goto out_free_cmd; +#ifdef CONFIG_NVME_PASS_REQFLAG + if (dev->ctrl.pass_reqflag_enabled && + (req_op(req) == REQ_OP_WRITE || req_op(req) == REQ_OP_READ)) { + /* Extract and pack request flags into reqflag from low to high bit, + * bit-0 informs backend that feature is enabled + */ + reqflag = get_and_pack_req_cmd_flags(req); + + /* Set reqflag to the high 16 bits of cdw3 */ + cmnd->common.cdw2[1] = (cmnd->common.cdw2[1] & cpu_to_le32(0xFFFF)) + | cpu_to_le32((u32)reqflag << 16); + } +#endif } if (blk_integrity_rq(req)) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 77c3bc2721faea5f2aae86226277f732d3a51b5b..1efbdcc9efe24d6ab0871f18c9a76c76deb15efd 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -2178,4 +2178,19 @@ struct io_comp_batch { #define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { } +static inline uint16_t get_and_pack_req_cmd_flags(struct request *req) +{ + /* Extract and pack request flags into uint16_t, + * bit-0 indicates that the value is valid + */ + return 1 << 0 | + ((req->cmd_flags & REQ_SYNC) ? (1 << 1) : 0) | + ((req->cmd_flags & REQ_META) ? (1 << 2) : 0) | + ((req->cmd_flags & REQ_PRIO) ? (1 << 3) : 0) | + ((req->cmd_flags & REQ_IDLE) ? (1 << 4) : 0) | + ((req->cmd_flags & REQ_PREFLUSH) ? (1 << 5) : 0) | + ((req->cmd_flags & REQ_RAHEAD) ? (1 << 6) : 0) | + ((req->cmd_flags & REQ_BACKGROUND) ? (1 << 7) : 0); +} + #endif /* _LINUX_BLKDEV_H */