1 /* $NetBSD: toolcontext.c,v 1.3 2009/01/06 23:21:16 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 6 * 7 * This file is part of LVM2. 8 * 9 * This copyrighted material is made available to anyone wishing to use, 10 * modify, copy, or redistribute it subject to the terms and conditions 11 * of the GNU Lesser General Public License v.2.1. 12 * 13 * You should have received a copy of the GNU Lesser General Public License 14 * along with this program; if not, write to the Free Software Foundation, 15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 */ 17 18 #include "lib.h" 19 #include "toolcontext.h" 20 #include "metadata.h" 21 #include "defaults.h" 22 #include "lvm-string.h" 23 #include "activate.h" 24 #include "filter.h" 25 #include "filter-composite.h" 26 #include "filter-md.h" 27 #include "filter-persistent.h" 28 #include "filter-regex.h" 29 #include "filter-sysfs.h" 30 #include "label.h" 31 #include "lvm-file.h" 32 #include "format-text.h" 33 #include "display.h" 34 #include "memlock.h" 35 #include "str_list.h" 36 #include "segtype.h" 37 #include "lvmcache.h" 38 #include "dev-cache.h" 39 #include "archiver.h" 40 41 #ifdef HAVE_LIBDL 42 #include "sharedlib.h" 43 #endif 44 45 #ifdef LVM1_INTERNAL 46 #include "format1.h" 47 #endif 48 49 #ifdef POOL_INTERNAL 50 #include "format_pool.h" 51 #endif 52 53 #include <locale.h> 54 #include <sys/stat.h> 55 #include <sys/utsname.h> 56 #include <syslog.h> 57 #include <time.h> 58 59 #ifdef linux 60 # include <malloc.h> 61 #endif 62 63 static int _get_env_vars(struct cmd_context *cmd) 64 { 65 const char *e; 66 67 /* Set to "" to avoid using any system directory */ 68 if ((e = getenv("LVM_SYSTEM_DIR"))) { 69 if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir), 70 "%s", e) < 0) { 71 log_error("LVM_SYSTEM_DIR environment variable " 72 "is too long."); 73 return 0; 74 } 75 } 76 77 return 1; 78 } 79 80 static void _get_sysfs_dir(struct cmd_context *cmd) 81 { 82 static char proc_mounts[PATH_MAX]; 83 static char *split[4], buffer[PATH_MAX + 16]; 84 FILE *fp; 85 char *sys_mnt = NULL; 86 87 cmd->sysfs_dir[0] = '\0'; 88 if (!*cmd->proc_dir) { 89 log_debug("No proc filesystem found: skipping sysfs detection"); 90 return; 91 } 92 93 if (dm_snprintf(proc_mounts, sizeof(proc_mounts), 94 "%s/mounts", cmd->proc_dir) < 0) { 95 log_error("Failed to create /proc/mounts string for sysfs detection"); 96 return; 97 } 98 99 if (!(fp = fopen(proc_mounts, "r"))) { 100 log_sys_error("_get_sysfs_dir: fopen %s", proc_mounts); 101 return; 102 } 103 104 while (fgets(buffer, sizeof(buffer), fp)) { 105 if (dm_split_words(buffer, 4, 0, split) == 4 && 106 !strcmp(split[2], "sysfs")) { 107 sys_mnt = split[1]; 108 break; 109 } 110 } 111 112 if (fclose(fp)) 113 log_sys_error("fclose", proc_mounts); 114 115 if (!sys_mnt) { 116 log_error("Failed to find sysfs mount point"); 117 return; 118 } 119 120 strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir)); 121 } 122 123 static void _init_logging(struct cmd_context *cmd) 124 { 125 int append = 1; 126 time_t t; 127 128 const char *log_file; 129 char timebuf[26]; 130 131 /* Syslog */ 132 cmd->default_settings.syslog = 133 find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG); 134 if (cmd->default_settings.syslog != 1) 135 fin_syslog(); 136 137 if (cmd->default_settings.syslog > 1) 138 init_syslog(cmd->default_settings.syslog); 139 140 /* Debug level for log file output */ 141 cmd->default_settings.debug = 142 find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL); 143 init_debug(cmd->default_settings.debug); 144 145 /* Verbose level for tty output */ 146 cmd->default_settings.verbose = 147 find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE); 148 init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL); 149 150 /* Log message formatting */ 151 init_indent(find_config_tree_int(cmd, "log/indent", 152 DEFAULT_INDENT)); 153 154 cmd->default_settings.msg_prefix = find_config_tree_str(cmd, 155 "log/prefix", 156 DEFAULT_MSG_PREFIX); 157 init_msg_prefix(cmd->default_settings.msg_prefix); 158 159 cmd->default_settings.cmd_name = find_config_tree_int(cmd, 160 "log/command_names", 161 DEFAULT_CMD_NAME); 162 init_cmd_name(cmd->default_settings.cmd_name); 163 164 /* Test mode */ 165 cmd->default_settings.test = 166 find_config_tree_int(cmd, "global/test", 0); 167 168 /* Settings for logging to file */ 169 if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE)) 170 append = 0; 171 172 log_file = find_config_tree_str(cmd, "log/file", 0); 173 174 if (log_file) { 175 release_log_memory(); 176 fin_log(); 177 init_log_file(log_file, append); 178 } 179 180 log_file = find_config_tree_str(cmd, "log/activate_file", 0); 181 if (log_file) 182 init_log_direct(log_file, append); 183 184 init_log_while_suspended(find_config_tree_int(cmd, 185 "log/activation", 0)); 186 187 t = time(NULL); 188 ctime_r(&t, &timebuf[0]); 189 timebuf[24] = '\0'; 190 log_verbose("Logging initialised at %s", timebuf); 191 192 /* Tell device-mapper about our logging */ 193 #ifdef DEVMAPPER_SUPPORT 194 dm_log_init(print_log); 195 #endif 196 } 197 198 static int _process_config(struct cmd_context *cmd) 199 { 200 mode_t old_umask; 201 const char *read_ahead; 202 struct stat st; 203 204 /* umask */ 205 cmd->default_settings.umask = find_config_tree_int(cmd, 206 "global/umask", 207 DEFAULT_UMASK); 208 209 if ((old_umask = umask((mode_t) cmd->default_settings.umask)) != 210 (mode_t) cmd->default_settings.umask) 211 log_verbose("Set umask to %04o", cmd->default_settings.umask); 212 213 /* dev dir */ 214 if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/", 215 find_config_tree_str(cmd, "devices/dir", 216 DEFAULT_DEV_DIR)) < 0) { 217 log_error("Device directory given in config file too long"); 218 return 0; 219 } 220 #ifdef DEVMAPPER_SUPPORT 221 dm_set_dev_dir(cmd->dev_dir); 222 #endif 223 #ifndef __NetBSD__ 224 /* proc dir */ 225 if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s", 226 find_config_tree_str(cmd, "global/proc", 227 DEFAULT_PROC_DIR)) < 0) { 228 log_error("Device directory given in config file too long"); 229 return 0; 230 } 231 #endif 232 if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) { 233 log_error("WARNING: proc dir %s not found - some checks will be bypassed", 234 cmd->proc_dir); 235 *cmd->proc_dir = '\0'; 236 } 237 238 _get_sysfs_dir(cmd); 239 240 /* activation? */ 241 cmd->default_settings.activation = find_config_tree_int(cmd, 242 "global/activation", 243 DEFAULT_ACTIVATION); 244 set_activation(cmd->default_settings.activation); 245 246 cmd->default_settings.suffix = find_config_tree_int(cmd, 247 "global/suffix", 248 DEFAULT_SUFFIX); 249 250 if (!(cmd->default_settings.unit_factor = 251 units_to_bytes(find_config_tree_str(cmd, 252 "global/units", 253 DEFAULT_UNITS), 254 &cmd->default_settings.unit_type))) { 255 log_error("Invalid units specification"); 256 return 0; 257 } 258 259 read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD); 260 if (!strcasecmp(read_ahead, "auto")) 261 cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO; 262 else if (!strcasecmp(read_ahead, "none")) 263 cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE; 264 else { 265 log_error("Invalid readahead specification"); 266 return 0; 267 } 268 269 cmd->stripe_filler = find_config_tree_str(cmd, 270 "activation/missing_stripe_filler", 271 DEFAULT_STRIPE_FILLER); 272 273 /* FIXME Missing error code checks from the stats, not log_warn?, notify if setting overridden, delay message/check till it is actually used (eg consider if lvm shell - file could appear later after this check)? */ 274 if (!strcmp(cmd->stripe_filler, "/dev/ioerror") && 275 stat(cmd->stripe_filler, &st)) 276 cmd->stripe_filler = "error"; 277 278 if (strcmp(cmd->stripe_filler, "error")) { 279 if (stat(cmd->stripe_filler, &st)) { 280 log_warn("WARNING: activation/missing_stripe_filler = \"%s\" " 281 "is invalid,", cmd->stripe_filler); 282 log_warn(" stat failed: %s", strerror(errno)); 283 log_warn("Falling back to \"error\" missing_stripe_filler."); 284 cmd->stripe_filler = "error"; 285 } else if (!S_ISBLK(st.st_mode)) { 286 log_warn("WARNING: activation/missing_stripe_filler = \"%s\" " 287 "is not a block device.", cmd->stripe_filler); 288 log_warn("Falling back to \"error\" missing_stripe_filler."); 289 cmd->stripe_filler = "error"; 290 } 291 } 292 293 return 1; 294 } 295 296 static int _set_tag(struct cmd_context *cmd, const char *tag) 297 { 298 log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag)); 299 300 if (!str_list_add(cmd->libmem, &cmd->tags, tag)) { 301 log_error("_set_tag: str_list_add %s failed", tag); 302 return 0; 303 } 304 305 return 1; 306 } 307 308 static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn, 309 int *passes) 310 { 311 struct config_node *cn; 312 struct config_value *cv; 313 314 *passes = 1; 315 316 for (cn = hn; cn; cn = cn->sib) { 317 if (!cn->v) 318 continue; 319 if (!strcmp(cn->key, "host_list")) { 320 *passes = 0; 321 if (cn->v->type == CFG_EMPTY_ARRAY) 322 continue; 323 for (cv = cn->v; cv; cv = cv->next) { 324 if (cv->type != CFG_STRING) { 325 log_error("Invalid hostname string " 326 "for tag %s", cn->key); 327 return 0; 328 } 329 if (!strcmp(cv->v.str, cmd->hostname)) { 330 *passes = 1; 331 return 1; 332 } 333 } 334 } 335 if (!strcmp(cn->key, "host_filter")) { 336 log_error("host_filter not supported yet"); 337 return 0; 338 } 339 } 340 341 return 1; 342 } 343 344 static int _init_tags(struct cmd_context *cmd, struct config_tree *cft) 345 { 346 const struct config_node *tn, *cn; 347 const char *tag; 348 int passes; 349 350 if (!(tn = find_config_node(cft->root, "tags")) || !tn->child) 351 return 1; 352 353 /* NB hosttags 0 when already 1 intentionally does not delete the tag */ 354 if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags", 355 DEFAULT_HOSTTAGS)) { 356 /* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */ 357 if (!_set_tag(cmd, cmd->hostname)) 358 return_0; 359 cmd->hosttags = 1; 360 } 361 362 for (cn = tn->child; cn; cn = cn->sib) { 363 if (cn->v) 364 continue; 365 tag = cn->key; 366 if (*tag == '@') 367 tag++; 368 if (!validate_name(tag)) { 369 log_error("Invalid tag in config file: %s", cn->key); 370 return 0; 371 } 372 if (cn->child) { 373 passes = 0; 374 if (!_check_host_filters(cmd, cn->child, &passes)) 375 return_0; 376 if (!passes) 377 continue; 378 } 379 if (!_set_tag(cmd, tag)) 380 return_0; 381 } 382 383 return 1; 384 } 385 386 static int _load_config_file(struct cmd_context *cmd, const char *tag) 387 { 388 char config_file[PATH_MAX] = ""; 389 const char *filler = ""; 390 struct stat info; 391 struct config_tree_list *cfl; 392 393 if (*tag) 394 filler = "_"; 395 396 if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf", 397 cmd->sys_dir, filler, tag) < 0) { 398 log_error("LVM_SYSTEM_DIR or tag was too long"); 399 return 0; 400 } 401 402 if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) { 403 log_error("config_tree_list allocation failed"); 404 return 0; 405 } 406 407 if (!(cfl->cft = create_config_tree(config_file, 0))) { 408 log_error("config_tree allocation failed"); 409 return 0; 410 } 411 412 /* Is there a config file? */ 413 if (stat(config_file, &info) == -1) { 414 if (errno == ENOENT) { 415 dm_list_add(&cmd->config_files, &cfl->list); 416 goto out; 417 } 418 log_sys_error("stat", config_file); 419 destroy_config_tree(cfl->cft); 420 return 0; 421 } 422 423 log_very_verbose("Loading config file: %s", config_file); 424 if (!read_config_file(cfl->cft)) { 425 log_error("Failed to load config file %s", config_file); 426 destroy_config_tree(cfl->cft); 427 return 0; 428 } 429 430 dm_list_add(&cmd->config_files, &cfl->list); 431 432 out: 433 if (*tag) 434 _init_tags(cmd, cfl->cft); 435 else 436 /* Use temporary copy of lvm.conf while loading other files */ 437 cmd->cft = cfl->cft; 438 439 return 1; 440 } 441 442 /* Find and read first config file */ 443 static int _init_lvm_conf(struct cmd_context *cmd) 444 { 445 /* No config file if LVM_SYSTEM_DIR is empty */ 446 if (!*cmd->sys_dir) { 447 if (!(cmd->cft = create_config_tree(NULL, 0))) { 448 log_error("Failed to create config tree"); 449 return 0; 450 } 451 return 1; 452 } 453 454 if (!_load_config_file(cmd, "")) 455 return_0; 456 457 return 1; 458 } 459 460 /* Read any additional config files */ 461 static int _init_tag_configs(struct cmd_context *cmd) 462 { 463 struct str_list *sl; 464 465 /* Tag list may grow while inside this loop */ 466 dm_list_iterate_items(sl, &cmd->tags) { 467 if (!_load_config_file(cmd, sl->str)) 468 return_0; 469 } 470 471 return 1; 472 } 473 474 static int _merge_config_files(struct cmd_context *cmd) 475 { 476 struct config_tree_list *cfl; 477 478 /* Replace temporary duplicate copy of lvm.conf */ 479 if (cmd->cft->root) { 480 if (!(cmd->cft = create_config_tree(NULL, 0))) { 481 log_error("Failed to create config tree"); 482 return 0; 483 } 484 } 485 486 dm_list_iterate_items(cfl, &cmd->config_files) { 487 /* Merge all config trees into cmd->cft using merge/tag rules */ 488 if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) 489 return_0; 490 } 491 492 return 1; 493 } 494 495 static void _destroy_tags(struct cmd_context *cmd) 496 { 497 struct dm_list *slh, *slht; 498 499 dm_list_iterate_safe(slh, slht, &cmd->tags) { 500 dm_list_del(slh); 501 } 502 } 503 504 int config_files_changed(struct cmd_context *cmd) 505 { 506 struct config_tree_list *cfl; 507 508 dm_list_iterate_items(cfl, &cmd->config_files) { 509 if (config_file_changed(cfl->cft)) 510 return 1; 511 } 512 513 return 0; 514 } 515 516 static void _destroy_tag_configs(struct cmd_context *cmd) 517 { 518 struct config_tree_list *cfl; 519 520 if (cmd->cft && cmd->cft->root) { 521 destroy_config_tree(cmd->cft); 522 cmd->cft = NULL; 523 } 524 525 dm_list_iterate_items(cfl, &cmd->config_files) { 526 destroy_config_tree(cfl->cft); 527 } 528 529 dm_list_init(&cmd->config_files); 530 } 531 532 static int _init_dev_cache(struct cmd_context *cmd) 533 { 534 const struct config_node *cn; 535 struct config_value *cv; 536 537 if (!dev_cache_init(cmd)) 538 return_0; 539 540 if (!(cn = find_config_tree_node(cmd, "devices/scan"))) { 541 if (!dev_cache_add_dir("/dev")) { 542 log_error("Failed to add /dev to internal " 543 "device cache"); 544 return 0; 545 } 546 log_verbose("device/scan not in config file: " 547 "Defaulting to /dev"); 548 return 1; 549 } 550 551 for (cv = cn->v; cv; cv = cv->next) { 552 if (cv->type != CFG_STRING) { 553 log_error("Invalid string in config file: " 554 "devices/scan"); 555 return 0; 556 } 557 558 if (!dev_cache_add_dir(cv->v.str)) { 559 log_error("Failed to add %s to internal device cache", 560 cv->v.str); 561 return 0; 562 } 563 } 564 565 if (!(cn = find_config_tree_node(cmd, "devices/loopfiles"))) 566 return 1; 567 568 for (cv = cn->v; cv; cv = cv->next) { 569 if (cv->type != CFG_STRING) { 570 log_error("Invalid string in config file: " 571 "devices/loopfiles"); 572 return 0; 573 } 574 575 if (!dev_cache_add_loopfile(cv->v.str)) { 576 log_error("Failed to add loopfile %s to internal " 577 "device cache", cv->v.str); 578 return 0; 579 } 580 } 581 582 583 return 1; 584 } 585 586 #define MAX_FILTERS 4 587 588 static struct dev_filter *_init_filter_components(struct cmd_context *cmd) 589 { 590 unsigned nr_filt = 0; 591 const struct config_node *cn; 592 struct dev_filter *filters[MAX_FILTERS]; 593 594 memset(filters, 0, sizeof(filters)); 595 596 /* 597 * Filters listed in order: top one gets applied first. 598 * Failure to initialise some filters is not fatal. 599 * Update MAX_FILTERS definition above when adding new filters. 600 */ 601 602 /* 603 * sysfs filter. Only available on 2.6 kernels. Non-critical. 604 * Listed first because it's very efficient at eliminating 605 * unavailable devices. 606 */ 607 if (find_config_tree_bool(cmd, "devices/sysfs_scan", 608 DEFAULT_SYSFS_SCAN)) { 609 if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir))) 610 nr_filt++; 611 } 612 613 /* regex filter. Optional. */ 614 if (!(cn = find_config_tree_node(cmd, "devices/filter"))) 615 log_very_verbose("devices/filter not found in config file: " 616 "no regex filter installed"); 617 618 else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) { 619 log_error("Failed to create regex device filter"); 620 return NULL; 621 } 622 623 /* device type filter. Required. */ 624 cn = find_config_tree_node(cmd, "devices/types"); 625 if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) { 626 log_error("Failed to create lvm type filter"); 627 return NULL; 628 } 629 630 /* md component filter. Optional, non-critical. */ 631 if (find_config_tree_bool(cmd, "devices/md_component_detection", 632 DEFAULT_MD_COMPONENT_DETECTION)) { 633 init_md_filtering(1); 634 if ((filters[nr_filt] = md_filter_create())) 635 nr_filt++; 636 } 637 638 /* Only build a composite filter if we really need it. */ 639 return (nr_filt == 1) ? 640 filters[0] : composite_filter_create(nr_filt, filters); 641 } 642 643 static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache) 644 { 645 const char *dev_cache = NULL, *cache_dir, *cache_file_prefix; 646 struct dev_filter *f3, *f4; 647 struct stat st; 648 char cache_file[PATH_MAX]; 649 650 cmd->dump_filter = 0; 651 652 if (!(f3 = _init_filter_components(cmd))) 653 return 0; 654 655 init_ignore_suspended_devices(find_config_tree_int(cmd, 656 "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES)); 657 658 /* 659 * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'. 660 */ 661 cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL); 662 cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL); 663 664 if (cache_dir || cache_file_prefix) { 665 if (dm_snprintf(cache_file, sizeof(cache_file), 666 "%s%s%s/%s.cache", 667 cache_dir ? "" : cmd->sys_dir, 668 cache_dir ? "" : "/", 669 cache_dir ? : DEFAULT_CACHE_SUBDIR, 670 cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) { 671 log_error("Persistent cache filename too long."); 672 return 0; 673 } 674 } else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) && 675 (dm_snprintf(cache_file, sizeof(cache_file), 676 "%s/%s/%s.cache", 677 cmd->sys_dir, DEFAULT_CACHE_SUBDIR, 678 DEFAULT_CACHE_FILE_PREFIX) < 0)) { 679 log_error("Persistent cache filename too long."); 680 return 0; 681 } 682 683 if (!dev_cache) 684 dev_cache = cache_file; 685 686 if (!(f4 = persistent_filter_create(f3, dev_cache))) { 687 log_error("Failed to create persistent device filter"); 688 return 0; 689 } 690 691 /* Should we ever dump persistent filter state? */ 692 if (find_config_tree_int(cmd, "devices/write_cache_state", 1)) 693 cmd->dump_filter = 1; 694 695 if (!*cmd->sys_dir) 696 cmd->dump_filter = 0; 697 698 /* 699 * Only load persistent filter device cache on startup if it is newer 700 * than the config file and this is not a long-lived process. 701 */ 702 if (load_persistent_cache && !cmd->is_long_lived && 703 !stat(dev_cache, &st) && 704 (st.st_ctime > config_file_timestamp(cmd->cft)) && 705 !persistent_filter_load(f4, NULL)) 706 log_verbose("Failed to load existing device cache from %s", 707 dev_cache); 708 709 cmd->filter = f4; 710 711 return 1; 712 } 713 714 static int _init_formats(struct cmd_context *cmd) 715 { 716 const char *format; 717 718 struct format_type *fmt; 719 720 #ifdef HAVE_LIBDL 721 const struct config_node *cn; 722 #endif 723 724 label_init(); 725 726 #ifdef LVM1_INTERNAL 727 if (!(fmt = init_lvm1_format(cmd))) 728 return 0; 729 fmt->library = NULL; 730 dm_list_add(&cmd->formats, &fmt->list); 731 #endif 732 733 #ifdef POOL_INTERNAL 734 if (!(fmt = init_pool_format(cmd))) 735 return 0; 736 fmt->library = NULL; 737 dm_list_add(&cmd->formats, &fmt->list); 738 #endif 739 740 #ifdef HAVE_LIBDL 741 /* Load any formats in shared libs if not static */ 742 if (!cmd->is_static && 743 (cn = find_config_tree_node(cmd, "global/format_libraries"))) { 744 745 struct config_value *cv; 746 struct format_type *(*init_format_fn) (struct cmd_context *); 747 void *lib; 748 749 for (cv = cn->v; cv; cv = cv->next) { 750 if (cv->type != CFG_STRING) { 751 log_error("Invalid string in config file: " 752 "global/format_libraries"); 753 return 0; 754 } 755 if (!(lib = load_shared_library(cmd, cv->v.str, 756 "format", 0))) 757 return_0; 758 759 if (!(init_format_fn = dlsym(lib, "init_format"))) { 760 log_error("Shared library %s does not contain " 761 "format functions", cv->v.str); 762 dlclose(lib); 763 return 0; 764 } 765 766 if (!(fmt = init_format_fn(cmd))) 767 return 0; 768 fmt->library = lib; 769 dm_list_add(&cmd->formats, &fmt->list); 770 } 771 } 772 #endif 773 774 if (!(fmt = create_text_format(cmd))) 775 return 0; 776 fmt->library = NULL; 777 dm_list_add(&cmd->formats, &fmt->list); 778 779 cmd->fmt_backup = fmt; 780 781 format = find_config_tree_str(cmd, "global/format", 782 DEFAULT_FORMAT); 783 784 dm_list_iterate_items(fmt, &cmd->formats) { 785 if (!strcasecmp(fmt->name, format) || 786 (fmt->alias && !strcasecmp(fmt->alias, format))) { 787 cmd->default_settings.fmt = fmt; 788 return 1; 789 } 790 } 791 792 log_error("_init_formats: Default format (%s) not found", format); 793 return 0; 794 } 795 796 int init_lvmcache_orphans(struct cmd_context *cmd) 797 { 798 struct format_type *fmt; 799 800 dm_list_iterate_items(fmt, &cmd->formats) 801 if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt)) 802 return_0; 803 804 return 1; 805 } 806 807 static int _init_segtypes(struct cmd_context *cmd) 808 { 809 struct segment_type *segtype; 810 811 #ifdef HAVE_LIBDL 812 const struct config_node *cn; 813 #endif 814 815 if (!(segtype = init_striped_segtype(cmd))) 816 return 0; 817 segtype->library = NULL; 818 dm_list_add(&cmd->segtypes, &segtype->list); 819 820 if (!(segtype = init_zero_segtype(cmd))) 821 return 0; 822 segtype->library = NULL; 823 dm_list_add(&cmd->segtypes, &segtype->list); 824 825 if (!(segtype = init_error_segtype(cmd))) 826 return 0; 827 segtype->library = NULL; 828 dm_list_add(&cmd->segtypes, &segtype->list); 829 830 if (!(segtype = init_free_segtype(cmd))) 831 return 0; 832 segtype->library = NULL; 833 dm_list_add(&cmd->segtypes, &segtype->list); 834 835 #ifdef SNAPSHOT_INTERNAL 836 if (!(segtype = init_snapshot_segtype(cmd))) 837 return 0; 838 segtype->library = NULL; 839 dm_list_add(&cmd->segtypes, &segtype->list); 840 #endif 841 842 #ifdef MIRRORED_INTERNAL 843 if (!(segtype = init_mirrored_segtype(cmd))) 844 return 0; 845 segtype->library = NULL; 846 dm_list_add(&cmd->segtypes, &segtype->list); 847 #endif 848 849 #ifdef HAVE_LIBDL 850 /* Load any formats in shared libs unless static */ 851 if (!cmd->is_static && 852 (cn = find_config_tree_node(cmd, "global/segment_libraries"))) { 853 854 struct config_value *cv; 855 struct segment_type *(*init_segtype_fn) (struct cmd_context *); 856 void *lib; 857 struct segment_type *segtype2; 858 859 for (cv = cn->v; cv; cv = cv->next) { 860 if (cv->type != CFG_STRING) { 861 log_error("Invalid string in config file: " 862 "global/segment_libraries"); 863 return 0; 864 } 865 if (!(lib = load_shared_library(cmd, cv->v.str, 866 "segment type", 0))) 867 return_0; 868 869 if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) { 870 log_error("Shared library %s does not contain " 871 "segment type functions", cv->v.str); 872 dlclose(lib); 873 return 0; 874 } 875 876 if (!(segtype = init_segtype_fn(cmd))) 877 return 0; 878 segtype->library = lib; 879 dm_list_add(&cmd->segtypes, &segtype->list); 880 881 dm_list_iterate_items(segtype2, &cmd->segtypes) { 882 if ((segtype == segtype2) || 883 strcmp(segtype2->name, segtype->name)) 884 continue; 885 log_error("Duplicate segment type %s: " 886 "unloading shared library %s", 887 segtype->name, cv->v.str); 888 dm_list_del(&segtype->list); 889 segtype->ops->destroy(segtype); 890 dlclose(lib); 891 } 892 } 893 } 894 #endif 895 896 return 1; 897 } 898 899 static int _init_hostname(struct cmd_context *cmd) 900 { 901 struct utsname uts; 902 903 if (uname(&uts)) { 904 log_sys_error("uname", "_init_hostname"); 905 return 0; 906 } 907 908 if (!(cmd->hostname = dm_pool_strdup(cmd->libmem, uts.nodename))) { 909 log_error("_init_hostname: dm_pool_strdup failed"); 910 return 0; 911 } 912 913 if (!(cmd->kernel_vsn = dm_pool_strdup(cmd->libmem, uts.release))) { 914 log_error("_init_hostname: dm_pool_strdup kernel_vsn failed"); 915 return 0; 916 } 917 918 return 1; 919 } 920 921 static int _init_backup(struct cmd_context *cmd) 922 { 923 uint32_t days, min; 924 char default_dir[PATH_MAX]; 925 const char *dir; 926 927 if (!cmd->sys_dir) { 928 log_warn("WARNING: Metadata changes will NOT be backed up"); 929 backup_init(cmd, ""); 930 archive_init(cmd, "", 0, 0); 931 return 1; 932 } 933 934 /* set up archiving */ 935 cmd->default_settings.archive = 936 find_config_tree_bool(cmd, "backup/archive", 937 DEFAULT_ARCHIVE_ENABLED); 938 939 days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days", 940 DEFAULT_ARCHIVE_DAYS); 941 942 min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min", 943 DEFAULT_ARCHIVE_NUMBER); 944 945 if (dm_snprintf 946 (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir, 947 DEFAULT_ARCHIVE_SUBDIR) == -1) { 948 log_err("Couldn't create default archive path '%s/%s'.", 949 cmd->sys_dir, DEFAULT_ARCHIVE_SUBDIR); 950 return 0; 951 } 952 953 dir = find_config_tree_str(cmd, "backup/archive_dir", 954 default_dir); 955 956 if (!archive_init(cmd, dir, days, min)) { 957 log_debug("backup_init failed."); 958 return 0; 959 } 960 961 /* set up the backup */ 962 cmd->default_settings.backup = 963 find_config_tree_bool(cmd, "backup/backup", 964 DEFAULT_BACKUP_ENABLED); 965 966 if (dm_snprintf 967 (default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir, 968 DEFAULT_BACKUP_SUBDIR) == -1) { 969 log_err("Couldn't create default backup path '%s/%s'.", 970 cmd->sys_dir, DEFAULT_BACKUP_SUBDIR); 971 return 0; 972 } 973 974 dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir); 975 976 if (!backup_init(cmd, dir)) { 977 log_debug("backup_init failed."); 978 return 0; 979 } 980 981 return 1; 982 } 983 984 /* Entry point */ 985 struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, 986 unsigned is_long_lived) 987 { 988 struct cmd_context *cmd; 989 990 #ifdef M_MMAP_MAX 991 mallopt(M_MMAP_MAX, 0); 992 #endif 993 994 if (!setlocale(LC_ALL, "")) 995 log_very_verbose("setlocale failed"); 996 997 #ifdef INTL_PACKAGE 998 bindtextdomain(INTL_PACKAGE, LOCALEDIR); 999 #endif 1000 1001 init_syslog(DEFAULT_LOG_FACILITY); 1002 1003 if (!(cmd = dm_malloc(sizeof(*cmd)))) { 1004 log_error("Failed to allocate command context"); 1005 return NULL; 1006 } 1007 memset(cmd, 0, sizeof(*cmd)); 1008 cmd->args = the_args; 1009 cmd->is_static = is_static; 1010 cmd->is_long_lived = is_long_lived; 1011 cmd->handles_missing_pvs = 0; 1012 cmd->hosttags = 0; 1013 dm_list_init(&cmd->formats); 1014 dm_list_init(&cmd->segtypes); 1015 dm_list_init(&cmd->tags); 1016 dm_list_init(&cmd->config_files); 1017 1018 strcpy(cmd->sys_dir, DEFAULT_SYS_DIR); 1019 1020 if (!_get_env_vars(cmd)) 1021 goto error; 1022 1023 /* Create system directory if it doesn't already exist */ 1024 if (*cmd->sys_dir && !dm_create_dir(cmd->sys_dir)) { 1025 log_error("Failed to create LVM2 system dir for metadata backups, config " 1026 "files and internal cache."); 1027 log_error("Set environment variable LVM_SYSTEM_DIR to alternative location " 1028 "or empty string."); 1029 goto error; 1030 } 1031 1032 if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) { 1033 log_error("Library memory pool creation failed"); 1034 goto error; 1035 } 1036 1037 if (!_init_lvm_conf(cmd)) 1038 goto error; 1039 1040 _init_logging(cmd); 1041 1042 if (!_init_hostname(cmd)) 1043 goto error; 1044 1045 if (!_init_tags(cmd, cmd->cft)) 1046 goto error; 1047 1048 if (!_init_tag_configs(cmd)) 1049 goto error; 1050 1051 if (!_merge_config_files(cmd)) 1052 goto error; 1053 1054 if (!_process_config(cmd)) 1055 goto error; 1056 1057 if (!_init_dev_cache(cmd)) 1058 goto error; 1059 1060 if (!_init_filters(cmd, 1)) 1061 goto error; 1062 1063 if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) { 1064 log_error("Command memory pool creation failed"); 1065 goto error; 1066 } 1067 1068 memlock_init(cmd); 1069 1070 if (!_init_formats(cmd)) 1071 goto error; 1072 1073 if (!init_lvmcache_orphans(cmd)) 1074 goto error; 1075 1076 if (!_init_segtypes(cmd)) 1077 goto error; 1078 1079 if (!_init_backup(cmd)) 1080 goto error; 1081 1082 cmd->default_settings.cache_vgmetadata = 1; 1083 cmd->current_settings = cmd->default_settings; 1084 1085 cmd->config_valid = 1; 1086 return cmd; 1087 1088 error: 1089 dm_free(cmd); 1090 return NULL; 1091 } 1092 1093 static void _destroy_formats(struct dm_list *formats) 1094 { 1095 struct dm_list *fmtl, *tmp; 1096 struct format_type *fmt; 1097 void *lib; 1098 1099 dm_list_iterate_safe(fmtl, tmp, formats) { 1100 fmt = dm_list_item(fmtl, struct format_type); 1101 dm_list_del(&fmt->list); 1102 lib = fmt->library; 1103 fmt->ops->destroy(fmt); 1104 #ifdef HAVE_LIBDL 1105 if (lib) 1106 dlclose(lib); 1107 #endif 1108 } 1109 } 1110 1111 static void _destroy_segtypes(struct dm_list *segtypes) 1112 { 1113 struct dm_list *sgtl, *tmp; 1114 struct segment_type *segtype; 1115 void *lib; 1116 1117 dm_list_iterate_safe(sgtl, tmp, segtypes) { 1118 segtype = dm_list_item(sgtl, struct segment_type); 1119 dm_list_del(&segtype->list); 1120 lib = segtype->library; 1121 segtype->ops->destroy(segtype); 1122 #ifdef HAVE_LIBDL 1123 if (lib) 1124 dlclose(lib); 1125 #endif 1126 } 1127 } 1128 1129 int refresh_toolcontext(struct cmd_context *cmd) 1130 { 1131 log_verbose("Reloading config files"); 1132 1133 /* 1134 * Don't update the persistent filter cache as we will 1135 * perform a full rescan. 1136 */ 1137 1138 activation_release(); 1139 lvmcache_destroy(cmd, 0); 1140 label_exit(); 1141 _destroy_segtypes(&cmd->segtypes); 1142 _destroy_formats(&cmd->formats); 1143 if (cmd->filter) { 1144 cmd->filter->destroy(cmd->filter); 1145 cmd->filter = NULL; 1146 } 1147 dev_cache_exit(); 1148 _destroy_tags(cmd); 1149 _destroy_tag_configs(cmd); 1150 1151 cmd->config_valid = 0; 1152 1153 cmd->hosttags = 0; 1154 1155 if (!_init_lvm_conf(cmd)) 1156 return 0; 1157 1158 _init_logging(cmd); 1159 1160 if (!_init_tags(cmd, cmd->cft)) 1161 return 0; 1162 1163 if (!_init_tag_configs(cmd)) 1164 return 0; 1165 1166 if (!_merge_config_files(cmd)) 1167 return 0; 1168 1169 if (!_process_config(cmd)) 1170 return 0; 1171 1172 if (!_init_dev_cache(cmd)) 1173 return 0; 1174 1175 if (!_init_filters(cmd, 0)) 1176 return 0; 1177 1178 if (!_init_formats(cmd)) 1179 return 0; 1180 1181 if (!init_lvmcache_orphans(cmd)) 1182 return 0; 1183 1184 if (!_init_segtypes(cmd)) 1185 return 0; 1186 1187 /* 1188 * If we are a long-lived process, write out the updated persistent 1189 * device cache for the benefit of short-lived processes. 1190 */ 1191 if (cmd->is_long_lived && cmd->dump_filter) 1192 persistent_filter_dump(cmd->filter); 1193 1194 cmd->config_valid = 1; 1195 return 1; 1196 } 1197 1198 void destroy_toolcontext(struct cmd_context *cmd) 1199 { 1200 if (cmd->dump_filter) 1201 persistent_filter_dump(cmd->filter); 1202 1203 archive_exit(cmd); 1204 backup_exit(cmd); 1205 lvmcache_destroy(cmd, 0); 1206 label_exit(); 1207 _destroy_segtypes(&cmd->segtypes); 1208 _destroy_formats(&cmd->formats); 1209 cmd->filter->destroy(cmd->filter); 1210 dm_pool_destroy(cmd->mem); 1211 dev_cache_exit(); 1212 _destroy_tags(cmd); 1213 _destroy_tag_configs(cmd); 1214 dm_pool_destroy(cmd->libmem); 1215 dm_free(cmd); 1216 1217 release_log_memory(); 1218 activation_exit(); 1219 fin_log(); 1220 fin_syslog(); 1221 } 1222