日期:2014-05-16  浏览次数:20670 次

<linux>from lvm2 to device mapper

?


?了解分布式存储的朋友 一定知道 lvm2 , PV LV VG等 ,简单看看lvm2是如何和内核交互的,为下一步开发自己的lvm 做准备

?

?

首先看 lvcreate 的调用走向 ?希望你自己摸索过lvm 也熟悉vfs ,fs子系统 ,这样可以一看就知道什么意思,然后大家一起交流。

?

lvm: dev_manager.c

?

?

/*
 * Add LV and any known dependencies
 */
static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct logical_volume *lv)
{
//...
	if (!_add_dev_to_dtree(dm, dtree, lv, NULL))
		return_0;

//...
	return 1;
}

?_add_dev_to_dtree ---》int _info() ---》 dm_task_run()

?

然后就是 dm 库

?

?

int dm_task_run(struct dm_task *dmt)
{


repeat_ioctl:/*关键就是这个*/
	if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor)))
		return 0;
	if (dmi->flags & DM_BUFFER_FULL_FLAG) {
		switch (dmt->type) {
		case DM_DEVICE_LIST_VERSIONS:
		case DM_DEVICE_LIST:
		case DM_DEVICE_DEPS:
		case DM_DEVICE_STATUS:
		case DM_DEVICE_TABLE:
		case DM_DEVICE_WAITEVENT:
			_ioctl_buffer_double_factor++;
			dm_free(dmi);
			goto repeat_ioctl;/*这里其实是在循环决定操作*/
		default:
			log_error("WARNING: libdevmapper buffer too small for data");
		}
//...


}
?

?

?

?

static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
				     unsigned repeat_count)
{
	struct dm_ioctl *dmi;

	dmi = _flatten(dmt, repeat_count);/*dm_task结构字段合法性检查*/
	if (!dmi) {
		log_error("Couldn't create ioctl argument.");
		return NULL;
	}

	if (dmt->type == DM_DEVICE_TABLE)
		dmi->flags |= DM_STATUS_TABLE_FLAG;

	dmi->flags |= DM_EXISTS_FLAG;	/* FIXME */

	if (dmt->no_open_count)
		dmi->flags |= DM_SKIP_BDGET_FLAG;

//...
#ifdef DM_IOCTLS
	if (ioctl(_control_fd, command, dmi) < 0) {/*注意这里的dmi  */
		if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
				       (dmt->type == DM_DEVICE_MKNODES) ||
				       (dmt->type == DM_DEVICE_STATUS)))
			dmi->flags &= ~DM_EXISTS_FLAG;	/* FIXME */
		else {
			if (_log_suppress)
				log_verbose("device-mapper: %s ioctl "
					    "failed: %s",
				    	    _cmd_data_v4[dmt->type].name,
					    strerror(errno));
			else
				log_error("device-mapper: %s ioctl "
					  "failed: %s",
				    	   _cmd_data_v4[dmt->type].name,
					  strerror(errno));
			dm_free(dmi);
			return NULL;
		}
	}
#else /* Userspace alternative for testing */
#endif
	return dmi;
}
?

?

?我把关键的这行扣出来

ioctl(_control_fd, command, dmi) < 0)
?

?

看一下 command的取值:

?

int dm_task_run(struct dm_task *dmt)
{
	struct dm_ioctl *dmi;
	unsigned command;
//...
command = _cmd_data_v4[dmt->type].cmd;
//...
}

?

?

对应一个全局数组

?

?

static struct cmd_data _cmd_data_v4[] = {
	{"create",	DM_DEV_CREATE,		{4, 0, 0}},
	{"reload",	DM_TABLE_LOAD,		{4, 0, 0}},
	{"remove",	DM_DEV_REMOVE,		{4, 0, 0}},
	{"remove_all",	DM_REMOVE_ALL,		{4, 0, 0}},
	{"suspend",	DM_DEV_SUSPEND,		{4, 0, 0}},
	{"resume",	DM_DEV_SUSPEND,		{4, 0, 0}},
	{"info",	DM_DEV_STATUS,		{4, 0, 0}},
	{"deps",	DM_TABLE_DEPS,		{4, 0, 0}},
	{"rename",	DM_DEV_RENAME,		{4, 0, 0}},
	{"version",	DM_VERSION,		{4, 0, 0}},
	{"status",	DM_TABLE_STATUS,	{4, 0, 0}},
	{"table",	DM_TABLE_STATUS,	{4, 0, 0}},
	{"waitevent",	DM_DEV_WAIT,		{4, 0, 0}},
	{"names",	DM_LIST_DEVICES,	{4, 0, 0}},
	{"clear",	DM_TABLE_CLEAR,		{4, 0, 0}},
	{"mknodes",	DM_DEV_STATUS,		{4, 0, 0}},
#ifdef DM_LIST_VERSIONS
	{"versions",	DM_LIST_VERSIONS,	{4, 1, 0}},
#endif
#ifdef DM_TARGET_MSG
	{"message",	DM_TARGET_MSG,		{4, 2, 0}},
#endif
#ifdef DM_DEV_SET_GEOMETRY
	{"setgeometry",	DM_DEV_SET_GEOMETRY,	{4, 6, 0}},
#endif
};
?

前面就是 shell输入的命令。 关键就是?

?