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

📄 libdm-deptree.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	dnode->props.read_only = read_only ? 1 : 0;	if (clear_inactive && !_node_clear_table(dnode))		return_NULL;	dnode->context = context;	return dnode;}int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor){	return _add_dev(dtree, &dtree->root, major, minor) ? 1 : 0;}const char *dm_tree_node_get_name(struct dm_tree_node *node){	return node->info.exists ? node->name : "";}const char *dm_tree_node_get_uuid(struct dm_tree_node *node){	return node->info.exists ? node->uuid : "";}const struct dm_info *dm_tree_node_get_info(struct dm_tree_node *node){	return &node->info;}void *dm_tree_node_get_context(struct dm_tree_node *node){	return node->context;}int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted){	if (inverted) {		if (_nodes_are_linked(&node->dtree->root, node))			return 0;		return list_size(&node->used_by);	}	if (_nodes_are_linked(node, &node->dtree->root))		return 0;	return list_size(&node->uses);}/* * Returns 1 if no prefix supplied */static int _uuid_prefix_matches(const char *uuid, const char *uuid_prefix, size_t uuid_prefix_len){	if (!uuid_prefix)		return 1;	if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))		return 1;	/* Handle transition: active device uuids might be missing the prefix */	if (uuid_prefix_len <= 4)		return 0;	if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))		return 0;	if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))		return 0;	if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))		return 1;	return 0;}/* * Returns 1 if no children. */static int _children_suspended(struct dm_tree_node *node,			       uint32_t inverted,			       const char *uuid_prefix,			       size_t uuid_prefix_len){	struct list *list;	struct dm_tree_link *dlink;	const struct dm_info *dinfo;	const char *uuid;	if (inverted) {		if (_nodes_are_linked(&node->dtree->root, node))			return 1;		list = &node->used_by;	} else {		if (_nodes_are_linked(node, &node->dtree->root))			return 1;		list = &node->uses;	}	list_iterate_items(dlink, list) {		if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {			stack;			continue;		}		/* Ignore if it doesn't belong to this VG */		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))			continue;		if (!(dinfo = dm_tree_node_get_info(dlink->node))) {			stack;	/* FIXME Is this normal? */			return 0;		}		if (!dinfo->suspended)			return 0;	}	return 1;}/* * Set major and minor to zero for root of tree. */struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,					  uint32_t major,					  uint32_t minor){	if (!major && !minor)		return &dtree->root;	return _find_dm_tree_node(dtree, major, minor);}/* * Set uuid to NULL for root of tree. */struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,						  const char *uuid){	if (!uuid || !*uuid)		return &dtree->root;	return _find_dm_tree_node_by_uuid(dtree, uuid);}/* * First time set *handle to NULL. * Set inverted to invert the tree. */struct dm_tree_node *dm_tree_next_child(void **handle,					   struct dm_tree_node *parent,					   uint32_t inverted){	struct list **dlink = (struct list **) handle;	struct list *use_list;	if (inverted)		use_list = &parent->used_by;	else		use_list = &parent->uses;	if (!*dlink)		*dlink = list_first(use_list);	else		*dlink = list_next(use_list, *dlink);	return (*dlink) ? list_item(*dlink, struct dm_tree_link)->node : NULL;}/* * Deactivate a device with its dependencies if the uuid prefix matches. */static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,			struct dm_info *info){	struct dm_task *dmt;	int r;	if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {		log_error("_info_by_dev: dm_task creation failed");		return 0;	}	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {		log_error("_info_by_dev: Failed to set device number");		dm_task_destroy(dmt);		return 0;	}	if (!with_open_count && !dm_task_no_open_count(dmt))		log_error("Failed to disable open_count");	if ((r = dm_task_run(dmt)))		r = dm_task_get_info(dmt, info);	dm_task_destroy(dmt);	return r;}static int _deactivate_node(const char *name, uint32_t major, uint32_t minor){	struct dm_task *dmt;	int r;	log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);	if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) {		log_error("Deactivation dm_task creation failed for %s", name);		return 0;	}	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {		log_error("Failed to set device number for %s deactivation", name);		dm_task_destroy(dmt);		return 0;	}	if (!dm_task_no_open_count(dmt))		log_error("Failed to disable open_count");	r = dm_task_run(dmt);	/* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */	rm_dev_node(name);	/* FIXME Remove node from tree or mark invalid? */	dm_task_destroy(dmt);	return r;}static int _rename_node(const char *old_name, const char *new_name, uint32_t major, uint32_t minor){	struct dm_task *dmt;	int r = 0;	log_verbose("Renaming %s (%" PRIu32 ":%" PRIu32 ") to %s", old_name, major, minor, new_name);	if (!(dmt = dm_task_create(DM_DEVICE_RENAME))) {		log_error("Rename dm_task creation failed for %s", old_name);		return 0;	}	if (!dm_task_set_name(dmt, old_name)) {		log_error("Failed to set name for %s rename.", old_name);		goto out;	}	if (!dm_task_set_newname(dmt, new_name))                goto_out;	if (!dm_task_no_open_count(dmt))		log_error("Failed to disable open_count");	r = dm_task_run(dmt);out:	dm_task_destroy(dmt);	return r;}/* FIXME Merge with _suspend_node? */static int _resume_node(const char *name, uint32_t major, uint32_t minor,			struct dm_info *newinfo){	struct dm_task *dmt;	int r;	log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);	if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) {		log_error("Suspend dm_task creation failed for %s", name);		return 0;	}	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {		log_error("Failed to set device number for %s resumption.", name);		dm_task_destroy(dmt);		return 0;	}	if (!dm_task_no_open_count(dmt))		log_error("Failed to disable open_count");	if ((r = dm_task_run(dmt)))		r = dm_task_get_info(dmt, newinfo);	dm_task_destroy(dmt);	return r;}static int _suspend_node(const char *name, uint32_t major, uint32_t minor,			 int skip_lockfs, int no_flush, struct dm_info *newinfo){	struct dm_task *dmt;	int r;	log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",		    name, major, minor,		    skip_lockfs ? "" : " with filesystem sync",		    no_flush ? "" : " without device flush");	if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {		log_error("Suspend dm_task creation failed for %s", name);		return 0;	}	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {		log_error("Failed to set device number for %s suspension.", name);		dm_task_destroy(dmt);		return 0;	}	if (!dm_task_no_open_count(dmt))		log_error("Failed to disable open_count");	if (skip_lockfs && !dm_task_skip_lockfs(dmt))		log_error("Failed to set skip_lockfs flag.");	if (no_flush && !dm_task_no_flush(dmt))		log_error("Failed to set no_flush flag.");	if ((r = dm_task_run(dmt)))		r = dm_task_get_info(dmt, newinfo);	dm_task_destroy(dmt);	return r;}int dm_tree_deactivate_children(struct dm_tree_node *dnode,				   const char *uuid_prefix,				   size_t uuid_prefix_len){	void *handle = NULL;	struct dm_tree_node *child = dnode;	struct dm_info info;	const struct dm_info *dinfo;	const char *name;	const char *uuid;	while ((child = dm_tree_next_child(&handle, dnode, 0))) {		if (!(dinfo = dm_tree_node_get_info(child))) {			stack;			continue;		}		if (!(name = dm_tree_node_get_name(child))) {			stack;			continue;		}		if (!(uuid = dm_tree_node_get_uuid(child))) {			stack;			continue;		}		/* Ignore if it doesn't belong to this VG */		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))			continue;		/* Refresh open_count */		if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||		    !info.exists || info.open_count)			continue;		if (!_deactivate_node(name, info.major, info.minor)) {			log_error("Unable to deactivate %s (%" PRIu32				  ":%" PRIu32 ")", name, info.major,				  info.minor);			continue;		}		if (dm_tree_node_num_children(child, 0))			dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len);	}	return 1;}void dm_tree_skip_lockfs(struct dm_tree_node *dnode){	dnode->dtree->skip_lockfs = 1;}void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode){	dnode->dtree->no_flush = 1;}int dm_tree_suspend_children(struct dm_tree_node *dnode,				   const char *uuid_prefix,				   size_t uuid_prefix_len){	void *handle = NULL;	struct dm_tree_node *child = dnode;	struct dm_info info, newinfo;	const struct dm_info *dinfo;	const char *name;	const char *uuid;	/* Suspend nodes at this level of the tree */	while ((child = dm_tree_next_child(&handle, dnode, 0))) {		if (!(dinfo = dm_tree_node_get_info(child))) {			stack;			continue;		}		if (!(name = dm_tree_node_get_name(child))) {			stack;			continue;		}		if (!(uuid = dm_tree_node_get_uuid(child))) {			stack;			continue;		}		/* Ignore if it doesn't belong to this VG */		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))			continue;		/* Ensure immediate parents are already suspended */		if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))			continue;		if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||		    !info.exists || info.suspended)			continue;		if (!_suspend_node(name, info.major, info.minor,				   child->dtree->skip_lockfs,				   child->dtree->no_flush, &newinfo)) {			log_error("Unable to suspend %s (%" PRIu32				  ":%" PRIu32 ")", name, info.major,				  info.minor);			continue;		}		/* Update cached info */		child->info = newinfo;	}	/* Then suspend any child nodes */	handle = NULL;	while ((child = dm_tree_next_child(&handle, dnode, 0))) {		if (!(uuid = dm_tree_node_get_uuid(child))) {			stack;			continue;		}		/* Ignore if it doesn't belong to this VG */		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))			continue;		if (dm_tree_node_num_children(child, 0))			dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len);	}	return 1;}int dm_tree_activate_children(struct dm_tree_node *dnode,				 const char *uuid_prefix,				 size_t uuid_prefix_len){	void *handle = NULL;	struct dm_tree_node *child = dnode;	struct dm_info newinfo;	const char *name;	const char *uuid;	int priority;	/* Activate children first */	while ((child = dm_tree_next_child(&handle, dnode, 0))) {		if (!(uuid = dm_tree_node_get_uuid(child))) {			stack;			continue;		}		if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))			continue;		if (dm_tree_node_num_children(child, 0))			dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len);	}	handle = NULL;	for (priority = 0; priority < 2; priority++) {		while ((child = dm_tree_next_child(&handle, dnode, 0))) {			if (!(uuid = dm_tree_node_get_uuid(child))) {				stack;				continue;			}			if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))				continue;			if (priority != child->activation_priority)				continue;			if (!(name = dm_tree_node_get_name(child))) {				stack;				continue;			}			/* Rename? */			if (child->props.new_name) {				if (!_rename_node(name, child->props.new_name, child->info.major, child->info.minor)) {					log_error("Failed to rename %s (%" PRIu32						  ":%" PRIu32 ") to %s", name, child->info.major,						  child->info.minor, child->props.new_name);					return 0;				}				child->name = child->props.new_name;				child->props.new_name = NULL;			}			if (!child->info.inactive_table && !child->info.suspended)				continue;			if (!_resume_node(name, child->info.major, child->info.minor, &newinfo)) {				log_error("Unable to resume %s (%" PRIu32					  ":%" PRIu32 ")", name, child->info.major,					  child->info.minor);				continue;			}			/* Update cached info */			child->info = newinfo;		}	}	handle = NULL;	return 1;}static int _create_node(struct dm_tree_node *dnode){	int r = 0;	struct dm_task *dmt;	log_verbose("Creating %s", dnode->name);	if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) {		log_error("Create dm_task creation failed for %s", dnode->name);		return 0;	}	if (!dm_task_set_name(dmt, dnode->name)) {		log_error("Failed to set device name for %s", dnode->name);		goto out;	}	if (!dm_task_set_uuid(dmt, dnode->uuid)) {		log_error("Failed to set uuid for %s", dnode->name);		goto out;	}	if (dnode->props.major &&	    (!dm_task_set_major(dmt, dnode->props.major) ||	     !dm_task_set_minor(dmt, dnode->props.minor))) {		log_error("Failed to set device number for %s creation.", dnode->name);		goto out;	}	if (dnode->props.read_only && !dm_task_set_ro(dmt)) {		log_error("Failed to set read only flag for %s", dnode->name);		goto out;	}	if (!dm_task_no_open_count(dmt))		log_error("Failed to disable open_count");	if ((r = dm_task_run(dmt)))		r = dm_task_get_info(dmt, &dnode->info);out:	dm_task_destroy(dmt);	return r;}static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node){	if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {                log_error("Failed to format %s device number for %s as dm "                          "target (%u,%u)",                          node->name, node->uuid, node->info.major, node->info.minor);                return 0;	}	return 1;}static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),			    struct load_segment *seg, char *params,

⌨️ 快捷键说明

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