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
_get_env_vars(struct cmd_context * cmd)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
_get_sysfs_dir(struct cmd_context * cmd)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
_init_logging(struct cmd_context * cmd)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
_process_config(struct cmd_context * cmd)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
_set_tag(struct cmd_context * cmd,const char * tag)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
_check_host_filters(struct cmd_context * cmd,struct config_node * hn,int * passes)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
_init_tags(struct cmd_context * cmd,struct config_tree * cft)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
_load_config_file(struct cmd_context * cmd,const char * tag)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 */
_init_lvm_conf(struct cmd_context * cmd)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 */
_init_tag_configs(struct cmd_context * cmd)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
_merge_config_files(struct cmd_context * cmd)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
_destroy_tags(struct cmd_context * cmd)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
config_files_changed(struct cmd_context * cmd)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
_destroy_tag_configs(struct cmd_context * cmd)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
_init_dev_cache(struct cmd_context * cmd)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
_init_filter_components(struct cmd_context * cmd)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
_init_filters(struct cmd_context * cmd,unsigned load_persistent_cache)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
_init_formats(struct cmd_context * cmd)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
init_lvmcache_orphans(struct cmd_context * cmd)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
lvm_register_segtype(struct segtype_library * seglib,struct segment_type * segtype)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
_init_single_segtype(struct cmd_context * cmd,struct segtype_library * seglib)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
_init_segtypes(struct cmd_context * cmd)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
_init_hostname(struct cmd_context * cmd)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
_init_backup(struct cmd_context * cmd)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
_init_rand(struct cmd_context * cmd)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
_init_globals(struct cmd_context * cmd)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 */
create_toolcontext(unsigned is_long_lived,const char * system_dir)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
_destroy_formats(struct dm_list * formats)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
_destroy_segtypes(struct dm_list * segtypes)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
refresh_filters(struct cmd_context * cmd)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
refresh_toolcontext(struct cmd_context * cmd)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
destroy_toolcontext(struct cmd_context * cmd)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