static int _config_def_check_node(struct cft_check_handle *handle, const char *vp, char *pvp, char *rp, char *prp, size_t buf_size, struct dm_config_node *cn, struct dm_hash_table *ht) { cfg_def_item_t *def; int sep = vp != pvp; /* don't use '/' separator for top-level node */ if (dm_snprintf(pvp, buf_size, "%s%s", sep ? "/" : "", cn->key) < 0 || dm_snprintf(prp, buf_size, "%s%s", sep ? "/" : "", cn->key) < 0) { log_error("Failed to construct path for configuration node %s.", cn->key); return 0; } if (!(def = (cfg_def_item_t *) dm_hash_lookup(ht, vp))) { /* If the node is not a section but a setting, fail now. */ if (cn->v) { log_warn_suppress(handle->suppress_messages, "Configuration setting \"%s\" unknown.", rp); cn->id = -1; return 0; } /* If the node is a section, try if the section name is variable. */ /* Modify virtual path vp in situ and replace the key name with a '#'. */ /* The real path without '#' is still stored in rp variable. */ pvp[sep] = '#', pvp[sep + 1] = '\0'; if (!(def = (cfg_def_item_t *) dm_hash_lookup(ht, vp))) { log_warn_suppress(handle->suppress_messages, "Configuration section \"%s\" unknown.", rp); cn->id = -1; return 0; } } handle->status[def->id] |= CFG_USED; cn->id = def->id; if (!_config_def_check_node_value(handle, rp, cn->v, def)) return 0; /* * Also check whether this configuration item is allowed * in certain types of configuration trees as in some * the use of configuration is restricted, e.g. profiles... */ if (handle->source == CONFIG_PROFILE && !(def->flags & CFG_PROFILABLE)) { log_warn_suppress(handle->suppress_messages, "Configuration %s \"%s\" is not customizable by " "a profile.", cn->v ? "option" : "section", rp); return 0; } handle->status[def->id] |= CFG_VALID; return 1; }
static int _config_def_check_node_single_value(const char *rp, const struct dm_config_value *v, const cfg_def_item_t *def, int suppress_messages) { /* Check empty array first if present. */ if (v->type == DM_CFG_EMPTY_ARRAY) { if (!(def->type & CFG_TYPE_ARRAY)) { _log_type_error(rp, CFG_TYPE_ARRAY, def->type, suppress_messages); return 0; } if (!(def->flags & CFG_ALLOW_EMPTY)) { log_warn_suppress(suppress_messages, "Configuration setting \"%s\" invalid. Empty value not allowed.", rp); return 0; } return 1; } switch (v->type) { case DM_CFG_INT: if (!(def->type & CFG_TYPE_INT) && !(def->type & CFG_TYPE_BOOL)) { _log_type_error(rp, CFG_TYPE_INT, def->type, suppress_messages); return 0; } break; case DM_CFG_FLOAT: if (!(def->type & CFG_TYPE_FLOAT)) { _log_type_error(rp, CFG_TYPE_FLOAT, def->type, suppress_messages); return 0; } break; case DM_CFG_STRING: if (def->type & CFG_TYPE_BOOL) { if (!dm_config_value_is_bool(v)) { log_warn_suppress(suppress_messages, "Configuration setting \"%s\" invalid. " "Found string value \"%s\", " "expected boolean value: 0/1, \"y/n\", " "\"yes/no\", \"on/off\", " "\"true/false\".", rp, v->v.str); return 0; } } else if (!(def->type & CFG_TYPE_STRING)) { _log_type_error(rp, CFG_TYPE_STRING, def->type, suppress_messages); return 0; } break; default: ; } return 1; }
static void _log_type_error(const char *path, cfg_def_type_t actual, cfg_def_type_t expected, int suppress_messages) { static char actual_type_name[128]; static char expected_type_name[128]; _get_type_name(actual_type_name, sizeof(actual_type_name), actual); _get_type_name(expected_type_name, sizeof(expected_type_name), expected); log_warn_suppress(suppress_messages, "Configuration setting \"%s\" has invalid type. " "Found%s, expected%s.", path, actual_type_name, expected_type_name); }
int init_external_locking(struct locking_type *locking, struct cmd_context *cmd, int suppress_messages) { const char *libname; if (_locking_lib) { log_error_suppress(suppress_messages, "External locking already initialised"); return 1; } locking->lock_resource = _lock_resource; locking->fin_locking = _fin_external_locking; locking->reset_locking = _reset_external_locking; locking->flags = 0; libname = find_config_tree_str(cmd, "global/locking_library", DEFAULT_LOCKING_LIB); if (!(_locking_lib = load_shared_library(cmd, libname, "locking", 1))) return_0; /* Get the functions we need */ if (!(_init_fn = dlsym(_locking_lib, "locking_init")) || !(_lock_fn = dlsym(_locking_lib, "lock_resource")) || !(_reset_fn = dlsym(_locking_lib, "reset_locking")) || !(_end_fn = dlsym(_locking_lib, "locking_end"))) { log_error_suppress(suppress_messages, "Shared library %s does " "not contain locking functions", libname); dlclose(_locking_lib); _locking_lib = NULL; return 0; } if (!(_lock_query_fn = dlsym(_locking_lib, "query_resource"))) log_warn_suppress(suppress_messages, "WARNING: %s: _query_resource() " "missing: Using inferior activation method.", libname); log_verbose("Loaded external locking library %s", libname); return _init_fn(2, cmd->cft, &locking->flags); }
/* * Select a locking type * type: locking type; if < 0, then read config tree value */ int init_locking(int type, struct cmd_context *cmd, int suppress_messages) { if (getenv("LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES")) suppress_messages = 1; if (type < 0) type = find_config_tree_int(cmd, global_locking_type_CFG, NULL); _blocking_supported = find_config_tree_bool(cmd, global_wait_for_locks_CFG, NULL); switch (type) { case 0: init_no_locking(&_locking, cmd, suppress_messages); log_warn("WARNING: Locking disabled. Be careful! " "This could corrupt your metadata."); return 1; case 1: log_very_verbose("%sFile-based locking selected.", _blocking_supported ? "" : "Non-blocking "); if (!init_file_locking(&_locking, cmd, suppress_messages)) { log_error_suppress(suppress_messages, "File-based locking initialisation failed."); break; } return 1; #ifdef HAVE_LIBDL case 2: if (!is_static()) { log_very_verbose("External locking selected."); if (init_external_locking(&_locking, cmd, suppress_messages)) return 1; } if (!find_config_tree_bool(cmd, global_fallback_to_clustered_locking_CFG, NULL)) { log_error_suppress(suppress_messages, "External locking initialisation failed."); break; } #endif #ifdef CLUSTER_LOCKING_INTERNAL log_very_verbose("Falling back to internal clustered locking."); /* Fall through */ case 3: log_very_verbose("Cluster locking selected."); if (!init_cluster_locking(&_locking, cmd, suppress_messages)) { log_error_suppress(suppress_messages, "Internal cluster locking initialisation failed."); break; } return 1; #endif case 4: log_verbose("Read-only locking selected. " "Only read operations permitted."); if (!init_readonly_locking(&_locking, cmd, suppress_messages)) break; return 1; default: log_error("Unknown locking type requested."); return 0; } if ((type == 2 || type == 3) && find_config_tree_bool(cmd, global_fallback_to_local_locking_CFG, NULL)) { log_warn_suppress(suppress_messages, "WARNING: Falling back to local file-based locking."); log_warn_suppress(suppress_messages, "Volume Groups with the clustered attribute will " "be inaccessible."); if (init_file_locking(&_locking, cmd, suppress_messages)) return 1; else log_error_suppress(suppress_messages, "File-based locking initialisation failed."); } if (!ignorelockingfailure()) return 0; log_verbose("Locking disabled - only read operations permitted."); init_readonly_locking(&_locking, cmd, suppress_messages); return 1; }