devicemapper源码理解

device-mapper.h

table的类型,mapped_device 的内存池和请求队列
enum dm_queue_mode {
DM_TYPE_NONE = 0,
DM_TYPE_BIO_BASED = 1,
DM_TYPE_REQUEST_BASED = 2,
DM_TYPE_MQ_REQUEST_BASED = 3,
DM_TYPE_DAX_BIO_BASED = 4,
};

一些函数原型如:
typedef int (dm_ctr_fn) (struct dm_target target,
unsigned int argc, char **argv);

/*

  • The map function must return:
  • < 0: error
  • = 0: The target will handle the io by resubmitting it later
  • = 1: simple remap complete
  • = 2: The target wants to push back the io
    /
    typedef int (
    dm_map_fn) (struct dm_target ti, struct bio bio);

/*

  • Returns:
  • < 0 : error (currently ignored)
  • 0 : ended successfully
  • 1 : for some reason the io has still not completed (eg,
  • multipath target might want to requeue a failed io).
  • 2 : The target wants to push back the io
    /
    typedef int (
    dm_endio_fn) (struct dm_target *ti,
    struct bio *bio, int error);
    

target_type

struct target_type {
uint64_t features;
const char name;
struct module
module;
unsigned version[3];
dm_ctr_fn ctr;
dm_dtr_fn dtr;
dm_map_fn map;
dm_map_request_fn map_rq;
dm_clone_and_map_request_fn clone_and_map_rq;
dm_release_clone_request_fn release_clone_rq;
dm_endio_fn end_io;
dm_request_endio_fn rq_end_io;
dm_presuspend_fn presuspend;
dm_presuspend_undo_fn presuspend_undo;
dm_postsuspend_fn postsuspend;
dm_preresume_fn preresume;
dm_resume_fn resume;
dm_status_fn status;
dm_message_fn message;
dm_prepare_ioctl_fn prepare_ioctl;
dm_merge_fn merge;
dm_busy_fn busy;
dm_iterate_devices_fn iterate_devices;
dm_io_hints_fn io_hints;
dm_dax_direct_access_fn direct_access;
dm_dax_memcpy_fromiovecend_fn dax_memcpy_fromiovecend;
dm_dax_memcpy_toiovecend_fn dax_memcpy_toiovecend;

/* For internal device-mapper use. */
struct list_head list;

};

2020-4-5
从devicemapper 初始化开始看:
在dm-ioctl.c中
创建混杂设备(混杂设备是一种字符设备):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __init dm_interface_init(void)
{
int r;

r = dm_hash_init();
if (r)
return r;

r = misc_register(&_dm_misc); //注册混杂设备
if (r) {
DMERR("misc_register failed for control device");
dm_hash_exit();
return r;
}

DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
DM_DRIVER_EMAIL);
return 0;
}

在dm.c 调用并初始化

1
2
3
4
5
6
static struct miscdevice _dm_misc = {
.minor = MAPPER_CTRL_MINOR,
.name = DM_NAME,
.nodename = DM_DIR "/" DM_CONTROL_NODE,
.fops = &_ctl_fops //设置混杂设备的一些操作
};

混杂设备具体的操作:

1
2
3
4
5
6
7
8
9
static const struct file_operations _ctl_fops = {
.open = dm_open,
.release = dm_release,
.poll = dm_poll,
.unlocked_ioctl = dm_ctl_ioctl,
.compat_ioctl = dm_compat_ctl_ioctl,
.owner = THIS_MODULE,
.llseek = noop_llseek,
};

在dm_ctl_ioctl中实现具体的ioctl操作
dm_ctl_ioctl() -> ctl_ioctl() -> lookup_ioctl() //查找对应的ioctl操作
在 ctl_ioctl中执行对应的ioctl操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
{
static const struct {
int cmd;
int flags;
ioctl_fn fn;
} _ioctls[] = {
{DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */
{DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, remove_all},
{DM_LIST_DEVICES_CMD, 0, list_devices},

{DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_create},
{DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_remove},
{DM_DEV_RENAME_CMD, IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_rename},
{DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend},
{DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status},
{DM_DEV_WAIT_CMD, 0, dev_wait},

{DM_TABLE_LOAD_CMD, 0, table_load},
{DM_TABLE_CLEAR_CMD, IOCTL_FLAGS_NO_PARAMS, table_clear},
{DM_TABLE_DEPS_CMD, 0, table_deps},
{DM_TABLE_STATUS_CMD, 0, table_status},

{DM_LIST_VERSIONS_CMD, 0, list_versions},

{DM_TARGET_MSG_CMD, 0, target_message},
{DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry},
{DM_DEV_ARM_POLL, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll},
};

if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))
return NULL;

*ioctl_flags = _ioctls[cmd].flags;
return _ioctls[cmd].fn;
}

看一下创建一个mapping device的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
static int dev_create(struct file *filp, struct dm_ioctl *param, size_t param_size)
{
int r, m = DM_ANY_MINOR;
struct mapped_device *md;

r = check_name(param->name);
if (r)
return r;

if (param->flags & DM_PERSISTENT_DEV_FLAG)
m = MINOR(huge_decode_dev(param->dev));

r = dm_create(m, &md);
if (r)
return r;

r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
if (r) {
dm_put(md);
dm_destroy(md);
return r;
}

param->flags &= ~DM_INACTIVE_PRESENT_FLAG;

__dev_status(md, param);

dm_put(md);

return 0;
}

-------------本文结束啦感谢您阅读-------------
0%