示例#1
0
文件: reserve.c 项目: spdk/spdk
static int
reservation_ns_register(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair,
                        uint16_t ns_id)
{
    int ret;
    struct spdk_nvme_reservation_register_data rr_data;
    struct spdk_nvme_ns *ns;

    ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);

    rr_data.crkey = CR_KEY;
    rr_data.nrkey = CR_KEY;

    outstanding_commands = 0;
    reserve_command_result = -1;

    ret = spdk_nvme_ns_cmd_reservation_register(ns, qpair, &rr_data, true,
            SPDK_NVME_RESERVE_REGISTER_KEY,
            SPDK_NVME_RESERVE_PTPL_NO_CHANGES,
            reservation_ns_completion, NULL);
    if (ret) {
        fprintf(stderr, "Reservation Register Failed\n");
        return -1;
    }

    outstanding_commands++;
    while (outstanding_commands) {
        spdk_nvme_qpair_process_completions(qpair, 100);
    }

    if (reserve_command_result)
        fprintf(stderr, "Reservation Register Failed\n");

    return 0;
}
示例#2
0
文件: reserve.c 项目: spdk/spdk
static int
reservation_ns_release(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, uint16_t ns_id)
{
    int ret;
    struct spdk_nvme_reservation_key_data cdata;
    struct spdk_nvme_ns *ns;

    ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
    cdata.crkey = CR_KEY;

    outstanding_commands = 0;
    reserve_command_result = -1;

    ret = spdk_nvme_ns_cmd_reservation_release(ns, qpair, &cdata,
            false,
            SPDK_NVME_RESERVE_RELEASE,
            SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
            reservation_ns_completion, NULL);
    if (ret) {
        fprintf(stderr, "Reservation Release Failed\n");
        return -1;
    }

    outstanding_commands++;
    while (outstanding_commands) {
        spdk_nvme_qpair_process_completions(qpair, 100);
    }

    if (reserve_command_result)
        fprintf(stderr, "Reservation Release Failed\n");

    return 0;
}
示例#3
0
文件: perf.c 项目: gongchuang/spdk
static void
check_io(struct ns_worker_ctx *ns_ctx)
{
#if HAVE_LIBAIO
	if (ns_ctx->entry->type == ENTRY_TYPE_AIO_FILE) {
		aio_check_io(ns_ctx);
	} else
#endif
	{
		spdk_nvme_qpair_process_completions(ns_ctx->u.nvme.qpair, g_max_completions);
	}
}
示例#4
0
文件: reservation.c 项目: NealXu/spdk
static int
reservation_ns_report(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, uint16_t ns_id)
{
	int ret, i;
	uint8_t *payload;
	struct spdk_nvme_reservation_status_data *status;
	struct spdk_nvme_reservation_ctrlr_data *cdata;
	struct spdk_nvme_ns *ns;

	ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
	payload = rte_zmalloc(NULL, 0x1000, 0x1000);

	outstanding_commands = 0;
	reserve_command_result = -1;

	ret = spdk_nvme_ns_cmd_reservation_report(ns, qpair, payload, 0x1000,
			reservation_ns_completion, NULL);
	if (ret) {
		fprintf(stderr, "Reservation Report Failed\n");
		rte_free(payload);
		return -1;
	}

	outstanding_commands++;
	while (outstanding_commands) {
		spdk_nvme_qpair_process_completions(qpair, 100);
	}

	if (reserve_command_result) {
		fprintf(stderr, "Reservation Report Failed\n");
		rte_free(payload);
		return 0;
	}

	status = (struct spdk_nvme_reservation_status_data *)payload;
	fprintf(stdout, "Reservation Generation Counter                  %u\n", status->generation);
	fprintf(stdout, "Reservation type                                %u\n", status->type);
	fprintf(stdout, "Reservation Number of Registered Controllers    %u\n", status->nr_regctl);
	fprintf(stdout, "Reservation Persist Through Power Loss State    %u\n", status->ptpl_state);
	for (i = 0; i < status->nr_regctl; i++) {
		cdata = (struct spdk_nvme_reservation_ctrlr_data *)(payload + sizeof(struct
				spdk_nvme_reservation_status_data) * (i + 1));
		fprintf(stdout, "Controller ID                           %u\n", cdata->ctrlr_id);
		fprintf(stdout, "Controller Reservation Status           %u\n", cdata->rcsts.status);
		fprintf(stdout, "Controller Host ID                      0x%"PRIx64"\n", cdata->host_id);
		fprintf(stdout, "Controller Reservation Key              0x%"PRIx64"\n", cdata->key);
	}

	rte_free(payload);
	return 0;
}
示例#5
0
文件: overhead.c 项目: spdk/spdk
static void
check_io(void)
{
	uint64_t end, tsc_complete;
	spdk_mb();
#if HAVE_LIBAIO
	if (g_ns->type == ENTRY_TYPE_AIO_FILE) {
		aio_check_io();
	} else
#endif
	{
		spdk_nvme_qpair_process_completions(g_ns->u.nvme.qpair, 0);
	}
	spdk_mb();
	end = spdk_get_ticks();
	if (g_ns->current_queue_depth == 1) {
		/*
		 * Account for race condition in AIO case where interrupt occurs
		 *  after checking for queue depth.  If the timestamp capture
		 *  is too big compared to the last capture, assume that an
		 *  interrupt fired, and do not bump the start tsc forward.  This
		 *  will ensure this extra time is accounted for next time through
		 *  when we see current_queue_depth drop to 0.
		 */
		if (g_ns->type == ENTRY_TYPE_NVME_NS || (end - g_complete_tsc_start) < 500) {
			g_complete_tsc_start = end;
		}
	} else {
		tsc_complete = end - g_complete_tsc_start;
		g_tsc_complete += tsc_complete;
		if (tsc_complete < g_tsc_complete_min) {
			g_tsc_complete_min = tsc_complete;
		}
		if (tsc_complete > g_tsc_complete_max) {
			g_tsc_complete_max = tsc_complete;
		}
		g_io_completed++;
		if (!g_ns->is_draining) {
			submit_single_io();
		}
		g_complete_tsc_start = spdk_get_ticks();
	}
}
示例#6
0
文件: reservation.c 项目: NealXu/spdk
static int
reservation_ns_acquire(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair, uint16_t ns_id)
{
	int ret;
	struct spdk_nvme_reservation_acquire_data *cdata;
	struct spdk_nvme_ns *ns;

	ns = spdk_nvme_ctrlr_get_ns(ctrlr, ns_id);
	cdata = rte_zmalloc(NULL, sizeof(struct spdk_nvme_reservation_acquire_data), 0);
	cdata->crkey = CR_KEY;

	outstanding_commands = 0;
	reserve_command_result = -1;

	ret = spdk_nvme_ns_cmd_reservation_acquire(ns, qpair, cdata,
			0,
			SPDK_NVME_RESERVE_ACQUIRE,
			SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
			reservation_ns_completion, NULL);
	if (ret) {
		fprintf(stderr, "Reservation Acquire Failed\n");
		rte_free(cdata);
		return -1;
	}

	outstanding_commands++;
	while (outstanding_commands) {
		spdk_nvme_qpair_process_completions(qpair, 100);
	}

	if (reserve_command_result)
		fprintf(stderr, "Reservation Acquire Failed\n");

	rte_free(cdata);
	return 0;
}
示例#7
0
文件: hello_world.c 项目: NealXu/spdk
static void
hello_world(void)
{
	struct ns_entry			*ns_entry;
	struct hello_world_sequence	sequence;
	int				rc;

	ns_entry = g_namespaces;
	while (ns_entry != NULL) {
		/*
		 * Allocate an I/O qpair that we can use to submit read/write requests
		 *  to namespaces on the controller.  NVMe controllers typically support
		 *  many qpairs per controller.  Any I/O qpair allocated for a controller
		 *  can submit I/O to any namespace on that controller.
		 *
		 * The SPDK NVMe driver provides no synchronization for qpair accesses -
		 *  the application must ensure only a single thread submits I/O to a
		 *  qpair, and that same thread must also check for completions on that
		 *  qpair.  This enables extremely efficient I/O processing by making all
		 *  I/O operations completely lockless.
		 */
		ns_entry->qpair = spdk_nvme_ctrlr_alloc_io_qpair(ns_entry->ctrlr, 0);
		if (ns_entry->qpair == NULL) {
			printf("ERROR: init_ns_worker_ctx() failed\n");
			return;
		}

		/*
		 * Use DPDK rte_zmalloc to allocate a 4KB zeroed buffer.  This memory
		 *  will be allocated from 2MB hugepages and will be pinned.  These are
		 *  both requirements for data buffers used for SPDK NVMe I/O operations.
		 */
		sequence.buf = rte_zmalloc(NULL, 0x1000, 0x1000);
		sequence.is_completed = 0;
		sequence.ns_entry = ns_entry;

		/*
		 * Print "Hello world!" to sequence.buf.  We will write this data to LBA
		 *  0 on the namespace, and then later read it back into a separate buffer
		 *  to demonstrate the full I/O path.
		 */
		sprintf(sequence.buf, "Hello world!\n");

		/*
		 * Write the data buffer to LBA 0 of this namespace.  "write_complete" and
		 *  "&sequence" are specified as the completion callback function and
		 *  argument respectively.  write_complete() will be called with the
		 *  value of &sequence as a parameter when the write I/O is completed.
		 *  This allows users to potentially specify different completion
		 *  callback routines for each I/O, as well as pass a unique handle
		 *  as an argument so the application knows which I/O has completed.
		 *
		 * Note that the SPDK NVMe driver will only check for completions
		 *  when the application calls spdk_nvme_qpair_process_completions().
		 *  It is the responsibility of the application to trigger the polling
		 *  process.
		 */
		rc = spdk_nvme_ns_cmd_write(ns_entry->ns, ns_entry->qpair, sequence.buf,
					    0, /* LBA start */
					    1, /* number of LBAs */
					    write_complete, &sequence, 0);
		if (rc != 0) {
			fprintf(stderr, "starting write I/O failed\n");
			exit(1);
		}

		/*
		 * Poll for completions.  0 here means process all available completions.
		 *  In certain usage models, the caller may specify a positive integer
		 *  instead of 0 to signify the maximum number of completions it should
		 *  process.  This function will never block - if there are no
		 *  completions pending on the specified qpair, it will return immediately.
		 *
		 * When the write I/O completes, write_complete() will submit a new I/O
		 *  to read LBA 0 into a separate buffer, specifying read_complete() as its
		 *  completion routine.  When the read I/O completes, read_complete() will
		 *  print the buffer contents and set sequence.is_completed = 1.  That will
		 *  break this loop and then exit the program.
		 */
		while (!sequence.is_completed) {
			spdk_nvme_qpair_process_completions(ns_entry->qpair, 0);
		}

		/*
		 * Free the I/O qpair.  This typically is done when an application exits.
		 *  But SPDK does support freeing and then reallocating qpairs during
		 *  operation.  It is the responsibility of the caller to ensure all
		 *  pending I/O are completed before trying to free the qpair.
		 */
		spdk_nvme_ctrlr_free_io_qpair(ns_entry->qpair);
		ns_entry = ns_entry->next;
	}
}
示例#8
0
文件: nvme_dp.c 项目: NealXu/spdk
static int
write_read_e2e_dp_tests(struct dev *dev, nvme_build_io_req_fn_t build_io_fn, const char *test_name)
{
	int rc = 0;
	uint32_t lba_count;
	uint32_t io_flags = 0;

	struct io_request *req;
	struct spdk_nvme_ns *ns;
	struct spdk_nvme_qpair *qpair;
	const struct spdk_nvme_ns_data *nsdata;

	ns = spdk_nvme_ctrlr_get_ns(dev->ctrlr, 1);
	if (!ns) {
		fprintf(stderr, "Null namespace\n");
		return 0;
	}

	if (!(spdk_nvme_ns_get_flags(ns) & SPDK_NVME_NS_DPS_PI_SUPPORTED))
		return 0;

	nsdata = spdk_nvme_ns_get_data(ns);
	if (!nsdata || !spdk_nvme_ns_get_sector_size(ns)) {
		fprintf(stderr, "Empty nsdata or wrong sector size\n");
		return 0;
	}

	req = rte_zmalloc(NULL, sizeof(*req), 0);
	if (!req) {
		fprintf(stderr, "Allocate request failed\n");
		return 0;
	}

	/* IO parameters setting */
	lba_count = build_io_fn(ns, req, &io_flags);

	if (!lba_count) {
		fprintf(stderr, "%s: %s bypass the test case\n", dev->name, test_name);
		free_req(req);
		return 0;
	}

	qpair = spdk_nvme_ctrlr_alloc_io_qpair(dev->ctrlr, 0);
	if (!qpair) {
		free_req(req);
		return -1;
	}

	ns_data_buffer_reset(ns, req, DATA_PATTERN);
	if (req->use_extended_lba)
		rc = spdk_nvme_ns_cmd_write(ns, qpair, req->contig, req->lba, lba_count,
					    io_complete, req, io_flags);
	else
		rc = spdk_nvme_ns_cmd_write_with_md(ns, qpair, req->contig, req->metadata, req->lba, lba_count,
						    io_complete, req, io_flags, req->apptag_mask, req->apptag);

	if (rc != 0) {
		fprintf(stderr, "%s: %s write submit failed\n", dev->name, test_name);
		spdk_nvme_ctrlr_free_io_qpair(qpair);
		free_req(req);
		return -1;
	}

	io_complete_flag = 0;

	while (!io_complete_flag)
		spdk_nvme_qpair_process_completions(qpair, 1);

	if (io_complete_flag != 1) {
		fprintf(stderr, "%s: %s write exec failed\n", dev->name, test_name);
		spdk_nvme_ctrlr_free_io_qpair(qpair);
		free_req(req);
		return -1;
	}

	/* reset completion flag */
	io_complete_flag = 0;

	ns_data_buffer_reset(ns, req, 0);
	if (req->use_extended_lba)
		rc = spdk_nvme_ns_cmd_read(ns, qpair, req->contig, req->lba, lba_count,
					   io_complete, req, io_flags);
	else
		rc = spdk_nvme_ns_cmd_read_with_md(ns, qpair, req->contig, req->metadata, req->lba, lba_count,
						   io_complete, req, io_flags, req->apptag_mask, req->apptag);

	if (rc != 0) {
		fprintf(stderr, "%s: %s read failed\n", dev->name, test_name);
		spdk_nvme_ctrlr_free_io_qpair(qpair);
		free_req(req);
		return -1;
	}

	while (!io_complete_flag)
		spdk_nvme_qpair_process_completions(qpair, 1);

	if (io_complete_flag != 1) {
		fprintf(stderr, "%s: %s read failed\n", dev->name, test_name);
		spdk_nvme_ctrlr_free_io_qpair(qpair);
		free_req(req);
		return -1;
	}

	rc = ns_data_buffer_compare(ns, req, DATA_PATTERN);
	if (rc < 0) {
		fprintf(stderr, "%s: %s write/read success, but memcmp Failed\n", dev->name, test_name);
		spdk_nvme_ctrlr_free_io_qpair(qpair);
		free_req(req);
		return -1;
	}

	fprintf(stdout, "%s: %s test passed\n", dev->name, test_name);
	spdk_nvme_ctrlr_free_io_qpair(qpair);
	free_req(req);
	return rc;
}
示例#9
0
文件: nvme_ns.c 项目: gongchuang/spdk
static
int nvme_ns_identify_update(struct spdk_nvme_ns *ns)
{
	struct nvme_completion_poll_status	status;
	struct spdk_nvme_ns_data		*nsdata;
	int					rc;

	nsdata = _nvme_ns_get_data(ns);
	status.done = false;
	rc = nvme_ctrlr_cmd_identify_namespace(ns->ctrlr, ns->id, nsdata,
					       nvme_completion_poll_cb, &status);
	if (rc != 0) {
		return rc;
	}

	while (status.done == false) {
		pthread_mutex_lock(&ns->ctrlr->ctrlr_lock);
		spdk_nvme_qpair_process_completions(&ns->ctrlr->adminq, 0);
		pthread_mutex_unlock(&ns->ctrlr->ctrlr_lock);
	}
	if (spdk_nvme_cpl_is_error(&status.cpl)) {
		/* This can occur if the namespace is not active. Simply zero the
		 * namespace data and continue. */
		memset(nsdata, 0, sizeof(*nsdata));
		ns->stripe_size = 0;
		ns->sector_size = 0;
		ns->md_size = 0;
		ns->pi_type = 0;
		ns->sectors_per_max_io = 0;
		ns->sectors_per_stripe = 0;
		ns->flags = 0;
		return 0;
	}

	ns->sector_size = 1 << nsdata->lbaf[nsdata->flbas.format].lbads;

	ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->sector_size;
	ns->sectors_per_stripe = ns->stripe_size / ns->sector_size;

	ns->flags = 0x0000;

	if (ns->ctrlr->cdata.oncs.dsm) {
		ns->flags |= SPDK_NVME_NS_DEALLOCATE_SUPPORTED;
	}

	if (ns->ctrlr->cdata.vwc.present) {
		ns->flags |= SPDK_NVME_NS_FLUSH_SUPPORTED;
	}

	if (ns->ctrlr->cdata.oncs.write_zeroes) {
		ns->flags |= SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED;
	}

	if (nsdata->nsrescap.raw) {
		ns->flags |= SPDK_NVME_NS_RESERVATION_SUPPORTED;
	}

	ns->md_size = nsdata->lbaf[nsdata->flbas.format].ms;
	ns->pi_type = SPDK_NVME_FMT_NVM_PROTECTION_DISABLE;
	if (nsdata->lbaf[nsdata->flbas.format].ms && nsdata->dps.pit) {
		ns->flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
		ns->pi_type = nsdata->dps.pit;
		if (nsdata->flbas.extended)
			ns->flags |= SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED;
	}
	return rc;
}
示例#10
0
文件: nvme_lat.c 项目: qzan9/jni-nvm
static int
u2_lat_bench(void)
{
	int i, rc;
	//int rc;

	void *buf;

	uint32_t io_size_blocks;
	uint64_t offset_in_ios, size_in_ios;

	uint64_t tsc_rate;
	uint64_t tsc_start, tsc_elapsed;
	//uint64_t tsc_end;

	buf = rte_malloc(NULL, io_size, U2_BUFFER_ALIGN);
	if (buf == NULL) {
		fprintf(stderr, "failed to rte_malloc buffer!\n");
		return 1;
	}
	memset(buf, 0xff, io_size);

	//io_num = 0;
	//io_depth = 0;

	io_size_blocks = io_size / u2_ns_sector;
	offset_in_ios = -1;
	size_in_ios = u2_ns_size / io_size;

	tsc_rate = rte_get_tsc_hz();
	tsc_elapsed = 0;
	tsc_start = rte_get_timer_cycles();
	//tsc_end = rte_get_timer_cycles() + time_in_sec * tsc_rate;
	for (i = 0; i < io_num; i++) {
	//while (1) {
		if (is_random) {
			offset_in_ios = rand_r(&seed) % size_in_ios;
		} else {
			if (++offset_in_ios >= size_in_ios) {
				offset_in_ios = 0;
			}
		}

		if (is_rw) {
			rc = spdk_nvme_ns_cmd_read (u2_ns, u2_qpair, buf, offset_in_ios * io_size_blocks, io_size_blocks, u2_io_complete, NULL, 0);
		} else {
			rc = spdk_nvme_ns_cmd_write(u2_ns, u2_qpair, buf, offset_in_ios * io_size_blocks, io_size_blocks, u2_io_complete, NULL, 0);
		}
		if (rc) {
			fprintf(stderr, "failed to submit request %d!\n", i);
			//fprintf(stderr, "failed to submit request %d!\n", io_num);
			return rc;
		}
		io_depth++;    // for latency benchmarking, queue depth stays at 1.

		while (io_depth > 0) {
			spdk_nvme_qpair_process_completions(u2_qpair, 0);
		}

		//if (rte_get_timer_cycles() > tsc_end) {
		//	break;
		//}
	}
	tsc_elapsed = rte_get_timer_cycles() - tsc_start;

	printf("\t\t%9.1f us", (float) (tsc_elapsed * 1000000) / (io_num * tsc_rate));
	printf("\t\t%10.1f s", (float) tsc_elapsed / tsc_rate);
	printf("\n");

	//printf("\t\t%9.1f us", (float) (time_in_sec * 1000000) / io_num);
	//printf("\t\t%12"PRIu64"\n", io_num);

	rte_free(buf);

	return 0;
}
示例#11
0
文件: direct.c 项目: spdk/spdk
static void
nvmf_direct_ctrlr_poll_for_completions(struct spdk_nvmf_session *session)
{
	spdk_nvme_ctrlr_process_admin_completions(session->subsys->dev.direct.ctrlr);
	spdk_nvme_qpair_process_completions(session->subsys->dev.direct.io_qpair, 0);
}