⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libdm-iface.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
	do {		names = (void *) names + next;		if (names->dev == dev) {			strncpy(buf, names->name, len);			r = 1;			break;		}		next = names->next;	} while (next);      out:	dm_task_destroy(dmt);	return r;}static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count){	const size_t min_size = 16 * 1024;	const int (*version)[3];	struct dm_ioctl *dmi;	struct target *t;	struct dm_target_msg *tmsg;	size_t len = sizeof(struct dm_ioctl);	void *b, *e;	int count = 0;	for (t = dmt->head; t; t = t->next) {		len += sizeof(struct dm_target_spec);		len += strlen(t->params) + 1 + ALIGNMENT;		count++;	}	if (count && (dmt->sector || dmt->message)) {		log_error("targets and message are incompatible");		return NULL;	}	if (count && dmt->newname) {		log_error("targets and newname are incompatible");		return NULL;	}	if (count && dmt->geometry) {		log_error("targets and geometry are incompatible");		return NULL;	}	if (dmt->newname && (dmt->sector || dmt->message)) {		log_error("message and newname are incompatible");		return NULL;	}	if (dmt->newname && dmt->geometry) {		log_error("geometry and newname are incompatible");		return NULL;	}	if (dmt->geometry && (dmt->sector || dmt->message)) {		log_error("geometry and message are incompatible");		return NULL;	}	if (dmt->sector && !dmt->message) {		log_error("message is required with sector");		return NULL;	}	if (dmt->newname)		len += strlen(dmt->newname) + 1;	if (dmt->message)		len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;	if (dmt->geometry)		len += strlen(dmt->geometry) + 1;	/*	 * Give len a minimum size so that we have space to store	 * dependencies or status information.	 */	if (len < min_size)		len = min_size;	/* Increase buffer size if repeating because buffer was too small */	while (repeat_count--)		len *= 2;	if (!(dmi = dm_malloc(len)))		return NULL;	memset(dmi, 0, len);	version = &_cmd_data_v4[dmt->type].version;	dmi->version[0] = (*version)[0];	dmi->version[1] = (*version)[1];	dmi->version[2] = (*version)[2];	dmi->data_size = len;	dmi->data_start = sizeof(struct dm_ioctl);	if (dmt->minor >= 0) {		if (dmt->major <= 0) {			log_error("Missing major number for persistent device.");			goto bad;		}		dmi->flags |= DM_PERSISTENT_DEV_FLAG;		dmi->dev = MKDEV(dmt->major, dmt->minor);	}	/* Does driver support device number referencing? */	if (_dm_version_minor < 3 && !dmt->dev_name && !dmt->uuid && dmi->dev) {		if (!_lookup_dev_name(dmi->dev, dmi->name, sizeof(dmi->name))) {			log_error("Unable to find name for device (%" PRIu32				  ":%" PRIu32 ")", dmt->major, dmt->minor);			goto bad;		}		log_verbose("device (%" PRIu32 ":%" PRIu32 ") is %s "			    "for compatibility with old kernel",			    dmt->major, dmt->minor, dmi->name);	}	if (dmt->dev_name)		strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));	if (dmt->uuid)		strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));	if (dmt->type == DM_DEVICE_SUSPEND)		dmi->flags |= DM_SUSPEND_FLAG;	if (dmt->no_flush)		dmi->flags |= DM_NOFLUSH_FLAG;	if (dmt->read_only)		dmi->flags |= DM_READONLY_FLAG;	if (dmt->skip_lockfs)		dmi->flags |= DM_SKIP_LOCKFS_FLAG;	dmi->target_count = count;	dmi->event_nr = dmt->event_nr;	b = (void *) (dmi + 1);	e = (void *) ((char *) dmi + len);	for (t = dmt->head; t; t = t->next)		if (!(b = _add_target(t, b, e)))			goto bad;	if (dmt->newname)		strcpy(b, dmt->newname);	if (dmt->message) {		tmsg = (struct dm_target_msg *) b;		tmsg->sector = dmt->sector;		strcpy(tmsg->message, dmt->message);	}	if (dmt->geometry)		strcpy(b, dmt->geometry);	return dmi;      bad:	dm_free(dmi);	return NULL;}static int _process_mapper_dir(struct dm_task *dmt){	struct dirent *dirent;	DIR *d;	const char *dir;	int r = 1;	dir = dm_dir();	if (!(d = opendir(dir))) {		log_sys_error("opendir", dir);		return 0;	}	while ((dirent = readdir(d))) {		if (!strcmp(dirent->d_name, ".") ||		    !strcmp(dirent->d_name, "..") ||		    !strcmp(dirent->d_name, "control"))			continue;		dm_task_set_name(dmt, dirent->d_name);		dm_task_run(dmt);	}	if (closedir(d))		log_sys_error("closedir", dir);	return r;}static int _process_all_v4(struct dm_task *dmt){	struct dm_task *task;	struct dm_names *names;	unsigned next = 0;	int r = 1;	if (!(task = dm_task_create(DM_DEVICE_LIST)))		return 0;	if (!dm_task_run(task)) {		r = 0;		goto out;	}	if (!(names = dm_task_get_names(task))) {		r = 0;		goto out;	}	if (!names->dev)		goto out;	do {		names = (void *) names + next;		if (!dm_task_set_name(dmt, names->name)) {			r = 0;			goto out;		}		if (!dm_task_run(dmt))			r = 0;		next = names->next;	} while (next);      out:	dm_task_destroy(task);	return r;}static int _mknodes_v4(struct dm_task *dmt){	(void) _process_mapper_dir(dmt);	return _process_all_v4(dmt);}static int _create_and_load_v4(struct dm_task *dmt){	struct dm_task *task;	int r;	/* Use new task struct to create the device */	if (!(task = dm_task_create(DM_DEVICE_CREATE))) {		log_error("Failed to create device-mapper task struct");		return 0;	}	/* Copy across relevant fields */	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {		dm_task_destroy(task);		return 0;	}	if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {		dm_task_destroy(task);		return 0;	}	task->major = dmt->major;	task->minor = dmt->minor;	task->uid = dmt->uid;	task->gid = dmt->gid;	task->mode = dmt->mode;	r = dm_task_run(task);	dm_task_destroy(task);	if (!r)		return r;	/* Next load the table */	if (!(task = dm_task_create(DM_DEVICE_RELOAD))) {		log_error("Failed to create device-mapper task struct");		return 0;	}	/* Copy across relevant fields */	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {		dm_task_destroy(task);		return 0;	}	task->read_only = dmt->read_only;	task->head = dmt->head;	task->tail = dmt->tail;	r = dm_task_run(task);	task->head = NULL;	task->tail = NULL;	dm_task_destroy(task);	if (!r)		goto revert;	/* Use the original structure last so the info will be correct */	dmt->type = DM_DEVICE_RESUME;	dm_free(dmt->uuid);	dmt->uuid = NULL;	r = dm_task_run(dmt);	if (r)		return r;      revert: 	dmt->type = DM_DEVICE_REMOVE;	dm_free(dmt->uuid);	dmt->uuid = NULL;	if (!dm_task_run(dmt))		log_error("Failed to revert device creation.");	return r;}static int _reload_with_suppression_v4(struct dm_task *dmt){	struct dm_task *task;	struct target *t1, *t2;	int r;	/* New task to get existing table information */	if (!(task = dm_task_create(DM_DEVICE_TABLE))) {		log_error("Failed to create device-mapper task struct");		return 0;	}	/* Copy across relevant fields */	if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {		dm_task_destroy(task);		return 0;	}	if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {		dm_task_destroy(task);		return 0;	}	task->major = dmt->major;	task->minor = dmt->minor;	r = dm_task_run(task);	if (!r) {		dm_task_destroy(task);		return r;	}	if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only)		goto no_match;	t1 = dmt->head;	t2 = task->head;	while (t1 && t2) {		while (t2->params[strlen(t2->params) - 1] == ' ')			t2->params[strlen(t2->params) - 1] = '\0';		if ((t1->start != t2->start) ||		    (t1->length != t2->length) ||		    (strcmp(t1->type, t2->type)) ||		    (strcmp(t1->params, t2->params)))			goto no_match;		t1 = t1->next;		t2 = t2->next;	}		if (!t1 && !t2) {		dmt->dmi.v4 = task->dmi.v4;		task->dmi.v4 = NULL;		dm_task_destroy(task);		return 1;	}no_match:	dm_task_destroy(task);	/* Now do the original reload */	dmt->suppress_identical_reload = 0;	r = dm_task_run(dmt);	return r;}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);	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;	log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"		  "%s%c%c%s %.0" PRIu64 " %s [%u]",		  _cmd_data_v4[dmt->type].name,		  dmi->name, dmi->uuid, dmt->newname ? " " : "",		  dmt->newname ? dmt->newname : "",		  dmt->major > 0 ? "(" : "",		  dmt->major > 0 ? dmt->major : 0,		  dmt->major > 0 ? ":" : "",		  dmt->minor > 0 ? dmt->minor : 0,		  dmt->major > 0 && dmt->minor == 0 ? "0" : "",		  dmt->major > 0 ? ") " : "",		  dmt->no_open_count ? 'N' : 'O',		  dmt->no_flush ? 'N' : 'F',		  dmt->skip_lockfs ? "S " : "",		  dmt->sector, dmt->message ? dmt->message : "",		  dmi->data_size);#ifdef DM_IOCTLS	if (ioctl(_control_fd, command, dmi) < 0) {		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;}void dm_task_update_nodes(void){	update_devs();}int dm_task_run(struct dm_task *dmt){	struct dm_ioctl *dmi;	unsigned command;#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_run_v1(dmt);#endif	if ((unsigned) dmt->type >=	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {		log_error("Internal error: unknown device-mapper task %d",			  dmt->type);		return 0;	}	command = _cmd_data_v4[dmt->type].cmd;	/* Old-style creation had a table supplied */	if (dmt->type == DM_DEVICE_CREATE && dmt->head)		return _create_and_load_v4(dmt);	if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&	    !dmt->uuid && dmt->major <= 0)		return _mknodes_v4(dmt);	if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)		return _reload_with_suppression_v4(dmt);	if (!_open_control())		return 0;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");		}	}	switch (dmt->type) {	case DM_DEVICE_CREATE:		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),			     dmt->uid, dmt->gid, dmt->mode);		break;	case DM_DEVICE_REMOVE:		/* FIXME Kernel needs to fill in dmi->name */		if (dmt->dev_name)			rm_dev_node(dmt->dev_name);		break;	case DM_DEVICE_RENAME:		/* FIXME Kernel needs to fill in dmi->name */		if (dmt->dev_name)			rename_dev_node(dmt->dev_name, dmt->newname);		break;	case DM_DEVICE_MKNODES:		if (dmi->flags & DM_EXISTS_FLAG)			add_dev_node(dmi->name, MAJOR(dmi->dev),				     MINOR(dmi->dev),				     dmt->uid, dmt->gid, dmt->mode);		else if (dmt->dev_name)			rm_dev_node(dmt->dev_name);		break;	case DM_DEVICE_STATUS:	case DM_DEVICE_TABLE:	case DM_DEVICE_WAITEVENT:		if (!_unmarshal_status(dmt, dmi))			goto bad;		break;	}	/* Was structure reused? */	if (dmt->dmi.v4)		dm_free(dmt->dmi.v4);	dmt->dmi.v4 = dmi;	return 1;      bad:	dm_free(dmi);	return 0;}void dm_lib_release(void){	if (_control_fd != -1) {		close(_control_fd);		_control_fd = -1;	}	update_devs();}void dm_lib_exit(void){	dm_lib_release();	if (_dm_bitset)		dm_bitset_destroy(_dm_bitset);	_dm_bitset = NULL;	dm_dump_memory();	_version_ok = 1;	_version_checked = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -