]> sourceware.org Git - lvm2.git/blob - lib/thin/thin.c
thin: use discards as plural rather than singular
[lvm2.git] / lib / thin / thin.c
1 /*
2 * Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
3 *
4 * This file is part of LVM2.
5 *
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU Lesser General Public License v.2.1.
9 *
10 * You should have received a copy of the GNU Lesser General Public License
11 * along with this program; if not, write to the Free Software Foundation,
12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13 */
14
15 #include "lib.h"
16 #include "toolcontext.h"
17 #include "metadata.h"
18 #include "segtype.h"
19 #include "text_export.h"
20 #include "text_import.h"
21 #include "config.h"
22 #include "activate.h"
23 #include "str_list.h"
24 #include "defaults.h"
25
26 #ifdef DMEVENTD
27 # include "sharedlib.h"
28 # include "libdevmapper-event.h"
29 #endif
30
31 /* Dm kernel module name for thin provisiong */
32 #define THIN_MODULE "thin-pool"
33
34 /*
35 * Macro used as return argument - returns 0.
36 * return is left to be written in the function for better readability.
37 */
38 #define SEG_LOG_ERROR(t, p...) \
39 log_error(t " segment %s of logical volume %s.", ## p, \
40 dm_config_parent_name(sn), seg->lv->name), 0;
41
42 static int _thin_target_present(struct cmd_context *cmd,
43 const struct lv_segment *seg,
44 unsigned *attributes);
45
46 static const char *_thin_pool_name(const struct lv_segment *seg)
47 {
48 return seg->segtype->name;
49 }
50
51 static int _thin_pool_add_message(struct lv_segment *seg,
52 const char *key,
53 const struct dm_config_node *sn)
54 {
55 const char *lv_name = NULL;
56 struct logical_volume *lv = NULL;
57 uint32_t delete_id = 0;
58 dm_thin_message_t type;
59
60 /* Message must have only one from: create, delete */
61 if (dm_config_get_str(sn, "create", &lv_name)) {
62 if (!(lv = find_lv(seg->lv->vg, lv_name)))
63 return SEG_LOG_ERROR("Unknown LV %s for create message in",
64 lv_name);
65 /* FIXME: switch to _SNAP later, if the created LV has an origin */
66 type = DM_THIN_MESSAGE_CREATE_THIN;
67 }
68
69 if (!dm_config_get_uint32(sn, "delete", &delete_id)) {
70 if (!lv)
71 return SEG_LOG_ERROR("Unknown message in");
72 } else {
73 if (lv)
74 return SEG_LOG_ERROR("Unsupported message format in");
75 type = DM_THIN_MESSAGE_DELETE;
76 }
77
78 if (!attach_pool_message(seg, type, lv, delete_id, 1))
79 return_0;
80
81 return 1;
82 }
83
84 static int _thin_pool_text_import(struct lv_segment *seg,
85 const struct dm_config_node *sn,
86 struct dm_hash_table *pv_hash __attribute__((unused)))
87 {
88 const char *lv_name;
89 struct logical_volume *pool_data_lv, *pool_metadata_lv;
90 const char *discards_str = NULL;
91
92 if (!dm_config_get_str(sn, "metadata", &lv_name))
93 return SEG_LOG_ERROR("Metadata must be a string in");
94
95 if (!(pool_metadata_lv = find_lv(seg->lv->vg, lv_name)))
96 return SEG_LOG_ERROR("Unknown metadata %s in", lv_name);
97
98 if (!dm_config_get_str(sn, "pool", &lv_name))
99 return SEG_LOG_ERROR("Pool must be a string in");
100
101 if (!(pool_data_lv = find_lv(seg->lv->vg, lv_name)))
102 return SEG_LOG_ERROR("Unknown pool %s in", lv_name);
103
104 seg->lv->status |= THIN_POOL;
105 if (!attach_pool_metadata_lv(seg, pool_metadata_lv))
106 return_0;
107
108 if (!attach_pool_data_lv(seg, pool_data_lv))
109 return_0;
110
111 if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id))
112 return SEG_LOG_ERROR("Could not read transaction_id for");
113
114 if (!dm_config_get_uint32(sn, "chunk_size", &seg->chunk_size))
115 return SEG_LOG_ERROR("Could not read chunk_size");
116
117 if (dm_config_has_node(sn, "discards") &&
118 !dm_config_get_str(sn, "discards", &discard_str))
119 return SEG_LOG_ERROR("Could not read discards for");
120
121 if (!discards_str)
122 seg->discards = THIN_DISCARDS_PASSDOWN;
123 else if (!get_pool_discards(discards_str, &seg->discards))
124 return SEG_LOG_ERROR("Discards option unsupported for");
125
126 if (dm_config_has_node(sn, "low_water_mark") &&
127 !dm_config_get_uint64(sn, "low_water_mark", &seg->low_water_mark))
128 return SEG_LOG_ERROR("Could not read low_water_mark");
129
130 if ((seg->chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE) ||
131 (seg->chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE))
132 return SEG_LOG_ERROR("Unsupported value %u for chunk_size",
133 seg->device_id);
134
135 if (dm_config_has_node(sn, "zero_new_blocks") &&
136 !dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks))
137 return SEG_LOG_ERROR("Could not read zero_new_blocks for");
138
139 /* Read messages */
140 for (; sn; sn = sn->sib)
141 if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
142 return_0;
143
144 return 1;
145 }
146
147 static int _thin_pool_text_import_area_count(const struct dm_config_node *sn,
148 uint32_t *area_count)
149 {
150 *area_count = 1;
151
152 return 1;
153 }
154
155 static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter *f)
156 {
157 unsigned cnt = 0;
158 const struct lv_thin_message *tmsg;
159
160 outf(f, "metadata = \"%s\"", seg->metadata_lv->name);
161 outf(f, "pool = \"%s\"", seg_lv(seg, 0)->name);
162 outf(f, "transaction_id = %" PRIu64, seg->transaction_id);
163 outsize(f, (uint64_t) seg->chunk_size,
164 "chunk_size = %u", seg->chunk_size);
165
166 switch (seg->discards) {
167 case THIN_DISCARDS_PASSDOWN:
168 case THIN_DISCARDS_NO_PASSDOWN:
169 case THIN_DISCARDS_IGNORE:
170 outf(f, "discards = \"%s\"", get_pool_discards_name(seg->discards));
171 break;
172 default:
173 log_error(INTERNAL_ERROR "Invalid discards value %d.", seg->discards);
174 return 0;
175 }
176
177 if (seg->low_water_mark)
178 outf(f, "low_water_mark = %" PRIu64, seg->low_water_mark);
179
180 if (seg->zero_new_blocks)
181 outf(f, "zero_new_blocks = 1");
182
183 dm_list_iterate_items(tmsg, &seg->thin_messages) {
184 /* Extra validation */
185 switch (tmsg->type) {
186 case DM_THIN_MESSAGE_CREATE_SNAP:
187 case DM_THIN_MESSAGE_CREATE_THIN:
188 if (!lv_is_thin_volume(tmsg->u.lv)) {
189 log_error(INTERNAL_ERROR
190 "LV %s is not a thin volume.",
191 tmsg->u.lv->name);
192 return 0;
193 }
194 break;
195 default:
196 break;
197 }
198
199 if (!cnt)
200 outnl(f);
201
202 outf(f, "message%d {", ++cnt);
203 out_inc_indent(f);
204
205 switch (tmsg->type) {
206 case DM_THIN_MESSAGE_CREATE_SNAP:
207 case DM_THIN_MESSAGE_CREATE_THIN:
208 outf(f, "create = \"%s\"", tmsg->u.lv->name);
209 break;
210 case DM_THIN_MESSAGE_DELETE:
211 outf(f, "delete = %d", tmsg->u.delete_id);
212 break;
213 default:
214 log_error(INTERNAL_ERROR "Passed unsupported message.");
215 return 0;
216 }
217
218 out_dec_indent(f);
219 outf(f, "}");
220 }
221
222 return 1;
223 }
224
225 #ifdef DEVMAPPER_SUPPORT
226 static int _thin_pool_add_target_line(struct dev_manager *dm,
227 struct dm_pool *mem,
228 struct cmd_context *cmd,
229 void **target_state __attribute__((unused)),
230 struct lv_segment *seg,
231 const struct lv_activate_opts *laopts,
232 struct dm_tree_node *node, uint64_t len,
233 uint32_t *pvmove_mirror_count __attribute__((unused)))
234 {
235 static int _no_discards = 0;
236 char *metadata_dlid, *pool_dlid;
237 const struct lv_thin_message *lmsg;
238 const struct logical_volume *origin;
239 struct lvinfo info;
240 uint64_t transaction_id = 0;
241 unsigned attr;
242
243 if (!_thin_target_present(cmd, seg, &attr))
244 return_0;
245
246 if (!laopts->real_pool) {
247 if (!(pool_dlid = build_dm_uuid(mem, seg->lv->lvid.s, "tpool"))) {
248 log_error("Failed to build uuid for thin pool LV %s.", seg->pool_lv->name);
249 return 0;
250 }
251
252 if (!add_linear_area_to_dtree(node, len, seg->lv->vg->extent_size,
253 cmd->use_linear_target,
254 seg->lv->vg->name, seg->lv->name) ||
255 !dm_tree_node_add_target_area(node, NULL, pool_dlid, 0))
256 return_0;
257
258 return 1;
259 }
260
261 if (!(metadata_dlid = build_dm_uuid(mem, seg->metadata_lv->lvid.s, NULL))) {
262 log_error("Failed to build uuid for metadata LV %s.",
263 seg->metadata_lv->name);
264 return 0;
265 }
266
267 if (!(pool_dlid = build_dm_uuid(mem, seg_lv(seg, 0)->lvid.s, NULL))) {
268 log_error("Failed to build uuid for pool LV %s.",
269 seg_lv(seg, 0)->name);
270 return 0;
271 }
272
273 if (!dm_tree_node_add_thin_pool_target(node, len, seg->transaction_id,
274 metadata_dlid, pool_dlid,
275 seg->chunk_size, seg->low_water_mark,
276 seg->zero_new_blocks ? 0 : 1))
277 return_0;
278
279 if (seg->discards != THIN_DISCARDS_PASSDOWN)
280 if (attr & THIN_FEATURE_DISCARDS) {
281 /* FIXME: Check whether underlying dev supports discards */
282 if (!dm_tree_node_set_thin_pool_discard(node,
283 seg->discards == THIN_DISCARDS_IGNORE,
284 seg->discards == THIN_DISCARDS_NO_PASSDOWN))
285 return_0;
286 } else
287 log_warn_suppress(_no_discards++, "WARNING: Thin pool target does "
288 "not support discards (needs kernel >= 3.4).");
289
290 /*
291 * Add messages only for activation tree.
292 * Otherwise avoid checking for existence of suspended origin.
293 * Also transation_id is checked only when snapshot origin is active.
294 * (This might change later)
295 */
296 if (!laopts->is_activate)
297 return 1;
298
299 dm_list_iterate_items(lmsg, &seg->thin_messages) {
300 switch (lmsg->type) {
301 case DM_THIN_MESSAGE_CREATE_THIN:
302 origin = first_seg(lmsg->u.lv)->origin;
303 /* Check if the origin is suspended */
304 if (origin && lv_info(cmd, origin, 0, &info, 0, 0) &&
305 info.exists && !info.suspended) {
306 /* Origin is not suspended, but the transaction may have been
307 * already transfered, so test for transaction_id and
308 * allow to pass in the message for dmtree processing
309 * so it will skip all messages later.
310 */
311 if (!lv_thin_pool_transaction_id(seg->lv, &transaction_id))
312 return_0; /* Thin pool should exist and work */
313 if (transaction_id != seg->transaction_id) {
314 log_error("Can't create snapshot %s as origin %s is not suspended.",
315 lmsg->u.lv->name, origin->name);
316 return 0;
317 }
318 }
319 log_debug("Thin pool create_%s %s.", (!origin) ? "thin" : "snap", lmsg->u.lv->name);
320 if (!dm_tree_node_add_thin_pool_message(node,
321 (!origin) ? lmsg->type : DM_THIN_MESSAGE_CREATE_SNAP,
322 first_seg(lmsg->u.lv)->device_id,
323 (!origin) ? 0 : first_seg(origin)->device_id))
324 return_0;
325 break;
326 case DM_THIN_MESSAGE_DELETE:
327 log_debug("Thin pool delete %u.", lmsg->u.delete_id);
328 if (!dm_tree_node_add_thin_pool_message(node,
329 lmsg->type,
330 lmsg->u.delete_id, 0))
331 return_0;
332 break;
333 default:
334 log_error(INTERNAL_ERROR "Unsupported message.");
335 return 0;
336 }
337 }
338
339 if (!dm_list_empty(&seg->thin_messages)) {
340 /* Messages were passed, modify transaction_id as the last one */
341 log_debug("Thin pool set transaction id %" PRIu64 ".", seg->transaction_id);
342 if (!dm_tree_node_add_thin_pool_message(node,
343 DM_THIN_MESSAGE_SET_TRANSACTION_ID,
344 seg->transaction_id - 1,
345 seg->transaction_id))
346 return_0;
347 }
348
349 return 1;
350 }
351
352 static int _thin_pool_target_percent(void **target_state __attribute__((unused)),
353 percent_t *percent,
354 struct dm_pool *mem,
355 struct cmd_context *cmd __attribute__((unused)),
356 struct lv_segment *seg,
357 char *params,
358 uint64_t *total_numerator,
359 uint64_t *total_denominator)
360 {
361 struct dm_status_thin_pool *s;
362
363 if (!dm_get_status_thin_pool(mem, params, &s))
364 return_0;
365
366 /* With 'seg' report metadata percent, otherwice data percent */
367 if (seg) {
368 *percent = make_percent(s->used_metadata_blocks,
369 s->total_metadata_blocks);
370 *total_numerator += s->used_metadata_blocks;
371 *total_denominator += s->total_metadata_blocks;
372 } else {
373 *percent = make_percent(s->used_data_blocks,
374 s->total_data_blocks);
375 *total_numerator += s->used_data_blocks;
376 *total_denominator += s->total_data_blocks;
377 }
378
379 return 1;
380 }
381
382 # ifdef DMEVENTD
383 static const char *_get_thin_dso_path(struct cmd_context *cmd)
384 {
385 return get_monitor_dso_path(cmd, find_config_tree_str(cmd, "dmeventd/thin_library",
386 DEFAULT_DMEVENTD_THIN_LIB));
387 }
388
389 /* FIXME Cache this */
390 static int _target_registered(struct lv_segment *seg, int *pending)
391 {
392 return target_registered_with_dmeventd(seg->lv->vg->cmd,
393 _get_thin_dso_path(seg->lv->vg->cmd),
394 seg->lv, pending);
395 }
396
397 /* FIXME This gets run while suspended and performs banned operations. */
398 static int _target_set_events(struct lv_segment *seg, int evmask, int set)
399 {
400 /* FIXME Make timeout (10) configurable */
401 return target_register_events(seg->lv->vg->cmd,
402 _get_thin_dso_path(seg->lv->vg->cmd),
403 seg->lv, evmask, set, 10);
404 }
405
406 static int _target_register_events(struct lv_segment *seg,
407 int events)
408 {
409 return _target_set_events(seg, events, 1);
410 }
411
412 static int _target_unregister_events(struct lv_segment *seg,
413 int events)
414 {
415 return _target_set_events(seg, events, 0);
416 }
417 # endif /* DMEVENTD */
418 #endif /* DEVMAPPER_SUPPORT */
419
420 static const char *_thin_name(const struct lv_segment *seg)
421 {
422 return seg->segtype->name;
423 }
424
425 static int _thin_text_import(struct lv_segment *seg,
426 const struct dm_config_node *sn,
427 struct dm_hash_table *pv_hash __attribute__((unused)))
428 {
429 const char *lv_name;
430 struct logical_volume *pool_lv, *origin = NULL;
431
432 if (!dm_config_get_str(sn, "thin_pool", &lv_name))
433 return SEG_LOG_ERROR("Thin pool must be a string in");
434
435 if (!(pool_lv = find_lv(seg->lv->vg, lv_name)))
436 return SEG_LOG_ERROR("Unknown thin pool %s in", lv_name);
437
438 if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id))
439 return SEG_LOG_ERROR("Could not read transaction_id for");
440
441 if (dm_config_has_node(sn, "origin")) {
442 if (!dm_config_get_str(sn, "origin", &lv_name))
443 return SEG_LOG_ERROR("Origin must be a string in");
444
445 if (!(origin = find_lv(seg->lv->vg, lv_name)))
446 return SEG_LOG_ERROR("Unknown origin %s in", lv_name);
447 }
448
449 if (!dm_config_get_uint32(sn, "device_id", &seg->device_id))
450 return SEG_LOG_ERROR("Could not read device_id for");
451
452 if (seg->device_id > DM_THIN_MAX_DEVICE_ID)
453 return SEG_LOG_ERROR("Unsupported value %u for device_id",
454 seg->device_id);
455
456 if (!attach_pool_lv(seg, pool_lv, origin))
457 return_0;
458
459 return 1;
460 }
461
462 static int _thin_text_export(const struct lv_segment *seg, struct formatter *f)
463 {
464 outf(f, "thin_pool = \"%s\"", seg->pool_lv->name);
465 outf(f, "transaction_id = %" PRIu64, seg->transaction_id);
466 outf(f, "device_id = %d", seg->device_id);
467
468 if (seg->origin)
469 outf(f, "origin = \"%s\"", seg->origin->name);
470
471 return 1;
472 }
473
474 #ifdef DEVMAPPER_SUPPORT
475 static int _thin_add_target_line(struct dev_manager *dm,
476 struct dm_pool *mem,
477 struct cmd_context *cmd __attribute__((unused)),
478 void **target_state __attribute__((unused)),
479 struct lv_segment *seg,
480 const struct lv_activate_opts *laopts __attribute__((unused)),
481 struct dm_tree_node *node, uint64_t len,
482 uint32_t *pvmove_mirror_count __attribute__((unused)))
483 {
484 char *pool_dlid;
485 uint32_t device_id = seg->device_id;
486
487 if (!(pool_dlid = build_dm_uuid(mem, seg->pool_lv->lvid.s, "tpool"))) {
488 log_error("Failed to build uuid for pool LV %s.",
489 seg->pool_lv->name);
490 return 0;
491 }
492
493 if (!dm_tree_node_add_thin_target(node, len, pool_dlid, device_id))
494 return_0;
495
496 return 1;
497 }
498
499 static int _thin_target_percent(void **target_state __attribute__((unused)),
500 percent_t *percent,
501 struct dm_pool *mem,
502 struct cmd_context *cmd __attribute__((unused)),
503 struct lv_segment *seg,
504 char *params,
505 uint64_t *total_numerator,
506 uint64_t *total_denominator)
507 {
508 struct dm_status_thin *s;
509
510 /* Status for thin device is in sectors */
511 if (!dm_get_status_thin(mem, params, &s))
512 return_0;
513
514 if (seg) {
515 *percent = make_percent(s->mapped_sectors, seg->lv->size);
516 *total_denominator += seg->lv->size;
517 } else {
518 /* No lv_segment info here */
519 *percent = PERCENT_INVALID;
520 /* FIXME: Using denominator to pass the mapped info upward? */
521 *total_denominator += s->highest_mapped_sector;
522 }
523
524 *total_numerator += s->mapped_sectors;
525
526 return 1;
527 }
528
529 static int _thin_target_present(struct cmd_context *cmd,
530 const struct lv_segment *seg,
531 unsigned *attributes)
532 {
533 static int _checked = 0;
534 static int _present = 0;
535 static int _attrs = 0;
536 uint32_t maj, min, patchlevel;
537
538 if (!_checked) {
539 _present = target_present(cmd, THIN_MODULE, 1);
540
541 if (!target_version(THIN_MODULE, &maj, &min, &patchlevel)) {
542 log_error("Cannot read " THIN_MODULE " target version.");
543 return 0;
544 }
545
546 if (maj >=1 && min >= 1)
547 _attrs |= THIN_FEATURE_DISCARDS;
548 else
549 /* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
550 log_debug("Target " THIN_MODULE " does not support discards.");
551
552 if (maj >=1 && min >= 1)
553 _attrs |= THIN_FEATURE_EXTERNAL_ORIGIN;
554 else
555 /* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
556 log_debug("Target " THIN_MODULE " does not support external origins.");
557 #if 0
558 if (maj >=1 && min >= 1)
559 _attrs |= THIN_FEATURE_BLOCK_SIZE;
560 else
561 /* FIXME Log this as WARNING later only if the user asked for the feature to be used but it's not present */
562 log_debug("Target " THIN_MODULE " does not support non power of 2 block sizes.");
563 #endif
564 _checked = 1;
565 }
566
567 if (attributes)
568 *attributes = _attrs;
569
570 return _present;
571 }
572 #endif
573
574 static int _thin_modules_needed(struct dm_pool *mem,
575 const struct lv_segment *seg __attribute__((unused)),
576 struct dm_list *modules)
577 {
578 if (!str_list_add(mem, modules, THIN_MODULE)) {
579 log_error("thin string list allocation failed");
580 return 0;
581 }
582
583 return 1;
584 }
585
586 static void _thin_destroy(struct segment_type *segtype)
587 {
588 dm_free(segtype);
589 }
590
591 static struct segtype_handler _thin_pool_ops = {
592 .name = _thin_pool_name,
593 .text_import = _thin_pool_text_import,
594 .text_import_area_count = _thin_pool_text_import_area_count,
595 .text_export = _thin_pool_text_export,
596 #ifdef DEVMAPPER_SUPPORT
597 .add_target_line = _thin_pool_add_target_line,
598 .target_percent = _thin_pool_target_percent,
599 .target_present = _thin_target_present,
600 # ifdef DMEVENTD
601 .target_monitored = _target_registered,
602 .target_monitor_events = _target_register_events,
603 .target_unmonitor_events = _target_unregister_events,
604 # endif /* DMEVENTD */
605 #endif
606 .modules_needed = _thin_modules_needed,
607 .destroy = _thin_destroy,
608 };
609
610 static struct segtype_handler _thin_ops = {
611 .name = _thin_name,
612 .text_import = _thin_text_import,
613 .text_export = _thin_text_export,
614 #ifdef DEVMAPPER_SUPPORT
615 .add_target_line = _thin_add_target_line,
616 .target_percent = _thin_target_percent,
617 .target_present = _thin_target_present,
618 #endif
619 .modules_needed = _thin_modules_needed,
620 .destroy = _thin_destroy,
621 };
622
623 #ifdef THIN_INTERNAL
624 int init_thin_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
625 #else /* Shared */
626 int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
627 int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib)
628 #endif
629 {
630 static const struct {
631 struct segtype_handler *ops;
632 const char name[16];
633 uint32_t flags;
634 } reg_segtypes[] = {
635 { &_thin_pool_ops, "thin-pool", SEG_THIN_POOL },
636 /* FIXME Maybe use SEG_THIN_VOLUME instead of SEG_VIRTUAL */
637 { &_thin_ops, "thin", SEG_THIN_VOLUME | SEG_VIRTUAL }
638 };
639
640 struct segment_type *segtype;
641 unsigned i;
642
643 for (i = 0; i < sizeof(reg_segtypes)/sizeof(reg_segtypes[0]); ++i) {
644 segtype = dm_zalloc(sizeof(*segtype));
645
646 if (!segtype) {
647 log_error("Failed to allocate memory for %s segtype",
648 reg_segtypes[i].name);
649 return 0;
650 }
651
652 segtype->ops = reg_segtypes[i].ops;
653 segtype->name = reg_segtypes[i].name;
654 segtype->flags = reg_segtypes[i].flags;
655
656 #ifdef DEVMAPPER_SUPPORT
657 # ifdef DMEVENTD
658 if ((reg_segtypes[i].flags & SEG_THIN_POOL) &&
659 _get_thin_dso_path(cmd))
660 segtype->flags |= SEG_MONITORED;
661 # endif /* DMEVENTD */
662 #endif
663 if (!lvm_register_segtype(seglib, segtype))
664 /* segtype is already destroyed */
665 return_0;
666
667 log_very_verbose("Initialised segtype: %s", segtype->name);
668 }
669
670 return 1;
671 }
This page took 0.095437 seconds and 5 git commands to generate.