static int _memlock_maps(struct cmd_context *cmd, lvmlock_t lock, size_t *mstats) { const struct dm_config_node *cn; char *line, *line_end; size_t len; ssize_t n; int ret = 1; if (_use_mlockall) { #ifdef MCL_CURRENT if (lock == LVM_MLOCK) { if (mlockall(MCL_CURRENT | MCL_FUTURE)) { log_sys_error("mlockall", ""); return 0; } } else { if (munlockall()) { log_sys_error("munlockall", ""); return 0; } } return 1; #else return 0; #endif } /* Reset statistic counters */ *mstats = 0; /* read mapping into a single memory chunk without reallocation * in the middle of reading maps file */ for (len = 0;;) { if (!_maps_buffer || len >= _maps_len) { if (_maps_buffer) _maps_len *= 2; if (!(line = dm_realloc(_maps_buffer, _maps_len))) { log_error("Allocation of maps buffer failed."); return 0; } _maps_buffer = line; } if (lseek(_maps_fd, 0, SEEK_SET)) log_sys_error("lseek", _procselfmaps); for (len = 0 ; len < _maps_len; len += n) { if (!(n = read(_maps_fd, _maps_buffer + len, _maps_len - len))) break; /* EOF */ if (n == -1) { log_sys_error("read", _procselfmaps); return 0; } } if (len < _maps_len) { /* fits in buffer */ _maps_buffer[len] = '\0'; break; } } line = _maps_buffer; cn = find_config_tree_array(cmd, activation_mlock_filter_CFG, NULL); while ((line_end = strchr(line, '\n'))) { *line_end = '\0'; /* remove \n */ if (!_maps_line(cn, lock, line, mstats)) ret = 0; line = line_end + 1; } log_debug_mem("%socked %ld bytes", (lock == LVM_MLOCK) ? "L" : "Unl", (long)*mstats); return ret; }
/* * Formats data LV for a use as a VDO pool LV. * * Calls tool 'vdoformat' on the already active volume. */ static int _format_vdo_pool_data_lv(struct logical_volume *data_lv, const struct dm_vdo_target_params *vtp, uint64_t *logical_size) { char *dpath; const struct dm_config_node *cn; const struct dm_config_value *cv; struct pipe_data pdata; FILE *f; uint64_t lb; unsigned slabbits; int args = 1; char buf_args[5][128]; char buf[256]; /* buffer for short disk header (64B) */ const char *argv[19] = { /* Max supported args */ find_config_tree_str_allow_empty(data_lv->vg->cmd, global_vdo_format_executable_CFG, NULL) }; if (!(dpath = lv_path_dup(data_lv->vg->cmd->mem, data_lv))) { log_error("Failed to build device path for VDO formating of data volume %s.", display_lvname(data_lv)); return 0; } if (*logical_size) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--logical-size=" FMTu64 "K", (*logical_size / 2)) < 0) return_0; argv[args] = buf_args[args]; args++; } slabbits = 31 - clz(vtp->slab_size_mb / DM_VDO_BLOCK_SIZE * 512); log_debug("Slab size %s converted to %u bits.", display_size(data_lv->vg->cmd, vtp->slab_size_mb * UINT64_C(2 * 1024)), slabbits); if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--slab-bits=%u", slabbits) < 0) return_0; argv[args] = buf_args[args]; args++; if (vtp->check_point_frequency) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-checkpoint-frequency=%u", vtp->check_point_frequency) < 0) return_0; argv[args] = buf_args[args]; args++; } /* Convert size to GiB units or one of these strings: 0.25, 0.50, 0.75 */ if (vtp->index_memory_size_mb >= 1024) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-memory-size=%u", vtp->index_memory_size_mb / 1024) < 0) return_0; } else if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-memory-size=0.%u", (vtp->index_memory_size_mb < 512) ? 25 : (vtp->index_memory_size_mb < 768) ? 50 : 75) < 0) return_0; argv[args] = buf_args[args]; args++; if (vtp->use_sparse_index) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-sparse") < 0) return_0; argv[args] = buf_args[args]; args++; } /* Any other user opts add here */ if (!(cn = find_config_tree_array(data_lv->vg->cmd, global_vdo_format_options_CFG, NULL))) { log_error(INTERNAL_ERROR "Unable to find configuration for vdoformat command options."); return 0; } for (cv = cn->v; cv && args < 16; cv = cv->next) { if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "global/vdoformat_options."); return 0; } if (cv->v.str[0]) argv[++args] = cv->v.str; } /* Only unused VDO data LV could be activated and wiped */ if (!dm_list_empty(&data_lv->segs_using_this_lv)) { log_error(INTERNAL_ERROR "Failed to wipe logical VDO data for volume %s.", display_lvname(data_lv)); return 0; } argv[args] = dpath; if (!(f = pipe_open(data_lv->vg->cmd, argv, 0, &pdata))) { log_error("WARNING: Cannot read output from %s.", argv[0]); return 0; } if (!*logical_size) while (fgets(buf, sizeof(buf), f)) { /* TODO: Watch out for locales */ if (sscanf(buf, "Logical blocks defaulted to " FMTu64 " blocks", &lb) == 1) { *logical_size = lb * DM_VDO_BLOCK_SIZE; log_verbose("Available VDO logical blocks " FMTu64 " (%s).", lb, display_size(data_lv->vg->cmd, *logical_size)); break; } else log_warn("WARNING: Cannot parse output '%s' from %s.", buf, argv[0]); } if (!pipe_close(&pdata)) { log_error("Command %s failed.", argv[0]); return 0; } return 1; }