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