Merge lp:~gandelman-a/ubuntu/saucy/lvm2/lp1223576 into lp:ubuntu/saucy/lvm2
- Saucy (13.10)
- lp1223576
- Merge into saucy
Status: | Merged | ||||
---|---|---|---|---|---|
Merge reported by: | Dimitri John Ledkov | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~gandelman-a/ubuntu/saucy/lvm2/lp1223576 | ||||
Merge into: | lp:ubuntu/saucy/lvm2 | ||||
Diff against target: |
19303 lines (+290/-18358) 50 files modified
.pc/applied-patches (+0/-9) .pc/avoid-dev-block.patch/lib/device/dev-cache.c (+0/-1037) .pc/dirs.patch/daemons/dmeventd/Makefile.in (+0/-108) .pc/dirs.patch/daemons/dmeventd/dmeventd.c (+0/-2026) .pc/dirs.patch/doc/example.conf.in (+0/-816) .pc/dirs.patch/lib/commands/toolcontext.c (+0/-1688) .pc/dm-event-api.patch/daemons/dmeventd/.exported_symbols (+0/-4) .pc/dm-event-api.patch/daemons/dmeventd/dmeventd.c (+0/-2035) .pc/dm-event-api.patch/daemons/dmeventd/libdevmapper-event.c (+0/-870) .pc/force-modprobe.patch/configure.in (+0/-1632) .pc/implicit-pointer.patch/tools/lvm.c (+0/-253) .pc/install.patch/daemons/dmeventd/plugins/lvm2/Makefile.in (+0/-31) .pc/install.patch/daemons/dmeventd/plugins/mirror/Makefile.in (+0/-37) .pc/install.patch/daemons/dmeventd/plugins/raid/Makefile.in (+0/-36) .pc/install.patch/daemons/dmeventd/plugins/snapshot/Makefile.in (+0/-33) .pc/install.patch/daemons/dmeventd/plugins/thin/Makefile.in (+0/-36) .pc/install.patch/make.tmpl.in (+0/-412) .pc/libs-cleanup.patch/configure.in (+0/-1685) .pc/missing-dmeventd.patch/daemons/dmeventd/libdevmapper-event.c (+0/-870) .pc/missing-dmeventd.patch/lib/activate/activate.c (+0/-1954) .pc/monitoring-default-off.patch/doc/example.conf.in (+0/-816) .pc/monitoring-default-off.patch/lib/config/defaults.h (+0/-180) .pc/monitoring-default-off.patch/tools/toollib.c (+0/-1632) configure.in (+65/-8) daemons/dmeventd/.exported_symbols (+3/-3) daemons/dmeventd/Makefile.in (+0/-1) daemons/dmeventd/dmeventd.c (+8/-17) daemons/dmeventd/libdevmapper-event.c (+13/-25) daemons/dmeventd/plugins/lvm2/Makefile.in (+1/-1) daemons/dmeventd/plugins/mirror/Makefile.in (+0/-1) daemons/dmeventd/plugins/raid/Makefile.in (+0/-1) daemons/dmeventd/plugins/snapshot/Makefile.in (+0/-1) daemons/dmeventd/plugins/thin/Makefile.in (+0/-1) debian/changelog (+110/-0) debian/clvm.defaults (+9/-0) debian/clvm.init (+1/-1) debian/control (+2/-1) debian/lvm2.init (+2/-12) debian/rules (+1/-1) debian/tree/dmsetup/lib/udev/rules.d/55-dm.rules (+3/-3) debian/tree/lvm2/lib/udev/rules.d/56-lvm.rules (+10/-2) debian/tree/lvm2/lib/udev/rules.d/60-persistent-storage-lvm.rules (+0/-12) doc/example.conf.in (+3/-3) lib/activate/activate.c (+20/-27) lib/commands/toolcontext.c (+6/-4) lib/config/defaults.h (+1/-1) lib/device/dev-cache.c (+0/-15) make.tmpl.in (+21/-10) tools/lvm.c (+3/-0) tools/toollib.c (+8/-7) |
||||
To merge this branch: | bzr merge lp:~gandelman-a/ubuntu/saucy/lvm2/lp1223576 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dimitri John Ledkov | Approve | ||
Review via email: mp+185573@code.launchpad.net |
Commit message
Description of the change
This merges Debian 2.02.98-6, which contains a number of fixes to udev rules that seem to fix many strange issue's I've been hitting on Saucy wrt LVM snapshot deletion.
lvm2 (2.02.98-6ubuntu1) saucy; urgency=low
* Merge from Debian unstable (LP: #1223576), remaining changes:
- Only build clvm support for corosync:
- debian/control: Drop Build-Depends on libcman-dev, openais-dev
- debian/rules: Remove openais + cman from --with-clvmd build option.
- debian/
names in /dev/block/ since lvm.conf won't handle this.
- debian/rules:
- copy .po file to .pot file for Rosetta (Ubuntu specific).
- debian/
- install initramfs and udev hooks in udebs (Debian bug 504341).
- auto-start VGs as their PVs are discovered (Ubuntu specific):
- add debian/
the sledgehammer of vgscan/vgchange to turn on VGs as they come online.
- debian/
- add 85-lvm2.rules to the list of udev rules to copy.
- depend on udev.
- debian/control:
- add versioned Depend on watershed in lvm2 for udev rules.
- add Depends on watershed-udeb in lvm2-udeb for udev rules.
- add versioned Depend/Breaks on udev in dmsetup for udev rules.
- add Depend on initramfs-tools in dmsetup so system is not potentially
rendered unbootable by out-of-order dpkg configuration.
- In libdevmapper-
(<< 2.02.95-4ubuntu1) due to debian symbol rename
- debian/rules:
- do not install local-top scripts since Ubuntu mounts root using udev.
- do not install init scripts for lvm2, since udev starts LVM.
- continue to build clvm support.
- debian/
- debian/
watch dm devices for changes with inotify
- add mountroot failure hooks to help fix bad boots (Debian bug 468115):
- debian/
- remaining changes to upstream event manager packages (Debian bug 514706):
- debian/rules:
- enable dmeventd during configure.
- debian/
- rename debian/
correctly.
- debian/control: add dmsetup-udeb to libdevmapper1.
- debian/rules: make sure dmsetup and lvm2 initramfs-tools scripts are
executable. When the Ubuntu-specific ones are added with a patch,
they may lose their executable bit.
- Add and install clvmd resource agent
- Add dependency on libudev-dev to libdevmapper-dev so that the .pc file
works.
- debian/
- create /run/lvm if it doesn't exist.
- debian/clvm.init:
- exit 3 if not running on status action.
- Call dh_installman so that our dmeventd manpage actually gets installed
- Install the missing fsadm manpage.
- Complete libdevmapper-dev multiarch:
- move .so symlinks and pkgconfig files to multiarched locations.
- mark libdevmapper-dev M-A: same
-- Adam Gandelman <email address hidden> Thu, 12 Sep 2013 16:03:09 -0700
- 85. By Adam Gandelman
-
Add merge bug ref.
Preview Diff
1 | === removed file '.pc/applied-patches' |
2 | --- .pc/applied-patches 2013-05-30 11:02:10 +0000 |
3 | +++ .pc/applied-patches 1970-01-01 00:00:00 +0000 |
4 | @@ -1,9 +0,0 @@ |
5 | -install.patch |
6 | -libs-cleanup.patch |
7 | -dirs.patch |
8 | -force-modprobe.patch |
9 | -implicit-pointer.patch |
10 | -avoid-dev-block.patch |
11 | -dm-event-api.patch |
12 | -monitoring-default-off.patch |
13 | -missing-dmeventd.patch |
14 | |
15 | === removed directory '.pc/avoid-dev-block.patch' |
16 | === removed directory '.pc/avoid-dev-block.patch/lib' |
17 | === removed directory '.pc/avoid-dev-block.patch/lib/device' |
18 | === removed file '.pc/avoid-dev-block.patch/lib/device/dev-cache.c' |
19 | --- .pc/avoid-dev-block.patch/lib/device/dev-cache.c 2013-05-30 11:02:10 +0000 |
20 | +++ .pc/avoid-dev-block.patch/lib/device/dev-cache.c 1970-01-01 00:00:00 +0000 |
21 | @@ -1,1037 +0,0 @@ |
22 | -/* |
23 | - * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
24 | - * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
25 | - * |
26 | - * This file is part of LVM2. |
27 | - * |
28 | - * This copyrighted material is made available to anyone wishing to use, |
29 | - * modify, copy, or redistribute it subject to the terms and conditions |
30 | - * of the GNU Lesser General Public License v.2.1. |
31 | - * |
32 | - * You should have received a copy of the GNU Lesser General Public License |
33 | - * along with this program; if not, write to the Free Software Foundation, |
34 | - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
35 | - */ |
36 | - |
37 | -#include "lib.h" |
38 | -#include "dev-cache.h" |
39 | -#include "lvm-types.h" |
40 | -#include "btree.h" |
41 | -#include "filter.h" |
42 | -#include "toolcontext.h" |
43 | - |
44 | -#include <unistd.h> |
45 | -#include <sys/param.h> |
46 | -#include <dirent.h> |
47 | - |
48 | -struct dev_iter { |
49 | - struct btree_iter *current; |
50 | - struct dev_filter *filter; |
51 | -}; |
52 | - |
53 | -struct dir_list { |
54 | - struct dm_list list; |
55 | - char dir[0]; |
56 | -}; |
57 | - |
58 | -static struct { |
59 | - struct dm_pool *mem; |
60 | - struct dm_hash_table *names; |
61 | - struct btree *devices; |
62 | - struct dm_regex *preferred_names_matcher; |
63 | - const char *dev_dir; |
64 | - |
65 | - int has_scanned; |
66 | - struct dm_list dirs; |
67 | - struct dm_list files; |
68 | - |
69 | -} _cache; |
70 | - |
71 | -#define _zalloc(x) dm_pool_zalloc(_cache.mem, (x)) |
72 | -#define _free(x) dm_pool_free(_cache.mem, (x)) |
73 | -#define _strdup(x) dm_pool_strdup(_cache.mem, (x)) |
74 | - |
75 | -static int _insert(const char *path, int rec, int check_with_udev_db); |
76 | - |
77 | -/* Setup non-zero members of passed zeroed 'struct device' */ |
78 | -static void _dev_init(struct device *dev, int max_error_count) |
79 | -{ |
80 | - dev->block_size = -1; |
81 | - dev->fd = -1; |
82 | - dev->read_ahead = -1; |
83 | - dev->max_error_count = max_error_count; |
84 | - |
85 | - dm_list_init(&dev->aliases); |
86 | - dm_list_init(&dev->open_list); |
87 | -} |
88 | - |
89 | -struct device *dev_create_file(const char *filename, struct device *dev, |
90 | - struct str_list *alias, int use_malloc) |
91 | -{ |
92 | - int allocate = !dev; |
93 | - |
94 | - if (allocate) { |
95 | - if (use_malloc) { |
96 | - if (!(dev = dm_zalloc(sizeof(*dev)))) { |
97 | - log_error("struct device allocation failed"); |
98 | - return NULL; |
99 | - } |
100 | - if (!(alias = dm_zalloc(sizeof(*alias)))) { |
101 | - log_error("struct str_list allocation failed"); |
102 | - dm_free(dev); |
103 | - return NULL; |
104 | - } |
105 | - if (!(alias->str = dm_strdup(filename))) { |
106 | - log_error("filename strdup failed"); |
107 | - dm_free(dev); |
108 | - dm_free(alias); |
109 | - return NULL; |
110 | - } |
111 | - } else { |
112 | - if (!(dev = _zalloc(sizeof(*dev)))) { |
113 | - log_error("struct device allocation failed"); |
114 | - return NULL; |
115 | - } |
116 | - if (!(alias = _zalloc(sizeof(*alias)))) { |
117 | - log_error("struct str_list allocation failed"); |
118 | - _free(dev); |
119 | - return NULL; |
120 | - } |
121 | - if (!(alias->str = _strdup(filename))) { |
122 | - log_error("filename strdup failed"); |
123 | - return NULL; |
124 | - } |
125 | - } |
126 | - } else if (!(alias->str = dm_strdup(filename))) { |
127 | - log_error("filename strdup failed"); |
128 | - return NULL; |
129 | - } |
130 | - |
131 | - _dev_init(dev, NO_DEV_ERROR_COUNT_LIMIT); |
132 | - dev->flags = DEV_REGULAR | ((use_malloc) ? DEV_ALLOCED : 0); |
133 | - dm_list_add(&dev->aliases, &alias->list); |
134 | - |
135 | - return dev; |
136 | -} |
137 | - |
138 | -static struct device *_dev_create(dev_t d) |
139 | -{ |
140 | - struct device *dev; |
141 | - |
142 | - if (!(dev = _zalloc(sizeof(*dev)))) { |
143 | - log_error("struct device allocation failed"); |
144 | - return NULL; |
145 | - } |
146 | - |
147 | - _dev_init(dev, dev_disable_after_error_count()); |
148 | - dev->dev = d; |
149 | - |
150 | - return dev; |
151 | -} |
152 | - |
153 | -void dev_set_preferred_name(struct str_list *sl, struct device *dev) |
154 | -{ |
155 | - /* |
156 | - * Don't interfere with ordering specified in config file. |
157 | - */ |
158 | - if (_cache.preferred_names_matcher) |
159 | - return; |
160 | - |
161 | - log_debug("%s: New preferred name", sl->str); |
162 | - dm_list_del(&sl->list); |
163 | - dm_list_add_h(&dev->aliases, &sl->list); |
164 | -} |
165 | - |
166 | -/* |
167 | - * Check whether path0 or path1 contains the subpath. The path that |
168 | - * *does not* contain the subpath wins (return 0 or 1). If both paths |
169 | - * contain the subpath, return -1. If none of them contains the subpath, |
170 | - * return -2. |
171 | - */ |
172 | -static int _builtin_preference(const char *path0, const char *path1, |
173 | - size_t skip_prefix_count, const char *subpath) |
174 | -{ |
175 | - size_t subpath_len; |
176 | - int r0, r1; |
177 | - |
178 | - subpath_len = strlen(subpath); |
179 | - |
180 | - r0 = !strncmp(path0 + skip_prefix_count, subpath, subpath_len); |
181 | - r1 = !strncmp(path1 + skip_prefix_count, subpath, subpath_len); |
182 | - |
183 | - if (!r0 && r1) |
184 | - /* path0 does not have the subpath - it wins */ |
185 | - return 0; |
186 | - else if (r0 && !r1) |
187 | - /* path1 does not have the subpath - it wins */ |
188 | - return 1; |
189 | - else if (r0 && r1) |
190 | - /* both of them have the subpath */ |
191 | - return -1; |
192 | - |
193 | - /* no path has the subpath */ |
194 | - return -2; |
195 | -} |
196 | - |
197 | -static int _apply_builtin_path_preference_rules(const char *path0, const char *path1) |
198 | -{ |
199 | - size_t devdir_len; |
200 | - int r; |
201 | - |
202 | - devdir_len = strlen(_cache.dev_dir); |
203 | - |
204 | - if (!strncmp(path0, _cache.dev_dir, devdir_len) && |
205 | - !strncmp(path1, _cache.dev_dir, devdir_len)) { |
206 | - /* |
207 | - * We're trying to achieve the ordering: |
208 | - * /dev/block/ < /dev/dm-* < /dev/disk/ < /dev/mapper/ < anything else |
209 | - */ |
210 | - |
211 | - /* Prefer any other path over /dev/block/ path. */ |
212 | - if ((r = _builtin_preference(path0, path1, devdir_len, "block/")) >= -1) |
213 | - return r; |
214 | - |
215 | - /* Prefer any other path over /dev/dm-* path. */ |
216 | - if ((r = _builtin_preference(path0, path1, devdir_len, "dm-")) >= -1) |
217 | - return r; |
218 | - |
219 | - /* Prefer any other path over /dev/disk/ path. */ |
220 | - if ((r = _builtin_preference(path0, path1, devdir_len, "disk/")) >= -1) |
221 | - return r; |
222 | - |
223 | - /* Prefer any other path over /dev/mapper/ path. */ |
224 | - if ((r = _builtin_preference(path0, path1, 0, dm_dir())) >= -1) |
225 | - return r; |
226 | - } |
227 | - |
228 | - return -1; |
229 | -} |
230 | - |
231 | -/* Return 1 if we prefer path1 else return 0 */ |
232 | -static int _compare_paths(const char *path0, const char *path1) |
233 | -{ |
234 | - int slash0 = 0, slash1 = 0; |
235 | - int m0, m1; |
236 | - const char *p; |
237 | - char p0[PATH_MAX], p1[PATH_MAX]; |
238 | - char *s0, *s1; |
239 | - struct stat stat0, stat1; |
240 | - int r; |
241 | - |
242 | - /* |
243 | - * FIXME Better to compare patterns one-at-a-time against all names. |
244 | - */ |
245 | - if (_cache.preferred_names_matcher) { |
246 | - m0 = dm_regex_match(_cache.preferred_names_matcher, path0); |
247 | - m1 = dm_regex_match(_cache.preferred_names_matcher, path1); |
248 | - |
249 | - if (m0 != m1) { |
250 | - if (m0 < 0) |
251 | - return 1; |
252 | - if (m1 < 0) |
253 | - return 0; |
254 | - if (m0 < m1) |
255 | - return 1; |
256 | - if (m1 < m0) |
257 | - return 0; |
258 | - } |
259 | - } |
260 | - |
261 | - /* Apply built-in preference rules first. */ |
262 | - if ((r = _apply_builtin_path_preference_rules(path0, path1)) >= 0) |
263 | - return r; |
264 | - |
265 | - /* Return the path with fewer slashes */ |
266 | - for (p = path0; p++; p = (const char *) strchr(p, '/')) |
267 | - slash0++; |
268 | - |
269 | - for (p = path1; p++; p = (const char *) strchr(p, '/')) |
270 | - slash1++; |
271 | - |
272 | - if (slash0 < slash1) |
273 | - return 0; |
274 | - if (slash1 < slash0) |
275 | - return 1; |
276 | - |
277 | - strncpy(p0, path0, sizeof(p0) - 1); |
278 | - p0[sizeof(p0) - 1] = '\0'; |
279 | - strncpy(p1, path1, sizeof(p1) - 1); |
280 | - p1[sizeof(p1) - 1] = '\0'; |
281 | - s0 = p0 + 1; |
282 | - s1 = p1 + 1; |
283 | - |
284 | - /* |
285 | - * If we reach here, both paths are the same length. |
286 | - * Now skip past identical path components. |
287 | - */ |
288 | - while (*s0 && *s0 == *s1) |
289 | - s0++, s1++; |
290 | - |
291 | - /* We prefer symlinks - they exist for a reason! |
292 | - * So we prefer a shorter path before the first symlink in the name. |
293 | - * FIXME Configuration option to invert this? */ |
294 | - while (s0) { |
295 | - s0 = strchr(s0, '/'); |
296 | - s1 = strchr(s1, '/'); |
297 | - if (s0) { |
298 | - *s0 = '\0'; |
299 | - *s1 = '\0'; |
300 | - } |
301 | - if (lstat(p0, &stat0)) { |
302 | - log_sys_very_verbose("lstat", p0); |
303 | - return 1; |
304 | - } |
305 | - if (lstat(p1, &stat1)) { |
306 | - log_sys_very_verbose("lstat", p1); |
307 | - return 0; |
308 | - } |
309 | - if (S_ISLNK(stat0.st_mode) && !S_ISLNK(stat1.st_mode)) |
310 | - return 0; |
311 | - if (!S_ISLNK(stat0.st_mode) && S_ISLNK(stat1.st_mode)) |
312 | - return 1; |
313 | - if (s0) { |
314 | - *s0++ = '/'; |
315 | - *s1++ = '/'; |
316 | - } |
317 | - } |
318 | - |
319 | - /* ASCII comparison */ |
320 | - if (strcmp(path0, path1) < 0) |
321 | - return 0; |
322 | - else |
323 | - return 1; |
324 | -} |
325 | - |
326 | -static int _add_alias(struct device *dev, const char *path) |
327 | -{ |
328 | - struct str_list *sl = _zalloc(sizeof(*sl)); |
329 | - struct str_list *strl; |
330 | - const char *oldpath; |
331 | - int prefer_old = 1; |
332 | - |
333 | - if (!sl) |
334 | - return_0; |
335 | - |
336 | - /* Is name already there? */ |
337 | - dm_list_iterate_items(strl, &dev->aliases) { |
338 | - if (!strcmp(strl->str, path)) { |
339 | - log_debug("%s: Already in device cache", path); |
340 | - return 1; |
341 | - } |
342 | - } |
343 | - |
344 | - sl->str = path; |
345 | - |
346 | - if (!dm_list_empty(&dev->aliases)) { |
347 | - oldpath = dm_list_item(dev->aliases.n, struct str_list)->str; |
348 | - prefer_old = _compare_paths(path, oldpath); |
349 | - log_debug("%s: Aliased to %s in device cache%s", |
350 | - path, oldpath, prefer_old ? "" : " (preferred name)"); |
351 | - |
352 | - } else |
353 | - log_debug("%s: Added to device cache", path); |
354 | - |
355 | - if (prefer_old) |
356 | - dm_list_add(&dev->aliases, &sl->list); |
357 | - else |
358 | - dm_list_add_h(&dev->aliases, &sl->list); |
359 | - |
360 | - return 1; |
361 | -} |
362 | - |
363 | -/* |
364 | - * Either creates a new dev, or adds an alias to |
365 | - * an existing dev. |
366 | - */ |
367 | -static int _insert_dev(const char *path, dev_t d) |
368 | -{ |
369 | - struct device *dev; |
370 | - static dev_t loopfile_count = 0; |
371 | - int loopfile = 0; |
372 | - char *path_copy; |
373 | - |
374 | - /* Generate pretend device numbers for loopfiles */ |
375 | - if (!d) { |
376 | - if (dm_hash_lookup(_cache.names, path)) |
377 | - return 1; |
378 | - d = ++loopfile_count; |
379 | - loopfile = 1; |
380 | - } |
381 | - |
382 | - /* is this device already registered ? */ |
383 | - if (!(dev = (struct device *) btree_lookup(_cache.devices, |
384 | - (uint32_t) d))) { |
385 | - /* create new device */ |
386 | - if (loopfile) { |
387 | - if (!(dev = dev_create_file(path, NULL, NULL, 0))) |
388 | - return_0; |
389 | - } else if (!(dev = _dev_create(d))) |
390 | - return_0; |
391 | - |
392 | - if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) { |
393 | - log_error("Couldn't insert device into binary tree."); |
394 | - _free(dev); |
395 | - return 0; |
396 | - } |
397 | - } |
398 | - |
399 | - if (!(path_copy = dm_pool_strdup(_cache.mem, path))) { |
400 | - log_error("Failed to duplicate path string."); |
401 | - return 0; |
402 | - } |
403 | - |
404 | - if (!loopfile && !_add_alias(dev, path_copy)) { |
405 | - log_error("Couldn't add alias to dev cache."); |
406 | - return 0; |
407 | - } |
408 | - |
409 | - if (!dm_hash_insert(_cache.names, path_copy, dev)) { |
410 | - log_error("Couldn't add name to hash in dev cache."); |
411 | - return 0; |
412 | - } |
413 | - |
414 | - return 1; |
415 | -} |
416 | - |
417 | -static char *_join(const char *dir, const char *name) |
418 | -{ |
419 | - size_t len = strlen(dir) + strlen(name) + 2; |
420 | - char *r = dm_malloc(len); |
421 | - if (r) |
422 | - snprintf(r, len, "%s/%s", dir, name); |
423 | - |
424 | - return r; |
425 | -} |
426 | - |
427 | -/* |
428 | - * Get rid of extra slashes in the path string. |
429 | - */ |
430 | -static void _collapse_slashes(char *str) |
431 | -{ |
432 | - char *ptr; |
433 | - int was_slash = 0; |
434 | - |
435 | - for (ptr = str; *ptr; ptr++) { |
436 | - if (*ptr == '/') { |
437 | - if (was_slash) |
438 | - continue; |
439 | - |
440 | - was_slash = 1; |
441 | - } else |
442 | - was_slash = 0; |
443 | - *str++ = *ptr; |
444 | - } |
445 | - |
446 | - *str = *ptr; |
447 | -} |
448 | - |
449 | -static int _insert_dir(const char *dir) |
450 | -{ |
451 | - int n, dirent_count, r = 1; |
452 | - struct dirent **dirent; |
453 | - char *path; |
454 | - |
455 | - dirent_count = scandir(dir, &dirent, NULL, alphasort); |
456 | - if (dirent_count > 0) { |
457 | - for (n = 0; n < dirent_count; n++) { |
458 | - if (dirent[n]->d_name[0] == '.') { |
459 | - free(dirent[n]); |
460 | - continue; |
461 | - } |
462 | - |
463 | - if (!(path = _join(dir, dirent[n]->d_name))) |
464 | - return_0; |
465 | - |
466 | - _collapse_slashes(path); |
467 | - r &= _insert(path, 1, 0); |
468 | - dm_free(path); |
469 | - |
470 | - free(dirent[n]); |
471 | - } |
472 | - free(dirent); |
473 | - } |
474 | - |
475 | - return r; |
476 | -} |
477 | - |
478 | -static int _insert_file(const char *path) |
479 | -{ |
480 | - struct stat info; |
481 | - |
482 | - if (stat(path, &info) < 0) { |
483 | - log_sys_very_verbose("stat", path); |
484 | - return 0; |
485 | - } |
486 | - |
487 | - if (!S_ISREG(info.st_mode)) { |
488 | - log_debug("%s: Not a regular file", path); |
489 | - return 0; |
490 | - } |
491 | - |
492 | - if (!_insert_dev(path, 0)) |
493 | - return_0; |
494 | - |
495 | - return 1; |
496 | -} |
497 | - |
498 | -#ifdef UDEV_SYNC_SUPPORT |
499 | - |
500 | -static int _device_in_udev_db(const dev_t d) |
501 | -{ |
502 | - struct udev *udev; |
503 | - struct udev_device *udev_device; |
504 | - |
505 | - if (!(udev = udev_get_library_context())) |
506 | - return_0; |
507 | - |
508 | - if ((udev_device = udev_device_new_from_devnum(udev, 'b', d))) { |
509 | - udev_device_unref(udev_device); |
510 | - return 1; |
511 | - } |
512 | - |
513 | - return 0; |
514 | -} |
515 | - |
516 | -static int _insert_udev_dir(struct udev *udev, const char *dir) |
517 | -{ |
518 | - struct udev_enumerate *udev_enum = NULL; |
519 | - struct udev_list_entry *device_entry, *symlink_entry; |
520 | - const char *entry_name, *node_name, *symlink_name; |
521 | - struct udev_device *device; |
522 | - int r = 1; |
523 | - |
524 | - if (!(udev_enum = udev_enumerate_new(udev))) |
525 | - goto bad; |
526 | - |
527 | - if (udev_enumerate_add_match_subsystem(udev_enum, "block") || |
528 | - udev_enumerate_scan_devices(udev_enum)) |
529 | - goto bad; |
530 | - |
531 | - /* |
532 | - * Report any missing information as "log_very_verbose" only, do not |
533 | - * report it as a "warning" or "error" - the record could be removed |
534 | - * by the time we ask for more info (node name, symlink name...). |
535 | - * Whatever removes *any* block device in the system (even unrelated |
536 | - * to our operation), we would have a warning/error on output then. |
537 | - * That could be misleading. If there's really any problem with missing |
538 | - * information from udev db, we can still have a look at the verbose log. |
539 | - */ |
540 | - udev_list_entry_foreach(device_entry, udev_enumerate_get_list_entry(udev_enum)) { |
541 | - entry_name = udev_list_entry_get_name(device_entry); |
542 | - |
543 | - if (!(device = udev_device_new_from_syspath(udev, entry_name))) { |
544 | - log_very_verbose("udev failed to return a device for entry %s.", |
545 | - entry_name); |
546 | - continue; |
547 | - } |
548 | - |
549 | - if (!(node_name = udev_device_get_devnode(device))) |
550 | - log_very_verbose("udev failed to return a device node for entry %s.", |
551 | - entry_name); |
552 | - else |
553 | - r &= _insert(node_name, 0, 0); |
554 | - |
555 | - udev_list_entry_foreach(symlink_entry, udev_device_get_devlinks_list_entry(device)) { |
556 | - if (!(symlink_name = udev_list_entry_get_name(symlink_entry))) |
557 | - log_very_verbose("udev failed to return a symlink name for entry %s.", |
558 | - entry_name); |
559 | - else |
560 | - r &= _insert(symlink_name, 0, 0); |
561 | - } |
562 | - |
563 | - udev_device_unref(device); |
564 | - } |
565 | - |
566 | - udev_enumerate_unref(udev_enum); |
567 | - return r; |
568 | - |
569 | -bad: |
570 | - log_error("Failed to enumerate udev device list."); |
571 | - udev_enumerate_unref(udev_enum); |
572 | - return 0; |
573 | -} |
574 | - |
575 | -static void _insert_dirs(struct dm_list *dirs) |
576 | -{ |
577 | - struct dir_list *dl; |
578 | - struct udev *udev; |
579 | - int with_udev; |
580 | - |
581 | - with_udev = obtain_device_list_from_udev() && |
582 | - (udev = udev_get_library_context()); |
583 | - |
584 | - dm_list_iterate_items(dl, &_cache.dirs) { |
585 | - if (with_udev) { |
586 | - if (!_insert_udev_dir(udev, dl->dir)) |
587 | - log_debug("%s: Failed to insert devices from " |
588 | - "udev-managed directory to device " |
589 | - "cache fully", dl->dir); |
590 | - } |
591 | - else if (!_insert_dir(dl->dir)) |
592 | - log_debug("%s: Failed to insert devices to " |
593 | - "device cache fully", dl->dir); |
594 | - } |
595 | -} |
596 | - |
597 | -#else /* UDEV_SYNC_SUPPORT */ |
598 | - |
599 | -static int _device_in_udev_db(const dev_t d) |
600 | -{ |
601 | - return 0; |
602 | -} |
603 | - |
604 | -static void _insert_dirs(struct dm_list *dirs) |
605 | -{ |
606 | - struct dir_list *dl; |
607 | - |
608 | - dm_list_iterate_items(dl, &_cache.dirs) |
609 | - _insert_dir(dl->dir); |
610 | -} |
611 | - |
612 | -#endif /* UDEV_SYNC_SUPPORT */ |
613 | - |
614 | -static int _insert(const char *path, int rec, int check_with_udev_db) |
615 | -{ |
616 | - struct stat info; |
617 | - int r = 0; |
618 | - |
619 | - if (stat(path, &info) < 0) { |
620 | - log_sys_very_verbose("stat", path); |
621 | - return 0; |
622 | - } |
623 | - |
624 | - if (check_with_udev_db && !_device_in_udev_db(info.st_rdev)) { |
625 | - log_very_verbose("%s: Not in udev db", path); |
626 | - return 0; |
627 | - } |
628 | - |
629 | - if (S_ISDIR(info.st_mode)) { /* add a directory */ |
630 | - /* check it's not a symbolic link */ |
631 | - if (lstat(path, &info) < 0) { |
632 | - log_sys_very_verbose("lstat", path); |
633 | - return 0; |
634 | - } |
635 | - |
636 | - if (S_ISLNK(info.st_mode)) { |
637 | - log_debug("%s: Symbolic link to directory", path); |
638 | - return 0; |
639 | - } |
640 | - |
641 | - if (rec) |
642 | - r = _insert_dir(path); |
643 | - |
644 | - } else { /* add a device */ |
645 | - if (!S_ISBLK(info.st_mode)) { |
646 | - log_debug("%s: Not a block device", path); |
647 | - return 0; |
648 | - } |
649 | - |
650 | - if (!_insert_dev(path, info.st_rdev)) |
651 | - return_0; |
652 | - |
653 | - r = 1; |
654 | - } |
655 | - |
656 | - return r; |
657 | -} |
658 | - |
659 | -static void _full_scan(int dev_scan) |
660 | -{ |
661 | - struct dir_list *dl; |
662 | - |
663 | - if (_cache.has_scanned && !dev_scan) |
664 | - return; |
665 | - |
666 | - _insert_dirs(&_cache.dirs); |
667 | - |
668 | - dm_list_iterate_items(dl, &_cache.files) |
669 | - _insert_file(dl->dir); |
670 | - |
671 | - _cache.has_scanned = 1; |
672 | - init_full_scan_done(1); |
673 | -} |
674 | - |
675 | -int dev_cache_has_scanned(void) |
676 | -{ |
677 | - return _cache.has_scanned; |
678 | -} |
679 | - |
680 | -void dev_cache_scan(int do_scan) |
681 | -{ |
682 | - if (!do_scan) |
683 | - _cache.has_scanned = 1; |
684 | - else |
685 | - _full_scan(1); |
686 | -} |
687 | - |
688 | -static int _init_preferred_names(struct cmd_context *cmd) |
689 | -{ |
690 | - const struct dm_config_node *cn; |
691 | - const struct dm_config_value *v; |
692 | - struct dm_pool *scratch = NULL; |
693 | - const char **regex; |
694 | - unsigned count = 0; |
695 | - int i, r = 0; |
696 | - |
697 | - _cache.preferred_names_matcher = NULL; |
698 | - |
699 | - if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) || |
700 | - cn->v->type == DM_CFG_EMPTY_ARRAY) { |
701 | - log_very_verbose("devices/preferred_names not found in config file: " |
702 | - "using built-in preferences"); |
703 | - return 1; |
704 | - } |
705 | - |
706 | - for (v = cn->v; v; v = v->next) { |
707 | - if (v->type != DM_CFG_STRING) { |
708 | - log_error("preferred_names patterns must be enclosed in quotes"); |
709 | - return 0; |
710 | - } |
711 | - |
712 | - count++; |
713 | - } |
714 | - |
715 | - if (!(scratch = dm_pool_create("preferred device name matcher", 1024))) |
716 | - return_0; |
717 | - |
718 | - if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) { |
719 | - log_error("Failed to allocate preferred device name " |
720 | - "pattern list."); |
721 | - goto out; |
722 | - } |
723 | - |
724 | - for (v = cn->v, i = count - 1; v; v = v->next, i--) { |
725 | - if (!(regex[i] = dm_pool_strdup(scratch, v->v.str))) { |
726 | - log_error("Failed to allocate a preferred device name " |
727 | - "pattern."); |
728 | - goto out; |
729 | - } |
730 | - } |
731 | - |
732 | - if (!(_cache.preferred_names_matcher = |
733 | - dm_regex_create(_cache.mem, regex, count))) { |
734 | - log_error("Preferred device name pattern matcher creation failed."); |
735 | - goto out; |
736 | - } |
737 | - |
738 | - r = 1; |
739 | - |
740 | -out: |
741 | - dm_pool_destroy(scratch); |
742 | - |
743 | - return r; |
744 | -} |
745 | - |
746 | -int dev_cache_init(struct cmd_context *cmd) |
747 | -{ |
748 | - _cache.names = NULL; |
749 | - _cache.has_scanned = 0; |
750 | - |
751 | - if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) |
752 | - return_0; |
753 | - |
754 | - if (!(_cache.names = dm_hash_create(128))) { |
755 | - dm_pool_destroy(_cache.mem); |
756 | - _cache.mem = 0; |
757 | - return_0; |
758 | - } |
759 | - |
760 | - if (!(_cache.devices = btree_create(_cache.mem))) { |
761 | - log_error("Couldn't create binary tree for dev-cache."); |
762 | - goto bad; |
763 | - } |
764 | - |
765 | - if (!(_cache.dev_dir = _strdup(cmd->dev_dir))) { |
766 | - log_error("strdup dev_dir failed."); |
767 | - goto bad; |
768 | - } |
769 | - |
770 | - dm_list_init(&_cache.dirs); |
771 | - dm_list_init(&_cache.files); |
772 | - |
773 | - if (!_init_preferred_names(cmd)) |
774 | - goto_bad; |
775 | - |
776 | - return 1; |
777 | - |
778 | - bad: |
779 | - dev_cache_exit(); |
780 | - return 0; |
781 | -} |
782 | - |
783 | -static void _check_closed(struct device *dev) |
784 | -{ |
785 | - if (dev->fd >= 0) |
786 | - log_error("Device '%s' has been left open.", dev_name(dev)); |
787 | -} |
788 | - |
789 | -static void _check_for_open_devices(void) |
790 | -{ |
791 | - dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed); |
792 | -} |
793 | - |
794 | -void dev_cache_exit(void) |
795 | -{ |
796 | - if (_cache.names) |
797 | - _check_for_open_devices(); |
798 | - |
799 | - if (_cache.preferred_names_matcher) |
800 | - _cache.preferred_names_matcher = NULL; |
801 | - |
802 | - if (_cache.mem) { |
803 | - dm_pool_destroy(_cache.mem); |
804 | - _cache.mem = NULL; |
805 | - } |
806 | - |
807 | - if (_cache.names) { |
808 | - dm_hash_destroy(_cache.names); |
809 | - _cache.names = NULL; |
810 | - } |
811 | - |
812 | - _cache.devices = NULL; |
813 | - _cache.has_scanned = 0; |
814 | - dm_list_init(&_cache.dirs); |
815 | - dm_list_init(&_cache.files); |
816 | -} |
817 | - |
818 | -int dev_cache_add_dir(const char *path) |
819 | -{ |
820 | - struct dir_list *dl; |
821 | - struct stat st; |
822 | - |
823 | - if (stat(path, &st)) { |
824 | - log_error("Ignoring %s: %s", path, strerror(errno)); |
825 | - /* But don't fail */ |
826 | - return 1; |
827 | - } |
828 | - |
829 | - if (!S_ISDIR(st.st_mode)) { |
830 | - log_error("Ignoring %s: Not a directory", path); |
831 | - return 1; |
832 | - } |
833 | - |
834 | - if (!(dl = _zalloc(sizeof(*dl) + strlen(path) + 1))) { |
835 | - log_error("dir_list allocation failed"); |
836 | - return 0; |
837 | - } |
838 | - |
839 | - strcpy(dl->dir, path); |
840 | - dm_list_add(&_cache.dirs, &dl->list); |
841 | - return 1; |
842 | -} |
843 | - |
844 | -int dev_cache_add_loopfile(const char *path) |
845 | -{ |
846 | - struct dir_list *dl; |
847 | - struct stat st; |
848 | - |
849 | - if (stat(path, &st)) { |
850 | - log_error("Ignoring %s: %s", path, strerror(errno)); |
851 | - /* But don't fail */ |
852 | - return 1; |
853 | - } |
854 | - |
855 | - if (!S_ISREG(st.st_mode)) { |
856 | - log_error("Ignoring %s: Not a regular file", path); |
857 | - return 1; |
858 | - } |
859 | - |
860 | - if (!(dl = _zalloc(sizeof(*dl) + strlen(path) + 1))) { |
861 | - log_error("dir_list allocation failed for file"); |
862 | - return 0; |
863 | - } |
864 | - |
865 | - strcpy(dl->dir, path); |
866 | - dm_list_add(&_cache.files, &dl->list); |
867 | - return 1; |
868 | -} |
869 | - |
870 | -/* Check cached device name is still valid before returning it */ |
871 | -/* This should be a rare occurrence */ |
872 | -/* set quiet if the cache is expected to be out-of-date */ |
873 | -/* FIXME Make rest of code pass/cache struct device instead of dev_name */ |
874 | -const char *dev_name_confirmed(struct device *dev, int quiet) |
875 | -{ |
876 | - struct stat buf; |
877 | - const char *name; |
878 | - int r; |
879 | - |
880 | - if ((dev->flags & DEV_REGULAR)) |
881 | - return dev_name(dev); |
882 | - |
883 | - while ((r = stat(name = dm_list_item(dev->aliases.n, |
884 | - struct str_list)->str, &buf)) || |
885 | - (buf.st_rdev != dev->dev)) { |
886 | - if (r < 0) { |
887 | - if (quiet) |
888 | - log_sys_debug("stat", name); |
889 | - else |
890 | - log_sys_error("stat", name); |
891 | - } |
892 | - if (quiet) |
893 | - log_debug("Path %s no longer valid for device(%d,%d)", |
894 | - name, (int) MAJOR(dev->dev), |
895 | - (int) MINOR(dev->dev)); |
896 | - else |
897 | - log_error("Path %s no longer valid for device(%d,%d)", |
898 | - name, (int) MAJOR(dev->dev), |
899 | - (int) MINOR(dev->dev)); |
900 | - |
901 | - /* Remove the incorrect hash entry */ |
902 | - dm_hash_remove(_cache.names, name); |
903 | - |
904 | - /* Leave list alone if there isn't an alternative name */ |
905 | - /* so dev_name will always find something to return. */ |
906 | - /* Otherwise add the name to the correct device. */ |
907 | - if (dm_list_size(&dev->aliases) > 1) { |
908 | - dm_list_del(dev->aliases.n); |
909 | - if (!r) |
910 | - _insert(name, 0, obtain_device_list_from_udev()); |
911 | - continue; |
912 | - } |
913 | - |
914 | - /* Scanning issues this inappropriately sometimes. */ |
915 | - log_debug("Aborting - please provide new pathname for what " |
916 | - "used to be %s", name); |
917 | - return NULL; |
918 | - } |
919 | - |
920 | - return dev_name(dev); |
921 | -} |
922 | - |
923 | -struct device *dev_cache_get(const char *name, struct dev_filter *f) |
924 | -{ |
925 | - struct stat buf; |
926 | - struct device *d = (struct device *) dm_hash_lookup(_cache.names, name); |
927 | - |
928 | - if (d && (d->flags & DEV_REGULAR)) |
929 | - return d; |
930 | - |
931 | - /* If the entry's wrong, remove it */ |
932 | - if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) { |
933 | - dm_hash_remove(_cache.names, name); |
934 | - d = NULL; |
935 | - } |
936 | - |
937 | - if (!d) { |
938 | - _insert(name, 0, obtain_device_list_from_udev()); |
939 | - d = (struct device *) dm_hash_lookup(_cache.names, name); |
940 | - if (!d) { |
941 | - _full_scan(0); |
942 | - d = (struct device *) dm_hash_lookup(_cache.names, name); |
943 | - } |
944 | - } |
945 | - |
946 | - return (d && (!f || (d->flags & DEV_REGULAR) || |
947 | - f->passes_filter(f, d))) ? d : NULL; |
948 | -} |
949 | - |
950 | -static struct device *_dev_cache_seek_devt(dev_t dev) |
951 | -{ |
952 | - struct device *d = NULL; |
953 | - struct dm_hash_node *n = dm_hash_get_first(_cache.names); |
954 | - while (n) { |
955 | - d = dm_hash_get_data(_cache.names, n); |
956 | - if (d->dev == dev) |
957 | - return d; |
958 | - n = dm_hash_get_next(_cache.names, n); |
959 | - } |
960 | - return NULL; |
961 | -} |
962 | - |
963 | -/* |
964 | - * TODO This is very inefficient. We probably want a hash table indexed by |
965 | - * major:minor for keys to speed up these lookups. |
966 | - */ |
967 | -struct device *dev_cache_get_by_devt(dev_t dev, struct dev_filter *f) |
968 | -{ |
969 | - struct device *d = _dev_cache_seek_devt(dev); |
970 | - |
971 | - if (d && (d->flags & DEV_REGULAR)) |
972 | - return d; |
973 | - |
974 | - if (!d) { |
975 | - _full_scan(0); |
976 | - d = _dev_cache_seek_devt(dev); |
977 | - } |
978 | - |
979 | - return (d && (!f || (d->flags & DEV_REGULAR) || |
980 | - f->passes_filter(f, d))) ? d : NULL; |
981 | -} |
982 | - |
983 | -struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan) |
984 | -{ |
985 | - struct dev_iter *di = dm_malloc(sizeof(*di)); |
986 | - |
987 | - if (!di) { |
988 | - log_error("dev_iter allocation failed"); |
989 | - return NULL; |
990 | - } |
991 | - |
992 | - if (dev_scan && !trust_cache()) { |
993 | - /* Flag gets reset between each command */ |
994 | - if (!full_scan_done()) { |
995 | - if (f && f->wipe) |
996 | - f->wipe(f); /* Calls _full_scan(1) */ |
997 | - else |
998 | - _full_scan(1); |
999 | - } |
1000 | - } else |
1001 | - _full_scan(0); |
1002 | - |
1003 | - di->current = btree_first(_cache.devices); |
1004 | - di->filter = f; |
1005 | - if (di->filter) |
1006 | - di->filter->use_count++; |
1007 | - |
1008 | - return di; |
1009 | -} |
1010 | - |
1011 | -void dev_iter_destroy(struct dev_iter *iter) |
1012 | -{ |
1013 | - if (iter->filter) |
1014 | - iter->filter->use_count--; |
1015 | - dm_free(iter); |
1016 | -} |
1017 | - |
1018 | -static struct device *_iter_next(struct dev_iter *iter) |
1019 | -{ |
1020 | - struct device *d = btree_get_data(iter->current); |
1021 | - iter->current = btree_next(iter->current); |
1022 | - return d; |
1023 | -} |
1024 | - |
1025 | -struct device *dev_iter_get(struct dev_iter *iter) |
1026 | -{ |
1027 | - while (iter->current) { |
1028 | - struct device *d = _iter_next(iter); |
1029 | - if (!iter->filter || (d->flags & DEV_REGULAR) || |
1030 | - iter->filter->passes_filter(iter->filter, d)) |
1031 | - return d; |
1032 | - } |
1033 | - |
1034 | - return NULL; |
1035 | -} |
1036 | - |
1037 | -void dev_reset_error_count(struct cmd_context *cmd) |
1038 | -{ |
1039 | - struct dev_iter iter; |
1040 | - |
1041 | - if (!_cache.devices) |
1042 | - return; |
1043 | - |
1044 | - iter.current = btree_first(_cache.devices); |
1045 | - while (iter.current) |
1046 | - _iter_next(&iter)->error_count = 0; |
1047 | -} |
1048 | - |
1049 | -int dev_fd(struct device *dev) |
1050 | -{ |
1051 | - return dev->fd; |
1052 | -} |
1053 | - |
1054 | -const char *dev_name(const struct device *dev) |
1055 | -{ |
1056 | - return (dev) ? dm_list_item(dev->aliases.n, struct str_list)->str : |
1057 | - "unknown device"; |
1058 | -} |
1059 | |
1060 | === removed directory '.pc/dirs.patch' |
1061 | === removed directory '.pc/dirs.patch/daemons' |
1062 | === removed directory '.pc/dirs.patch/daemons/dmeventd' |
1063 | === removed file '.pc/dirs.patch/daemons/dmeventd/Makefile.in' |
1064 | --- .pc/dirs.patch/daemons/dmeventd/Makefile.in 2012-05-27 19:05:21 +0000 |
1065 | +++ .pc/dirs.patch/daemons/dmeventd/Makefile.in 1970-01-01 00:00:00 +0000 |
1066 | @@ -1,108 +0,0 @@ |
1067 | -# |
1068 | -# Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved. |
1069 | -# |
1070 | -# This file is part of the device-mapper userspace tools. |
1071 | -# |
1072 | -# This copyrighted material is made available to anyone wishing to use, |
1073 | -# modify, copy, or redistribute it subject to the terms and conditions |
1074 | -# of the GNU Lesser General Public License v.2.1. |
1075 | -# |
1076 | -# You should have received a copy of the GNU Lesser General Public License |
1077 | -# along with this program; if not, write to the Free Software Foundation, |
1078 | -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1079 | - |
1080 | -srcdir = @srcdir@ |
1081 | -top_srcdir = @top_srcdir@ |
1082 | -top_builddir = @top_builddir@ |
1083 | - |
1084 | -SOURCES = libdevmapper-event.c |
1085 | -SOURCES2 = dmeventd.c |
1086 | - |
1087 | -TARGETS = dmeventd |
1088 | - |
1089 | -.PHONY: install_lib_dynamic install_lib_static install_include \ |
1090 | - install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \ |
1091 | - install_lib install_dmeventd |
1092 | - |
1093 | -INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic |
1094 | -INSTALL_LIB_TARGETS = install_lib_dynamic |
1095 | - |
1096 | -LIB_NAME = libdevmapper-event |
1097 | -ifeq ("@STATIC_LINK@", "yes") |
1098 | - LIB_STATIC = $(LIB_NAME).a |
1099 | - TARGETS += $(LIB_STATIC) dmeventd.static |
1100 | - INSTALL_DMEVENTD_TARGETS += install_dmeventd_static |
1101 | - INSTALL_LIB_TARGETS += install_lib_static |
1102 | -endif |
1103 | - |
1104 | -LIB_VERSION = $(LIB_VERSION_DM) |
1105 | -LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) |
1106 | - |
1107 | -CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a |
1108 | - |
1109 | -ifneq ($(MAKECMDGOALS),device-mapper) |
1110 | - SUBDIRS+=plugins |
1111 | -endif |
1112 | - |
1113 | -CFLOW_LIST = $(SOURCES) |
1114 | -CFLOW_LIST_TARGET = $(LIB_NAME).cflow |
1115 | -CFLOW_TARGET = dmeventd |
1116 | - |
1117 | -EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h |
1118 | -EXPORTED_FN_PREFIX = dm_event |
1119 | - |
1120 | -include $(top_builddir)/make.tmpl |
1121 | - |
1122 | -all: device-mapper |
1123 | -device-mapper: $(TARGETS) |
1124 | - |
1125 | -LIBS += -ldevmapper |
1126 | -LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS) |
1127 | - |
1128 | -dmeventd: $(LIB_SHARED) dmeventd.o |
1129 | - $(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \ |
1130 | - $(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic |
1131 | - |
1132 | -dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a |
1133 | - $(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \ |
1134 | - dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS) |
1135 | - |
1136 | -ifeq ("@PKGCONFIG@", "yes") |
1137 | - INSTALL_LIB_TARGETS += install_pkgconfig |
1138 | -endif |
1139 | - |
1140 | -ifneq ("$(CFLOW_CMD)", "") |
1141 | -CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) |
1142 | --include $(top_builddir)/libdm/libdevmapper.cflow |
1143 | --include $(top_builddir)/lib/liblvm-internal.cflow |
1144 | --include $(top_builddir)/lib/liblvm2cmd.cflow |
1145 | --include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow |
1146 | --include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow |
1147 | -endif |
1148 | - |
1149 | -install_include: $(srcdir)/libdevmapper-event.h |
1150 | - $(INSTALL_DATA) -D $< $(includedir)/$(<F) |
1151 | - |
1152 | -install_pkgconfig: libdevmapper-event.pc |
1153 | - $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc |
1154 | - |
1155 | -install_lib_dynamic: install_lib_shared |
1156 | - |
1157 | -install_lib_static: $(LIB_STATIC) |
1158 | - $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F) |
1159 | - |
1160 | -install_lib: $(INSTALL_LIB_TARGETS) |
1161 | - |
1162 | -install_dmeventd_dynamic: dmeventd |
1163 | - $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F) |
1164 | - |
1165 | -install_dmeventd_static: dmeventd.static |
1166 | - $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F) |
1167 | - |
1168 | -install_dmeventd: $(INSTALL_DMEVENTD_TARGETS) |
1169 | - |
1170 | -install: install_include install_lib install_dmeventd |
1171 | - |
1172 | -install_device-mapper: install_include install_lib install_dmeventd |
1173 | - |
1174 | -DISTCLEAN_TARGETS += libdevmapper-event.pc |
1175 | |
1176 | === removed file '.pc/dirs.patch/daemons/dmeventd/dmeventd.c' |
1177 | --- .pc/dirs.patch/daemons/dmeventd/dmeventd.c 2013-03-03 12:33:47 +0000 |
1178 | +++ .pc/dirs.patch/daemons/dmeventd/dmeventd.c 1970-01-01 00:00:00 +0000 |
1179 | @@ -1,2026 +0,0 @@ |
1180 | -/* |
1181 | - * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
1182 | - * |
1183 | - * This file is part of the device-mapper userspace tools. |
1184 | - * |
1185 | - * This copyrighted material is made available to anyone wishing to use, |
1186 | - * modify, copy, or redistribute it subject to the terms and conditions |
1187 | - * of the GNU Lesser General Public License v.2.1. |
1188 | - * |
1189 | - * You should have received a copy of the GNU Lesser General Public License |
1190 | - * along with this program; if not, write to the Free Software Foundation, |
1191 | - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1192 | - */ |
1193 | - |
1194 | -/* |
1195 | - * dmeventd - dm event daemon to monitor active mapped devices |
1196 | - */ |
1197 | - |
1198 | -#define _GNU_SOURCE |
1199 | -#define _FILE_OFFSET_BITS 64 |
1200 | - |
1201 | -#include "configure.h" |
1202 | -#include "libdevmapper.h" |
1203 | -#include "libdevmapper-event.h" |
1204 | -#include "dmeventd.h" |
1205 | -//#include "libmultilog.h" |
1206 | -#include "dm-logging.h" |
1207 | - |
1208 | -#include <dlfcn.h> |
1209 | -#include <errno.h> |
1210 | -#include <pthread.h> |
1211 | -#include <sys/file.h> |
1212 | -#include <sys/stat.h> |
1213 | -#include <sys/wait.h> |
1214 | -#include <sys/time.h> |
1215 | -#include <sys/resource.h> |
1216 | -#include <unistd.h> |
1217 | -#include <signal.h> |
1218 | -#include <arpa/inet.h> /* for htonl, ntohl */ |
1219 | - |
1220 | -#ifdef linux |
1221 | -/* |
1222 | - * Kernel version 2.6.36 and higher has |
1223 | - * new OOM killer adjustment interface. |
1224 | - */ |
1225 | -# define OOM_ADJ_FILE_OLD "/proc/self/oom_adj" |
1226 | -# define OOM_ADJ_FILE "/proc/self/oom_score_adj" |
1227 | - |
1228 | -/* From linux/oom.h */ |
1229 | -/* Old interface */ |
1230 | -# define OOM_DISABLE (-17) |
1231 | -# define OOM_ADJUST_MIN (-16) |
1232 | -/* New interface */ |
1233 | -# define OOM_SCORE_ADJ_MIN (-1000) |
1234 | - |
1235 | -/* Systemd on-demand activation support */ |
1236 | -# define SD_ACTIVATION_ENV_VAR_NAME "SD_ACTIVATION" |
1237 | -# define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID" |
1238 | -# define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS" |
1239 | -# define SD_LISTEN_FDS_START 3 |
1240 | -# define SD_FD_FIFO_SERVER SD_LISTEN_FDS_START |
1241 | -# define SD_FD_FIFO_CLIENT (SD_LISTEN_FDS_START + 1) |
1242 | - |
1243 | -#endif |
1244 | - |
1245 | -/* FIXME We use syslog for now, because multilog is not yet implemented */ |
1246 | -#include <syslog.h> |
1247 | - |
1248 | -static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */ |
1249 | -static volatile sig_atomic_t _thread_registries_empty = 1; /* registries are empty initially */ |
1250 | - |
1251 | -/* List (un)link macros. */ |
1252 | -#define LINK(x, head) dm_list_add(head, &(x)->list) |
1253 | -#define LINK_DSO(dso) LINK(dso, &_dso_registry) |
1254 | -#define LINK_THREAD(thread) LINK(thread, &_thread_registry) |
1255 | - |
1256 | -#define UNLINK(x) dm_list_del(&(x)->list) |
1257 | -#define UNLINK_DSO(x) UNLINK(x) |
1258 | -#define UNLINK_THREAD(x) UNLINK(x) |
1259 | - |
1260 | -#define DAEMON_NAME "dmeventd" |
1261 | - |
1262 | -/* |
1263 | - Global mutex for thread list access. Has to be held when: |
1264 | - - iterating thread list |
1265 | - - adding or removing elements from thread list |
1266 | - - changing or reading thread_status's fields: |
1267 | - processing, status, events |
1268 | - Use _lock_mutex() and _unlock_mutex() to hold/release it |
1269 | -*/ |
1270 | -static pthread_mutex_t _global_mutex; |
1271 | - |
1272 | -/* |
1273 | - There are three states a thread can attain (see struct |
1274 | - thread_status, field int status): |
1275 | - |
1276 | - - DM_THREAD_RUNNING: thread has started up and is either working or |
1277 | - waiting for events... transitions to either SHUTDOWN or DONE |
1278 | - - DM_THREAD_SHUTDOWN: thread is still doing something, but it is |
1279 | - supposed to terminate (and transition to DONE) as soon as it |
1280 | - finishes whatever it was doing at the point of flipping state to |
1281 | - SHUTDOWN... the thread is still on the thread list |
1282 | - - DM_THREAD_DONE: thread has terminated and has been moved over to |
1283 | - unused thread list, cleanup pending |
1284 | - */ |
1285 | -#define DM_THREAD_RUNNING 0 |
1286 | -#define DM_THREAD_SHUTDOWN 1 |
1287 | -#define DM_THREAD_DONE 2 |
1288 | - |
1289 | -#define THREAD_STACK_SIZE (300*1024) |
1290 | - |
1291 | -int dmeventd_debug = 0; |
1292 | -static int _systemd_activation = 0; |
1293 | -static int _foreground = 0; |
1294 | -static int _restart = 0; |
1295 | -static char **_initial_registrations = 0; |
1296 | - |
1297 | -/* Data kept about a DSO. */ |
1298 | -struct dso_data { |
1299 | - struct dm_list list; |
1300 | - |
1301 | - char *dso_name; /* DSO name (eg, "evms", "dmraid", "lvm2"). */ |
1302 | - |
1303 | - void *dso_handle; /* Opaque handle as returned from dlopen(). */ |
1304 | - unsigned int ref_count; /* Library reference count. */ |
1305 | - |
1306 | - /* |
1307 | - * Event processing. |
1308 | - * |
1309 | - * The DSO can do whatever appropriate steps if an event |
1310 | - * happens such as changing the mapping in case a mirror |
1311 | - * fails, update the application metadata etc. |
1312 | - * |
1313 | - * This function gets a dm_task that is a result of |
1314 | - * DM_DEVICE_WAITEVENT ioctl (results equivalent to |
1315 | - * DM_DEVICE_STATUS). It should not destroy it. |
1316 | - * The caller must dispose of the task. |
1317 | - */ |
1318 | - void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user); |
1319 | - |
1320 | - /* |
1321 | - * Device registration. |
1322 | - * |
1323 | - * When an application registers a device for an event, the DSO |
1324 | - * can carry out appropriate steps so that a later call to |
1325 | - * the process_event() function is sane (eg, read metadata |
1326 | - * and activate a mapping). |
1327 | - */ |
1328 | - int (*register_device)(const char *device, const char *uuid, int major, |
1329 | - int minor, void **user); |
1330 | - |
1331 | - /* |
1332 | - * Device unregistration. |
1333 | - * |
1334 | - * In case all devices of a mapping (eg, RAID10) are unregistered |
1335 | - * for events, the DSO can recognize this and carry out appropriate |
1336 | - * steps (eg, deactivate mapping, metadata update). |
1337 | - */ |
1338 | - int (*unregister_device)(const char *device, const char *uuid, |
1339 | - int major, int minor, void **user); |
1340 | -}; |
1341 | -static DM_LIST_INIT(_dso_registry); |
1342 | - |
1343 | -/* Structure to keep parsed register variables from client message. */ |
1344 | -struct message_data { |
1345 | - char *id; |
1346 | - char *dso_name; /* Name of DSO. */ |
1347 | - char *device_uuid; /* Mapped device path. */ |
1348 | - union { |
1349 | - char *str; /* Events string as fetched from message. */ |
1350 | - enum dm_event_mask field; /* Events bitfield. */ |
1351 | - } events; |
1352 | - union { |
1353 | - char *str; |
1354 | - uint32_t secs; |
1355 | - } timeout; |
1356 | - struct dm_event_daemon_message *msg; /* Pointer to message buffer. */ |
1357 | -}; |
1358 | - |
1359 | -/* |
1360 | - * Housekeeping of thread+device states. |
1361 | - * |
1362 | - * One thread per mapped device which can block on it until an event |
1363 | - * occurs and the event processing function of the DSO gets called. |
1364 | - */ |
1365 | -struct thread_status { |
1366 | - struct dm_list list; |
1367 | - |
1368 | - pthread_t thread; |
1369 | - |
1370 | - struct dso_data *dso_data; /* DSO this thread accesses. */ |
1371 | - |
1372 | - struct { |
1373 | - char *uuid; |
1374 | - char *name; |
1375 | - int major, minor; |
1376 | - } device; |
1377 | - uint32_t event_nr; /* event number */ |
1378 | - int processing; /* Set when event is being processed */ |
1379 | - |
1380 | - int status; /* see DM_THREAD_{RUNNING,SHUTDOWN,DONE} |
1381 | - constants above */ |
1382 | - enum dm_event_mask events; /* bitfield for event filter. */ |
1383 | - enum dm_event_mask current_events; /* bitfield for occured events. */ |
1384 | - struct dm_task *current_task; |
1385 | - time_t next_time; |
1386 | - uint32_t timeout; |
1387 | - struct dm_list timeout_list; |
1388 | - void *dso_private; /* dso per-thread status variable */ |
1389 | -}; |
1390 | -static DM_LIST_INIT(_thread_registry); |
1391 | -static DM_LIST_INIT(_thread_registry_unused); |
1392 | - |
1393 | -static int _timeout_running; |
1394 | -static DM_LIST_INIT(_timeout_registry); |
1395 | -static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER; |
1396 | -static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER; |
1397 | - |
1398 | -/* Allocate/free the status structure for a monitoring thread. */ |
1399 | -static struct thread_status *_alloc_thread_status(struct message_data *data, |
1400 | - struct dso_data *dso_data) |
1401 | -{ |
1402 | - struct thread_status *ret = (typeof(ret)) dm_zalloc(sizeof(*ret)); |
1403 | - |
1404 | - if (!ret) |
1405 | - return NULL; |
1406 | - |
1407 | - if (!(ret->device.uuid = dm_strdup(data->device_uuid))) { |
1408 | - dm_free(ret); |
1409 | - return NULL; |
1410 | - } |
1411 | - |
1412 | - ret->current_task = NULL; |
1413 | - ret->device.name = NULL; |
1414 | - ret->device.major = ret->device.minor = 0; |
1415 | - ret->dso_data = dso_data; |
1416 | - ret->events = data->events.field; |
1417 | - ret->timeout = data->timeout.secs; |
1418 | - dm_list_init(&ret->timeout_list); |
1419 | - |
1420 | - return ret; |
1421 | -} |
1422 | - |
1423 | -static void _lib_put(struct dso_data *data); |
1424 | -static void _free_thread_status(struct thread_status *thread) |
1425 | -{ |
1426 | - _lib_put(thread->dso_data); |
1427 | - if (thread->current_task) |
1428 | - dm_task_destroy(thread->current_task); |
1429 | - dm_free(thread->device.uuid); |
1430 | - dm_free(thread->device.name); |
1431 | - dm_free(thread); |
1432 | -} |
1433 | - |
1434 | -/* Allocate/free DSO data. */ |
1435 | -static struct dso_data *_alloc_dso_data(struct message_data *data) |
1436 | -{ |
1437 | - struct dso_data *ret = (typeof(ret)) dm_zalloc(sizeof(*ret)); |
1438 | - |
1439 | - if (!ret) |
1440 | - return NULL; |
1441 | - |
1442 | - if (!(ret->dso_name = dm_strdup(data->dso_name))) { |
1443 | - dm_free(ret); |
1444 | - return NULL; |
1445 | - } |
1446 | - |
1447 | - return ret; |
1448 | -} |
1449 | - |
1450 | -/* Create a device monitoring thread. */ |
1451 | -static int _pthread_create_smallstack(pthread_t *t, void *(*fun)(void *), void *arg) |
1452 | -{ |
1453 | - pthread_attr_t attr; |
1454 | - pthread_attr_init(&attr); |
1455 | - /* |
1456 | - * We use a smaller stack since it gets preallocated in its entirety |
1457 | - */ |
1458 | - pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE); |
1459 | - return pthread_create(t, &attr, fun, arg); |
1460 | -} |
1461 | - |
1462 | -static void _free_dso_data(struct dso_data *data) |
1463 | -{ |
1464 | - dm_free(data->dso_name); |
1465 | - dm_free(data); |
1466 | -} |
1467 | - |
1468 | -/* |
1469 | - * Fetch a string off src and duplicate it into *ptr. |
1470 | - * Pay attention to zero-length strings. |
1471 | - */ |
1472 | -/* FIXME? move to libdevmapper to share with the client lib (need to |
1473 | - make delimiter a parameter then) */ |
1474 | -static int _fetch_string(char **ptr, char **src, const int delimiter) |
1475 | -{ |
1476 | - int ret = 0; |
1477 | - char *p; |
1478 | - size_t len; |
1479 | - |
1480 | - if ((p = strchr(*src, delimiter))) |
1481 | - *p = 0; |
1482 | - |
1483 | - if ((*ptr = dm_strdup(*src))) { |
1484 | - if ((len = strlen(*ptr))) |
1485 | - *src += len; |
1486 | - else { |
1487 | - dm_free(*ptr); |
1488 | - *ptr = NULL; |
1489 | - } |
1490 | - |
1491 | - (*src)++; |
1492 | - ret = 1; |
1493 | - } |
1494 | - |
1495 | - if (p) |
1496 | - *p = delimiter; |
1497 | - |
1498 | - return ret; |
1499 | -} |
1500 | - |
1501 | -/* Free message memory. */ |
1502 | -static void _free_message(struct message_data *message_data) |
1503 | -{ |
1504 | - dm_free(message_data->id); |
1505 | - dm_free(message_data->dso_name); |
1506 | - |
1507 | - dm_free(message_data->device_uuid); |
1508 | - |
1509 | -} |
1510 | - |
1511 | -/* Parse a register message from the client. */ |
1512 | -static int _parse_message(struct message_data *message_data) |
1513 | -{ |
1514 | - int ret = 0; |
1515 | - char *p = message_data->msg->data; |
1516 | - struct dm_event_daemon_message *msg = message_data->msg; |
1517 | - |
1518 | - if (!msg->data) |
1519 | - return 0; |
1520 | - |
1521 | - /* |
1522 | - * Retrieve application identifier, mapped device |
1523 | - * path and events # string from message. |
1524 | - */ |
1525 | - if (_fetch_string(&message_data->id, &p, ' ') && |
1526 | - _fetch_string(&message_data->dso_name, &p, ' ') && |
1527 | - _fetch_string(&message_data->device_uuid, &p, ' ') && |
1528 | - _fetch_string(&message_data->events.str, &p, ' ') && |
1529 | - _fetch_string(&message_data->timeout.str, &p, ' ')) { |
1530 | - if (message_data->events.str) { |
1531 | - enum dm_event_mask i = atoi(message_data->events.str); |
1532 | - |
1533 | - /* |
1534 | - * Free string representaion of events. |
1535 | - * Not needed an more. |
1536 | - */ |
1537 | - dm_free(message_data->events.str); |
1538 | - message_data->events.field = i; |
1539 | - } |
1540 | - if (message_data->timeout.str) { |
1541 | - uint32_t secs = atoi(message_data->timeout.str); |
1542 | - dm_free(message_data->timeout.str); |
1543 | - message_data->timeout.secs = secs ? secs : |
1544 | - DM_EVENT_DEFAULT_TIMEOUT; |
1545 | - } |
1546 | - |
1547 | - ret = 1; |
1548 | - } |
1549 | - |
1550 | - dm_free(msg->data); |
1551 | - msg->data = NULL; |
1552 | - msg->size = 0; |
1553 | - return ret; |
1554 | -}; |
1555 | - |
1556 | -/* Global mutex to lock access to lists et al. See _global_mutex |
1557 | - above. */ |
1558 | -static int _lock_mutex(void) |
1559 | -{ |
1560 | - return pthread_mutex_lock(&_global_mutex); |
1561 | -} |
1562 | - |
1563 | -static int _unlock_mutex(void) |
1564 | -{ |
1565 | - return pthread_mutex_unlock(&_global_mutex); |
1566 | -} |
1567 | - |
1568 | -/* Check, if a device exists. */ |
1569 | -static int _fill_device_data(struct thread_status *ts) |
1570 | -{ |
1571 | - struct dm_task *dmt; |
1572 | - struct dm_info dmi; |
1573 | - |
1574 | - if (!ts->device.uuid) |
1575 | - return 0; |
1576 | - |
1577 | - ts->device.name = NULL; |
1578 | - ts->device.major = ts->device.minor = 0; |
1579 | - |
1580 | - dmt = dm_task_create(DM_DEVICE_INFO); |
1581 | - if (!dmt) |
1582 | - return 0; |
1583 | - |
1584 | - if (!dm_task_set_uuid(dmt, ts->device.uuid)) |
1585 | - goto fail; |
1586 | - |
1587 | - if (!dm_task_run(dmt)) |
1588 | - goto fail; |
1589 | - |
1590 | - ts->device.name = dm_strdup(dm_task_get_name(dmt)); |
1591 | - if (!ts->device.name) |
1592 | - goto fail; |
1593 | - |
1594 | - if (!dm_task_get_info(dmt, &dmi)) |
1595 | - goto fail; |
1596 | - |
1597 | - ts->device.major = dmi.major; |
1598 | - ts->device.minor = dmi.minor; |
1599 | - |
1600 | - dm_task_destroy(dmt); |
1601 | - return 1; |
1602 | - |
1603 | - fail: |
1604 | - dm_task_destroy(dmt); |
1605 | - dm_free(ts->device.name); |
1606 | - return 0; |
1607 | -} |
1608 | - |
1609 | -/* |
1610 | - * Find an existing thread for a device. |
1611 | - * |
1612 | - * Mutex must be held when calling this. |
1613 | - */ |
1614 | -static struct thread_status *_lookup_thread_status(struct message_data *data) |
1615 | -{ |
1616 | - struct thread_status *thread; |
1617 | - |
1618 | - dm_list_iterate_items(thread, &_thread_registry) |
1619 | - if (!strcmp(data->device_uuid, thread->device.uuid)) |
1620 | - return thread; |
1621 | - |
1622 | - return NULL; |
1623 | -} |
1624 | - |
1625 | -static int _get_status(struct message_data *message_data) |
1626 | -{ |
1627 | - struct dm_event_daemon_message *msg = message_data->msg; |
1628 | - struct thread_status *thread; |
1629 | - int i, j; |
1630 | - int ret = -1; |
1631 | - int count = dm_list_size(&_thread_registry); |
1632 | - int size = 0, current = 0; |
1633 | - char *buffers[count]; |
1634 | - char *message; |
1635 | - |
1636 | - dm_free(msg->data); |
1637 | - |
1638 | - for (i = 0; i < count; ++i) |
1639 | - buffers[i] = NULL; |
1640 | - |
1641 | - i = 0; |
1642 | - _lock_mutex(); |
1643 | - dm_list_iterate_items(thread, &_thread_registry) { |
1644 | - if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";", |
1645 | - i, thread->dso_data->dso_name, |
1646 | - thread->device.uuid, thread->events, |
1647 | - thread->timeout)) < 0) { |
1648 | - _unlock_mutex(); |
1649 | - goto out; |
1650 | - } |
1651 | - ++ i; |
1652 | - size += current; |
1653 | - } |
1654 | - _unlock_mutex(); |
1655 | - |
1656 | - msg->size = size + strlen(message_data->id) + 1; |
1657 | - msg->data = dm_malloc(msg->size); |
1658 | - if (!msg->data) |
1659 | - goto out; |
1660 | - *msg->data = 0; |
1661 | - |
1662 | - message = msg->data; |
1663 | - strcpy(message, message_data->id); |
1664 | - message += strlen(message_data->id); |
1665 | - *message = ' '; |
1666 | - message ++; |
1667 | - for (j = 0; j < i; ++j) { |
1668 | - strcpy(message, buffers[j]); |
1669 | - message += strlen(buffers[j]); |
1670 | - } |
1671 | - |
1672 | - ret = 0; |
1673 | - out: |
1674 | - for (j = 0; j < i; ++j) |
1675 | - dm_free(buffers[j]); |
1676 | - return ret; |
1677 | - |
1678 | -} |
1679 | - |
1680 | -/* Cleanup at exit. */ |
1681 | -static void _exit_dm_lib(void) |
1682 | -{ |
1683 | - dm_lib_release(); |
1684 | - dm_lib_exit(); |
1685 | -} |
1686 | - |
1687 | -static void _exit_timeout(void *unused __attribute__((unused))) |
1688 | -{ |
1689 | - _timeout_running = 0; |
1690 | - pthread_mutex_unlock(&_timeout_mutex); |
1691 | -} |
1692 | - |
1693 | -/* Wake up monitor threads every so often. */ |
1694 | -static void *_timeout_thread(void *unused __attribute__((unused))) |
1695 | -{ |
1696 | - struct timespec timeout; |
1697 | - time_t curr_time; |
1698 | - |
1699 | - timeout.tv_nsec = 0; |
1700 | - pthread_cleanup_push(_exit_timeout, NULL); |
1701 | - pthread_mutex_lock(&_timeout_mutex); |
1702 | - |
1703 | - while (!dm_list_empty(&_timeout_registry)) { |
1704 | - struct thread_status *thread; |
1705 | - |
1706 | - timeout.tv_sec = 0; |
1707 | - curr_time = time(NULL); |
1708 | - |
1709 | - dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) { |
1710 | - if (thread->next_time <= curr_time) { |
1711 | - thread->next_time = curr_time + thread->timeout; |
1712 | - pthread_kill(thread->thread, SIGALRM); |
1713 | - } |
1714 | - |
1715 | - if (thread->next_time < timeout.tv_sec || !timeout.tv_sec) |
1716 | - timeout.tv_sec = thread->next_time; |
1717 | - } |
1718 | - |
1719 | - pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex, |
1720 | - &timeout); |
1721 | - } |
1722 | - |
1723 | - pthread_cleanup_pop(1); |
1724 | - |
1725 | - return NULL; |
1726 | -} |
1727 | - |
1728 | -static int _register_for_timeout(struct thread_status *thread) |
1729 | -{ |
1730 | - int ret = 0; |
1731 | - |
1732 | - pthread_mutex_lock(&_timeout_mutex); |
1733 | - |
1734 | - thread->next_time = time(NULL) + thread->timeout; |
1735 | - |
1736 | - if (dm_list_empty(&thread->timeout_list)) { |
1737 | - dm_list_add(&_timeout_registry, &thread->timeout_list); |
1738 | - if (_timeout_running) |
1739 | - pthread_cond_signal(&_timeout_cond); |
1740 | - } |
1741 | - |
1742 | - if (!_timeout_running) { |
1743 | - pthread_t timeout_id; |
1744 | - |
1745 | - if (!(ret = -_pthread_create_smallstack(&timeout_id, _timeout_thread, NULL))) |
1746 | - _timeout_running = 1; |
1747 | - } |
1748 | - |
1749 | - pthread_mutex_unlock(&_timeout_mutex); |
1750 | - |
1751 | - return ret; |
1752 | -} |
1753 | - |
1754 | -static void _unregister_for_timeout(struct thread_status *thread) |
1755 | -{ |
1756 | - pthread_mutex_lock(&_timeout_mutex); |
1757 | - if (!dm_list_empty(&thread->timeout_list)) { |
1758 | - dm_list_del(&thread->timeout_list); |
1759 | - dm_list_init(&thread->timeout_list); |
1760 | - } |
1761 | - pthread_mutex_unlock(&_timeout_mutex); |
1762 | -} |
1763 | - |
1764 | -__attribute__((format(printf, 4, 5))) |
1765 | -static void _no_intr_log(int level, const char *file, int line, |
1766 | - const char *f, ...) |
1767 | -{ |
1768 | - va_list ap; |
1769 | - |
1770 | - if (errno == EINTR) |
1771 | - return; |
1772 | - if (level > _LOG_WARN) |
1773 | - return; |
1774 | - |
1775 | - va_start(ap, f); |
1776 | - |
1777 | - if (level < _LOG_WARN) |
1778 | - vfprintf(stderr, f, ap); |
1779 | - else |
1780 | - vprintf(f, ap); |
1781 | - |
1782 | - va_end(ap); |
1783 | - |
1784 | - if (level < _LOG_WARN) |
1785 | - fprintf(stderr, "\n"); |
1786 | - else |
1787 | - fprintf(stdout, "\n"); |
1788 | -} |
1789 | - |
1790 | -static sigset_t _unblock_sigalrm(void) |
1791 | -{ |
1792 | - sigset_t set, old; |
1793 | - |
1794 | - sigemptyset(&set); |
1795 | - sigaddset(&set, SIGALRM); |
1796 | - pthread_sigmask(SIG_UNBLOCK, &set, &old); |
1797 | - return old; |
1798 | -} |
1799 | - |
1800 | -#define DM_WAIT_RETRY 0 |
1801 | -#define DM_WAIT_INTR 1 |
1802 | -#define DM_WAIT_FATAL 2 |
1803 | - |
1804 | -/* Wait on a device until an event occurs. */ |
1805 | -static int _event_wait(struct thread_status *thread, struct dm_task **task) |
1806 | -{ |
1807 | - sigset_t set; |
1808 | - int ret = DM_WAIT_RETRY; |
1809 | - struct dm_task *dmt; |
1810 | - struct dm_info info; |
1811 | - |
1812 | - *task = 0; |
1813 | - |
1814 | - if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT))) |
1815 | - return DM_WAIT_RETRY; |
1816 | - |
1817 | - thread->current_task = dmt; |
1818 | - |
1819 | - if (!dm_task_set_uuid(dmt, thread->device.uuid) || |
1820 | - !dm_task_set_event_nr(dmt, thread->event_nr)) |
1821 | - goto out; |
1822 | - |
1823 | - /* |
1824 | - * This is so that you can break out of waiting on an event, |
1825 | - * either for a timeout event, or to cancel the thread. |
1826 | - */ |
1827 | - set = _unblock_sigalrm(); |
1828 | - dm_log_init(_no_intr_log); |
1829 | - errno = 0; |
1830 | - if (dm_task_run(dmt)) { |
1831 | - thread->current_events |= DM_EVENT_DEVICE_ERROR; |
1832 | - ret = DM_WAIT_INTR; |
1833 | - |
1834 | - if ((ret = dm_task_get_info(dmt, &info))) |
1835 | - thread->event_nr = info.event_nr; |
1836 | - } else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) { |
1837 | - thread->current_events |= DM_EVENT_TIMEOUT; |
1838 | - ret = DM_WAIT_INTR; |
1839 | - } else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) { |
1840 | - ret = DM_WAIT_FATAL; |
1841 | - } else { |
1842 | - syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s", |
1843 | - errno, strerror(errno)); |
1844 | - if (errno == ENXIO) { |
1845 | - syslog(LOG_ERR, "%s disappeared, detaching", |
1846 | - thread->device.name); |
1847 | - ret = DM_WAIT_FATAL; |
1848 | - } |
1849 | - } |
1850 | - |
1851 | - pthread_sigmask(SIG_SETMASK, &set, NULL); |
1852 | - dm_log_init(NULL); |
1853 | - |
1854 | - out: |
1855 | - if (ret == DM_WAIT_FATAL || ret == DM_WAIT_RETRY) { |
1856 | - dm_task_destroy(dmt); |
1857 | - thread->current_task = NULL; |
1858 | - } else |
1859 | - *task = dmt; |
1860 | - |
1861 | - return ret; |
1862 | -} |
1863 | - |
1864 | -/* Register a device with the DSO. */ |
1865 | -static int _do_register_device(struct thread_status *thread) |
1866 | -{ |
1867 | - return thread->dso_data->register_device(thread->device.name, |
1868 | - thread->device.uuid, |
1869 | - thread->device.major, |
1870 | - thread->device.minor, |
1871 | - &(thread->dso_private)); |
1872 | -} |
1873 | - |
1874 | -/* Unregister a device with the DSO. */ |
1875 | -static int _do_unregister_device(struct thread_status *thread) |
1876 | -{ |
1877 | - return thread->dso_data->unregister_device(thread->device.name, |
1878 | - thread->device.uuid, |
1879 | - thread->device.major, |
1880 | - thread->device.minor, |
1881 | - &(thread->dso_private)); |
1882 | -} |
1883 | - |
1884 | -/* Process an event in the DSO. */ |
1885 | -static void _do_process_event(struct thread_status *thread, struct dm_task *task) |
1886 | -{ |
1887 | - thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private)); |
1888 | -} |
1889 | - |
1890 | -/* Thread cleanup handler to unregister device. */ |
1891 | -static void _monitor_unregister(void *arg) |
1892 | -{ |
1893 | - struct thread_status *thread = arg, *thread_iter; |
1894 | - |
1895 | - if (!_do_unregister_device(thread)) |
1896 | - syslog(LOG_ERR, "%s: %s unregister failed\n", __func__, |
1897 | - thread->device.name); |
1898 | - if (thread->current_task) |
1899 | - dm_task_destroy(thread->current_task); |
1900 | - thread->current_task = NULL; |
1901 | - |
1902 | - _lock_mutex(); |
1903 | - if (thread->events & DM_EVENT_TIMEOUT) { |
1904 | - /* _unregister_for_timeout locks another mutex, we |
1905 | - don't want to deadlock so we release our mutex for |
1906 | - a bit */ |
1907 | - _unlock_mutex(); |
1908 | - _unregister_for_timeout(thread); |
1909 | - _lock_mutex(); |
1910 | - } |
1911 | - /* we may have been relinked to unused registry since we were |
1912 | - called, so check that */ |
1913 | - dm_list_iterate_items(thread_iter, &_thread_registry_unused) |
1914 | - if (thread_iter == thread) { |
1915 | - thread->status = DM_THREAD_DONE; |
1916 | - _unlock_mutex(); |
1917 | - return; |
1918 | - } |
1919 | - thread->status = DM_THREAD_DONE; |
1920 | - pthread_mutex_lock(&_timeout_mutex); |
1921 | - UNLINK_THREAD(thread); |
1922 | - LINK(thread, &_thread_registry_unused); |
1923 | - pthread_mutex_unlock(&_timeout_mutex); |
1924 | - _unlock_mutex(); |
1925 | -} |
1926 | - |
1927 | -static struct dm_task *_get_device_status(struct thread_status *ts) |
1928 | -{ |
1929 | - struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS); |
1930 | - |
1931 | - if (!dmt) |
1932 | - return NULL; |
1933 | - |
1934 | - if (!dm_task_set_uuid(dmt, ts->device.uuid)) { |
1935 | - dm_task_destroy(dmt); |
1936 | - return NULL; |
1937 | - } |
1938 | - |
1939 | - if (!dm_task_run(dmt)) { |
1940 | - dm_task_destroy(dmt); |
1941 | - return NULL; |
1942 | - } |
1943 | - |
1944 | - return dmt; |
1945 | -} |
1946 | - |
1947 | -/* Device monitoring thread. */ |
1948 | -static void *_monitor_thread(void *arg) |
1949 | -{ |
1950 | - struct thread_status *thread = arg; |
1951 | - int wait_error = 0; |
1952 | - struct dm_task *task; |
1953 | - |
1954 | - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); |
1955 | - pthread_cleanup_push(_monitor_unregister, thread); |
1956 | - |
1957 | - /* Wait for do_process_request() to finish its task. */ |
1958 | - _lock_mutex(); |
1959 | - thread->status = DM_THREAD_RUNNING; |
1960 | - _unlock_mutex(); |
1961 | - |
1962 | - /* Loop forever awaiting/analyzing device events. */ |
1963 | - while (1) { |
1964 | - thread->current_events = 0; |
1965 | - |
1966 | - wait_error = _event_wait(thread, &task); |
1967 | - if (wait_error == DM_WAIT_RETRY) |
1968 | - continue; |
1969 | - |
1970 | - if (wait_error == DM_WAIT_FATAL) |
1971 | - break; |
1972 | - |
1973 | - /* Timeout occurred, task is not filled properly. |
1974 | - * We get device status here for processing it in DSO. |
1975 | - */ |
1976 | - if (wait_error == DM_WAIT_INTR && |
1977 | - thread->current_events & DM_EVENT_TIMEOUT) { |
1978 | - dm_task_destroy(task); |
1979 | - task = _get_device_status(thread); |
1980 | - /* FIXME: syslog fail here ? */ |
1981 | - if (!(thread->current_task = task)) |
1982 | - continue; |
1983 | - } |
1984 | - |
1985 | - /* |
1986 | - * We know that wait succeeded and stored a |
1987 | - * pointer to dm_task with device status into task. |
1988 | - */ |
1989 | - |
1990 | - /* |
1991 | - * Check against filter. |
1992 | - * |
1993 | - * If there's current events delivered from _event_wait() AND |
1994 | - * the device got registered for those events AND |
1995 | - * those events haven't been processed yet, call |
1996 | - * the DSO's process_event() handler. |
1997 | - */ |
1998 | - _lock_mutex(); |
1999 | - if (thread->status == DM_THREAD_SHUTDOWN) { |
2000 | - _unlock_mutex(); |
2001 | - break; |
2002 | - } |
2003 | - _unlock_mutex(); |
2004 | - |
2005 | - if (thread->events & thread->current_events) { |
2006 | - _lock_mutex(); |
2007 | - thread->processing = 1; |
2008 | - _unlock_mutex(); |
2009 | - |
2010 | - _do_process_event(thread, task); |
2011 | - dm_task_destroy(task); |
2012 | - thread->current_task = NULL; |
2013 | - |
2014 | - _lock_mutex(); |
2015 | - thread->processing = 0; |
2016 | - _unlock_mutex(); |
2017 | - } else { |
2018 | - dm_task_destroy(task); |
2019 | - thread->current_task = NULL; |
2020 | - } |
2021 | - } |
2022 | - |
2023 | - pthread_cleanup_pop(1); |
2024 | - |
2025 | - return NULL; |
2026 | -} |
2027 | - |
2028 | -/* Create a device monitoring thread. */ |
2029 | -static int _create_thread(struct thread_status *thread) |
2030 | -{ |
2031 | - return _pthread_create_smallstack(&thread->thread, _monitor_thread, thread); |
2032 | -} |
2033 | - |
2034 | -static int _terminate_thread(struct thread_status *thread) |
2035 | -{ |
2036 | - return pthread_kill(thread->thread, SIGALRM); |
2037 | -} |
2038 | - |
2039 | -/* DSO reference counting. Call with _global_mutex locked! */ |
2040 | -static void _lib_get(struct dso_data *data) |
2041 | -{ |
2042 | - data->ref_count++; |
2043 | -} |
2044 | - |
2045 | -static void _lib_put(struct dso_data *data) |
2046 | -{ |
2047 | - if (!--data->ref_count) { |
2048 | - dlclose(data->dso_handle); |
2049 | - UNLINK_DSO(data); |
2050 | - _free_dso_data(data); |
2051 | - } |
2052 | -} |
2053 | - |
2054 | -/* Find DSO data. */ |
2055 | -static struct dso_data *_lookup_dso(struct message_data *data) |
2056 | -{ |
2057 | - struct dso_data *dso_data, *ret = NULL; |
2058 | - |
2059 | - dm_list_iterate_items(dso_data, &_dso_registry) |
2060 | - if (!strcmp(data->dso_name, dso_data->dso_name)) { |
2061 | - _lib_get(dso_data); |
2062 | - ret = dso_data; |
2063 | - break; |
2064 | - } |
2065 | - |
2066 | - return ret; |
2067 | -} |
2068 | - |
2069 | -/* Lookup DSO symbols we need. */ |
2070 | -static int _lookup_symbol(void *dl, void **symbol, const char *name) |
2071 | -{ |
2072 | - if ((*symbol = dlsym(dl, name))) |
2073 | - return 1; |
2074 | - |
2075 | - return 0; |
2076 | -} |
2077 | - |
2078 | -static int lookup_symbols(void *dl, struct dso_data *data) |
2079 | -{ |
2080 | - return _lookup_symbol(dl, (void *) &data->process_event, |
2081 | - "process_event") && |
2082 | - _lookup_symbol(dl, (void *) &data->register_device, |
2083 | - "register_device") && |
2084 | - _lookup_symbol(dl, (void *) &data->unregister_device, |
2085 | - "unregister_device"); |
2086 | -} |
2087 | - |
2088 | -/* Load an application specific DSO. */ |
2089 | -static struct dso_data *_load_dso(struct message_data *data) |
2090 | -{ |
2091 | - void *dl; |
2092 | - struct dso_data *ret = NULL; |
2093 | - |
2094 | - if (!(dl = dlopen(data->dso_name, RTLD_NOW))) { |
2095 | - const char *dlerr = dlerror(); |
2096 | - syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name, |
2097 | - dlerr); |
2098 | - data->msg->size = |
2099 | - dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s", |
2100 | - data->id, data->dso_name, dlerr); |
2101 | - return NULL; |
2102 | - } |
2103 | - |
2104 | - if (!(ret = _alloc_dso_data(data))) { |
2105 | - dlclose(dl); |
2106 | - return NULL; |
2107 | - } |
2108 | - |
2109 | - if (!(lookup_symbols(dl, ret))) { |
2110 | - _free_dso_data(ret); |
2111 | - dlclose(dl); |
2112 | - return NULL; |
2113 | - } |
2114 | - |
2115 | - /* |
2116 | - * Keep handle to close the library once |
2117 | - * we've got no references to it any more. |
2118 | - */ |
2119 | - ret->dso_handle = dl; |
2120 | - _lib_get(ret); |
2121 | - |
2122 | - _lock_mutex(); |
2123 | - LINK_DSO(ret); |
2124 | - _unlock_mutex(); |
2125 | - |
2126 | - return ret; |
2127 | -} |
2128 | - |
2129 | -/* Return success on daemon active check. */ |
2130 | -static int _active(struct message_data *message_data) |
2131 | -{ |
2132 | - return 0; |
2133 | -} |
2134 | - |
2135 | -/* |
2136 | - * Register for an event. |
2137 | - * |
2138 | - * Only one caller at a time here, because we use |
2139 | - * a FIFO and lock it against multiple accesses. |
2140 | - */ |
2141 | -static int _register_for_event(struct message_data *message_data) |
2142 | -{ |
2143 | - int ret = 0; |
2144 | - struct thread_status *thread, *thread_new = NULL; |
2145 | - struct dso_data *dso_data; |
2146 | - |
2147 | - if (!(dso_data = _lookup_dso(message_data)) && |
2148 | - !(dso_data = _load_dso(message_data))) { |
2149 | - stack; |
2150 | -#ifdef ELIBACC |
2151 | - ret = -ELIBACC; |
2152 | -#else |
2153 | - ret = -ENODEV; |
2154 | -#endif |
2155 | - goto out; |
2156 | - } |
2157 | - |
2158 | - /* Preallocate thread status struct to avoid deadlock. */ |
2159 | - if (!(thread_new = _alloc_thread_status(message_data, dso_data))) { |
2160 | - stack; |
2161 | - ret = -ENOMEM; |
2162 | - goto out; |
2163 | - } |
2164 | - |
2165 | - if (!_fill_device_data(thread_new)) { |
2166 | - stack; |
2167 | - ret = -ENODEV; |
2168 | - goto out; |
2169 | - } |
2170 | - |
2171 | - _lock_mutex(); |
2172 | - |
2173 | - /* If creation of timeout thread fails (as it may), we fail |
2174 | - here completely. The client is responsible for either |
2175 | - retrying later or trying to register without timeout |
2176 | - events. However, if timeout thread cannot be started, it |
2177 | - usually means we are so starved on resources that we are |
2178 | - almost as good as dead already... */ |
2179 | - if (thread_new->events & DM_EVENT_TIMEOUT) { |
2180 | - ret = -_register_for_timeout(thread_new); |
2181 | - if (ret) |
2182 | - goto outth; |
2183 | - } |
2184 | - |
2185 | - if (!(thread = _lookup_thread_status(message_data))) { |
2186 | - _unlock_mutex(); |
2187 | - |
2188 | - if (!(ret = _do_register_device(thread_new))) |
2189 | - goto out; |
2190 | - |
2191 | - thread = thread_new; |
2192 | - thread_new = NULL; |
2193 | - |
2194 | - /* Try to create the monitoring thread for this device. */ |
2195 | - _lock_mutex(); |
2196 | - if ((ret = -_create_thread(thread))) { |
2197 | - _unlock_mutex(); |
2198 | - _do_unregister_device(thread); |
2199 | - _free_thread_status(thread); |
2200 | - goto out; |
2201 | - } else |
2202 | - LINK_THREAD(thread); |
2203 | - } |
2204 | - |
2205 | - /* Or event # into events bitfield. */ |
2206 | - thread->events |= message_data->events.field; |
2207 | - |
2208 | - outth: |
2209 | - _unlock_mutex(); |
2210 | - |
2211 | - out: |
2212 | - /* |
2213 | - * Deallocate thread status after releasing |
2214 | - * the lock in case we haven't used it. |
2215 | - */ |
2216 | - if (thread_new) |
2217 | - _free_thread_status(thread_new); |
2218 | - |
2219 | - return ret; |
2220 | -} |
2221 | - |
2222 | -/* |
2223 | - * Unregister for an event. |
2224 | - * |
2225 | - * Only one caller at a time here as with register_for_event(). |
2226 | - */ |
2227 | -static int _unregister_for_event(struct message_data *message_data) |
2228 | -{ |
2229 | - int ret = 0; |
2230 | - struct thread_status *thread; |
2231 | - |
2232 | - /* |
2233 | - * Clear event in bitfield and deactivate |
2234 | - * monitoring thread in case bitfield is 0. |
2235 | - */ |
2236 | - _lock_mutex(); |
2237 | - |
2238 | - if (!(thread = _lookup_thread_status(message_data))) { |
2239 | - _unlock_mutex(); |
2240 | - ret = -ENODEV; |
2241 | - goto out; |
2242 | - } |
2243 | - |
2244 | - if (thread->status == DM_THREAD_DONE) { |
2245 | - /* the thread has terminated while we were not |
2246 | - watching */ |
2247 | - _unlock_mutex(); |
2248 | - return 0; |
2249 | - } |
2250 | - |
2251 | - thread->events &= ~message_data->events.field; |
2252 | - |
2253 | - if (!(thread->events & DM_EVENT_TIMEOUT)) |
2254 | - _unregister_for_timeout(thread); |
2255 | - /* |
2256 | - * In case there's no events to monitor on this device -> |
2257 | - * unlink and terminate its monitoring thread. |
2258 | - */ |
2259 | - if (!thread->events) { |
2260 | - pthread_mutex_lock(&_timeout_mutex); |
2261 | - UNLINK_THREAD(thread); |
2262 | - LINK(thread, &_thread_registry_unused); |
2263 | - pthread_mutex_unlock(&_timeout_mutex); |
2264 | - } |
2265 | - _unlock_mutex(); |
2266 | - |
2267 | - out: |
2268 | - return ret; |
2269 | -} |
2270 | - |
2271 | -/* |
2272 | - * Get registered device. |
2273 | - * |
2274 | - * Only one caller at a time here as with register_for_event(). |
2275 | - */ |
2276 | -static int _registered_device(struct message_data *message_data, |
2277 | - struct thread_status *thread) |
2278 | -{ |
2279 | - struct dm_event_daemon_message *msg = message_data->msg; |
2280 | - |
2281 | - const char *fmt = "%s %s %s %u"; |
2282 | - const char *id = message_data->id; |
2283 | - const char *dso = thread->dso_data->dso_name; |
2284 | - const char *dev = thread->device.uuid; |
2285 | - int r; |
2286 | - unsigned events = ((thread->status == DM_THREAD_RUNNING) |
2287 | - && (thread->events)) ? thread->events : thread-> |
2288 | - events | DM_EVENT_REGISTRATION_PENDING; |
2289 | - |
2290 | - dm_free(msg->data); |
2291 | - |
2292 | - if ((r = dm_asprintf(&(msg->data), fmt, id, dso, dev, events)) < 0) { |
2293 | - msg->size = 0; |
2294 | - return -ENOMEM; |
2295 | - } |
2296 | - |
2297 | - msg->size = (uint32_t) r; |
2298 | - |
2299 | - return 0; |
2300 | -} |
2301 | - |
2302 | -static int _want_registered_device(char *dso_name, char *device_uuid, |
2303 | - struct thread_status *thread) |
2304 | -{ |
2305 | - /* If DSO names and device paths are equal. */ |
2306 | - if (dso_name && device_uuid) |
2307 | - return !strcmp(dso_name, thread->dso_data->dso_name) && |
2308 | - !strcmp(device_uuid, thread->device.uuid) && |
2309 | - (thread->status == DM_THREAD_RUNNING || |
2310 | - (thread->events & DM_EVENT_REGISTRATION_PENDING)); |
2311 | - |
2312 | - /* If DSO names are equal. */ |
2313 | - if (dso_name) |
2314 | - return !strcmp(dso_name, thread->dso_data->dso_name) && |
2315 | - (thread->status == DM_THREAD_RUNNING || |
2316 | - (thread->events & DM_EVENT_REGISTRATION_PENDING)); |
2317 | - |
2318 | - /* If device paths are equal. */ |
2319 | - if (device_uuid) |
2320 | - return !strcmp(device_uuid, thread->device.uuid) && |
2321 | - (thread->status == DM_THREAD_RUNNING || |
2322 | - (thread->events & DM_EVENT_REGISTRATION_PENDING)); |
2323 | - |
2324 | - return 1; |
2325 | -} |
2326 | - |
2327 | -static int _get_registered_dev(struct message_data *message_data, int next) |
2328 | -{ |
2329 | - struct thread_status *thread, *hit = NULL; |
2330 | - int ret = -ENOENT; |
2331 | - |
2332 | - _lock_mutex(); |
2333 | - |
2334 | - /* Iterate list of threads checking if we want a particular one. */ |
2335 | - dm_list_iterate_items(thread, &_thread_registry) |
2336 | - if (_want_registered_device(message_data->dso_name, |
2337 | - message_data->device_uuid, |
2338 | - thread)) { |
2339 | - hit = thread; |
2340 | - break; |
2341 | - } |
2342 | - |
2343 | - /* |
2344 | - * If we got a registered device and want the next one -> |
2345 | - * fetch next conforming element off the list. |
2346 | - */ |
2347 | - if (hit && !next) |
2348 | - goto reg; |
2349 | - |
2350 | - if (!hit) |
2351 | - goto out; |
2352 | - |
2353 | - while (1) { |
2354 | - if (dm_list_end(&_thread_registry, &thread->list)) |
2355 | - goto out; |
2356 | - |
2357 | - thread = dm_list_item(thread->list.n, struct thread_status); |
2358 | - if (_want_registered_device(message_data->dso_name, NULL, thread)) { |
2359 | - hit = thread; |
2360 | - break; |
2361 | - } |
2362 | - } |
2363 | - |
2364 | - reg: |
2365 | - ret = _registered_device(message_data, hit); |
2366 | - |
2367 | - out: |
2368 | - _unlock_mutex(); |
2369 | - |
2370 | - return ret; |
2371 | -} |
2372 | - |
2373 | -static int _get_registered_device(struct message_data *message_data) |
2374 | -{ |
2375 | - return _get_registered_dev(message_data, 0); |
2376 | -} |
2377 | - |
2378 | -static int _get_next_registered_device(struct message_data *message_data) |
2379 | -{ |
2380 | - return _get_registered_dev(message_data, 1); |
2381 | -} |
2382 | - |
2383 | -static int _set_timeout(struct message_data *message_data) |
2384 | -{ |
2385 | - struct thread_status *thread; |
2386 | - |
2387 | - _lock_mutex(); |
2388 | - if ((thread = _lookup_thread_status(message_data))) |
2389 | - thread->timeout = message_data->timeout.secs; |
2390 | - _unlock_mutex(); |
2391 | - |
2392 | - return thread ? 0 : -ENODEV; |
2393 | -} |
2394 | - |
2395 | -static int _get_timeout(struct message_data *message_data) |
2396 | -{ |
2397 | - struct thread_status *thread; |
2398 | - struct dm_event_daemon_message *msg = message_data->msg; |
2399 | - |
2400 | - dm_free(msg->data); |
2401 | - |
2402 | - _lock_mutex(); |
2403 | - if ((thread = _lookup_thread_status(message_data))) { |
2404 | - msg->size = |
2405 | - dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id, |
2406 | - thread->timeout); |
2407 | - } else { |
2408 | - msg->data = NULL; |
2409 | - msg->size = 0; |
2410 | - } |
2411 | - _unlock_mutex(); |
2412 | - |
2413 | - return thread ? 0 : -ENODEV; |
2414 | -} |
2415 | - |
2416 | -/* Initialize a fifos structure with path names. */ |
2417 | -static void _init_fifos(struct dm_event_fifos *fifos) |
2418 | -{ |
2419 | - memset(fifos, 0, sizeof(*fifos)); |
2420 | - |
2421 | - fifos->client_path = DM_EVENT_FIFO_CLIENT; |
2422 | - fifos->server_path = DM_EVENT_FIFO_SERVER; |
2423 | -} |
2424 | - |
2425 | -/* Open fifos used for client communication. */ |
2426 | -static int _open_fifos(struct dm_event_fifos *fifos) |
2427 | -{ |
2428 | - struct stat st; |
2429 | - |
2430 | - /* Create client fifo. */ |
2431 | - (void) dm_prepare_selinux_context(fifos->client_path, S_IFIFO); |
2432 | - if ((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) { |
2433 | - syslog(LOG_ERR, "%s: Failed to create client fifo %s: %m.\n", |
2434 | - __func__, fifos->client_path); |
2435 | - (void) dm_prepare_selinux_context(NULL, 0); |
2436 | - return 0; |
2437 | - } |
2438 | - |
2439 | - /* Create server fifo. */ |
2440 | - (void) dm_prepare_selinux_context(fifos->server_path, S_IFIFO); |
2441 | - if ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST) { |
2442 | - syslog(LOG_ERR, "%s: Failed to create server fifo %s: %m.\n", |
2443 | - __func__, fifos->server_path); |
2444 | - (void) dm_prepare_selinux_context(NULL, 0); |
2445 | - return 0; |
2446 | - } |
2447 | - |
2448 | - (void) dm_prepare_selinux_context(NULL, 0); |
2449 | - |
2450 | - /* Warn about wrong permissions if applicable */ |
2451 | - if ((!stat(fifos->client_path, &st)) && (st.st_mode & 0777) != 0600) |
2452 | - syslog(LOG_WARNING, "Fixing wrong permissions on %s: %m.\n", |
2453 | - fifos->client_path); |
2454 | - |
2455 | - if ((!stat(fifos->server_path, &st)) && (st.st_mode & 0777) != 0600) |
2456 | - syslog(LOG_WARNING, "Fixing wrong permissions on %s: %m.\n", |
2457 | - fifos->server_path); |
2458 | - |
2459 | - /* If they were already there, make sure permissions are ok. */ |
2460 | - if (chmod(fifos->client_path, 0600)) { |
2461 | - syslog(LOG_ERR, "Unable to set correct file permissions on %s: %m.\n", |
2462 | - fifos->client_path); |
2463 | - return 0; |
2464 | - } |
2465 | - |
2466 | - if (chmod(fifos->server_path, 0600)) { |
2467 | - syslog(LOG_ERR, "Unable to set correct file permissions on %s: %m.\n", |
2468 | - fifos->server_path); |
2469 | - return 0; |
2470 | - } |
2471 | - |
2472 | - /* Need to open read+write or we will block or fail */ |
2473 | - if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) { |
2474 | - syslog(LOG_ERR, "Failed to open fifo server %s: %m.\n", |
2475 | - fifos->server_path); |
2476 | - return 0; |
2477 | - } |
2478 | - |
2479 | - /* Need to open read+write for select() to work. */ |
2480 | - if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) { |
2481 | - syslog(LOG_ERR, "Failed to open fifo client %s: %m", fifos->client_path); |
2482 | - if (close(fifos->server)) |
2483 | - syslog(LOG_ERR, "Failed to close fifo server %s: %m", fifos->server_path); |
2484 | - return 0; |
2485 | - } |
2486 | - |
2487 | - return 1; |
2488 | -} |
2489 | - |
2490 | -/* |
2491 | - * Read message from client making sure that data is available |
2492 | - * and a complete message is read. Must not block indefinitely. |
2493 | - */ |
2494 | -static int _client_read(struct dm_event_fifos *fifos, |
2495 | - struct dm_event_daemon_message *msg) |
2496 | -{ |
2497 | - struct timeval t; |
2498 | - unsigned bytes = 0; |
2499 | - int ret = 0; |
2500 | - fd_set fds; |
2501 | - size_t size = 2 * sizeof(uint32_t); /* status + size */ |
2502 | - uint32_t *header = alloca(size); |
2503 | - char *buf = (char *)header; |
2504 | - |
2505 | - msg->data = NULL; |
2506 | - |
2507 | - errno = 0; |
2508 | - while (bytes < size && errno != EOF) { |
2509 | - /* Watch client read FIFO for input. */ |
2510 | - FD_ZERO(&fds); |
2511 | - FD_SET(fifos->client, &fds); |
2512 | - t.tv_sec = 1; |
2513 | - t.tv_usec = 0; |
2514 | - ret = select(fifos->client + 1, &fds, NULL, NULL, &t); |
2515 | - |
2516 | - if (!ret && !bytes) /* nothing to read */ |
2517 | - return 0; |
2518 | - |
2519 | - if (!ret) /* trying to finish read */ |
2520 | - continue; |
2521 | - |
2522 | - if (ret < 0) /* error */ |
2523 | - return 0; |
2524 | - |
2525 | - ret = read(fifos->client, buf + bytes, size - bytes); |
2526 | - bytes += ret > 0 ? ret : 0; |
2527 | - if (header && (bytes == 2 * sizeof(uint32_t))) { |
2528 | - msg->cmd = ntohl(header[0]); |
2529 | - msg->size = ntohl(header[1]); |
2530 | - buf = msg->data = dm_malloc(msg->size); |
2531 | - size = msg->size; |
2532 | - bytes = 0; |
2533 | - header = 0; |
2534 | - } |
2535 | - } |
2536 | - |
2537 | - if (bytes != size) { |
2538 | - dm_free(msg->data); |
2539 | - msg->data = NULL; |
2540 | - msg->size = 0; |
2541 | - } |
2542 | - |
2543 | - return bytes == size; |
2544 | -} |
2545 | - |
2546 | -/* |
2547 | - * Write a message to the client making sure that it is ready to write. |
2548 | - */ |
2549 | -static int _client_write(struct dm_event_fifos *fifos, |
2550 | - struct dm_event_daemon_message *msg) |
2551 | -{ |
2552 | - unsigned bytes = 0; |
2553 | - int ret = 0; |
2554 | - fd_set fds; |
2555 | - |
2556 | - size_t size = 2 * sizeof(uint32_t) + msg->size; |
2557 | - uint32_t *header = alloca(size); |
2558 | - char *buf = (char *)header; |
2559 | - |
2560 | - header[0] = htonl(msg->cmd); |
2561 | - header[1] = htonl(msg->size); |
2562 | - if (msg->data) |
2563 | - memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size); |
2564 | - |
2565 | - errno = 0; |
2566 | - while (bytes < size && errno != EIO) { |
2567 | - do { |
2568 | - /* Watch client write FIFO to be ready for output. */ |
2569 | - FD_ZERO(&fds); |
2570 | - FD_SET(fifos->server, &fds); |
2571 | - } while (select(fifos->server + 1, NULL, &fds, NULL, NULL) != |
2572 | - 1); |
2573 | - |
2574 | - ret = write(fifos->server, buf + bytes, size - bytes); |
2575 | - bytes += ret > 0 ? ret : 0; |
2576 | - } |
2577 | - |
2578 | - return bytes == size; |
2579 | -} |
2580 | - |
2581 | -/* |
2582 | - * Handle a client request. |
2583 | - * |
2584 | - * We put the request handling functions into |
2585 | - * a list because of the growing number. |
2586 | - */ |
2587 | -static int _handle_request(struct dm_event_daemon_message *msg, |
2588 | - struct message_data *message_data) |
2589 | -{ |
2590 | - static struct request { |
2591 | - unsigned int cmd; |
2592 | - int (*f)(struct message_data *); |
2593 | - } requests[] = { |
2594 | - { DM_EVENT_CMD_REGISTER_FOR_EVENT, _register_for_event}, |
2595 | - { DM_EVENT_CMD_UNREGISTER_FOR_EVENT, _unregister_for_event}, |
2596 | - { DM_EVENT_CMD_GET_REGISTERED_DEVICE, _get_registered_device}, |
2597 | - { DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE, |
2598 | - _get_next_registered_device}, |
2599 | - { DM_EVENT_CMD_SET_TIMEOUT, _set_timeout}, |
2600 | - { DM_EVENT_CMD_GET_TIMEOUT, _get_timeout}, |
2601 | - { DM_EVENT_CMD_ACTIVE, _active}, |
2602 | - { DM_EVENT_CMD_GET_STATUS, _get_status}, |
2603 | - }, *req; |
2604 | - |
2605 | - for (req = requests; req < requests + sizeof(requests) / sizeof(struct request); req++) |
2606 | - if (req->cmd == msg->cmd) |
2607 | - return req->f(message_data); |
2608 | - |
2609 | - return -EINVAL; |
2610 | -} |
2611 | - |
2612 | -/* Process a request passed from the communication thread. */ |
2613 | -static int _do_process_request(struct dm_event_daemon_message *msg) |
2614 | -{ |
2615 | - int ret; |
2616 | - char *answer; |
2617 | - struct message_data message_data = { .msg = msg }; |
2618 | - |
2619 | - /* Parse the message. */ |
2620 | - if (msg->cmd == DM_EVENT_CMD_HELLO || msg->cmd == DM_EVENT_CMD_DIE) { |
2621 | - ret = 0; |
2622 | - answer = msg->data; |
2623 | - if (answer) { |
2624 | - msg->size = dm_asprintf(&(msg->data), "%s %s %d", answer, |
2625 | - msg->cmd == DM_EVENT_CMD_DIE ? "DYING" : "HELLO", |
2626 | - DM_EVENT_PROTOCOL_VERSION); |
2627 | - dm_free(answer); |
2628 | - } else { |
2629 | - msg->size = 0; |
2630 | - msg->data = NULL; |
2631 | - } |
2632 | - } else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) { |
2633 | - stack; |
2634 | - ret = -EINVAL; |
2635 | - } else |
2636 | - ret = _handle_request(msg, &message_data); |
2637 | - |
2638 | - msg->cmd = ret; |
2639 | - if (!msg->data) |
2640 | - msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret)); |
2641 | - |
2642 | - _free_message(&message_data); |
2643 | - |
2644 | - return ret; |
2645 | -} |
2646 | - |
2647 | -/* Only one caller at a time. */ |
2648 | -static void _process_request(struct dm_event_fifos *fifos) |
2649 | -{ |
2650 | - int die = 0; |
2651 | - struct dm_event_daemon_message msg = { 0 }; |
2652 | - |
2653 | - /* |
2654 | - * Read the request from the client (client_read, client_write |
2655 | - * give true on success and false on failure). |
2656 | - */ |
2657 | - if (!_client_read(fifos, &msg)) |
2658 | - return; |
2659 | - |
2660 | - if (msg.cmd == DM_EVENT_CMD_DIE) |
2661 | - die = 1; |
2662 | - |
2663 | - /* _do_process_request fills in msg (if memory allows for |
2664 | - data, otherwise just cmd and size = 0) */ |
2665 | - _do_process_request(&msg); |
2666 | - |
2667 | - if (!_client_write(fifos, &msg)) |
2668 | - stack; |
2669 | - |
2670 | - dm_free(msg.data); |
2671 | - |
2672 | - if (die) raise(9); |
2673 | -} |
2674 | - |
2675 | -static void _process_initial_registrations(void) |
2676 | -{ |
2677 | - int i = 0; |
2678 | - char *reg; |
2679 | - struct dm_event_daemon_message msg = { 0, 0, NULL }; |
2680 | - |
2681 | - while ((reg = _initial_registrations[i])) { |
2682 | - msg.cmd = DM_EVENT_CMD_REGISTER_FOR_EVENT; |
2683 | - if ((msg.size = strlen(reg))) { |
2684 | - msg.data = reg; |
2685 | - _do_process_request(&msg); |
2686 | - } |
2687 | - ++ i; |
2688 | - } |
2689 | -} |
2690 | - |
2691 | -static void _cleanup_unused_threads(void) |
2692 | -{ |
2693 | - int ret; |
2694 | - struct dm_list *l; |
2695 | - struct thread_status *thread; |
2696 | - int join_ret = 0; |
2697 | - |
2698 | - _lock_mutex(); |
2699 | - while ((l = dm_list_first(&_thread_registry_unused))) { |
2700 | - thread = dm_list_item(l, struct thread_status); |
2701 | - if (thread->processing) |
2702 | - break; /* cleanup on the next round */ |
2703 | - |
2704 | - if (thread->status == DM_THREAD_RUNNING) { |
2705 | - thread->status = DM_THREAD_SHUTDOWN; |
2706 | - break; |
2707 | - } |
2708 | - |
2709 | - if (thread->status == DM_THREAD_SHUTDOWN) { |
2710 | - if (!thread->events) { |
2711 | - /* turn codes negative -- should we be returning this? */ |
2712 | - ret = _terminate_thread(thread); |
2713 | - |
2714 | - if (ret == ESRCH) { |
2715 | - thread->status = DM_THREAD_DONE; |
2716 | - } else if (ret) { |
2717 | - syslog(LOG_ERR, |
2718 | - "Unable to terminate thread: %s\n", |
2719 | - strerror(-ret)); |
2720 | - stack; |
2721 | - } |
2722 | - break; |
2723 | - } |
2724 | - |
2725 | - dm_list_del(l); |
2726 | - syslog(LOG_ERR, |
2727 | - "thread can't be on unused list unless !thread->events"); |
2728 | - thread->status = DM_THREAD_RUNNING; |
2729 | - LINK_THREAD(thread); |
2730 | - |
2731 | - continue; |
2732 | - } |
2733 | - |
2734 | - if (thread->status == DM_THREAD_DONE) { |
2735 | - dm_list_del(l); |
2736 | - join_ret = pthread_join(thread->thread, NULL); |
2737 | - _free_thread_status(thread); |
2738 | - } |
2739 | - } |
2740 | - |
2741 | - _unlock_mutex(); |
2742 | - |
2743 | - if (join_ret) |
2744 | - syslog(LOG_ERR, "Failed pthread_join: %s\n", strerror(join_ret)); |
2745 | -} |
2746 | - |
2747 | -static void _sig_alarm(int signum __attribute__((unused))) |
2748 | -{ |
2749 | - pthread_testcancel(); |
2750 | -} |
2751 | - |
2752 | -/* Init thread signal handling. */ |
2753 | -static void _init_thread_signals(void) |
2754 | -{ |
2755 | - sigset_t my_sigset; |
2756 | - struct sigaction act = { .sa_handler = _sig_alarm }; |
2757 | - |
2758 | - sigaction(SIGALRM, &act, NULL); |
2759 | - sigfillset(&my_sigset); |
2760 | - |
2761 | - /* These are used for exiting */ |
2762 | - sigdelset(&my_sigset, SIGTERM); |
2763 | - sigdelset(&my_sigset, SIGINT); |
2764 | - sigdelset(&my_sigset, SIGHUP); |
2765 | - sigdelset(&my_sigset, SIGQUIT); |
2766 | - |
2767 | - pthread_sigmask(SIG_BLOCK, &my_sigset, NULL); |
2768 | -} |
2769 | - |
2770 | -/* |
2771 | - * exit_handler |
2772 | - * @sig |
2773 | - * |
2774 | - * Set the global variable which the process should |
2775 | - * be watching to determine when to exit. |
2776 | - */ |
2777 | -static void _exit_handler(int sig __attribute__((unused))) |
2778 | -{ |
2779 | - /* |
2780 | - * We exit when '_exit_now' is set. |
2781 | - * That is, when a signal has been received. |
2782 | - * |
2783 | - * We can not simply set '_exit_now' unless all |
2784 | - * threads are done processing. |
2785 | - */ |
2786 | - if (!_thread_registries_empty) { |
2787 | - syslog(LOG_ERR, "There are still devices being monitored."); |
2788 | - syslog(LOG_ERR, "Refusing to exit."); |
2789 | - } else |
2790 | - _exit_now = 1; |
2791 | - |
2792 | -} |
2793 | - |
2794 | -#ifdef linux |
2795 | -static int _set_oom_adj(const char *oom_adj_path, int val) |
2796 | -{ |
2797 | - FILE *fp; |
2798 | - |
2799 | - if (!(fp = fopen(oom_adj_path, "w"))) { |
2800 | - perror("oom_adj: fopen failed"); |
2801 | - return 0; |
2802 | - } |
2803 | - |
2804 | - fprintf(fp, "%i", val); |
2805 | - |
2806 | - if (dm_fclose(fp)) |
2807 | - perror("oom_adj: fclose failed"); |
2808 | - |
2809 | - return 1; |
2810 | -} |
2811 | - |
2812 | -/* |
2813 | - * Protection against OOM killer if kernel supports it |
2814 | - */ |
2815 | -static int _protect_against_oom_killer(void) |
2816 | -{ |
2817 | - struct stat st; |
2818 | - |
2819 | - if (stat(OOM_ADJ_FILE, &st) == -1) { |
2820 | - if (errno != ENOENT) |
2821 | - perror(OOM_ADJ_FILE ": stat failed"); |
2822 | - |
2823 | - /* Try old oom_adj interface as a fallback */ |
2824 | - if (stat(OOM_ADJ_FILE_OLD, &st) == -1) { |
2825 | - if (errno == ENOENT) |
2826 | - perror(OOM_ADJ_FILE_OLD " not found"); |
2827 | - else |
2828 | - perror(OOM_ADJ_FILE_OLD ": stat failed"); |
2829 | - return 1; |
2830 | - } |
2831 | - |
2832 | - return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) || |
2833 | - _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN); |
2834 | - } |
2835 | - |
2836 | - return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN); |
2837 | -} |
2838 | - |
2839 | -static int _handle_preloaded_fifo(int fd, const char *path) |
2840 | -{ |
2841 | - struct stat st_fd, st_path; |
2842 | - int flags; |
2843 | - |
2844 | - if ((flags = fcntl(fd, F_GETFD)) < 0) |
2845 | - return 0; |
2846 | - |
2847 | - if (flags & FD_CLOEXEC) |
2848 | - return 0; |
2849 | - |
2850 | - if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode)) |
2851 | - return 0; |
2852 | - |
2853 | - if (stat(path, &st_path) < 0 || |
2854 | - st_path.st_dev != st_fd.st_dev || |
2855 | - st_path.st_ino != st_fd.st_ino) |
2856 | - return 0; |
2857 | - |
2858 | - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) |
2859 | - return 0; |
2860 | - |
2861 | - return 1; |
2862 | -} |
2863 | - |
2864 | -static int _systemd_handover(struct dm_event_fifos *fifos) |
2865 | -{ |
2866 | - const char *e; |
2867 | - char *p; |
2868 | - unsigned long env_pid, env_listen_fds; |
2869 | - int r = 0; |
2870 | - |
2871 | - memset(fifos, 0, sizeof(*fifos)); |
2872 | - |
2873 | - /* SD_ACTIVATION must be set! */ |
2874 | - if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1")) |
2875 | - goto out; |
2876 | - |
2877 | - /* LISTEN_PID must be equal to our PID! */ |
2878 | - if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME))) |
2879 | - goto out; |
2880 | - |
2881 | - errno = 0; |
2882 | - env_pid = strtoul(e, &p, 10); |
2883 | - if (errno || !p || *p || env_pid <= 0 || |
2884 | - getpid() != (pid_t) env_pid) |
2885 | - goto out; |
2886 | - |
2887 | - /* LISTEN_FDS must be 2 and the fds must be FIFOSs! */ |
2888 | - if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME))) |
2889 | - goto out; |
2890 | - |
2891 | - errno = 0; |
2892 | - env_listen_fds = strtoul(e, &p, 10); |
2893 | - if (errno || !p || *p || env_listen_fds != 2) |
2894 | - goto out; |
2895 | - |
2896 | - /* Check and handle the FIFOs passed in */ |
2897 | - r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) && |
2898 | - _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT)); |
2899 | - |
2900 | - if (r) { |
2901 | - fifos->server = SD_FD_FIFO_SERVER; |
2902 | - fifos->server_path = DM_EVENT_FIFO_SERVER; |
2903 | - fifos->client = SD_FD_FIFO_CLIENT; |
2904 | - fifos->client_path = DM_EVENT_FIFO_CLIENT; |
2905 | - } |
2906 | - |
2907 | -out: |
2908 | - unsetenv(SD_ACTIVATION_ENV_VAR_NAME); |
2909 | - unsetenv(SD_LISTEN_PID_ENV_VAR_NAME); |
2910 | - unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME); |
2911 | - return r; |
2912 | -} |
2913 | -#endif |
2914 | - |
2915 | -static void _remove_files_on_exit(void) |
2916 | -{ |
2917 | - if (unlink(DMEVENTD_PIDFILE)) |
2918 | - perror(DMEVENTD_PIDFILE ": unlink failed"); |
2919 | - |
2920 | - if (!_systemd_activation) { |
2921 | - if (unlink(DM_EVENT_FIFO_CLIENT)) |
2922 | - perror(DM_EVENT_FIFO_CLIENT " : unlink failed"); |
2923 | - |
2924 | - if (unlink(DM_EVENT_FIFO_SERVER)) |
2925 | - perror(DM_EVENT_FIFO_SERVER " : unlink failed"); |
2926 | - } |
2927 | -} |
2928 | - |
2929 | -static void _daemonize(void) |
2930 | -{ |
2931 | - int child_status; |
2932 | - int fd; |
2933 | - pid_t pid; |
2934 | - struct rlimit rlim; |
2935 | - struct timeval tval; |
2936 | - sigset_t my_sigset; |
2937 | - |
2938 | - sigemptyset(&my_sigset); |
2939 | - if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) { |
2940 | - fprintf(stderr, "Unable to restore signals.\n"); |
2941 | - exit(EXIT_FAILURE); |
2942 | - } |
2943 | - signal(SIGTERM, &_exit_handler); |
2944 | - |
2945 | - switch (pid = fork()) { |
2946 | - case -1: |
2947 | - perror("fork failed:"); |
2948 | - exit(EXIT_FAILURE); |
2949 | - |
2950 | - case 0: /* Child */ |
2951 | - break; |
2952 | - |
2953 | - default: |
2954 | - /* Wait for response from child */ |
2955 | - while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) { |
2956 | - tval.tv_sec = 0; |
2957 | - tval.tv_usec = 250000; /* .25 sec */ |
2958 | - select(0, NULL, NULL, NULL, &tval); |
2959 | - } |
2960 | - |
2961 | - if (_exit_now) /* Child has signaled it is ok - we can exit now */ |
2962 | - exit(EXIT_SUCCESS); |
2963 | - |
2964 | - /* Problem with child. Determine what it is by exit code */ |
2965 | - switch (WEXITSTATUS(child_status)) { |
2966 | - case EXIT_DESC_CLOSE_FAILURE: |
2967 | - case EXIT_DESC_OPEN_FAILURE: |
2968 | - case EXIT_FIFO_FAILURE: |
2969 | - case EXIT_CHDIR_FAILURE: |
2970 | - default: |
2971 | - fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status)); |
2972 | - break; |
2973 | - } |
2974 | - |
2975 | - exit(WEXITSTATUS(child_status)); |
2976 | - } |
2977 | - |
2978 | - if (chdir("/")) |
2979 | - exit(EXIT_CHDIR_FAILURE); |
2980 | - |
2981 | - if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) |
2982 | - fd = 256; /* just have to guess */ |
2983 | - else |
2984 | - fd = rlim.rlim_cur; |
2985 | - |
2986 | - for (--fd; fd >= 0; fd--) { |
2987 | -#ifdef linux |
2988 | - /* Do not close fds preloaded by systemd! */ |
2989 | - if (_systemd_activation && |
2990 | - (fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT)) |
2991 | - continue; |
2992 | -#endif |
2993 | - (void) close(fd); |
2994 | - } |
2995 | - |
2996 | - if ((open("/dev/null", O_RDONLY) < 0) || |
2997 | - (open("/dev/null", O_WRONLY) < 0) || |
2998 | - (open("/dev/null", O_WRONLY) < 0)) |
2999 | - exit(EXIT_DESC_OPEN_FAILURE); |
3000 | - |
3001 | - setsid(); |
3002 | -} |
3003 | - |
3004 | -static void restart(void) |
3005 | -{ |
3006 | - struct dm_event_fifos fifos; |
3007 | - struct dm_event_daemon_message msg = { 0, 0, NULL }; |
3008 | - int i, count = 0; |
3009 | - char *message; |
3010 | - int length; |
3011 | - int version; |
3012 | - |
3013 | - /* Get the list of registrations from the running daemon. */ |
3014 | - |
3015 | - if (!init_fifos(&fifos)) { |
3016 | - fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n"); |
3017 | - exit(EXIT_FAILURE); |
3018 | - } |
3019 | - |
3020 | - if (!dm_event_get_version(&fifos, &version)) { |
3021 | - fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n"); |
3022 | - fini_fifos(&fifos); |
3023 | - exit(EXIT_FAILURE); |
3024 | - } |
3025 | - |
3026 | - if (version < 1) { |
3027 | - fprintf(stderr, "WARNING: The running dmeventd instance is too old.\n" |
3028 | - "Protocol version %d (required: 1). Action cancelled.\n", |
3029 | - version); |
3030 | - exit(EXIT_FAILURE); |
3031 | - } |
3032 | - |
3033 | - if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0)) { |
3034 | - exit(EXIT_FAILURE); |
3035 | - } |
3036 | - |
3037 | - message = msg.data; |
3038 | - message = strchr(message, ' '); |
3039 | - ++ message; |
3040 | - length = strlen(msg.data); |
3041 | - for (i = 0; i < length; ++i) { |
3042 | - if (msg.data[i] == ';') { |
3043 | - msg.data[i] = 0; |
3044 | - ++count; |
3045 | - } |
3046 | - } |
3047 | - |
3048 | - if (!(_initial_registrations = dm_malloc(sizeof(char*) * (count + 1)))) { |
3049 | - fprintf(stderr, "Memory allocation registration failed.\n"); |
3050 | - exit(EXIT_FAILURE); |
3051 | - } |
3052 | - |
3053 | - for (i = 0; i < count; ++i) { |
3054 | - if (!(_initial_registrations[i] = dm_strdup(message))) { |
3055 | - fprintf(stderr, "Memory allocation for message failed.\n"); |
3056 | - exit(EXIT_FAILURE); |
3057 | - } |
3058 | - message += strlen(message) + 1; |
3059 | - } |
3060 | - _initial_registrations[count] = 0; |
3061 | - |
3062 | - if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) { |
3063 | - fprintf(stderr, "Old dmeventd refused to die.\n"); |
3064 | - exit(EXIT_FAILURE); |
3065 | - } |
3066 | - |
3067 | - /* |
3068 | - * Wait for daemon to die, detected by sending further DIE messages |
3069 | - * until one fails. |
3070 | - */ |
3071 | - for (i = 0; i < 10; ++i) { |
3072 | - if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) |
3073 | - break; /* yep, it's dead probably */ |
3074 | - usleep(10); |
3075 | - } |
3076 | - |
3077 | - fini_fifos(&fifos); |
3078 | -} |
3079 | - |
3080 | -static void usage(char *prog, FILE *file) |
3081 | -{ |
3082 | - fprintf(file, "Usage:\n" |
3083 | - "%s [-d [-d [-d]]] [-f] [-h] [-R] [-V] [-?]\n\n" |
3084 | - " -d Log debug messages to syslog (-d, -dd, -ddd)\n" |
3085 | - " -f Don't fork, run in the foreground\n" |
3086 | - " -h -? Show this help information\n" |
3087 | - " -R Restart dmeventd\n" |
3088 | - " -V Show version of dmeventd\n\n", prog); |
3089 | -} |
3090 | - |
3091 | -int main(int argc, char *argv[]) |
3092 | -{ |
3093 | - signed char opt; |
3094 | - struct dm_event_fifos fifos; |
3095 | - //struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON}; |
3096 | - |
3097 | - opterr = 0; |
3098 | - optind = 0; |
3099 | - |
3100 | - while ((opt = getopt(argc, argv, "?fhVdR")) != EOF) { |
3101 | - switch (opt) { |
3102 | - case 'h': |
3103 | - usage(argv[0], stdout); |
3104 | - exit(0); |
3105 | - case '?': |
3106 | - usage(argv[0], stderr); |
3107 | - exit(0); |
3108 | - case 'R': |
3109 | - _restart++; |
3110 | - break; |
3111 | - case 'f': |
3112 | - _foreground++; |
3113 | - break; |
3114 | - case 'd': |
3115 | - dmeventd_debug++; |
3116 | - break; |
3117 | - case 'V': |
3118 | - printf("dmeventd version: %s\n", DM_LIB_VERSION); |
3119 | - exit(1); |
3120 | - } |
3121 | - } |
3122 | - |
3123 | - /* |
3124 | - * Switch to C locale to avoid reading large locale-archive file |
3125 | - * used by some glibc (on some distributions it takes over 100MB). |
3126 | - * Daemon currently needs to use mlockall(). |
3127 | - */ |
3128 | - if (setenv("LANG", "C", 1)) |
3129 | - perror("Cannot set LANG to C"); |
3130 | - |
3131 | - if (_restart) |
3132 | - restart(); |
3133 | - |
3134 | -#ifdef linux |
3135 | - _systemd_activation = _systemd_handover(&fifos); |
3136 | -#endif |
3137 | - |
3138 | - if (!_foreground) |
3139 | - _daemonize(); |
3140 | - |
3141 | - openlog("dmeventd", LOG_PID, LOG_DAEMON); |
3142 | - |
3143 | - (void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG); |
3144 | - if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0) |
3145 | - exit(EXIT_FAILURE); |
3146 | - |
3147 | - atexit(_remove_files_on_exit); |
3148 | - (void) dm_prepare_selinux_context(NULL, 0); |
3149 | - |
3150 | - /* Set the rest of the signals to cause '_exit_now' to be set */ |
3151 | - signal(SIGTERM, &_exit_handler); |
3152 | - signal(SIGINT, &_exit_handler); |
3153 | - signal(SIGHUP, &_exit_handler); |
3154 | - signal(SIGQUIT, &_exit_handler); |
3155 | - |
3156 | -#ifdef linux |
3157 | - /* Systemd has adjusted oom killer for us already */ |
3158 | - if (!_systemd_activation && !_protect_against_oom_killer()) |
3159 | - syslog(LOG_ERR, "Failed to protect against OOM killer"); |
3160 | -#endif |
3161 | - |
3162 | - _init_thread_signals(); |
3163 | - |
3164 | - //multilog_clear_logging(); |
3165 | - //multilog_add_type(std_syslog, &logdata); |
3166 | - //multilog_init_verbose(std_syslog, _LOG_DEBUG); |
3167 | - //multilog_async(1); |
3168 | - |
3169 | - if (!_systemd_activation) |
3170 | - _init_fifos(&fifos); |
3171 | - |
3172 | - pthread_mutex_init(&_global_mutex, NULL); |
3173 | - |
3174 | - if (!_systemd_activation && !_open_fifos(&fifos)) |
3175 | - exit(EXIT_FIFO_FAILURE); |
3176 | - |
3177 | - /* Signal parent, letting them know we are ready to go. */ |
3178 | - if (!_foreground) |
3179 | - kill(getppid(), SIGTERM); |
3180 | - syslog(LOG_NOTICE, "dmeventd ready for processing."); |
3181 | - |
3182 | - if (_initial_registrations) |
3183 | - _process_initial_registrations(); |
3184 | - |
3185 | - while (!_exit_now) { |
3186 | - _process_request(&fifos); |
3187 | - _cleanup_unused_threads(); |
3188 | - _lock_mutex(); |
3189 | - if (!dm_list_empty(&_thread_registry) |
3190 | - || !dm_list_empty(&_thread_registry_unused)) |
3191 | - _thread_registries_empty = 0; |
3192 | - else |
3193 | - _thread_registries_empty = 1; |
3194 | - _unlock_mutex(); |
3195 | - } |
3196 | - |
3197 | - _exit_dm_lib(); |
3198 | - |
3199 | - pthread_mutex_destroy(&_global_mutex); |
3200 | - |
3201 | - syslog(LOG_NOTICE, "dmeventd shutting down."); |
3202 | - closelog(); |
3203 | - |
3204 | - exit(EXIT_SUCCESS); |
3205 | -} |
3206 | |
3207 | === removed directory '.pc/dirs.patch/doc' |
3208 | === removed file '.pc/dirs.patch/doc/example.conf.in' |
3209 | --- .pc/dirs.patch/doc/example.conf.in 2013-05-30 11:02:10 +0000 |
3210 | +++ .pc/dirs.patch/doc/example.conf.in 1970-01-01 00:00:00 +0000 |
3211 | @@ -1,816 +0,0 @@ |
3212 | -# This is an example configuration file for the LVM2 system. |
3213 | -# It contains the default settings that would be used if there was no |
3214 | -# @DEFAULT_SYS_DIR@/lvm.conf file. |
3215 | -# |
3216 | -# Refer to 'man lvm.conf' for further information including the file layout. |
3217 | -# |
3218 | -# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set |
3219 | -# the environment variable LVM_SYSTEM_DIR before running the tools. |
3220 | -# |
3221 | -# N.B. Take care that each setting only appears once if uncommenting |
3222 | -# example settings in this file. |
3223 | - |
3224 | - |
3225 | -# This section allows you to configure which block devices should |
3226 | -# be used by the LVM system. |
3227 | -devices { |
3228 | - |
3229 | - # Where do you want your volume groups to appear ? |
3230 | - dir = "/dev" |
3231 | - |
3232 | - # An array of directories that contain the device nodes you wish |
3233 | - # to use with LVM2. |
3234 | - scan = [ "/dev" ] |
3235 | - |
3236 | - # If set, the cache of block device nodes with all associated symlinks |
3237 | - # will be constructed out of the existing udev database content. |
3238 | - # This avoids using and opening any inapplicable non-block devices or |
3239 | - # subdirectories found in the device directory. This setting is applied |
3240 | - # to udev-managed device directory only, other directories will be scanned |
3241 | - # fully. LVM2 needs to be compiled with udev support for this setting to |
3242 | - # take effect. N.B. Any device node or symlink not managed by udev in |
3243 | - # udev directory will be ignored with this setting on. |
3244 | - obtain_device_list_from_udev = 1 |
3245 | - |
3246 | - # If several entries in the scanned directories correspond to the |
3247 | - # same block device and the tools need to display a name for device, |
3248 | - # all the pathnames are matched against each item in the following |
3249 | - # list of regular expressions in turn and the first match is used. |
3250 | - preferred_names = [ ] |
3251 | - |
3252 | - # Try to avoid using undescriptive /dev/dm-N names, if present. |
3253 | - # preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] |
3254 | - |
3255 | - # A filter that tells LVM2 to only use a restricted set of devices. |
3256 | - # The filter consists of an array of regular expressions. These |
3257 | - # expressions can be delimited by a character of your choice, and |
3258 | - # prefixed with either an 'a' (for accept) or 'r' (for reject). |
3259 | - # The first expression found to match a device name determines if |
3260 | - # the device will be accepted or rejected (ignored). Devices that |
3261 | - # don't match any patterns are accepted. |
3262 | - |
3263 | - # Be careful if there there are symbolic links or multiple filesystem |
3264 | - # entries for the same device as each name is checked separately against |
3265 | - # the list of patterns. The effect is that if the first pattern in the |
3266 | - # list to match a name is an 'a' pattern for any of the names, the device |
3267 | - # is accepted; otherwise if the first pattern in the list to match a name |
3268 | - # is an 'r' pattern for any of the names it is rejected; otherwise it is |
3269 | - # accepted. |
3270 | - |
3271 | - # Don't have more than one filter line active at once: only one gets used. |
3272 | - |
3273 | - # Run vgscan after you change this parameter to ensure that |
3274 | - # the cache file gets regenerated (see below). |
3275 | - # If it doesn't do what you expect, check the output of 'vgscan -vvvv'. |
3276 | - |
3277 | - |
3278 | - # By default we accept every block device: |
3279 | - filter = [ "a/.*/" ] |
3280 | - |
3281 | - # Exclude the cdrom drive |
3282 | - # filter = [ "r|/dev/cdrom|" ] |
3283 | - |
3284 | - # When testing I like to work with just loopback devices: |
3285 | - # filter = [ "a/loop/", "r/.*/" ] |
3286 | - |
3287 | - # Or maybe all loops and ide drives except hdc: |
3288 | - # filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ] |
3289 | - |
3290 | - # Use anchors if you want to be really specific |
3291 | - # filter = [ "a|^/dev/hda8$|", "r/.*/" ] |
3292 | - |
3293 | - # Since "filter" is often overriden from command line, it is not suitable |
3294 | - # for system-wide device filtering (udev rules, lvmetad). To hide devices |
3295 | - # from LVM-specific udev processing and/or from lvmetad, you need to set |
3296 | - # global_filter. The syntax is the same as for normal "filter" |
3297 | - # above. Devices that fail the global_filter are not even opened by LVM. |
3298 | - |
3299 | - # global_filter = [] |
3300 | - |
3301 | - # The results of the filtering are cached on disk to avoid |
3302 | - # rescanning dud devices (which can take a very long time). |
3303 | - # By default this cache is stored in the @DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@ directory |
3304 | - # in a file called '.cache'. |
3305 | - # It is safe to delete the contents: the tools regenerate it. |
3306 | - # (The old setting 'cache' is still respected if neither of |
3307 | - # these new ones is present.) |
3308 | - # N.B. If obtain_device_list_from_udev is set to 1 the list of |
3309 | - # devices is instead obtained from udev and any existing .cache |
3310 | - # file is removed. |
3311 | - cache_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_CACHE_SUBDIR@" |
3312 | - cache_file_prefix = "" |
3313 | - |
3314 | - # You can turn off writing this cache file by setting this to 0. |
3315 | - write_cache_state = 1 |
3316 | - |
3317 | - # Advanced settings. |
3318 | - |
3319 | - # List of pairs of additional acceptable block device types found |
3320 | - # in /proc/devices with maximum (non-zero) number of partitions. |
3321 | - # types = [ "fd", 16 ] |
3322 | - |
3323 | - # If sysfs is mounted (2.6 kernels) restrict device scanning to |
3324 | - # the block devices it believes are valid. |
3325 | - # 1 enables; 0 disables. |
3326 | - sysfs_scan = 1 |
3327 | - |
3328 | - # By default, LVM2 will ignore devices used as component paths |
3329 | - # of device-mapper multipath devices. |
3330 | - # 1 enables; 0 disables. |
3331 | - multipath_component_detection = 1 |
3332 | - |
3333 | - # By default, LVM2 will ignore devices used as components of |
3334 | - # software RAID (md) devices by looking for md superblocks. |
3335 | - # 1 enables; 0 disables. |
3336 | - md_component_detection = 1 |
3337 | - |
3338 | - # By default, if a PV is placed directly upon an md device, LVM2 |
3339 | - # will align its data blocks with the md device's stripe-width. |
3340 | - # 1 enables; 0 disables. |
3341 | - md_chunk_alignment = 1 |
3342 | - |
3343 | - # Default alignment of the start of a data area in MB. If set to 0, |
3344 | - # a value of 64KB will be used. Set to 1 for 1MiB, 2 for 2MiB, etc. |
3345 | - # default_data_alignment = @DEFAULT_DATA_ALIGNMENT@ |
3346 | - |
3347 | - # By default, the start of a PV's data area will be a multiple of |
3348 | - # the 'minimum_io_size' or 'optimal_io_size' exposed in sysfs. |
3349 | - # - minimum_io_size - the smallest request the device can perform |
3350 | - # w/o incurring a read-modify-write penalty (e.g. MD's chunk size) |
3351 | - # - optimal_io_size - the device's preferred unit of receiving I/O |
3352 | - # (e.g. MD's stripe width) |
3353 | - # minimum_io_size is used if optimal_io_size is undefined (0). |
3354 | - # If md_chunk_alignment is enabled, that detects the optimal_io_size. |
3355 | - # This setting takes precedence over md_chunk_alignment. |
3356 | - # 1 enables; 0 disables. |
3357 | - data_alignment_detection = 1 |
3358 | - |
3359 | - # Alignment (in KB) of start of data area when creating a new PV. |
3360 | - # md_chunk_alignment and data_alignment_detection are disabled if set. |
3361 | - # Set to 0 for the default alignment (see: data_alignment_default) |
3362 | - # or page size, if larger. |
3363 | - data_alignment = 0 |
3364 | - |
3365 | - # By default, the start of the PV's aligned data area will be shifted by |
3366 | - # the 'alignment_offset' exposed in sysfs. This offset is often 0 but |
3367 | - # may be non-zero; e.g.: certain 4KB sector drives that compensate for |
3368 | - # windows partitioning will have an alignment_offset of 3584 bytes |
3369 | - # (sector 7 is the lowest aligned logical block, the 4KB sectors start |
3370 | - # at LBA -1, and consequently sector 63 is aligned on a 4KB boundary). |
3371 | - # But note that pvcreate --dataalignmentoffset will skip this detection. |
3372 | - # 1 enables; 0 disables. |
3373 | - data_alignment_offset_detection = 1 |
3374 | - |
3375 | - # If, while scanning the system for PVs, LVM2 encounters a device-mapper |
3376 | - # device that has its I/O suspended, it waits for it to become accessible. |
3377 | - # Set this to 1 to skip such devices. This should only be needed |
3378 | - # in recovery situations. |
3379 | - ignore_suspended_devices = 0 |
3380 | - |
3381 | - # During each LVM operation errors received from each device are counted. |
3382 | - # If the counter of a particular device exceeds the limit set here, no |
3383 | - # further I/O is sent to that device for the remainder of the respective |
3384 | - # operation. Setting the parameter to 0 disables the counters altogether. |
3385 | - disable_after_error_count = 0 |
3386 | - |
3387 | - # Allow use of pvcreate --uuid without requiring --restorefile. |
3388 | - require_restorefile_with_uuid = 1 |
3389 | - |
3390 | - # Minimum size (in KB) of block devices which can be used as PVs. |
3391 | - # In a clustered environment all nodes must use the same value. |
3392 | - # Any value smaller than 512KB is ignored. |
3393 | - |
3394 | - # Ignore devices smaller than 2MB such as floppy drives. |
3395 | - pv_min_size = 2048 |
3396 | - |
3397 | - # The original built-in setting was 512 up to and including version 2.02.84. |
3398 | - # pv_min_size = 512 |
3399 | - |
3400 | - # Issue discards to a logical volumes's underlying physical volume(s) when |
3401 | - # the logical volume is no longer using the physical volumes' space (e.g. |
3402 | - # lvremove, lvreduce, etc). Discards inform the storage that a region is |
3403 | - # no longer in use. Storage that supports discards advertise the protocol |
3404 | - # specific way discards should be issued by the kernel (TRIM, UNMAP, or |
3405 | - # WRITE SAME with UNMAP bit set). Not all storage will support or benefit |
3406 | - # from discards but SSDs and thinly provisioned LUNs generally do. If set |
3407 | - # to 1, discards will only be issued if both the storage and kernel provide |
3408 | - # support. |
3409 | - # 1 enables; 0 disables. |
3410 | - issue_discards = 0 |
3411 | -} |
3412 | - |
3413 | -# This section allows you to configure the way in which LVM selects |
3414 | -# free space for its Logical Volumes. |
3415 | -allocation { |
3416 | - |
3417 | - # When searching for free space to extend an LV, the "cling" |
3418 | - # allocation policy will choose space on the same PVs as the last |
3419 | - # segment of the existing LV. If there is insufficient space and a |
3420 | - # list of tags is defined here, it will check whether any of them are |
3421 | - # attached to the PVs concerned and then seek to match those PV tags |
3422 | - # between existing extents and new extents. |
3423 | - # Use the special tag "@*" as a wildcard to match any PV tag. |
3424 | - |
3425 | - # Example: LVs are mirrored between two sites within a single VG. |
3426 | - # PVs are tagged with either @site1 or @site2 to indicate where |
3427 | - # they are situated. |
3428 | - |
3429 | - # cling_tag_list = [ "@site1", "@site2" ] |
3430 | - # cling_tag_list = [ "@*" ] |
3431 | - |
3432 | - # Changes made in version 2.02.85 extended the reach of the 'cling' |
3433 | - # policies to detect more situations where data can be grouped |
3434 | - # onto the same disks. Set this to 0 to revert to the previous |
3435 | - # algorithm. |
3436 | - maximise_cling = 1 |
3437 | - |
3438 | - # Set to 1 to guarantee that mirror logs will always be placed on |
3439 | - # different PVs from the mirror images. This was the default |
3440 | - # until version 2.02.85. |
3441 | - mirror_logs_require_separate_pvs = 0 |
3442 | - |
3443 | - # Set to 1 to guarantee that thin pool metadata will always |
3444 | - # be placed on different PVs from the pool data. |
3445 | - thin_pool_metadata_require_separate_pvs = 0 |
3446 | -} |
3447 | - |
3448 | -# This section that allows you to configure the nature of the |
3449 | -# information that LVM2 reports. |
3450 | -log { |
3451 | - |
3452 | - # Controls the messages sent to stdout or stderr. |
3453 | - # There are three levels of verbosity, 3 being the most verbose. |
3454 | - verbose = 0 |
3455 | - |
3456 | - # Set to 1 to suppress all non-essential messages from stdout. |
3457 | - # This has the same effect as -qq. |
3458 | - # When this is set, the following commands still produce output: |
3459 | - # dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay, |
3460 | - # pvs, version, vgcfgrestore -l, vgdisplay, vgs. |
3461 | - # Non-essential messages are shifted from log level 4 to log level 5 |
3462 | - # for syslog and lvm2_log_fn purposes. |
3463 | - # Any 'yes' or 'no' questions not overridden by other arguments |
3464 | - # are suppressed and default to 'no'. |
3465 | - silent = 0 |
3466 | - |
3467 | - # Should we send log messages through syslog? |
3468 | - # 1 is yes; 0 is no. |
3469 | - syslog = 1 |
3470 | - |
3471 | - # Should we log error and debug messages to a file? |
3472 | - # By default there is no log file. |
3473 | - #file = "/var/log/lvm2.log" |
3474 | - |
3475 | - # Should we overwrite the log file each time the program is run? |
3476 | - # By default we append. |
3477 | - overwrite = 0 |
3478 | - |
3479 | - # What level of log messages should we send to the log file and/or syslog? |
3480 | - # There are 6 syslog-like log levels currently in use - 2 to 7 inclusive. |
3481 | - # 7 is the most verbose (LOG_DEBUG). |
3482 | - level = 0 |
3483 | - |
3484 | - # Format of output messages |
3485 | - # Whether or not (1 or 0) to indent messages according to their severity |
3486 | - indent = 1 |
3487 | - |
3488 | - # Whether or not (1 or 0) to display the command name on each line output |
3489 | - command_names = 0 |
3490 | - |
3491 | - # A prefix to use before the message text (but after the command name, |
3492 | - # if selected). Default is two spaces, so you can see/grep the severity |
3493 | - # of each message. |
3494 | - prefix = " " |
3495 | - |
3496 | - # To make the messages look similar to the original LVM tools use: |
3497 | - # indent = 0 |
3498 | - # command_names = 1 |
3499 | - # prefix = " -- " |
3500 | - |
3501 | - # Set this if you want log messages during activation. |
3502 | - # Don't use this in low memory situations (can deadlock). |
3503 | - # activation = 0 |
3504 | -} |
3505 | - |
3506 | -# Configuration of metadata backups and archiving. In LVM2 when we |
3507 | -# talk about a 'backup' we mean making a copy of the metadata for the |
3508 | -# *current* system. The 'archive' contains old metadata configurations. |
3509 | -# Backups are stored in a human readeable text format. |
3510 | -backup { |
3511 | - |
3512 | - # Should we maintain a backup of the current metadata configuration ? |
3513 | - # Use 1 for Yes; 0 for No. |
3514 | - # Think very hard before turning this off! |
3515 | - backup = 1 |
3516 | - |
3517 | - # Where shall we keep it ? |
3518 | - # Remember to back up this directory regularly! |
3519 | - backup_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_BACKUP_SUBDIR@" |
3520 | - |
3521 | - # Should we maintain an archive of old metadata configurations. |
3522 | - # Use 1 for Yes; 0 for No. |
3523 | - # On by default. Think very hard before turning this off. |
3524 | - archive = 1 |
3525 | - |
3526 | - # Where should archived files go ? |
3527 | - # Remember to back up this directory regularly! |
3528 | - archive_dir = "@DEFAULT_SYS_DIR@/@DEFAULT_ARCHIVE_SUBDIR@" |
3529 | - |
3530 | - # What is the minimum number of archive files you wish to keep ? |
3531 | - retain_min = 10 |
3532 | - |
3533 | - # What is the minimum time you wish to keep an archive file for ? |
3534 | - retain_days = 30 |
3535 | -} |
3536 | - |
3537 | -# Settings for the running LVM2 in shell (readline) mode. |
3538 | -shell { |
3539 | - |
3540 | - # Number of lines of history to store in ~/.lvm_history |
3541 | - history_size = 100 |
3542 | -} |
3543 | - |
3544 | - |
3545 | -# Miscellaneous global LVM2 settings |
3546 | -global { |
3547 | - |
3548 | - # The file creation mask for any files and directories created. |
3549 | - # Interpreted as octal if the first digit is zero. |
3550 | - umask = 077 |
3551 | - |
3552 | - # Allow other users to read the files |
3553 | - #umask = 022 |
3554 | - |
3555 | - # Enabling test mode means that no changes to the on disk metadata |
3556 | - # will be made. Equivalent to having the -t option on every |
3557 | - # command. Defaults to off. |
3558 | - test = 0 |
3559 | - |
3560 | - # Default value for --units argument |
3561 | - units = "h" |
3562 | - |
3563 | - # Since version 2.02.54, the tools distinguish between powers of |
3564 | - # 1024 bytes (e.g. KiB, MiB, GiB) and powers of 1000 bytes (e.g. |
3565 | - # KB, MB, GB). |
3566 | - # If you have scripts that depend on the old behaviour, set this to 0 |
3567 | - # temporarily until you update them. |
3568 | - si_unit_consistency = 1 |
3569 | - |
3570 | - # Whether or not to communicate with the kernel device-mapper. |
3571 | - # Set to 0 if you want to use the tools to manipulate LVM metadata |
3572 | - # without activating any logical volumes. |
3573 | - # If the device-mapper kernel driver is not present in your kernel |
3574 | - # setting this to 0 should suppress the error messages. |
3575 | - activation = 1 |
3576 | - |
3577 | - # If we can't communicate with device-mapper, should we try running |
3578 | - # the LVM1 tools? |
3579 | - # This option only applies to 2.4 kernels and is provided to help you |
3580 | - # switch between device-mapper kernels and LVM1 kernels. |
3581 | - # The LVM1 tools need to be installed with .lvm1 suffices |
3582 | - # e.g. vgscan.lvm1 and they will stop working after you start using |
3583 | - # the new lvm2 on-disk metadata format. |
3584 | - # The default value is set when the tools are built. |
3585 | - # fallback_to_lvm1 = 0 |
3586 | - |
3587 | - # The default metadata format that commands should use - "lvm1" or "lvm2". |
3588 | - # The command line override is -M1 or -M2. |
3589 | - # Defaults to "lvm2". |
3590 | - # format = "lvm2" |
3591 | - |
3592 | - # Location of proc filesystem |
3593 | - proc = "/proc" |
3594 | - |
3595 | - # Type of locking to use. Defaults to local file-based locking (1). |
3596 | - # Turn locking off by setting to 0 (dangerous: risks metadata corruption |
3597 | - # if LVM2 commands get run concurrently). |
3598 | - # Type 2 uses the external shared library locking_library. |
3599 | - # Type 3 uses built-in clustered locking. |
3600 | - # Type 4 uses read-only locking which forbids any operations that might |
3601 | - # change metadata. |
3602 | - locking_type = 1 |
3603 | - |
3604 | - # Set to 0 to fail when a lock request cannot be satisfied immediately. |
3605 | - wait_for_locks = 1 |
3606 | - |
3607 | - # If using external locking (type 2) and initialisation fails, |
3608 | - # with this set to 1 an attempt will be made to use the built-in |
3609 | - # clustered locking. |
3610 | - # If you are using a customised locking_library you should set this to 0. |
3611 | - fallback_to_clustered_locking = 1 |
3612 | - |
3613 | - # If an attempt to initialise type 2 or type 3 locking failed, perhaps |
3614 | - # because cluster components such as clvmd are not running, with this set |
3615 | - # to 1 an attempt will be made to use local file-based locking (type 1). |
3616 | - # If this succeeds, only commands against local volume groups will proceed. |
3617 | - # Volume Groups marked as clustered will be ignored. |
3618 | - fallback_to_local_locking = 1 |
3619 | - |
3620 | - # Local non-LV directory that holds file-based locks while commands are |
3621 | - # in progress. A directory like /tmp that may get wiped on reboot is OK. |
3622 | - locking_dir = "@DEFAULT_LOCK_DIR@" |
3623 | - |
3624 | - # Whenever there are competing read-only and read-write access requests for |
3625 | - # a volume group's metadata, instead of always granting the read-only |
3626 | - # requests immediately, delay them to allow the read-write requests to be |
3627 | - # serviced. Without this setting, write access may be stalled by a high |
3628 | - # volume of read-only requests. |
3629 | - # NB. This option only affects locking_type = 1 viz. local file-based |
3630 | - # locking. |
3631 | - prioritise_write_locks = 1 |
3632 | - |
3633 | - # Other entries can go here to allow you to load shared libraries |
3634 | - # e.g. if support for LVM1 metadata was compiled as a shared library use |
3635 | - # format_libraries = "liblvm2format1.so" |
3636 | - # Full pathnames can be given. |
3637 | - |
3638 | - # Search this directory first for shared libraries. |
3639 | - # library_dir = "/lib" |
3640 | - |
3641 | - # The external locking library to load if locking_type is set to 2. |
3642 | - # locking_library = "liblvm2clusterlock.so" |
3643 | - |
3644 | - # Treat any internal errors as fatal errors, aborting the process that |
3645 | - # encountered the internal error. Please only enable for debugging. |
3646 | - abort_on_internal_errors = 0 |
3647 | - |
3648 | - # Check whether CRC is matching when parsed VG is used multiple times. |
3649 | - # This is useful to catch unexpected internal cached volume group |
3650 | - # structure modification. Please only enable for debugging. |
3651 | - detect_internal_vg_cache_corruption = 0 |
3652 | - |
3653 | - # If set to 1, no operations that change on-disk metadata will be permitted. |
3654 | - # Additionally, read-only commands that encounter metadata in need of repair |
3655 | - # will still be allowed to proceed exactly as if the repair had been |
3656 | - # performed (except for the unchanged vg_seqno). |
3657 | - # Inappropriate use could mess up your system, so seek advice first! |
3658 | - metadata_read_only = 0 |
3659 | - |
3660 | - # 'mirror_segtype_default' defines which segtype will be used when the |
3661 | - # shorthand '-m' option is used for mirroring. The possible options are: |
3662 | - # |
3663 | - # "mirror" - The original RAID1 implementation provided by LVM2/DM. It is |
3664 | - # characterized by a flexible log solution (core, disk, mirrored) |
3665 | - # and by the necessity to block I/O while reconfiguring in the |
3666 | - # event of a failure. |
3667 | - # |
3668 | - # There is an inherent race in the dmeventd failure handling |
3669 | - # logic with snapshots of devices using this type of RAID1 that |
3670 | - # in the worst case could cause a deadlock. |
3671 | - # Ref: https://bugzilla.redhat.com/show_bug.cgi?id=817130#c10 |
3672 | - # |
3673 | - # "raid1" - This implementation leverages MD's RAID1 personality through |
3674 | - # device-mapper. It is characterized by a lack of log options. |
3675 | - # (A log is always allocated for every device and they are placed |
3676 | - # on the same device as the image - no separate devices are |
3677 | - # required.) This mirror implementation does not require I/O |
3678 | - # to be blocked in the kernel in the event of a failure. |
3679 | - # This mirror implementation is not cluster-aware and cannot be |
3680 | - # used in a shared (active/active) fashion in a cluster. |
3681 | - # |
3682 | - # Specify the '--type <mirror|raid1>' option to override this default |
3683 | - # setting. |
3684 | - mirror_segtype_default = "mirror" |
3685 | - |
3686 | - # The default format for displaying LV names in lvdisplay was changed |
3687 | - # in version 2.02.89 to show the LV name and path separately. |
3688 | - # Previously this was always shown as /dev/vgname/lvname even when that |
3689 | - # was never a valid path in the /dev filesystem. |
3690 | - # Set to 1 to reinstate the previous format. |
3691 | - # |
3692 | - # lvdisplay_shows_full_device_path = 0 |
3693 | - |
3694 | - # Whether to use (trust) a running instance of lvmetad. If this is set to |
3695 | - # 0, all commands fall back to the usual scanning mechanisms. When set to 1 |
3696 | - # *and* when lvmetad is running (it is not auto-started), the volume group |
3697 | - # metadata and PV state flags are obtained from the lvmetad instance and no |
3698 | - # scanning is done by the individual commands. In a setup with lvmetad, |
3699 | - # lvmetad udev rules *must* be set up for LVM to work correctly. Without |
3700 | - # proper udev rules, all changes in block device configuration will be |
3701 | - # *ignored* until a manual 'pvscan --cache' is performed. |
3702 | - # |
3703 | - # If lvmetad has been running while use_lvmetad was 0, it MUST be stopped |
3704 | - # before changing use_lvmetad to 1 and started again afterwards. |
3705 | - use_lvmetad = 0 |
3706 | - |
3707 | - # Full path of the utility called to check that a thin metadata device |
3708 | - # is in a state that allows it to be used. |
3709 | - # Each time a thin pool needs to be activated or after it is deactivated |
3710 | - # this utility is executed. The activation will only proceed if the utility |
3711 | - # has an exit status of 0. |
3712 | - # Set to "" to skip this check. (Not recommended.) |
3713 | - # The thin tools are available as part of the device-mapper-persistent-data |
3714 | - # package from https://github.com/jthornber/thin-provisioning-tools. |
3715 | - # |
3716 | - thin_check_executable = "@THIN_CHECK_CMD@" |
3717 | - |
3718 | - # String with options passed with thin_check command. By default, |
3719 | - # option '-q' is for quiet output. |
3720 | - thin_check_options = [ "-q" ] |
3721 | -} |
3722 | - |
3723 | -activation { |
3724 | - # Set to 1 to perform internal checks on the operations issued to |
3725 | - # libdevmapper. Useful for debugging problems with activation. |
3726 | - # Some of the checks may be expensive, so it's best to use this |
3727 | - # only when there seems to be a problem. |
3728 | - checks = 0 |
3729 | - |
3730 | - # Set to 0 to disable udev synchronisation (if compiled into the binaries). |
3731 | - # Processes will not wait for notification from udev. |
3732 | - # They will continue irrespective of any possible udev processing |
3733 | - # in the background. You should only use this if udev is not running |
3734 | - # or has rules that ignore the devices LVM2 creates. |
3735 | - # The command line argument --nodevsync takes precedence over this setting. |
3736 | - # If set to 1 when udev is not running, and there are LVM2 processes |
3737 | - # waiting for udev, run 'dmsetup udevcomplete_all' manually to wake them up. |
3738 | - udev_sync = 1 |
3739 | - |
3740 | - # Set to 0 to disable the udev rules installed by LVM2 (if built with |
3741 | - # --enable-udev_rules). LVM2 will then manage the /dev nodes and symlinks |
3742 | - # for active logical volumes directly itself. |
3743 | - # N.B. Manual intervention may be required if this setting is changed |
3744 | - # while any logical volumes are active. |
3745 | - udev_rules = 1 |
3746 | - |
3747 | - # Set to 1 for LVM2 to verify operations performed by udev. This turns on |
3748 | - # additional checks (and if necessary, repairs) on entries in the device |
3749 | - # directory after udev has completed processing its events. |
3750 | - # Useful for diagnosing problems with LVM2/udev interactions. |
3751 | - verify_udev_operations = 0 |
3752 | - |
3753 | - # If set to 1 and if deactivation of an LV fails, perhaps because |
3754 | - # a process run from a quick udev rule temporarily opened the device, |
3755 | - # retry the operation for a few seconds before failing. |
3756 | - retry_deactivation = 1 |
3757 | - |
3758 | - # How to fill in missing stripes if activating an incomplete volume. |
3759 | - # Using "error" will make inaccessible parts of the device return |
3760 | - # I/O errors on access. You can instead use a device path, in which |
3761 | - # case, that device will be used to in place of missing stripes. |
3762 | - # But note that using anything other than "error" with mirrored |
3763 | - # or snapshotted volumes is likely to result in data corruption. |
3764 | - missing_stripe_filler = "error" |
3765 | - |
3766 | - # The linear target is an optimised version of the striped target |
3767 | - # that only handles a single stripe. Set this to 0 to disable this |
3768 | - # optimisation and always use the striped target. |
3769 | - use_linear_target = 1 |
3770 | - |
3771 | - # How much stack (in KB) to reserve for use while devices suspended |
3772 | - # Prior to version 2.02.89 this used to be set to 256KB |
3773 | - reserved_stack = 64 |
3774 | - |
3775 | - # How much memory (in KB) to reserve for use while devices suspended |
3776 | - reserved_memory = 8192 |
3777 | - |
3778 | - # Nice value used while devices suspended |
3779 | - process_priority = -18 |
3780 | - |
3781 | - # If volume_list is defined, each LV is only activated if there is a |
3782 | - # match against the list. |
3783 | - # "vgname" and "vgname/lvname" are matched exactly. |
3784 | - # "@tag" matches any tag set in the LV or VG. |
3785 | - # "@*" matches if any tag defined on the host is also set in the LV or VG |
3786 | - # |
3787 | - # volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ] |
3788 | - |
3789 | - # If auto_activation_volume_list is defined, each LV that is to be |
3790 | - # activated is checked against the list while using the autoactivation |
3791 | - # option (--activate ay/-a ay), and if it matches, it is activated. |
3792 | - # "vgname" and "vgname/lvname" are matched exactly. |
3793 | - # "@tag" matches any tag set in the LV or VG. |
3794 | - # "@*" matches if any tag defined on the host is also set in the LV or VG |
3795 | - # |
3796 | - # auto_activation_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ] |
3797 | - |
3798 | - # If read_only_volume_list is defined, each LV that is to be activated |
3799 | - # is checked against the list, and if it matches, it as activated |
3800 | - # in read-only mode. (This overrides '--permission rw' stored in the |
3801 | - # metadata.) |
3802 | - # "vgname" and "vgname/lvname" are matched exactly. |
3803 | - # "@tag" matches any tag set in the LV or VG. |
3804 | - # "@*" matches if any tag defined on the host is also set in the LV or VG |
3805 | - # |
3806 | - # read_only_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ] |
3807 | - |
3808 | - # Size (in KB) of each copy operation when mirroring |
3809 | - mirror_region_size = 512 |
3810 | - |
3811 | - # Setting to use when there is no readahead value stored in the metadata. |
3812 | - # |
3813 | - # "none" - Disable readahead. |
3814 | - # "auto" - Use default value chosen by kernel. |
3815 | - readahead = "auto" |
3816 | - |
3817 | - # 'raid_fault_policy' defines how a device failure in a RAID logical |
3818 | - # volume is handled. This includes logical volumes that have the following |
3819 | - # segment types: raid1, raid4, raid5*, and raid6*. |
3820 | - # |
3821 | - # In the event of a failure, the following policies will determine what |
3822 | - # actions are performed during the automated response to failures (when |
3823 | - # dmeventd is monitoring the RAID logical volume) and when 'lvconvert' is |
3824 | - # called manually with the options '--repair' and '--use-policies'. |
3825 | - # |
3826 | - # "warn" - Use the system log to warn the user that a device in the RAID |
3827 | - # logical volume has failed. It is left to the user to run |
3828 | - # 'lvconvert --repair' manually to remove or replace the failed |
3829 | - # device. As long as the number of failed devices does not |
3830 | - # exceed the redundancy of the logical volume (1 device for |
3831 | - # raid4/5, 2 for raid6, etc) the logical volume will remain |
3832 | - # usable. |
3833 | - # |
3834 | - # "allocate" - Attempt to use any extra physical volumes in the volume |
3835 | - # group as spares and replace faulty devices. |
3836 | - # |
3837 | - raid_fault_policy = "warn" |
3838 | - |
3839 | - # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define |
3840 | - # how a device failure affecting a mirror (of "mirror" segment type) is |
3841 | - # handled. A mirror is composed of mirror images (copies) and a log. |
3842 | - # A disk log ensures that a mirror does not need to be re-synced |
3843 | - # (all copies made the same) every time a machine reboots or crashes. |
3844 | - # |
3845 | - # In the event of a failure, the specified policy will be used to determine |
3846 | - # what happens. This applies to automatic repairs (when the mirror is being |
3847 | - # monitored by dmeventd) and to manual lvconvert --repair when |
3848 | - # --use-policies is given. |
3849 | - # |
3850 | - # "remove" - Simply remove the faulty device and run without it. If |
3851 | - # the log device fails, the mirror would convert to using |
3852 | - # an in-memory log. This means the mirror will not |
3853 | - # remember its sync status across crashes/reboots and |
3854 | - # the entire mirror will be re-synced. If a |
3855 | - # mirror image fails, the mirror will convert to a |
3856 | - # non-mirrored device if there is only one remaining good |
3857 | - # copy. |
3858 | - # |
3859 | - # "allocate" - Remove the faulty device and try to allocate space on |
3860 | - # a new device to be a replacement for the failed device. |
3861 | - # Using this policy for the log is fast and maintains the |
3862 | - # ability to remember sync state through crashes/reboots. |
3863 | - # Using this policy for a mirror device is slow, as it |
3864 | - # requires the mirror to resynchronize the devices, but it |
3865 | - # will preserve the mirror characteristic of the device. |
3866 | - # This policy acts like "remove" if no suitable device and |
3867 | - # space can be allocated for the replacement. |
3868 | - # |
3869 | - # "allocate_anywhere" - Not yet implemented. Useful to place the log device |
3870 | - # temporarily on same physical volume as one of the mirror |
3871 | - # images. This policy is not recommended for mirror devices |
3872 | - # since it would break the redundant nature of the mirror. This |
3873 | - # policy acts like "remove" if no suitable device and space can |
3874 | - # be allocated for the replacement. |
3875 | - |
3876 | - mirror_log_fault_policy = "allocate" |
3877 | - mirror_image_fault_policy = "remove" |
3878 | - |
3879 | - # 'snapshot_autoextend_threshold' and 'snapshot_autoextend_percent' define |
3880 | - # how to handle automatic snapshot extension. The former defines when the |
3881 | - # snapshot should be extended: when its space usage exceeds this many |
3882 | - # percent. The latter defines how much extra space should be allocated for |
3883 | - # the snapshot, in percent of its current size. |
3884 | - # |
3885 | - # For example, if you set snapshot_autoextend_threshold to 70 and |
3886 | - # snapshot_autoextend_percent to 20, whenever a snapshot exceeds 70% usage, |
3887 | - # it will be extended by another 20%. For a 1G snapshot, using up 700M will |
3888 | - # trigger a resize to 1.2G. When the usage exceeds 840M, the snapshot will |
3889 | - # be extended to 1.44G, and so on. |
3890 | - # |
3891 | - # Setting snapshot_autoextend_threshold to 100 disables automatic |
3892 | - # extensions. The minimum value is 50 (A setting below 50 will be treated |
3893 | - # as 50). |
3894 | - |
3895 | - snapshot_autoextend_threshold = 100 |
3896 | - snapshot_autoextend_percent = 20 |
3897 | - |
3898 | - # 'thin_pool_autoextend_threshold' and 'thin_pool_autoextend_percent' define |
3899 | - # how to handle automatic pool extension. The former defines when the |
3900 | - # pool should be extended: when its space usage exceeds this many |
3901 | - # percent. The latter defines how much extra space should be allocated for |
3902 | - # the pool, in percent of its current size. |
3903 | - # |
3904 | - # For example, if you set thin_pool_autoextend_threshold to 70 and |
3905 | - # thin_pool_autoextend_percent to 20, whenever a pool exceeds 70% usage, |
3906 | - # it will be extended by another 20%. For a 1G pool, using up 700M will |
3907 | - # trigger a resize to 1.2G. When the usage exceeds 840M, the pool will |
3908 | - # be extended to 1.44G, and so on. |
3909 | - # |
3910 | - # Setting thin_pool_autoextend_threshold to 100 disables automatic |
3911 | - # extensions. The minimum value is 50 (A setting below 50 will be treated |
3912 | - # as 50). |
3913 | - |
3914 | - thin_pool_autoextend_threshold = 100 |
3915 | - thin_pool_autoextend_percent = 20 |
3916 | - |
3917 | - # While activating devices, I/O to devices being (re)configured is |
3918 | - # suspended, and as a precaution against deadlocks, LVM2 needs to pin |
3919 | - # any memory it is using so it is not paged out. Groups of pages that |
3920 | - # are known not to be accessed during activation need not be pinned |
3921 | - # into memory. Each string listed in this setting is compared against |
3922 | - # each line in /proc/self/maps, and the pages corresponding to any |
3923 | - # lines that match are not pinned. On some systems locale-archive was |
3924 | - # found to make up over 80% of the memory used by the process. |
3925 | - # mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ] |
3926 | - |
3927 | - # Set to 1 to revert to the default behaviour prior to version 2.02.62 |
3928 | - # which used mlockall() to pin the whole process's memory while activating |
3929 | - # devices. |
3930 | - use_mlockall = 0 |
3931 | - |
3932 | - # Monitoring is enabled by default when activating logical volumes. |
3933 | - # Set to 0 to disable monitoring or use the --ignoremonitoring option. |
3934 | - monitoring = 1 |
3935 | - |
3936 | - # When pvmove or lvconvert must wait for the kernel to finish |
3937 | - # synchronising or merging data, they check and report progress |
3938 | - # at intervals of this number of seconds. The default is 15 seconds. |
3939 | - # If this is set to 0 and there is only one thing to wait for, there |
3940 | - # are no progress reports, but the process is awoken immediately the |
3941 | - # operation is complete. |
3942 | - polling_interval = 15 |
3943 | -} |
3944 | - |
3945 | - |
3946 | -#################### |
3947 | -# Advanced section # |
3948 | -#################### |
3949 | - |
3950 | -# Metadata settings |
3951 | -# |
3952 | -# metadata { |
3953 | - # Default number of copies of metadata to hold on each PV. 0, 1 or 2. |
3954 | - # You might want to override it from the command line with 0 |
3955 | - # when running pvcreate on new PVs which are to be added to large VGs. |
3956 | - |
3957 | - # pvmetadatacopies = 1 |
3958 | - |
3959 | - # Default number of copies of metadata to maintain for each VG. |
3960 | - # If set to a non-zero value, LVM automatically chooses which of |
3961 | - # the available metadata areas to use to achieve the requested |
3962 | - # number of copies of the VG metadata. If you set a value larger |
3963 | - # than the the total number of metadata areas available then |
3964 | - # metadata is stored in them all. |
3965 | - # The default value of 0 ("unmanaged") disables this automatic |
3966 | - # management and allows you to control which metadata areas |
3967 | - # are used at the individual PV level using 'pvchange |
3968 | - # --metadataignore y/n'. |
3969 | - |
3970 | - # vgmetadatacopies = 0 |
3971 | - |
3972 | - # Approximate default size of on-disk metadata areas in sectors. |
3973 | - # You should increase this if you have large volume groups or |
3974 | - # you want to retain a large on-disk history of your metadata changes. |
3975 | - |
3976 | - # pvmetadatasize = 255 |
3977 | - |
3978 | - # List of directories holding live copies of text format metadata. |
3979 | - # These directories must not be on logical volumes! |
3980 | - # It's possible to use LVM2 with a couple of directories here, |
3981 | - # preferably on different (non-LV) filesystems, and with no other |
3982 | - # on-disk metadata (pvmetadatacopies = 0). Or this can be in |
3983 | - # addition to on-disk metadata areas. |
3984 | - # The feature was originally added to simplify testing and is not |
3985 | - # supported under low memory situations - the machine could lock up. |
3986 | - # |
3987 | - # Never edit any files in these directories by hand unless you |
3988 | - # you are absolutely sure you know what you are doing! Use |
3989 | - # the supplied toolset to make changes (e.g. vgcfgrestore). |
3990 | - |
3991 | - # dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ] |
3992 | -#} |
3993 | - |
3994 | -# Event daemon |
3995 | -# |
3996 | -dmeventd { |
3997 | - # mirror_library is the library used when monitoring a mirror device. |
3998 | - # |
3999 | - # "libdevmapper-event-lvm2mirror.so" attempts to recover from |
4000 | - # failures. It removes failed devices from a volume group and |
4001 | - # reconfigures a mirror as necessary. If no mirror library is |
4002 | - # provided, mirrors are not monitored through dmeventd. |
4003 | - |
4004 | - mirror_library = "libdevmapper-event-lvm2mirror.so" |
4005 | - |
4006 | - # snapshot_library is the library used when monitoring a snapshot device. |
4007 | - # |
4008 | - # "libdevmapper-event-lvm2snapshot.so" monitors the filling of |
4009 | - # snapshots and emits a warning through syslog when the use of |
4010 | - # the snapshot exceeds 80%. The warning is repeated when 85%, 90% and |
4011 | - # 95% of the snapshot is filled. |
4012 | - |
4013 | - snapshot_library = "libdevmapper-event-lvm2snapshot.so" |
4014 | - |
4015 | - # thin_library is the library used when monitoring a thin device. |
4016 | - # |
4017 | - # "libdevmapper-event-lvm2thin.so" monitors the filling of |
4018 | - # pool and emits a warning through syslog when the use of |
4019 | - # the pool exceeds 80%. The warning is repeated when 85%, 90% and |
4020 | - # 95% of the pool is filled. |
4021 | - |
4022 | - thin_library = "libdevmapper-event-lvm2thin.so" |
4023 | - |
4024 | - # Full path of the dmeventd binary. |
4025 | - # |
4026 | - # executable = "@DMEVENTD_PATH@" |
4027 | -} |
4028 | |
4029 | === removed directory '.pc/dirs.patch/lib' |
4030 | === removed directory '.pc/dirs.patch/lib/commands' |
4031 | === removed file '.pc/dirs.patch/lib/commands/toolcontext.c' |
4032 | --- .pc/dirs.patch/lib/commands/toolcontext.c 2013-05-30 11:02:10 +0000 |
4033 | +++ .pc/dirs.patch/lib/commands/toolcontext.c 1970-01-01 00:00:00 +0000 |
4034 | @@ -1,1688 +0,0 @@ |
4035 | -/* |
4036 | - * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
4037 | - * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved. |
4038 | - * |
4039 | - * This file is part of LVM2. |
4040 | - * |
4041 | - * This copyrighted material is made available to anyone wishing to use, |
4042 | - * modify, copy, or redistribute it subject to the terms and conditions |
4043 | - * of the GNU Lesser General Public License v.2.1. |
4044 | - * |
4045 | - * You should have received a copy of the GNU Lesser General Public License |
4046 | - * along with this program; if not, write to the Free Software Foundation, |
4047 | - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
4048 | - */ |
4049 | - |
4050 | -#include "lib.h" |
4051 | -#include "toolcontext.h" |
4052 | -#include "metadata.h" |
4053 | -#include "defaults.h" |
4054 | -#include "lvm-string.h" |
4055 | -#include "activate.h" |
4056 | -#include "filter.h" |
4057 | -#include "filter-composite.h" |
4058 | -#include "filter-md.h" |
4059 | -#include "filter-mpath.h" |
4060 | -#include "filter-persistent.h" |
4061 | -#include "filter-regex.h" |
4062 | -#include "filter-sysfs.h" |
4063 | -#include "label.h" |
4064 | -#include "lvm-file.h" |
4065 | -#include "format-text.h" |
4066 | -#include "display.h" |
4067 | -#include "memlock.h" |
4068 | -#include "str_list.h" |
4069 | -#include "segtype.h" |
4070 | -#include "lvmcache.h" |
4071 | -#include "lvmetad.h" |
4072 | -#include "dev-cache.h" |
4073 | -#include "archiver.h" |
4074 | - |
4075 | -#ifdef HAVE_LIBDL |
4076 | -#include "sharedlib.h" |
4077 | -#endif |
4078 | - |
4079 | -#ifdef LVM1_INTERNAL |
4080 | -#include "format1.h" |
4081 | -#endif |
4082 | - |
4083 | -#ifdef POOL_INTERNAL |
4084 | -#include "format_pool.h" |
4085 | -#endif |
4086 | - |
4087 | -#include <locale.h> |
4088 | -#include <sys/stat.h> |
4089 | -#include <sys/utsname.h> |
4090 | -#include <syslog.h> |
4091 | -#include <time.h> |
4092 | - |
4093 | -#ifdef linux |
4094 | -# include <malloc.h> |
4095 | -#endif |
4096 | - |
4097 | -static const size_t linebuffer_size = 4096; |
4098 | - |
4099 | -static int _get_env_vars(struct cmd_context *cmd) |
4100 | -{ |
4101 | - const char *e; |
4102 | - |
4103 | - /* Set to "" to avoid using any system directory */ |
4104 | - if ((e = getenv("LVM_SYSTEM_DIR"))) { |
4105 | - if (dm_snprintf(cmd->system_dir, sizeof(cmd->system_dir), |
4106 | - "%s", e) < 0) { |
4107 | - log_error("LVM_SYSTEM_DIR environment variable " |
4108 | - "is too long."); |
4109 | - return 0; |
4110 | - } |
4111 | - } |
4112 | - |
4113 | - return 1; |
4114 | -} |
4115 | - |
4116 | -static void _get_sysfs_dir(struct cmd_context *cmd) |
4117 | -{ |
4118 | - static char proc_mounts[PATH_MAX]; |
4119 | - static char *split[4], buffer[PATH_MAX + 16]; |
4120 | - FILE *fp; |
4121 | - char *sys_mnt = NULL; |
4122 | - |
4123 | - cmd->sysfs_dir[0] = '\0'; |
4124 | - if (!*cmd->proc_dir) { |
4125 | - log_debug("No proc filesystem found: skipping sysfs detection"); |
4126 | - return; |
4127 | - } |
4128 | - |
4129 | - if (dm_snprintf(proc_mounts, sizeof(proc_mounts), |
4130 | - "%s/mounts", cmd->proc_dir) < 0) { |
4131 | - log_error("Failed to create /proc/mounts string for sysfs detection"); |
4132 | - return; |
4133 | - } |
4134 | - |
4135 | - if (!(fp = fopen(proc_mounts, "r"))) { |
4136 | - log_sys_error("_get_sysfs_dir fopen", proc_mounts); |
4137 | - return; |
4138 | - } |
4139 | - |
4140 | - while (fgets(buffer, sizeof(buffer), fp)) { |
4141 | - if (dm_split_words(buffer, 4, 0, split) == 4 && |
4142 | - !strcmp(split[2], "sysfs")) { |
4143 | - sys_mnt = split[1]; |
4144 | - break; |
4145 | - } |
4146 | - } |
4147 | - |
4148 | - if (fclose(fp)) |
4149 | - log_sys_error("fclose", proc_mounts); |
4150 | - |
4151 | - if (!sys_mnt) { |
4152 | - log_error("Failed to find sysfs mount point"); |
4153 | - return; |
4154 | - } |
4155 | - |
4156 | - strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir)); |
4157 | -} |
4158 | - |
4159 | -static void _init_logging(struct cmd_context *cmd) |
4160 | -{ |
4161 | - int append = 1; |
4162 | - time_t t; |
4163 | - |
4164 | - const char *log_file; |
4165 | - char timebuf[26]; |
4166 | - |
4167 | - /* Syslog */ |
4168 | - cmd->default_settings.syslog = |
4169 | - find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG); |
4170 | - if (cmd->default_settings.syslog != 1) |
4171 | - fin_syslog(); |
4172 | - |
4173 | - if (cmd->default_settings.syslog > 1) |
4174 | - init_syslog(cmd->default_settings.syslog); |
4175 | - |
4176 | - /* Debug level for log file output */ |
4177 | - cmd->default_settings.debug = |
4178 | - find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL); |
4179 | - init_debug(cmd->default_settings.debug); |
4180 | - |
4181 | - /* |
4182 | - * Suppress all non-essential stdout? |
4183 | - * -qq can override the default of 0 to 1 later. |
4184 | - * Once set to 1, there is no facility to change it back to 0. |
4185 | - */ |
4186 | - cmd->default_settings.silent = silent_mode() ? : |
4187 | - find_config_tree_int(cmd, "log/silent", DEFAULT_SILENT); |
4188 | - init_silent(cmd->default_settings.silent); |
4189 | - |
4190 | - /* Verbose level for tty output */ |
4191 | - cmd->default_settings.verbose = |
4192 | - find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE); |
4193 | - init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL); |
4194 | - |
4195 | - /* Log message formatting */ |
4196 | - init_indent(find_config_tree_int(cmd, "log/indent", |
4197 | - DEFAULT_INDENT)); |
4198 | - init_abort_on_internal_errors(find_config_tree_int(cmd, "global/abort_on_internal_errors", |
4199 | - DEFAULT_ABORT_ON_INTERNAL_ERRORS)); |
4200 | - |
4201 | - cmd->default_settings.msg_prefix = |
4202 | - find_config_tree_str_allow_empty(cmd, "log/prefix", DEFAULT_MSG_PREFIX); |
4203 | - |
4204 | - init_msg_prefix(cmd->default_settings.msg_prefix); |
4205 | - |
4206 | - cmd->default_settings.cmd_name = find_config_tree_int(cmd, |
4207 | - "log/command_names", |
4208 | - DEFAULT_CMD_NAME); |
4209 | - init_cmd_name(cmd->default_settings.cmd_name); |
4210 | - |
4211 | - /* Test mode */ |
4212 | - cmd->default_settings.test = |
4213 | - find_config_tree_int(cmd, "global/test", 0); |
4214 | - init_test(cmd->default_settings.test); |
4215 | - |
4216 | - /* Settings for logging to file */ |
4217 | - if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE)) |
4218 | - append = 0; |
4219 | - |
4220 | - log_file = find_config_tree_str(cmd, "log/file", 0); |
4221 | - |
4222 | - if (log_file) { |
4223 | - release_log_memory(); |
4224 | - fin_log(); |
4225 | - init_log_file(log_file, append); |
4226 | - } |
4227 | - |
4228 | - log_file = find_config_tree_str(cmd, "log/activate_file", 0); |
4229 | - if (log_file) |
4230 | - init_log_direct(log_file, append); |
4231 | - |
4232 | - init_log_while_suspended(find_config_tree_int(cmd, |
4233 | - "log/activation", 0)); |
4234 | - |
4235 | - t = time(NULL); |
4236 | - ctime_r(&t, &timebuf[0]); |
4237 | - timebuf[24] = '\0'; |
4238 | - log_verbose("Logging initialised at %s", timebuf); |
4239 | - |
4240 | - /* Tell device-mapper about our logging */ |
4241 | -#ifdef DEVMAPPER_SUPPORT |
4242 | - dm_log_with_errno_init(print_log); |
4243 | -#endif |
4244 | - reset_log_duplicated(); |
4245 | - reset_lvm_errno(1); |
4246 | -} |
4247 | - |
4248 | -#ifdef UDEV_SYNC_SUPPORT |
4249 | -/* |
4250 | - * Until the DM_UEVENT_GENERATED_FLAG was introduced in kernel patch |
4251 | - * 856a6f1dbd8940e72755af145ebcd806408ecedd |
4252 | - * some operations could not be performed by udev, requiring our fallback code. |
4253 | - */ |
4254 | -static int _dm_driver_has_stable_udev_support(void) |
4255 | -{ |
4256 | - char vsn[80]; |
4257 | - unsigned maj, min, patchlevel; |
4258 | - |
4259 | - return driver_version(vsn, sizeof(vsn)) && |
4260 | - (sscanf(vsn, "%u.%u.%u", &maj, &min, &patchlevel) == 3) && |
4261 | - (maj == 4 ? min >= 18 : maj > 4); |
4262 | -} |
4263 | -#endif |
4264 | - |
4265 | -static int _process_config(struct cmd_context *cmd) |
4266 | -{ |
4267 | - mode_t old_umask; |
4268 | - const char *read_ahead; |
4269 | - struct stat st; |
4270 | - const struct dm_config_node *cn; |
4271 | - const struct dm_config_value *cv; |
4272 | - int64_t pv_min_kb; |
4273 | - const char *lvmetad_socket; |
4274 | - |
4275 | - /* umask */ |
4276 | - cmd->default_settings.umask = find_config_tree_int(cmd, |
4277 | - "global/umask", |
4278 | - DEFAULT_UMASK); |
4279 | - |
4280 | - if ((old_umask = umask((mode_t) cmd->default_settings.umask)) != |
4281 | - (mode_t) cmd->default_settings.umask) |
4282 | - log_verbose("Set umask from %04o to %04o", |
4283 | - old_umask, cmd->default_settings.umask); |
4284 | - |
4285 | - /* dev dir */ |
4286 | - if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/", |
4287 | - find_config_tree_str(cmd, "devices/dir", |
4288 | - DEFAULT_DEV_DIR)) < 0) { |
4289 | - log_error("Device directory given in config file too long"); |
4290 | - return 0; |
4291 | - } |
4292 | -#ifdef DEVMAPPER_SUPPORT |
4293 | - dm_set_dev_dir(cmd->dev_dir); |
4294 | - |
4295 | - if (!dm_set_uuid_prefix("LVM-")) |
4296 | - return_0; |
4297 | -#endif |
4298 | - |
4299 | - /* proc dir */ |
4300 | - if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s", |
4301 | - find_config_tree_str(cmd, "global/proc", |
4302 | - DEFAULT_PROC_DIR)) < 0) { |
4303 | - log_error("Device directory given in config file too long"); |
4304 | - return 0; |
4305 | - } |
4306 | - |
4307 | - if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) { |
4308 | - log_warn("WARNING: proc dir %s not found - some checks will be bypassed", |
4309 | - cmd->proc_dir); |
4310 | - cmd->proc_dir[0] = '\0'; |
4311 | - } |
4312 | - |
4313 | - /* FIXME Use global value of sysfs_dir everywhere instead cmd->sysfs_dir. */ |
4314 | - _get_sysfs_dir(cmd); |
4315 | - set_sysfs_dir_path(cmd->sysfs_dir); |
4316 | - dm_set_sysfs_dir(cmd->sysfs_dir); |
4317 | - |
4318 | - /* activation? */ |
4319 | - cmd->default_settings.activation = find_config_tree_int(cmd, |
4320 | - "global/activation", |
4321 | - DEFAULT_ACTIVATION); |
4322 | - set_activation(cmd->default_settings.activation); |
4323 | - |
4324 | - cmd->default_settings.suffix = find_config_tree_int(cmd, |
4325 | - "global/suffix", |
4326 | - DEFAULT_SUFFIX); |
4327 | - |
4328 | - if (!(cmd->default_settings.unit_factor = |
4329 | - units_to_bytes(find_config_tree_str(cmd, |
4330 | - "global/units", |
4331 | - DEFAULT_UNITS), |
4332 | - &cmd->default_settings.unit_type))) { |
4333 | - log_error("Invalid units specification"); |
4334 | - return 0; |
4335 | - } |
4336 | - |
4337 | - read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD); |
4338 | - if (!strcasecmp(read_ahead, "auto")) |
4339 | - cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO; |
4340 | - else if (!strcasecmp(read_ahead, "none")) |
4341 | - cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE; |
4342 | - else { |
4343 | - log_error("Invalid readahead specification"); |
4344 | - return 0; |
4345 | - } |
4346 | - |
4347 | - cmd->default_settings.udev_rules = find_config_tree_int(cmd, |
4348 | - "activation/udev_rules", |
4349 | - DEFAULT_UDEV_RULES); |
4350 | - |
4351 | - cmd->default_settings.udev_sync = find_config_tree_int(cmd, |
4352 | - "activation/udev_sync", |
4353 | - DEFAULT_UDEV_SYNC); |
4354 | - |
4355 | - init_retry_deactivation(find_config_tree_int(cmd, "activation/retry_deactivation", |
4356 | - DEFAULT_RETRY_DEACTIVATION)); |
4357 | - |
4358 | - init_activation_checks(find_config_tree_int(cmd, "activation/checks", |
4359 | - DEFAULT_ACTIVATION_CHECKS)); |
4360 | - |
4361 | -#ifdef UDEV_SYNC_SUPPORT |
4362 | - /* |
4363 | - * We need udev rules to be applied, otherwise we would end up with no |
4364 | - * nodes and symlinks! However, we can disable the synchronization itself |
4365 | - * in runtime and still have only udev to create the nodes and symlinks |
4366 | - * without any fallback. |
4367 | - */ |
4368 | - cmd->default_settings.udev_fallback = cmd->default_settings.udev_rules ? |
4369 | - find_config_tree_int(cmd, "activation/verify_udev_operations", |
4370 | - DEFAULT_VERIFY_UDEV_OPERATIONS) : 1; |
4371 | - |
4372 | - /* Do not rely fully on udev if the udev support is known to be incomplete. */ |
4373 | - if (!cmd->default_settings.udev_fallback && !_dm_driver_has_stable_udev_support()) { |
4374 | - log_very_verbose("Kernel driver has incomplete udev support so " |
4375 | - "LVM will check and perform some operations itself."); |
4376 | - cmd->default_settings.udev_fallback = 1; |
4377 | - } |
4378 | - |
4379 | -#else |
4380 | - /* We must use old node/symlink creation code if not compiled with udev support at all! */ |
4381 | - cmd->default_settings.udev_fallback = 1; |
4382 | -#endif |
4383 | - |
4384 | - cmd->use_linear_target = find_config_tree_int(cmd, |
4385 | - "activation/use_linear_target", |
4386 | - DEFAULT_USE_LINEAR_TARGET); |
4387 | - |
4388 | - cmd->stripe_filler = find_config_tree_str(cmd, |
4389 | - "activation/missing_stripe_filler", |
4390 | - DEFAULT_STRIPE_FILLER); |
4391 | - |
4392 | - /* 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)? */ |
4393 | - if (!strcmp(cmd->stripe_filler, "/dev/ioerror") && |
4394 | - stat(cmd->stripe_filler, &st)) |
4395 | - cmd->stripe_filler = "error"; |
4396 | - |
4397 | - if (strcmp(cmd->stripe_filler, "error")) { |
4398 | - if (stat(cmd->stripe_filler, &st)) { |
4399 | - log_warn("WARNING: activation/missing_stripe_filler = \"%s\" " |
4400 | - "is invalid,", cmd->stripe_filler); |
4401 | - log_warn(" stat failed: %s", strerror(errno)); |
4402 | - log_warn("Falling back to \"error\" missing_stripe_filler."); |
4403 | - cmd->stripe_filler = "error"; |
4404 | - } else if (!S_ISBLK(st.st_mode)) { |
4405 | - log_warn("WARNING: activation/missing_stripe_filler = \"%s\" " |
4406 | - "is not a block device.", cmd->stripe_filler); |
4407 | - log_warn("Falling back to \"error\" missing_stripe_filler."); |
4408 | - cmd->stripe_filler = "error"; |
4409 | - } |
4410 | - } |
4411 | - |
4412 | - cmd->si_unit_consistency = find_config_tree_int(cmd, |
4413 | - "global/si_unit_consistency", |
4414 | - DEFAULT_SI_UNIT_CONSISTENCY); |
4415 | - |
4416 | - if ((cn = find_config_tree_node(cmd, "activation/mlock_filter"))) |
4417 | - for (cv = cn->v; cv; cv = cv->next) |
4418 | - if ((cv->type != DM_CFG_STRING) || !cv->v.str[0]) |
4419 | - log_error("Ignoring invalid activation/mlock_filter entry in config file"); |
4420 | - |
4421 | - cmd->metadata_read_only = find_config_tree_int(cmd, "global/metadata_read_only", |
4422 | - DEFAULT_METADATA_READ_ONLY); |
4423 | - |
4424 | - pv_min_kb = find_config_tree_int64(cmd, "devices/pv_min_size", DEFAULT_PV_MIN_SIZE_KB); |
4425 | - if (pv_min_kb < PV_MIN_SIZE_KB) { |
4426 | - log_warn("Ignoring too small pv_min_size %" PRId64 "KB, using default %dKB.", |
4427 | - pv_min_kb, PV_MIN_SIZE_KB); |
4428 | - pv_min_kb = PV_MIN_SIZE_KB; |
4429 | - } |
4430 | - /* LVM stores sizes internally in units of 512-byte sectors. */ |
4431 | - init_pv_min_size((uint64_t)pv_min_kb * (1024 >> SECTOR_SHIFT)); |
4432 | - |
4433 | - init_detect_internal_vg_cache_corruption |
4434 | - (find_config_tree_int(cmd, "global/detect_internal_vg_cache_corruption", |
4435 | - DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION)); |
4436 | - |
4437 | - lvmetad_disconnect(); |
4438 | - |
4439 | - lvmetad_socket = getenv("LVM_LVMETAD_SOCKET"); |
4440 | - if (!lvmetad_socket) |
4441 | - lvmetad_socket = DEFAULT_RUN_DIR "/lvmetad.socket"; |
4442 | - |
4443 | - /* TODO? |
4444 | - lvmetad_socket = find_config_tree_str(cmd, "lvmetad/socket_path", |
4445 | - DEFAULT_RUN_DIR "/lvmetad.socket"); |
4446 | - */ |
4447 | - lvmetad_set_socket(lvmetad_socket); |
4448 | - cn = find_config_tree_node(cmd, "devices/global_filter"); |
4449 | - lvmetad_set_token(cn ? cn->v : NULL); |
4450 | - lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0)); |
4451 | - lvmetad_init(cmd); |
4452 | - |
4453 | - return 1; |
4454 | -} |
4455 | - |
4456 | -static int _set_tag(struct cmd_context *cmd, const char *tag) |
4457 | -{ |
4458 | - log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag)); |
4459 | - |
4460 | - if (!str_list_add(cmd->libmem, &cmd->tags, tag)) { |
4461 | - log_error("_set_tag: str_list_add %s failed", tag); |
4462 | - return 0; |
4463 | - } |
4464 | - |
4465 | - return 1; |
4466 | -} |
4467 | - |
4468 | -static int _check_host_filters(struct cmd_context *cmd, const struct dm_config_node *hn, |
4469 | - int *passes) |
4470 | -{ |
4471 | - const struct dm_config_node *cn; |
4472 | - const struct dm_config_value *cv; |
4473 | - |
4474 | - *passes = 1; |
4475 | - |
4476 | - for (cn = hn; cn; cn = cn->sib) { |
4477 | - if (!cn->v) |
4478 | - continue; |
4479 | - if (!strcmp(cn->key, "host_list")) { |
4480 | - *passes = 0; |
4481 | - if (cn->v->type == DM_CFG_EMPTY_ARRAY) |
4482 | - continue; |
4483 | - for (cv = cn->v; cv; cv = cv->next) { |
4484 | - if (cv->type != DM_CFG_STRING) { |
4485 | - log_error("Invalid hostname string " |
4486 | - "for tag %s", cn->key); |
4487 | - return 0; |
4488 | - } |
4489 | - if (!strcmp(cv->v.str, cmd->hostname)) { |
4490 | - *passes = 1; |
4491 | - return 1; |
4492 | - } |
4493 | - } |
4494 | - } |
4495 | - if (!strcmp(cn->key, "host_filter")) { |
4496 | - log_error("host_filter not supported yet"); |
4497 | - return 0; |
4498 | - } |
4499 | - } |
4500 | - |
4501 | - return 1; |
4502 | -} |
4503 | - |
4504 | -static int _init_tags(struct cmd_context *cmd, struct dm_config_tree *cft) |
4505 | -{ |
4506 | - const struct dm_config_node *tn, *cn; |
4507 | - const char *tag; |
4508 | - int passes; |
4509 | - |
4510 | - if (!(tn = dm_config_find_node(cft->root, "tags")) || !tn->child) |
4511 | - return 1; |
4512 | - |
4513 | - /* NB hosttags 0 when already 1 intentionally does not delete the tag */ |
4514 | - if (!cmd->hosttags && dm_config_find_int(cft->root, "tags/hosttags", |
4515 | - DEFAULT_HOSTTAGS)) { |
4516 | - /* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */ |
4517 | - if (!_set_tag(cmd, cmd->hostname)) |
4518 | - return_0; |
4519 | - cmd->hosttags = 1; |
4520 | - } |
4521 | - |
4522 | - for (cn = tn->child; cn; cn = cn->sib) { |
4523 | - if (cn->v) |
4524 | - continue; |
4525 | - tag = cn->key; |
4526 | - if (*tag == '@') |
4527 | - tag++; |
4528 | - if (!validate_name(tag)) { |
4529 | - log_error("Invalid tag in config file: %s", cn->key); |
4530 | - return 0; |
4531 | - } |
4532 | - if (cn->child) { |
4533 | - passes = 0; |
4534 | - if (!_check_host_filters(cmd, cn->child, &passes)) |
4535 | - return_0; |
4536 | - if (!passes) |
4537 | - continue; |
4538 | - } |
4539 | - if (!_set_tag(cmd, tag)) |
4540 | - return_0; |
4541 | - } |
4542 | - |
4543 | - return 1; |
4544 | -} |
4545 | - |
4546 | -static int _load_config_file(struct cmd_context *cmd, const char *tag) |
4547 | -{ |
4548 | - static char config_file[PATH_MAX] = ""; |
4549 | - const char *filler = ""; |
4550 | - struct stat info; |
4551 | - struct config_tree_list *cfl; |
4552 | - |
4553 | - if (*tag) |
4554 | - filler = "_"; |
4555 | - |
4556 | - if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf", |
4557 | - cmd->system_dir, filler, tag) < 0) { |
4558 | - log_error("LVM_SYSTEM_DIR or tag was too long"); |
4559 | - return 0; |
4560 | - } |
4561 | - |
4562 | - if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) { |
4563 | - log_error("config_tree_list allocation failed"); |
4564 | - return 0; |
4565 | - } |
4566 | - |
4567 | - if (!(cfl->cft = config_file_open(config_file, 0))) { |
4568 | - log_error("config_tree allocation failed"); |
4569 | - return 0; |
4570 | - } |
4571 | - |
4572 | - /* Is there a config file? */ |
4573 | - if (stat(config_file, &info) == -1) { |
4574 | - if (errno == ENOENT) { |
4575 | - dm_list_add(&cmd->config_files, &cfl->list); |
4576 | - goto out; |
4577 | - } |
4578 | - log_sys_error("stat", config_file); |
4579 | - config_file_destroy(cfl->cft); |
4580 | - return 0; |
4581 | - } |
4582 | - |
4583 | - log_very_verbose("Loading config file: %s", config_file); |
4584 | - if (!config_file_read(cfl->cft)) { |
4585 | - log_error("Failed to load config file %s", config_file); |
4586 | - config_file_destroy(cfl->cft); |
4587 | - return 0; |
4588 | - } |
4589 | - |
4590 | - dm_list_add(&cmd->config_files, &cfl->list); |
4591 | - |
4592 | - out: |
4593 | - if (*tag) { |
4594 | - if (!_init_tags(cmd, cfl->cft)) |
4595 | - return_0; |
4596 | - } else |
4597 | - /* Use temporary copy of lvm.conf while loading other files */ |
4598 | - cmd->cft = cfl->cft; |
4599 | - |
4600 | - return 1; |
4601 | -} |
4602 | - |
4603 | -/* Find and read first config file */ |
4604 | -static int _init_lvm_conf(struct cmd_context *cmd) |
4605 | -{ |
4606 | - /* No config file if LVM_SYSTEM_DIR is empty */ |
4607 | - if (!*cmd->system_dir) { |
4608 | - if (!(cmd->cft = config_file_open(NULL, 0))) { |
4609 | - log_error("Failed to create config tree"); |
4610 | - return 0; |
4611 | - } |
4612 | - return 1; |
4613 | - } |
4614 | - |
4615 | - if (!_load_config_file(cmd, "")) |
4616 | - return_0; |
4617 | - |
4618 | - return 1; |
4619 | -} |
4620 | - |
4621 | -/* Read any additional config files */ |
4622 | -static int _init_tag_configs(struct cmd_context *cmd) |
4623 | -{ |
4624 | - struct str_list *sl; |
4625 | - |
4626 | - /* Tag list may grow while inside this loop */ |
4627 | - dm_list_iterate_items(sl, &cmd->tags) { |
4628 | - if (!_load_config_file(cmd, sl->str)) |
4629 | - return_0; |
4630 | - } |
4631 | - |
4632 | - return 1; |
4633 | -} |
4634 | - |
4635 | -static struct dm_config_tree *_merge_config_files(struct cmd_context *cmd, struct dm_config_tree *cft) |
4636 | -{ |
4637 | - struct config_tree_list *cfl; |
4638 | - |
4639 | - /* Replace temporary duplicate copy of lvm.conf */ |
4640 | - if (cft->root) { |
4641 | - if (!(cft = config_file_open(NULL, 0))) { |
4642 | - log_error("Failed to create config tree"); |
4643 | - return 0; |
4644 | - } |
4645 | - } |
4646 | - |
4647 | - dm_list_iterate_items(cfl, &cmd->config_files) { |
4648 | - /* Merge all config trees into cmd->cft using merge/tag rules */ |
4649 | - if (!merge_config_tree(cmd, cft, cfl->cft)) |
4650 | - return_0; |
4651 | - } |
4652 | - |
4653 | - return cft; |
4654 | -} |
4655 | - |
4656 | -static void _destroy_tags(struct cmd_context *cmd) |
4657 | -{ |
4658 | - struct dm_list *slh, *slht; |
4659 | - |
4660 | - dm_list_iterate_safe(slh, slht, &cmd->tags) { |
4661 | - dm_list_del(slh); |
4662 | - } |
4663 | -} |
4664 | - |
4665 | -int config_files_changed(struct cmd_context *cmd) |
4666 | -{ |
4667 | - struct config_tree_list *cfl; |
4668 | - |
4669 | - dm_list_iterate_items(cfl, &cmd->config_files) { |
4670 | - if (config_file_changed(cfl->cft)) |
4671 | - return 1; |
4672 | - } |
4673 | - |
4674 | - return 0; |
4675 | -} |
4676 | - |
4677 | -/* |
4678 | - * Returns cmdline config_tree that overrides all others, if present. |
4679 | - */ |
4680 | -static struct dm_config_tree *_destroy_tag_configs(struct cmd_context *cmd) |
4681 | -{ |
4682 | - struct config_tree_list *cfl; |
4683 | - struct dm_config_tree *cft_cmdline = NULL, *cft; |
4684 | - |
4685 | - cft = dm_config_remove_cascaded_tree(cmd->cft); |
4686 | - if (cft) { |
4687 | - cft_cmdline = cmd->cft; |
4688 | - cmd->cft = cft; |
4689 | - } |
4690 | - |
4691 | - dm_list_iterate_items(cfl, &cmd->config_files) { |
4692 | - if (cfl->cft == cmd->cft) |
4693 | - cmd->cft = NULL; |
4694 | - config_file_destroy(cfl->cft); |
4695 | - } |
4696 | - |
4697 | - if (cmd->cft) { |
4698 | - config_file_destroy(cmd->cft); |
4699 | - cmd->cft = NULL; |
4700 | - } |
4701 | - |
4702 | - dm_list_init(&cmd->config_files); |
4703 | - |
4704 | - return cft_cmdline; |
4705 | -} |
4706 | - |
4707 | -static int _init_dev_cache(struct cmd_context *cmd) |
4708 | -{ |
4709 | - const struct dm_config_node *cn; |
4710 | - const struct dm_config_value *cv; |
4711 | - size_t len, udev_dir_len = strlen(DM_UDEV_DEV_DIR); |
4712 | - int len_diff; |
4713 | - int device_list_from_udev; |
4714 | - |
4715 | - init_dev_disable_after_error_count( |
4716 | - find_config_tree_int(cmd, "devices/disable_after_error_count", |
4717 | - DEFAULT_DISABLE_AFTER_ERROR_COUNT)); |
4718 | - |
4719 | - if (!dev_cache_init(cmd)) |
4720 | - return_0; |
4721 | - |
4722 | - device_list_from_udev = udev_is_running() ? |
4723 | - find_config_tree_bool(cmd, "devices/obtain_device_list_from_udev", |
4724 | - DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV) : 0; |
4725 | - init_obtain_device_list_from_udev(device_list_from_udev); |
4726 | - |
4727 | - if (!(cn = find_config_tree_node(cmd, "devices/scan"))) { |
4728 | - if (!dev_cache_add_dir("/dev")) { |
4729 | - log_error("Failed to add /dev to internal " |
4730 | - "device cache"); |
4731 | - return 0; |
4732 | - } |
4733 | - log_verbose("device/scan not in config file: " |
4734 | - "Defaulting to /dev"); |
4735 | - return 1; |
4736 | - } |
4737 | - |
4738 | - for (cv = cn->v; cv; cv = cv->next) { |
4739 | - if (cv->type != DM_CFG_STRING) { |
4740 | - log_error("Invalid string in config file: " |
4741 | - "devices/scan"); |
4742 | - return 0; |
4743 | - } |
4744 | - |
4745 | - if (device_list_from_udev) { |
4746 | - len = strlen(cv->v.str); |
4747 | - |
4748 | - /* |
4749 | - * DM_UDEV_DEV_DIR always has '/' at its end. |
4750 | - * If the item in the conf does not have it, be sure |
4751 | - * to make the right comparison without the '/' char! |
4752 | - */ |
4753 | - len_diff = len && cv->v.str[len - 1] != '/' ? |
4754 | - udev_dir_len - 1 != len : |
4755 | - udev_dir_len != len; |
4756 | - |
4757 | - if (len_diff || strncmp(DM_UDEV_DEV_DIR, cv->v.str, len)) { |
4758 | - device_list_from_udev = 0; |
4759 | - init_obtain_device_list_from_udev(0); |
4760 | - } |
4761 | - } |
4762 | - |
4763 | - if (!dev_cache_add_dir(cv->v.str)) { |
4764 | - log_error("Failed to add %s to internal device cache", |
4765 | - cv->v.str); |
4766 | - return 0; |
4767 | - } |
4768 | - } |
4769 | - |
4770 | - if (!(cn = find_config_tree_node(cmd, "devices/loopfiles"))) |
4771 | - return 1; |
4772 | - |
4773 | - for (cv = cn->v; cv; cv = cv->next) { |
4774 | - if (cv->type != DM_CFG_STRING) { |
4775 | - log_error("Invalid string in config file: " |
4776 | - "devices/loopfiles"); |
4777 | - return 0; |
4778 | - } |
4779 | - |
4780 | - if (!dev_cache_add_loopfile(cv->v.str)) { |
4781 | - log_error("Failed to add loopfile %s to internal " |
4782 | - "device cache", cv->v.str); |
4783 | - return 0; |
4784 | - } |
4785 | - } |
4786 | - |
4787 | - |
4788 | - return 1; |
4789 | -} |
4790 | - |
4791 | -#define MAX_FILTERS 5 |
4792 | - |
4793 | -static struct dev_filter *_init_filter_components(struct cmd_context *cmd) |
4794 | -{ |
4795 | - int nr_filt = 0; |
4796 | - const struct dm_config_node *cn; |
4797 | - struct dev_filter *filters[MAX_FILTERS] = { 0 }; |
4798 | - struct dev_filter *composite; |
4799 | - |
4800 | - /* |
4801 | - * Filters listed in order: top one gets applied first. |
4802 | - * Failure to initialise some filters is not fatal. |
4803 | - * Update MAX_FILTERS definition above when adding new filters. |
4804 | - */ |
4805 | - |
4806 | - /* |
4807 | - * sysfs filter. Only available on 2.6 kernels. Non-critical. |
4808 | - * Listed first because it's very efficient at eliminating |
4809 | - * unavailable devices. |
4810 | - */ |
4811 | - if (find_config_tree_bool(cmd, "devices/sysfs_scan", |
4812 | - DEFAULT_SYSFS_SCAN)) { |
4813 | - if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir))) |
4814 | - nr_filt++; |
4815 | - } |
4816 | - |
4817 | - /* regex filter. Optional. */ |
4818 | - if (!(cn = find_config_tree_node(cmd, "devices/filter"))) |
4819 | - log_very_verbose("devices/filter not found in config file: " |
4820 | - "no regex filter installed"); |
4821 | - |
4822 | - else if (!(filters[nr_filt] = regex_filter_create(cn->v))) { |
4823 | - log_error("Failed to create regex device filter"); |
4824 | - goto bad; |
4825 | - } else |
4826 | - nr_filt++; |
4827 | - |
4828 | - /* device type filter. Required. */ |
4829 | - cn = find_config_tree_node(cmd, "devices/types"); |
4830 | - if (!(filters[nr_filt] = lvm_type_filter_create(cmd->proc_dir, cn))) { |
4831 | - log_error("Failed to create lvm type filter"); |
4832 | - goto bad; |
4833 | - } |
4834 | - nr_filt++; |
4835 | - |
4836 | - /* md component filter. Optional, non-critical. */ |
4837 | - if (find_config_tree_bool(cmd, "devices/md_component_detection", |
4838 | - DEFAULT_MD_COMPONENT_DETECTION)) { |
4839 | - init_md_filtering(1); |
4840 | - if ((filters[nr_filt] = md_filter_create())) |
4841 | - nr_filt++; |
4842 | - } |
4843 | - |
4844 | - /* mpath component filter. Optional, non-critical. */ |
4845 | - if (find_config_tree_bool(cmd, "devices/multipath_component_detection", |
4846 | - DEFAULT_MULTIPATH_COMPONENT_DETECTION)) { |
4847 | - if ((filters[nr_filt] = mpath_filter_create(cmd->sysfs_dir))) |
4848 | - nr_filt++; |
4849 | - } |
4850 | - |
4851 | - /* Only build a composite filter if we really need it. */ |
4852 | - if (nr_filt == 1) |
4853 | - return filters[0]; |
4854 | - |
4855 | - if (!(composite = composite_filter_create(nr_filt, filters))) |
4856 | - goto_bad; |
4857 | - |
4858 | - return composite; |
4859 | -bad: |
4860 | - while (--nr_filt >= 0) |
4861 | - filters[nr_filt]->destroy(filters[nr_filt]); |
4862 | - |
4863 | - return NULL; |
4864 | -} |
4865 | - |
4866 | -static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache) |
4867 | -{ |
4868 | - static char cache_file[PATH_MAX]; |
4869 | - const char *dev_cache = NULL, *cache_dir, *cache_file_prefix; |
4870 | - struct dev_filter *f3 = NULL, *f4 = NULL, *toplevel_components[2] = { 0 }; |
4871 | - struct stat st; |
4872 | - const struct dm_config_node *cn; |
4873 | - |
4874 | - cmd->dump_filter = 0; |
4875 | - |
4876 | - if (!(f3 = _init_filter_components(cmd))) |
4877 | - goto_bad; |
4878 | - |
4879 | - init_ignore_suspended_devices(find_config_tree_int(cmd, |
4880 | - "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES)); |
4881 | - |
4882 | - /* |
4883 | - * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'. |
4884 | - */ |
4885 | - cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL); |
4886 | - cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL); |
4887 | - |
4888 | - if (cache_dir || cache_file_prefix) { |
4889 | - if (dm_snprintf(cache_file, sizeof(cache_file), |
4890 | - "%s%s%s/%s.cache", |
4891 | - cache_dir ? "" : cmd->system_dir, |
4892 | - cache_dir ? "" : "/", |
4893 | - cache_dir ? : DEFAULT_CACHE_SUBDIR, |
4894 | - cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) { |
4895 | - log_error("Persistent cache filename too long."); |
4896 | - goto bad; |
4897 | - } |
4898 | - } else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) && |
4899 | - (dm_snprintf(cache_file, sizeof(cache_file), |
4900 | - "%s/%s/%s.cache", |
4901 | - cmd->system_dir, DEFAULT_CACHE_SUBDIR, |
4902 | - DEFAULT_CACHE_FILE_PREFIX) < 0)) { |
4903 | - log_error("Persistent cache filename too long."); |
4904 | - goto bad; |
4905 | - } |
4906 | - |
4907 | - if (!dev_cache) |
4908 | - dev_cache = cache_file; |
4909 | - |
4910 | - if (!(f4 = persistent_filter_create(f3, dev_cache))) { |
4911 | - log_verbose("Failed to create persistent device filter."); |
4912 | - f3->destroy(f3); |
4913 | - return_0; |
4914 | - } |
4915 | - |
4916 | - /* Should we ever dump persistent filter state? */ |
4917 | - if (find_config_tree_int(cmd, "devices/write_cache_state", 1)) |
4918 | - cmd->dump_filter = 1; |
4919 | - |
4920 | - if (!*cmd->system_dir) |
4921 | - cmd->dump_filter = 0; |
4922 | - |
4923 | - /* |
4924 | - * Only load persistent filter device cache on startup if it is newer |
4925 | - * than the config file and this is not a long-lived process. |
4926 | - */ |
4927 | - if (load_persistent_cache && !cmd->is_long_lived && |
4928 | - !stat(dev_cache, &st) && |
4929 | - (st.st_ctime > config_file_timestamp(cmd->cft)) && |
4930 | - !persistent_filter_load(f4, NULL)) |
4931 | - log_verbose("Failed to load existing device cache from %s", |
4932 | - dev_cache); |
4933 | - |
4934 | - if (!(cn = find_config_tree_node(cmd, "devices/global_filter"))) { |
4935 | - cmd->filter = f4; |
4936 | - } else if (!(cmd->lvmetad_filter = regex_filter_create(cn->v))) |
4937 | - goto_bad; |
4938 | - else { |
4939 | - toplevel_components[0] = cmd->lvmetad_filter; |
4940 | - toplevel_components[1] = f4; |
4941 | - if (!(cmd->filter = composite_filter_create(2, toplevel_components))) |
4942 | - goto_bad; |
4943 | - } |
4944 | - |
4945 | - return 1; |
4946 | -bad: |
4947 | - if (f3) |
4948 | - f3->destroy(f3); |
4949 | - if (f4) |
4950 | - f4->destroy(f4); |
4951 | - if (toplevel_components[0]) |
4952 | - toplevel_components[0]->destroy(toplevel_components[0]); |
4953 | - return 0; |
4954 | -} |
4955 | - |
4956 | -struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format) |
4957 | -{ |
4958 | - struct format_type *fmt; |
4959 | - |
4960 | - dm_list_iterate_items(fmt, &cmd->formats) |
4961 | - if (!strcasecmp(fmt->name, format) || |
4962 | - !strcasecmp(fmt->name + 3, format) || |
4963 | - (fmt->alias && !strcasecmp(fmt->alias, format))) |
4964 | - return fmt; |
4965 | - |
4966 | - return NULL; |
4967 | -} |
4968 | - |
4969 | -static int _init_formats(struct cmd_context *cmd) |
4970 | -{ |
4971 | - const char *format; |
4972 | - |
4973 | - struct format_type *fmt; |
4974 | - |
4975 | -#ifdef HAVE_LIBDL |
4976 | - const struct dm_config_node *cn; |
4977 | -#endif |
4978 | - |
4979 | -#ifdef LVM1_INTERNAL |
4980 | - if (!(fmt = init_lvm1_format(cmd))) |
4981 | - return 0; |
4982 | - fmt->library = NULL; |
4983 | - dm_list_add(&cmd->formats, &fmt->list); |
4984 | -#endif |
4985 | - |
4986 | -#ifdef POOL_INTERNAL |
4987 | - if (!(fmt = init_pool_format(cmd))) |
4988 | - return 0; |
4989 | - fmt->library = NULL; |
4990 | - dm_list_add(&cmd->formats, &fmt->list); |
4991 | -#endif |
4992 | - |
4993 | -#ifdef HAVE_LIBDL |
4994 | - /* Load any formats in shared libs if not static */ |
4995 | - if (!is_static() && |
4996 | - (cn = find_config_tree_node(cmd, "global/format_libraries"))) { |
4997 | - |
4998 | - const struct dm_config_value *cv; |
4999 | - struct format_type *(*init_format_fn) (struct cmd_context *); |
5000 | - void *lib; |
review on the bug report.