如果enable drviers/nvme/target 之后会调用nvmet_init_configfs 来创建configs 文件系统.按组行目录/sys/kernel/config
可以通过cat /proc/mounts 或者mount 命令来查看config的mount点
static struct configfs_subsystem nvmet_configfs_subsystem = {
.su_group = {
.cg_item = {
.ci_namebuf = "nvmet",
.ci_type = &nvmet_root_type,
},
},
};
这里的cg_item表示一个目录,这个目录的名字是nvme.
ci_type 表示属性和属性对应的操作,其类型是config_item_type,这里所谓的属性其实就是表示单个文件.
struct config_item_type {
struct module *ct_owner; //定义属于哪个module,一般赋值为THIS_MODULE
struct configfs_item_operations *ct_item_ops;// 针对属性的操作
struct configfs_group_operations *ct_group_ops;//针对group的操作,这里的group就是目录
struct configfs_attribute **ct_attrs;//定义具体的属性,这里属性为文件
struct configfs_bin_attribute **ct_bin_attrs;//定义具体的属性,这里的属性为binary
};
而这里的nvmet_root_type 定义如下,暂时并没有定义属性和其对应的操作
static struct config_item_type nvmet_root_type = {
.ct_owner = THIS_MODULE,
};
明白了这些后,我们看看nvmet_init_configfs 具体都做了什么
int __init nvmet_init_configfs(void)
{
int ret;
// 新建目录
config_group_init(&nvmet_configfs_subsystem.su_group);
mutex_init(&nvmet_configfs_subsystem.su_mutex);
//新建目录subsystems,这个目录对应的操作为nvmet_subsystems_type
config_group_init_type_name(&nvmet_subsystems_group,
"subsystems", &nvmet_subsystems_type);
//将目录当到nvmet 这个目录下面
configfs_add_default_group(&nvmet_subsystems_group,
&nvmet_configfs_subsystem.su_group);
//同上类似
config_group_init_type_name(&nvmet_ports_group,
"ports", &nvmet_ports_type);
configfs_add_default_group(&nvmet_ports_group,
&nvmet_configfs_subsystem.su_group);
//同上类似
config_group_init_type_name(&nvmet_hosts_group,
"hosts", &nvmet_hosts_type);
configfs_add_default_group(&nvmet_hosts_group,
&nvmet_configfs_subsystem.su_group);
注册nvmet 这个名为nvmet的config文件系统
ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
if (ret) {
pr_err("configfs_register_subsystem: %d\n", ret);
return ret;
}
return 0;
}
我们先看看config_group_init_type_name 中针对subsystems 这个目录的操作函数nvmet_subsystems_type
static struct config_item_type nvmet_subsystems_type = {
.ct_group_ops = &nvmet_subsystems_group_ops,
.ct_owner = THIS_MODULE,
};
具体操作见nvmet_subsystems_group_ops
static struct configfs_group_operations nvmet_subsystems_group_ops = {
.make_group = nvmet_subsys_make,
};
static struct config_group *nvmet_subsys_make(struct config_group *group,
const char *name)
{
struct nvmet_subsys *subsys;
if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
pr_err("can't create discovery subsystem through configfs\n");
return ERR_PTR(-EINVAL);
}
subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
if (!subsys)
return ERR_PTR(-ENOMEM);
config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
config_group_init_type_name(&subsys->namespaces_group,
"namespaces", &nvmet_namespaces_type);
configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
config_group_init_type_name(&subsys->allowed_hosts_group,
"allowed_hosts", &nvmet_allowed_hosts_type);
configfs_add_default_group(&subsys->allowed_hosts_group,
&subsys->group);
return &subsys->group;
}
原来又是在subsystems 这个目录下建立namespaces和allowed_hosts 两个子目录.
可以通过cat /proc/mounts 或者mount 命令来查看config的mount点
static struct configfs_subsystem nvmet_configfs_subsystem = {
.su_group = {
.cg_item = {
.ci_namebuf = "nvmet",
.ci_type = &nvmet_root_type,
},
},
};
这里的cg_item表示一个目录,这个目录的名字是nvme.
ci_type 表示属性和属性对应的操作,其类型是config_item_type,这里所谓的属性其实就是表示单个文件.
struct config_item_type {
struct module *ct_owner; //定义属于哪个module,一般赋值为THIS_MODULE
struct configfs_item_operations *ct_item_ops;// 针对属性的操作
struct configfs_group_operations *ct_group_ops;//针对group的操作,这里的group就是目录
struct configfs_attribute **ct_attrs;//定义具体的属性,这里属性为文件
struct configfs_bin_attribute **ct_bin_attrs;//定义具体的属性,这里的属性为binary
};
而这里的nvmet_root_type 定义如下,暂时并没有定义属性和其对应的操作
static struct config_item_type nvmet_root_type = {
.ct_owner = THIS_MODULE,
};
明白了这些后,我们看看nvmet_init_configfs 具体都做了什么
int __init nvmet_init_configfs(void)
{
int ret;
// 新建目录
config_group_init(&nvmet_configfs_subsystem.su_group);
mutex_init(&nvmet_configfs_subsystem.su_mutex);
//新建目录subsystems,这个目录对应的操作为nvmet_subsystems_type
config_group_init_type_name(&nvmet_subsystems_group,
"subsystems", &nvmet_subsystems_type);
//将目录当到nvmet 这个目录下面
configfs_add_default_group(&nvmet_subsystems_group,
&nvmet_configfs_subsystem.su_group);
//同上类似
config_group_init_type_name(&nvmet_ports_group,
"ports", &nvmet_ports_type);
configfs_add_default_group(&nvmet_ports_group,
&nvmet_configfs_subsystem.su_group);
//同上类似
config_group_init_type_name(&nvmet_hosts_group,
"hosts", &nvmet_hosts_type);
configfs_add_default_group(&nvmet_hosts_group,
&nvmet_configfs_subsystem.su_group);
注册nvmet 这个名为nvmet的config文件系统
ret = configfs_register_subsystem(&nvmet_configfs_subsystem);
if (ret) {
pr_err("configfs_register_subsystem: %d\n", ret);
return ret;
}
return 0;
}
我们先看看config_group_init_type_name 中针对subsystems 这个目录的操作函数nvmet_subsystems_type
static struct config_item_type nvmet_subsystems_type = {
.ct_group_ops = &nvmet_subsystems_group_ops,
.ct_owner = THIS_MODULE,
};
具体操作见nvmet_subsystems_group_ops
static struct configfs_group_operations nvmet_subsystems_group_ops = {
.make_group = nvmet_subsys_make,
};
static struct config_group *nvmet_subsys_make(struct config_group *group,
const char *name)
{
struct nvmet_subsys *subsys;
if (sysfs_streq(name, NVME_DISC_SUBSYS_NAME)) {
pr_err("can't create discovery subsystem through configfs\n");
return ERR_PTR(-EINVAL);
}
subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
if (!subsys)
return ERR_PTR(-ENOMEM);
config_group_init_type_name(&subsys->group, name, &nvmet_subsys_type);
config_group_init_type_name(&subsys->namespaces_group,
"namespaces", &nvmet_namespaces_type);
configfs_add_default_group(&subsys->namespaces_group, &subsys->group);
config_group_init_type_name(&subsys->allowed_hosts_group,
"allowed_hosts", &nvmet_allowed_hosts_type);
configfs_add_default_group(&subsys->allowed_hosts_group,
&subsys->group);
return &subsys->group;
}
原来又是在subsystems 这个目录下建立namespaces和allowed_hosts 两个子目录.