drivers/nvme/target/io-cmd-file.c

Source file repositories/reference/linux-study-clean/drivers/nvme/target/io-cmd-file.c

File Facts

System
Linux kernel
Corpus path
drivers/nvme/target/io-cmd-file.c
Extension
.c
Size
9259 bytes
Lines
382
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: implementation source
Status
source implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

if (offset + len > req->ns->size) {
			req->error_slba = le64_to_cpu(range.slba);
			status = errno_to_nvme_status(req, -ENOSPC);
			break;
		}

		ret = vfs_fallocate(req->ns->file, mode, offset, len);
		if (ret && ret != -EOPNOTSUPP) {
			req->error_slba = le64_to_cpu(range.slba);
			status = errno_to_nvme_status(req, ret);
			break;
		}
	}

	nvmet_req_complete(req, status);
}

static void nvmet_file_dsm_work(struct work_struct *w)
{
	struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);

	switch (le32_to_cpu(req->cmd->dsm.attributes)) {
	case NVME_DSMGMT_AD:
		nvmet_file_execute_discard(req);
		return;
	case NVME_DSMGMT_IDR:
	case NVME_DSMGMT_IDW:
	default:
		/* Not supported yet */
		nvmet_req_complete(req, 0);
		return;
	}
}

static void nvmet_file_execute_dsm(struct nvmet_req *req)
{
	if (!nvmet_check_data_len_lte(req, nvmet_dsm_len(req)))
		return;
	INIT_WORK(&req->f.work, nvmet_file_dsm_work);
	queue_work(nvmet_wq, &req->f.work);
}

static void nvmet_file_write_zeroes_work(struct work_struct *w)
{
	struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);
	struct nvme_write_zeroes_cmd *write_zeroes = &req->cmd->write_zeroes;
	int mode = FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE;
	loff_t offset;
	loff_t len;
	int ret;

	offset = le64_to_cpu(write_zeroes->slba) << req->ns->blksize_shift;
	len = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) <<
			req->ns->blksize_shift);

	if (unlikely(offset + len > req->ns->size)) {
		nvmet_req_complete(req, errno_to_nvme_status(req, -ENOSPC));
		return;
	}

	ret = vfs_fallocate(req->ns->file, mode, offset, len);
	nvmet_req_complete(req, ret < 0 ? errno_to_nvme_status(req, ret) : 0);
}

static void nvmet_file_execute_write_zeroes(struct nvmet_req *req)
{
	if (!nvmet_check_transfer_len(req, 0))
		return;
	INIT_WORK(&req->f.work, nvmet_file_write_zeroes_work);
	queue_work(nvmet_wq, &req->f.work);
}

u16 nvmet_file_parse_io_cmd(struct nvmet_req *req)
{
	switch (req->cmd->common.opcode) {
	case nvme_cmd_read:
	case nvme_cmd_write:
		req->execute = nvmet_file_execute_rw;
		return 0;
	case nvme_cmd_flush:
		req->execute = nvmet_file_execute_flush;
		return 0;
	case nvme_cmd_dsm:
		req->execute = nvmet_file_execute_dsm;
		return 0;
	case nvme_cmd_write_zeroes:
		req->execute = nvmet_file_execute_write_zeroes;
		return 0;
	default:
		return nvmet_report_invalid_opcode(req);

Annotation

Implementation Notes