实验任务

学习Blob基本原理
完成hello_blob 程序运行
修改底层bdev为nvme
Blob构建在bdev之上,是对数据存储的进一步抽象,类似于文件,但是不具备文件POSIX接口,可近似按文件形式理解。

 

了解Blob知识

 

 

实验过程

 

启动虚拟机

📌
注意挂载的是普通SSD,而不是ZNS SSD
启动命令
sudo qemu-system-x86_64 -name qemucsd -m 2G --enable-kvm -cpu host -smp 4 -hda ./ubuntu.qcow2 -net user,hostfwd=tcp:127.0.0.1:7777-:22,hostfwd=tcp:127.0.0.1:2222-:2000 -net nic -drive file=nvme.qcow2,if=none,id=nvm -device nvme,serial=deadbeef,drive=nvm -nographic -fsdev local,id=fsdev0,path=./work/,security_model=none  -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare
sudo qemu-system-x86_64 -name qemucsd -m 2G --enable-kvm -cpu host -smp 4 -hda ./ubuntu.qcow2 -net user,hostfwd=tcp:127.0.0.1:7777-:22,hostfwd=tcp:127.0.0.1:2222-:2000 -net nic -drive file=nvme.qcow2,if=none,id=nvm -device nvme,serial=deadbeef,drive=nvm -nographic -fsdev local,id=fsdev0,path=./work/,security_model=none  -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare
Shell
 

 
挂载共享目录
sudo mount hostshare -t 9p ./work
sudo mount hostshare -t 9p ./work
Shell
 

 

 

运行hello_blob

初始化环境
cd work/spdk
sudo HUGEMEM=1024 scripts/setup.sh
cd work/spdk
sudo HUGEMEM=1024 scripts/setup.sh
Shell
 

 
运行hello_blob
cd build/examples
sudo ./hello_blob ../../examples/blob/hello_world/hello_blob.json
cd build/examples
sudo ./hello_blob ../../examples/blob/hello_world/hello_blob.json
Shell
 

 
出现以下错误
cwj@chengwj:~/work/spdk/build/examples$ sudo ./hello_blob ../../examples/blob/hello_world/hello_blob.json
[2022-11-25 07:24:00.353279] hello_blob.c: 451:main: *NOTICE*: entry
[2022-11-25 07:24:00.373272] Starting SPDK v21.04-pre git sha1 522343136 / DPDK 20.11.0 initialization...
[2022-11-25 07:24:00.373389] [ DPDK EAL parameters: [2022-11-25 07:24:00.373585] hello_blob [2022-11-25 07:24:00.373605]]
EAL: No legacy callbacks, legacy socket not created
[2022-11-25 07:24:00.597814] app.c: 535:spdk_app_start: *NOTICE*: Total cores available: 1
[2022-11-25 07:24:02.125492] reactor.c: 911:reactor_run: *NOTICE*: Reactor started on core 0
[2022-11-25 07:24:02.175051] accel_engine.c: 854:spdk_accel_engine_initialize: *NOTICE*: Accel engine initialized to use.
[2022-11-25 07:24:02.664398] hello_blob.c: 414:hello_start: *NOTICE*: entry
[2022-11-25 07:24:02.685907] hello_blob.c: 373:bs_init_complete: *NOTICE*: entry
[2022-11-25 07:24:02.705117] hello_blob.c: 381:bs_init_complete: *NOTICE*: blobstore: 0x55ee2de698b0
[2022-11-25 07:24:02.705484] hello_blob.c: 360:create_blob: *NOTICE*: entry
[2022-11-25 07:24:02.707208] hello_blob.c: 339:blob_create_complete: *NOTICE*: entry
[2022-11-25 07:24:02.707262] hello_blob.c: 347:blob_create_complete: *NOTICE*: new blob id 4294967296
[2022-11-25 07:24:02.707643] hello_blob.c: 308:open_complete: *NOTICE*: entry
[2022-11-25 07:24:02.707665] hello_blob.c: 318:open_complete: *NOTICE*: blobstore has FREE clusters of 15
[2022-11-25 07:24:02.707703] hello_blob.c: 284:resize_complete: *NOTICE*: resized blob now has USED clusters of 15
[2022-11-25 07:24:02.708435] hello_blob.c: 261:sync_complete: *NOTICE*: entry
[2022-11-25 07:24:02.708506] hello_blob.c: 223:blob_write: *NOTICE*: entry
[2022-11-25 07:24:02.708793] hello_blob.c: 206:write_complete: *NOTICE*: entry
[2022-11-25 07:24:02.708810] hello_blob.c: 181:read_blob: *NOTICE*: entry
[2022-11-25 07:24:02.708840] hello_blob.c: 154:read_complete: *NOTICE*: entry
[2022-11-25 07:24:02.708875] hello_blob.c:  94:unload_bs: *ERROR*: Error in data compare (err -1)
[2022-11-25 07:24:02.709098] blobstore.c:5224:spdk_bs_unload: *ERROR*: Blobstore still has open blobs
[2022-11-25 07:24:02.709113] hello_blob.c:  78:unload_complete: *NOTICE*: entry
[2022-11-25 07:24:02.709140] hello_blob.c:  80:unload_complete: *ERROR*: Error -16 unloading the bobstore
[2022-11-25 07:24:02.709165] app.c: 626:spdk_app_stop: *WARNING*: spdk_app_stop'd on non-zero
[2022-11-25 07:24:02.709247] hello_blob.c: 401:base_bdev_event_cb: *WARNING*: Unsupported bdev event: type 0
^C[2022-11-25 07:31:37.669203] app.c: 612:app_stop: *NOTICE*: spdk_app_stop called twice
cwj@chengwj:~/work/spdk/build/examples$ sudo ./hello_blob ../../examples/blob/hello_world/hello_blob.json
[2022-11-25 07:24:00.353279] hello_blob.c: 451:main: *NOTICE*: entry
[2022-11-25 07:24:00.373272] Starting SPDK v21.04-pre git sha1 522343136 / DPDK 20.11.0 initialization...
[2022-11-25 07:24:00.373389] [ DPDK EAL parameters: [2022-11-25 07:24:00.373585] hello_blob [2022-11-25 07:24:00.373605]]
EAL: No legacy callbacks, legacy socket not created
[2022-11-25 07:24:00.597814] app.c: 535:spdk_app_start: *NOTICE*: Total cores available: 1
[2022-11-25 07:24:02.125492] reactor.c: 911:reactor_run: *NOTICE*: Reactor started on core 0
[2022-11-25 07:24:02.175051] accel_engine.c: 854:spdk_accel_engine_initialize: *NOTICE*: Accel engine initialized to use.
[2022-11-25 07:24:02.664398] hello_blob.c: 414:hello_start: *NOTICE*: entry
[2022-11-25 07:24:02.685907] hello_blob.c: 373:bs_init_complete: *NOTICE*: entry
[2022-11-25 07:24:02.705117] hello_blob.c: 381:bs_init_complete: *NOTICE*: blobstore: 0x55ee2de698b0
[2022-11-25 07:24:02.705484] hello_blob.c: 360:create_blob: *NOTICE*: entry
[2022-11-25 07:24:02.707208] hello_blob.c: 339:blob_create_complete: *NOTICE*: entry
[2022-11-25 07:24:02.707262] hello_blob.c: 347:blob_create_complete: *NOTICE*: new blob id 4294967296
[2022-11-25 07:24:02.707643] hello_blob.c: 308:open_complete: *NOTICE*: entry
[2022-11-25 07:24:02.707665] hello_blob.c: 318:open_complete: *NOTICE*: blobstore has FREE clusters of 15
[2022-11-25 07:24:02.707703] hello_blob.c: 284:resize_complete: *NOTICE*: resized blob now has USED clusters of 15
[2022-11-25 07:24:02.708435] hello_blob.c: 261:sync_complete: *NOTICE*: entry
[2022-11-25 07:24:02.708506] hello_blob.c: 223:blob_write: *NOTICE*: entry
[2022-11-25 07:24:02.708793] hello_blob.c: 206:write_complete: *NOTICE*: entry
[2022-11-25 07:24:02.708810] hello_blob.c: 181:read_blob: *NOTICE*: entry
[2022-11-25 07:24:02.708840] hello_blob.c: 154:read_complete: *NOTICE*: entry
[2022-11-25 07:24:02.708875] hello_blob.c:  94:unload_bs: *ERROR*: Error in data compare (err -1)
[2022-11-25 07:24:02.709098] blobstore.c:5224:spdk_bs_unload: *ERROR*: Blobstore still has open blobs
[2022-11-25 07:24:02.709113] hello_blob.c:  78:unload_complete: *NOTICE*: entry
[2022-11-25 07:24:02.709140] hello_blob.c:  80:unload_complete: *ERROR*: Error -16 unloading the bobstore
[2022-11-25 07:24:02.709165] app.c: 626:spdk_app_stop: *WARNING*: spdk_app_stop'd on non-zero
[2022-11-25 07:24:02.709247] hello_blob.c: 401:base_bdev_event_cb: *WARNING*: Unsupported bdev event: type 0
^C[2022-11-25 07:31:37.669203] app.c: 612:app_stop: *NOTICE*: spdk_app_stop called twice
Shell
 

 
根据,尝试将hello_blob.json中的block_size改为4096。失败
根据https://review.gerrithub.io/c/spdk/spdk/+/450069,尝试将hello_blob.c文件更改为最新版,重新make并运行。失败

 

尝试重装spdk。

为了完整安装spdk,这一步先不recursive。参考https://blog.csdn.net/m0_37604813/article/details/107130881
git clone https://github.com/spdk/spdk
git clone https://github.com/spdk/spdk
Shell
 

 
(可以尝试其他镜像源)
进入spdk文件夹,打开.gitmodules文件,修改克隆地址为国内可用地址(找不到镜像可以先拉取到自己的gitee)
[submodule "dpdk"]
        path = dpdk
        url = https://gitee.com/realchengwj/dpdk.git
[submodule "intel-ipsec-mb"]
        path = intel-ipsec-mb
        url = https://gitee.com/realchengwj/intel-ipsec-mb.git
[submodule "isa-l"]
        path = isa-l
        url = https://gitee.com/realchengwj/isa-l.git
[submodule "ocf"]
        path = ocf
        url = https://gitee.com/realchengwj/ocf.git
[submodule "libvfio-user"]
        path = libvfio-user
        url = https://gitee.com/realchengwj/libvfio-user.git
[submodule "xnvme"]
        path = xnvme
        url = https://gitee.com/realchengwj/xNVMe.git
[submodule "dpdk"]
        path = dpdk
        url = https://gitee.com/realchengwj/dpdk.git
[submodule "intel-ipsec-mb"]
        path = intel-ipsec-mb
        url = https://gitee.com/realchengwj/intel-ipsec-mb.git
[submodule "isa-l"]
        path = isa-l
        url = https://gitee.com/realchengwj/isa-l.git
[submodule "ocf"]
        path = ocf
        url = https://gitee.com/realchengwj/ocf.git
[submodule "libvfio-user"]
        path = libvfio-user
        url = https://gitee.com/realchengwj/libvfio-user.git
[submodule "xnvme"]
        path = xnvme
        url = https://gitee.com/realchengwj/xNVMe.git
Shell
 

 
执行git submodule syncgit submodule update --init后,重新编译。
./configure
make
./configure
make
Shell
 

 
尝试运行单元测试,成功。
./test/unit/unittest.sh
./test/unit/unittest.sh
Shell
 

 
notion image
接下来再重装的SPDK上运行hello_blob,成功。
notion image

 

修改hello_blob.c文件,让其底层使用nvme bdev

以上命令实在Malloc Bdev上执行的,该设备是一个RamDisk虚拟盘
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (C) 2017 Intel Corporation.
 *   All rights reserved.
 */

#include "spdk/stdinc.h"

#include "spdk/bdev.h"
#include "spdk/env.h"
#include "spdk/event.h"
#include "spdk/blob_bdev.h"
#include "spdk/blob.h"
#include "spdk/log.h"
#include "spdk/string.h"

struct lab4_context_t {
	struct spdk_blob_store *bs;
	struct spdk_blob *blob;
	spdk_blob_id blobid;
	struct spdk_io_channel *channel;
	uint8_t *read_buff;
	uint8_t *write_buff;
	uint64_t io_unit_size;
	int rc;
};

static void
cleanup(struct lab4_context_t *lab4_context)
{
	spdk_free(lab4_context->read_buff);
	spdk_free(lab4_context->write_buff);
	free(lab4_context);
}

static void
unload_complete(void *cb_arg, int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		SPDK_ERRLOG("Error %d unloading the bobstore\n", bserrno);
		lab4_context->rc = bserrno;
	}

	spdk_app_stop(lab4_context->rc);
}

static void
unload_bs(struct lab4_context_t *lab4_context, char *msg, int bserrno)
{
	if (bserrno) {
		SPDK_ERRLOG("%s (err %d)\n", msg, bserrno);
		lab4_context->rc = bserrno;
	}
	if (lab4_context->bs) {
		if (lab4_context->channel) {
			spdk_bs_free_io_channel(lab4_context->channel);
		}
		spdk_bs_unload(lab4_context->bs, unload_complete, lab4_context);
	} else {
		spdk_app_stop(bserrno);
	}
}

static void
delete_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in delete completion",
			  bserrno);
		return;
	}

	unload_bs(lab4_context, "", 0);
}

static void
delete_blob(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in close completion",
			  bserrno);
		return;
	}

	spdk_bs_delete_blob(lab4_context->bs, lab4_context->blobid,
			    delete_complete, lab4_context);
}

/*
 * Callback function for reading a blob.
 */
static void
read_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;
	int match_res = -1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in read completion",
			  bserrno);
		return;
	}

	match_res = memcmp(lab4_context->write_buff, lab4_context->read_buff,
			   lab4_context->io_unit_size);
	if (match_res) {
		unload_bs(lab4_context, "Error in data compare", -1);
		return;
	} else {
		SPDK_NOTICELOG("read SUCCESS and data matches!\n");
	}

	spdk_blob_close(lab4_context->blob, delete_blob, lab4_context);
}

static void
read_blob(struct lab4_context_t *lab4_context)
{
	SPDK_NOTICELOG("entry\n");

	lab4_context->read_buff = spdk_malloc(lab4_context->io_unit_size,
					       0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
					       SPDK_MALLOC_DMA);
	if (lab4_context->read_buff == NULL) {
		unload_bs(lab4_context, "Error in memory allocation",
			  -ENOMEM);
		return;
	}

	spdk_blob_io_read(lab4_context->blob, lab4_context->channel,
			  lab4_context->read_buff, 0, 1, read_complete,
			  lab4_context);
}

/*
 * Callback function for writing a blob.
 */
static void
write_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in write completion",
			  bserrno);
		return;
	}

	read_blob(lab4_context);
}

/*
 * Function for writing to a blob.
 */
static void
blob_write(struct lab4_context_t *lab4_context)
{
	SPDK_NOTICELOG("entry\n");

	lab4_context->write_buff = spdk_malloc(lab4_context->io_unit_size,
						0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
						SPDK_MALLOC_DMA);
	if (lab4_context->write_buff == NULL) {
		unload_bs(lab4_context, "Error in allocating memory",
			  -ENOMEM);
		return;
	}
	memset(lab4_context->write_buff, 0x5a, lab4_context->io_unit_size);

	lab4_context->channel = spdk_bs_alloc_io_channel(lab4_context->bs);
	if (lab4_context->channel == NULL) {
		unload_bs(lab4_context, "Error in allocating channel",
			  -ENOMEM);
		return;
	}

	spdk_blob_io_write(lab4_context->blob, lab4_context->channel,
			   lab4_context->write_buff,
			   0, 1, write_complete, lab4_context);
}

static void
sync_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in sync callback",
			  bserrno);
		return;
	}

	blob_write(lab4_context);
}

static void
resize_complete(void *cb_arg, int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;
	uint64_t total = 0;

	if (bserrno) {
		unload_bs(lab4_context, "Error in blob resize", bserrno);
		return;
	}

	total = spdk_blob_get_num_clusters(lab4_context->blob);
	SPDK_NOTICELOG("resized blob now has USED clusters of %" PRIu64 "\n",
		       total);

	spdk_blob_sync_md(lab4_context->blob, sync_complete, lab4_context);
}

/*
 * Callback function for opening a blob.
 */
static void
open_complete(void *cb_arg, struct spdk_blob *blob, int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;
	uint64_t free = 0;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in open completion",
			  bserrno);
		return;
	}

	lab4_context->blob = blob;
	free = spdk_bs_free_cluster_count(lab4_context->bs);
	SPDK_NOTICELOG("blobstore has FREE clusters of %" PRIu64 "\n",
		       free);

	spdk_blob_resize(lab4_context->blob, free, resize_complete, lab4_context);
}

/*
 * Callback function for creating a blob.
 */
static void
blob_create_complete(void *arg1, spdk_blob_id blobid, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in blob create callback",
			  bserrno);
		return;
	}

	lab4_context->blobid = blobid;
	SPDK_NOTICELOG("new blob id %" PRIu64 "\n", lab4_context->blobid);

	spdk_bs_open_blob(lab4_context->bs, lab4_context->blobid,
			  open_complete, lab4_context);
}

static void
create_blob(struct lab4_context_t *lab4_context)
{
	SPDK_NOTICELOG("entry\n");
	spdk_bs_create_blob(lab4_context->bs, blob_create_complete, lab4_context);
}

static void
bs_init_complete(void *cb_arg, struct spdk_blob_store *bs,
		 int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error initing the blobstore",
			  bserrno);
		return;
	}

	lab4_context->bs = bs;
	SPDK_NOTICELOG("blobstore: %p\n", lab4_context->bs);

	lab4_context->io_unit_size = spdk_bs_get_io_unit_size(lab4_context->bs);

	create_blob(lab4_context);
}

static void
base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
		   void *event_ctx)
{
	SPDK_WARNLOG("Unsupported bdev event: type %d\n", type);
}

/*
 * Our initial event that kicks off everything from main().
 */
static void
lab4_start(void *arg1)
{
	struct lab4_context_t *lab4_context = arg1;
	struct spdk_bs_dev *bs_dev = NULL;
	int rc;

	SPDK_NOTICELOG("entry\n");

	rc = spdk_bdev_create_bs_dev_ext("Nvme0n1", base_bdev_event_cb, NULL, &bs_dev);
	if (rc != 0) {
		SPDK_ERRLOG("Could not create blob bdev, %s!!\n",
			    spdk_strerror(-rc));
		spdk_app_stop(-1);
		return;
	}

	spdk_bs_init(bs_dev, NULL, bs_init_complete, lab4_context);
}

int
main(int argc, char **argv)
{
	struct spdk_app_opts opts = {};
	int rc = 0;
	struct lab4_context_t *lab4_context = NULL;

	SPDK_NOTICELOG("entry\n");

	spdk_app_opts_init(&opts, sizeof(opts));

	/*
	 * Setup a few specifics before we init, for most SPDK cmd line
	 * apps, the config file will be passed in as an arg but to make
	 * this example super simple we just hardcode it. We also need to
	 * specify a name for the app.
	 */
	opts.name = "lab4_blob";
	opts.json_config_file = argv[1];


	/*
	 * Now we'll allocate and initialize the blobstore itself. We
	 * can pass in an spdk_bs_opts if we want something other than
	 * the defaults (cluster size, etc), but here we'll just take the
	 * defaults.  We'll also pass in a struct that we'll use for
	 * callbacks so we've got efficient bookkeeping of what we're
	 * creating. This is an async operation and bs_init_complete()
	 * will be called when it is complete.
	 */
	lab4_context = calloc(1, sizeof(struct lab4_context_t));
	if (lab4_context != NULL) {
		/*
		 * spdk_app_start() will block running lab4_start() until
		 * spdk_app_stop() is called by someone (not simply when
		 * lab4_start() returns), or if an error occurs during
		 * spdk_app_start() before lab4_start() runs.
		 */
		rc = spdk_app_start(&opts, lab4_start, lab4_context);
		if (rc) {
			SPDK_NOTICELOG("ERROR!\n");
		} else {
			SPDK_NOTICELOG("SUCCESS!\n");
		}
		/* Free up memory that we allocated */
		cleanup(lab4_context);
	} else {
		SPDK_ERRLOG("Could not alloc lab4_context struct!!\n");
		rc = -ENOMEM;
	}

	/* Gracefully close out all of the SPDK subsystems. */
	spdk_app_fini();
	return rc;
}
/*   SPDX-License-Identifier: BSD-3-Clause
 *   Copyright (C) 2017 Intel Corporation.
 *   All rights reserved.
 */

#include "spdk/stdinc.h"

#include "spdk/bdev.h"
#include "spdk/env.h"
#include "spdk/event.h"
#include "spdk/blob_bdev.h"
#include "spdk/blob.h"
#include "spdk/log.h"
#include "spdk/string.h"

struct lab4_context_t {
	struct spdk_blob_store *bs;
	struct spdk_blob *blob;
	spdk_blob_id blobid;
	struct spdk_io_channel *channel;
	uint8_t *read_buff;
	uint8_t *write_buff;
	uint64_t io_unit_size;
	int rc;
};

static void
cleanup(struct lab4_context_t *lab4_context)
{
	spdk_free(lab4_context->read_buff);
	spdk_free(lab4_context->write_buff);
	free(lab4_context);
}

static void
unload_complete(void *cb_arg, int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		SPDK_ERRLOG("Error %d unloading the bobstore\n", bserrno);
		lab4_context->rc = bserrno;
	}

	spdk_app_stop(lab4_context->rc);
}

static void
unload_bs(struct lab4_context_t *lab4_context, char *msg, int bserrno)
{
	if (bserrno) {
		SPDK_ERRLOG("%s (err %d)\n", msg, bserrno);
		lab4_context->rc = bserrno;
	}
	if (lab4_context->bs) {
		if (lab4_context->channel) {
			spdk_bs_free_io_channel(lab4_context->channel);
		}
		spdk_bs_unload(lab4_context->bs, unload_complete, lab4_context);
	} else {
		spdk_app_stop(bserrno);
	}
}

static void
delete_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in delete completion",
			  bserrno);
		return;
	}

	unload_bs(lab4_context, "", 0);
}

static void
delete_blob(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in close completion",
			  bserrno);
		return;
	}

	spdk_bs_delete_blob(lab4_context->bs, lab4_context->blobid,
			    delete_complete, lab4_context);
}

/*
 * Callback function for reading a blob.
 */
static void
read_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;
	int match_res = -1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in read completion",
			  bserrno);
		return;
	}

	match_res = memcmp(lab4_context->write_buff, lab4_context->read_buff,
			   lab4_context->io_unit_size);
	if (match_res) {
		unload_bs(lab4_context, "Error in data compare", -1);
		return;
	} else {
		SPDK_NOTICELOG("read SUCCESS and data matches!\n");
	}

	spdk_blob_close(lab4_context->blob, delete_blob, lab4_context);
}

static void
read_blob(struct lab4_context_t *lab4_context)
{
	SPDK_NOTICELOG("entry\n");

	lab4_context->read_buff = spdk_malloc(lab4_context->io_unit_size,
					       0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
					       SPDK_MALLOC_DMA);
	if (lab4_context->read_buff == NULL) {
		unload_bs(lab4_context, "Error in memory allocation",
			  -ENOMEM);
		return;
	}

	spdk_blob_io_read(lab4_context->blob, lab4_context->channel,
			  lab4_context->read_buff, 0, 1, read_complete,
			  lab4_context);
}

/*
 * Callback function for writing a blob.
 */
static void
write_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in write completion",
			  bserrno);
		return;
	}

	read_blob(lab4_context);
}

/*
 * Function for writing to a blob.
 */
static void
blob_write(struct lab4_context_t *lab4_context)
{
	SPDK_NOTICELOG("entry\n");

	lab4_context->write_buff = spdk_malloc(lab4_context->io_unit_size,
						0x1000, NULL, SPDK_ENV_LCORE_ID_ANY,
						SPDK_MALLOC_DMA);
	if (lab4_context->write_buff == NULL) {
		unload_bs(lab4_context, "Error in allocating memory",
			  -ENOMEM);
		return;
	}
	memset(lab4_context->write_buff, 0x5a, lab4_context->io_unit_size);

	lab4_context->channel = spdk_bs_alloc_io_channel(lab4_context->bs);
	if (lab4_context->channel == NULL) {
		unload_bs(lab4_context, "Error in allocating channel",
			  -ENOMEM);
		return;
	}

	spdk_blob_io_write(lab4_context->blob, lab4_context->channel,
			   lab4_context->write_buff,
			   0, 1, write_complete, lab4_context);
}

static void
sync_complete(void *arg1, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in sync callback",
			  bserrno);
		return;
	}

	blob_write(lab4_context);
}

static void
resize_complete(void *cb_arg, int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;
	uint64_t total = 0;

	if (bserrno) {
		unload_bs(lab4_context, "Error in blob resize", bserrno);
		return;
	}

	total = spdk_blob_get_num_clusters(lab4_context->blob);
	SPDK_NOTICELOG("resized blob now has USED clusters of %" PRIu64 "\n",
		       total);

	spdk_blob_sync_md(lab4_context->blob, sync_complete, lab4_context);
}

/*
 * Callback function for opening a blob.
 */
static void
open_complete(void *cb_arg, struct spdk_blob *blob, int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;
	uint64_t free = 0;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in open completion",
			  bserrno);
		return;
	}

	lab4_context->blob = blob;
	free = spdk_bs_free_cluster_count(lab4_context->bs);
	SPDK_NOTICELOG("blobstore has FREE clusters of %" PRIu64 "\n",
		       free);

	spdk_blob_resize(lab4_context->blob, free, resize_complete, lab4_context);
}

/*
 * Callback function for creating a blob.
 */
static void
blob_create_complete(void *arg1, spdk_blob_id blobid, int bserrno)
{
	struct lab4_context_t *lab4_context = arg1;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error in blob create callback",
			  bserrno);
		return;
	}

	lab4_context->blobid = blobid;
	SPDK_NOTICELOG("new blob id %" PRIu64 "\n", lab4_context->blobid);

	spdk_bs_open_blob(lab4_context->bs, lab4_context->blobid,
			  open_complete, lab4_context);
}

static void
create_blob(struct lab4_context_t *lab4_context)
{
	SPDK_NOTICELOG("entry\n");
	spdk_bs_create_blob(lab4_context->bs, blob_create_complete, lab4_context);
}

static void
bs_init_complete(void *cb_arg, struct spdk_blob_store *bs,
		 int bserrno)
{
	struct lab4_context_t *lab4_context = cb_arg;

	SPDK_NOTICELOG("entry\n");
	if (bserrno) {
		unload_bs(lab4_context, "Error initing the blobstore",
			  bserrno);
		return;
	}

	lab4_context->bs = bs;
	SPDK_NOTICELOG("blobstore: %p\n", lab4_context->bs);

	lab4_context->io_unit_size = spdk_bs_get_io_unit_size(lab4_context->bs);

	create_blob(lab4_context);
}

static void
base_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
		   void *event_ctx)
{
	SPDK_WARNLOG("Unsupported bdev event: type %d\n", type);
}

/*
 * Our initial event that kicks off everything from main().
 */
static void
lab4_start(void *arg1)
{
	struct lab4_context_t *lab4_context = arg1;
	struct spdk_bs_dev *bs_dev = NULL;
	int rc;

	SPDK_NOTICELOG("entry\n");

	rc = spdk_bdev_create_bs_dev_ext("Nvme0n1", base_bdev_event_cb, NULL, &bs_dev);
	if (rc != 0) {
		SPDK_ERRLOG("Could not create blob bdev, %s!!\n",
			    spdk_strerror(-rc));
		spdk_app_stop(-1);
		return;
	}

	spdk_bs_init(bs_dev, NULL, bs_init_complete, lab4_context);
}

int
main(int argc, char **argv)
{
	struct spdk_app_opts opts = {};
	int rc = 0;
	struct lab4_context_t *lab4_context = NULL;

	SPDK_NOTICELOG("entry\n");

	spdk_app_opts_init(&opts, sizeof(opts));

	/*
	 * Setup a few specifics before we init, for most SPDK cmd line
	 * apps, the config file will be passed in as an arg but to make
	 * this example super simple we just hardcode it. We also need to
	 * specify a name for the app.
	 */
	opts.name = "lab4_blob";
	opts.json_config_file = argv[1];


	/*
	 * Now we'll allocate and initialize the blobstore itself. We
	 * can pass in an spdk_bs_opts if we want something other than
	 * the defaults (cluster size, etc), but here we'll just take the
	 * defaults.  We'll also pass in a struct that we'll use for
	 * callbacks so we've got efficient bookkeeping of what we're
	 * creating. This is an async operation and bs_init_complete()
	 * will be called when it is complete.
	 */
	lab4_context = calloc(1, sizeof(struct lab4_context_t));
	if (lab4_context != NULL) {
		/*
		 * spdk_app_start() will block running lab4_start() until
		 * spdk_app_stop() is called by someone (not simply when
		 * lab4_start() returns), or if an error occurs during
		 * spdk_app_start() before lab4_start() runs.
		 */
		rc = spdk_app_start(&opts, lab4_start, lab4_context);
		if (rc) {
			SPDK_NOTICELOG("ERROR!\n");
		} else {
			SPDK_NOTICELOG("SUCCESS!\n");
		}
		/* Free up memory that we allocated */
		cleanup(lab4_context);
	} else {
		SPDK_ERRLOG("Could not alloc lab4_context struct!!\n");
		rc = -ENOMEM;
	}

	/* Gracefully close out all of the SPDK subsystems. */
	spdk_app_fini();
	return rc;
}
C
 

 
Makefile
SPDK_ROOT_DIR :=  /home/cwj/work/spdk
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk

APP = lab4_blob

C_SRCS := lab4_blob.c

SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev

include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
SPDK_ROOT_DIR :=  /home/cwj/work/spdk
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk

APP = lab4_blob

C_SRCS := lab4_blob.c

SPDK_LIB_LIST = $(ALL_MODULES_LIST) event event_bdev

include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
Makefile
 

 
在spdk文件夹生成nvme配置文件
./scripts/gen_nvme.sh --json-with-subsystems > ../lab4/nvme.json
./scripts/gen_nvme.sh --json-with-subsystems > ../lab4/nvme.json
Shell
 

 
进入lab4文件夹运行
sudo ./lab4_blob ./nvme.json
sudo ./lab4_blob ./nvme.json
Shell
 

 
notion image
可以看到运行成功。

原文地址:http://www.cnblogs.com/hushrush/p/16928036.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性