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

📄 libdm-deptree.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
			    size_t paramsize, int *pos){	struct seg_area *area;	char devbuf[10];	int tw;	const char *prefix = "";	list_iterate_items(area, &seg->areas) {		if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))			return_0;		if ((tw = _dm_snprintf(params + *pos, paramsize - *pos, "%s%s %" PRIu64,					prefix, devbuf, area->offset)) < 0) {                        stack;	/* Out of space */                        return -1;                }		prefix = " ";		*pos += tw;	}	return 1;}static int _emit_segment_line(struct dm_task *dmt, struct load_segment *seg, uint64_t *seg_start, char *params, size_t paramsize){	unsigned log_parm_count;        int pos = 0;	int tw;        int r;	char originbuf[10], cowbuf[10], logbuf[10];	const char *logtype;	switch(seg->type) {	case SEG_ERROR:	case SEG_ZERO:		params[0] = '\0';	case SEG_LINEAR:		break;	case SEG_MIRRORED:		log_parm_count = 1;	/* Region size */		log_parm_count += hweight32(seg->flags);	/* [no]sync, block_on_error etc. */		if (seg->flags & DM_CORELOG)			log_parm_count--;   /* DM_CORELOG does not count in the param list */		if (seg->clustered) {			if (seg->uuid)				log_parm_count++;			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "clustered_")) < 0) {                        	stack;	/* Out of space */                        	return -1;                	}			pos += tw;		}		if (!seg->log)			logtype = "core";		else {			logtype = "disk";			log_parm_count++;			if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))				return_0;		}		if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s %u ", logtype, log_parm_count)) < 0) {                        stack;	/* Out of space */                        return -1;                }		pos += tw;		if (seg->log) {			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s ", logbuf)) < 0) {                        	stack;	/* Out of space */                        	return -1;                	}			pos += tw;		}		if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u ", seg->region_size)) < 0) {                       	stack; /* Out of space */                       	return -1;               	}		pos += tw;		if (seg->clustered && seg->uuid) {			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s ", seg->uuid)) < 0) {				stack;  /* Out of space */				return -1;			}			pos += tw;		}		if ((seg->flags & DM_NOSYNC)) {			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "nosync ")) < 0) {                       		stack; /* Out of space */                       		return -1;               		}			pos += tw;		} else if ((seg->flags & DM_FORCESYNC)) {			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "sync ")) < 0) {                       		stack; /* Out of space */                       		return -1;               		}			pos += tw;		}		if ((seg->flags & DM_BLOCK_ON_ERROR)) {			if ((tw = _dm_snprintf(params + pos, paramsize - pos, "block_on_error ")) < 0) {                       		stack; /* Out of space */                       		return -1;               		}			pos += tw;		}		if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u ", seg->mirror_area_count)) < 0) {                       	stack; /* Out of space */                       	return -1;               	}		pos += tw;		break;	case SEG_SNAPSHOT:		if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))			return_0;		if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))			return_0;		if ((pos = _dm_snprintf(params, paramsize, "%s %s %c %d",                                        originbuf, cowbuf,					seg->persistent ? 'P' : 'N',                                        seg->chunk_size)) < 0) {                        stack;	/* Out of space */                        return -1;                }		break;	case SEG_SNAPSHOT_ORIGIN:		if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))			return_0;		if ((pos = _dm_snprintf(params, paramsize, "%s",                                        originbuf)) < 0) {                        stack;	/* Out of space */                        return -1;                }		break;	case SEG_STRIPED:		if ((pos = _dm_snprintf(params, paramsize, "%u %u ",                                         seg->area_count,                                         seg->stripe_size)) < 0) {                        stack;	/* Out of space */                        return -1;                }		break;	}	switch(seg->type) {	case SEG_ERROR:	case SEG_SNAPSHOT:	case SEG_SNAPSHOT_ORIGIN:	case SEG_ZERO:		break;	case SEG_LINEAR:	case SEG_MIRRORED:	case SEG_STRIPED:		if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {			stack;			return r;		}		break;	}	log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",		  *seg_start, seg->size, dm_segtypes[seg->type].target, params);	if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params))		return_0;	*seg_start += seg->size;	return 1;}static int _emit_segment(struct dm_task *dmt, struct load_segment *seg,			 uint64_t *seg_start){	char *params;	size_t paramsize = 4096;	int ret;	do {		if (!(params = dm_malloc(paramsize))) {			log_error("Insufficient space for target parameters.");			return 0;		}		ret = _emit_segment_line(dmt, seg, seg_start, params, paramsize);		dm_free(params);		if (!ret)			stack;		if (ret >= 0)			return ret;		log_debug("Insufficient space in params[%" PRIsize_t			  "] for target parameters.", paramsize);		paramsize *= 2;	} while (paramsize < MAX_TARGET_PARAMSIZE);	log_error("Target parameter size too big. Aborting.");	return 0;}static int _load_node(struct dm_tree_node *dnode){	int r = 0;	struct dm_task *dmt;	struct load_segment *seg;	uint64_t seg_start = 0;	log_verbose("Loading %s table", dnode->name);	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {		log_error("Reload dm_task creation failed for %s", dnode->name);		return 0;	}	if (!dm_task_set_major(dmt, dnode->info.major) ||	    !dm_task_set_minor(dmt, dnode->info.minor)) {		log_error("Failed to set device number for %s reload.", 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");	list_iterate_items(seg, &dnode->props.segs)		if (!_emit_segment(dmt, seg, &seg_start))			goto_out;	if (!dm_task_suppress_identical_reload(dmt))		log_error("Failed to suppress reload of identical tables.");	if ((r = dm_task_run(dmt))) {		r = dm_task_get_info(dmt, &dnode->info);		if (r && !dnode->info.inactive_table)			log_verbose("Suppressed %s identical table reload.",				    dnode->name);	}	dnode->props.segment_count = 0;out:	dm_task_destroy(dmt);	return r;}int dm_tree_preload_children(struct dm_tree_node *dnode,				 const char *uuid_prefix,				 size_t uuid_prefix_len){	void *handle = NULL;	struct dm_tree_node *child;	struct dm_info newinfo;	const char *name;	/* Preload children first */	while ((child = dm_tree_next_child(&handle, dnode, 0))) {		/* Skip existing non-device-mapper devices */		if (!child->info.exists && child->info.major)			continue;		/* Ignore if it doesn't belong to this VG */		if (child->info.exists &&		    !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))			continue;		if (dm_tree_node_num_children(child, 0))			dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len);		if (!(name = dm_tree_node_get_name(child))) {			stack;			continue;		}		/* FIXME Cope if name exists with no uuid? */		if (!child->info.exists) {			if (!_create_node(child)) {				stack;				return 0;			}		}		if (!child->info.inactive_table && child->props.segment_count) {			if (!_load_node(child)) {				stack;				return 0;			}		}		/* Resume device immediately if it has parents */		if (!dm_tree_node_num_children(child, 1))			continue;		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;}/* * Returns 1 if unsure. */int dm_tree_children_use_uuid(struct dm_tree_node *dnode,				 const char *uuid_prefix,				 size_t uuid_prefix_len){	void *handle = NULL;	struct dm_tree_node *child = dnode;	const char *uuid;	while ((child = dm_tree_next_child(&handle, dnode, 0))) {		if (!(uuid = dm_tree_node_get_uuid(child))) {			log_error("Failed to get uuid for dtree node.");			return 1;		}		if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))			return 1;		if (dm_tree_node_num_children(child, 0))			dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);	}	return 0;}/* * Target functions */static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size){	struct load_segment *seg;	if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {		log_error("dtree node segment allocation failed");		return NULL;	}	seg->type = type;	seg->size = size;	seg->area_count = 0;	list_init(&seg->areas);	seg->stripe_size = 0;	seg->persistent = 0;	seg->chunk_size = 0;	seg->cow = NULL;	seg->origin = NULL;	list_add(&dnode->props.segs, &seg->list);	dnode->props.segment_count++;	return seg;}int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,                                               uint64_t size,                                               const char *origin_uuid){	struct load_segment *seg;	struct dm_tree_node *origin_node;	if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))		return_0;	if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {		log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);		return 0;	}	seg->origin = origin_node;	if (!_link_tree_nodes(dnode, origin_node))		return_0;	/* Resume snapshot origins after new snapshots */	dnode->activation_priority = 1;	return 1;}int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,                                        uint64_t size,                                        const char *origin_uuid,                                        const char *cow_uuid,                                        int persistent,                                        uint32_t chunk_size){	struct load_segment *seg;	struct dm_tree_node *origin_node, *cow_node;	if (!(seg = _add_segment(node, SEG_SNAPSHOT, size)))		return_0;	if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {		log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);		return 0;	}	seg->origin = origin_node;	if (!_link_tree_nodes(node, origin_node))		return_0;	if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {		log_error("Couldn't find snapshot origin uuid %s.", cow_uuid);		return 0;	}	seg->cow = cow_node;	if (!_link_tree_nodes(node, cow_node))		return_0;	seg->persistent = persistent ? 1 : 0;	seg->chunk_size = chunk_size;	return 1;}int dm_tree_node_add_error_target(struct dm_tree_node *node,                                     uint64_t size){	if (!_add_segment(node, SEG_ERROR, size))		return_0;	return 1;}int dm_tree_node_add_zero_target(struct dm_tree_node *node,                                    uint64_t size){	if (!_add_segment(node, SEG_ZERO, size))		return_0;	return 1;}int dm_tree_node_add_linear_target(struct dm_tree_node *node,                                      uint64_t size){	if (!_add_segment(node, SEG_LINEAR, size))		return_0;	return 1;}int dm_tree_node_add_striped_target(struct dm_tree_node *node,                                       uint64_t size,                                       uint32_t stripe_size){	struct load_segment *seg;	if (!(seg = _add_segment(node, SEG_STRIPED, size)))		return_0;	seg->stripe_size = stripe_size;	return 1;}int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,					  uint32_t region_size,					  unsigned clustered, 					  const char *log_uuid,					  unsigned area_count,					  uint32_t flags){	struct dm_tree_node *log_node = NULL;	struct load_segment *seg;	if (!node->props.segment_count) {		log_error("Internal error: Attempt to add target area to missing segment.");		return 0;	}	seg = list_item(list_last(&node->props.segs), struct load_segment);	if (log_uuid) {		if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {			log_error("log uuid pool_strdup failed");			return 0;		}		if (!(flags & DM_CORELOG)) {			if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {				log_error("Couldn't find mirror log uuid %s.", log_uuid);				return 0;			}			if (!_link_tree_nodes(node, log_node))				return_0;		}	}	seg->log = log_node;	seg->region_size = region_size;	seg->clustered = clustered;	seg->mirror_area_count = area_count;	seg->flags = flags;	return 1;}int dm_tree_node_add_mirror_target(struct dm_tree_node *node,                                      uint64_t size){	struct load_segment *seg;	if (!(seg = _add_segment(node, SEG_MIRRORED, size)))		return_0;	return 1;}static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset){	struct seg_area *area;	if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {		log_error("Failed to allocate target segment area.");		return 0;	}	area->dev_node = dev_node;	area->offset = offset;	list_add(&seg->areas, &area->list);	seg->area_count++;	return 1;}int dm_tree_node_add_target_area(struct dm_tree_node *node,                                    const char *dev_name,                                    const char *uuid,                                    uint64_t offset){	struct load_segment *seg;	struct stat info;	struct dm_tree_node *dev_node;	if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {		log_error("dm_tree_node_add_target_area called without device");		return 0;	}	if (uuid) {		if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {			log_error("Couldn't find area uuid %s.", uuid);			return 0;		}		if (!_link_tree_nodes(node, dev_node))			return_0;	} else {        	if (stat(dev_name, &info) < 0) {			log_error("Device %s not found.", dev_name);			return 0;		}        	if (!S_ISBLK(info.st_mode)) {			log_error("Device %s is not a block device.", dev_name);			return 0;		}		/* FIXME Check correct macro use */		if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev), MINOR(info.st_rdev))))			return_0;	}	if (!node->props.segment_count) {		log_error("Internal error: Attempt to add target area to missing segment.");		return 0;	}	seg = list_item(list_last(&node->props.segs), struct load_segment);	if (!_add_area(node, seg, dev_node, offset))		return_0;	return 1;}

⌨️ 快捷键说明

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