📄 libdm-deptree.c
字号:
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 + -