SPDK从功能角度将各个独立的部分划分为“子系统“。例如对各种后端存储的访问属于bdev子系统,又例如对虚拟机呈现各种设备属于vhost子系统。不同场景下,各种工具可以通过组合不同的子系统来实现各种不同的功能。例如虚拟化场景下,vhost主要集成了bdev、vhost、scsi等子系统。这些子系统存在一定依赖关系,例如vhost子系统依赖bdev,这就需要将被依赖的子系统先初始化完成,才能执行其它子系统的初始化。
本篇博文我们先整体介绍一下SPDK子系统的初始化流程,然后再深入分析一下bdev子系统。vhost子系统我们将在独立的博文中展开分析。
SPDK子系统
通过前文的分析,我们知道主线程在执行_spdk_reactor_run时,首先处理的事件便是verify事件,该事件处理函数为spdk_subsystem_verify:
spdk/lib/event/subsystem.c:
static void
spdk_subsystem_verify(void *arg1, void *arg2)
{
struct spdk_subsystem_depend *dep;
/* 检查当前应用中所有需要的子系统及其依赖系统是否均已成功注册 */
/* Verify that all dependency name and depends_on subsystems are registered */
TAILQ_FOREACH(dep, &g_subsystems_deps, tailq) {
if (!spdk_subsystem_find(&g_subsystems, dep->name)) {
SPDK_ERRLOG("subsystem %s is missing\n", dep->name);
spdk_app_stop(-1);
return;
}
if (!spdk_subsystem_find(&g_subsystems, dep->depends_on)) {
SPDK_ERRLOG("subsystem %s dependency %s is missing\n",
dep->name, dep->depends_on);
spdk_app_stop(-1);
return;
}
}
/* 按依赖关系对所有子系统进行排序 */
subsystem_sort();
/* 依据排序依次执行各个子系统的init函数 */
spdk_subsystem_init_next(0);
}
bdev子系统
bdev和vhost是虚拟化场景下两个最为主要的子系统,且vhost依赖bdev,因此我们先来分析一下bdev子系统。
我们可以看到bdev子系统的初始化函数为spdk_bdev_subsystem_initialize:
spdk/lib/event/subsystems/bdev/bdev.c:
static struct spdk_subsystem g_spdk_subsystem_bdev = {
.name = "bdev",
.init = spdk_bdev_subsystem_initialize,
.fini = spdk_bdev_subsystem_finish,
.config = spdk_bdev_config_text,
.write_config_json = _spdk_bdev_subsystem_config_json,
};
bdev子系统针对不同的后端存储设备实现了不同的“模块”,例如nvme模块主要实现了用户态对nvme设备的访问操作,virtio实现了用户态对virtio设备的访问操