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