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