2 * Copyright (C) 2012 Red Hat, Inc.
4 * This file is part of LVM2.
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.
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
16 #include "toolcontext.h"
21 #include "lvmetad-client.h"
22 #include "format-text.h" // TODO for disk_locn, used as a DA representation
25 static int _using_lvmetad
= 0;
26 static daemon_handle _lvmetad
;
28 void lvmetad_init(void)
30 const char *socket
= getenv("LVM_LVMETAD_SOCKET");
31 if (_using_lvmetad
) { /* configured by the toolcontext */
32 _lvmetad
= lvmetad_open(socket
?: DEFAULT_RUN_DIR
"/lvmetad.socket");
33 if (_lvmetad
.socket_fd
< 0 || _lvmetad
.error
) {
34 log_warn("Failed to connect to lvmetad: %s. Falling back to scanning.", strerror(_lvmetad
.error
));
41 * Helper; evaluate the reply from lvmetad, check for errors, print diagnostics
42 * and return a summary success/failure exit code. Frees up the reply resources
45 static int _lvmetad_handle_reply(daemon_reply reply
, const char *action
, const char *object
) {
46 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
47 log_error("Request to %s %s in lvmetad has failed. Reason: %s",
48 action
, object
, reply
.error
? strerror(reply
.error
) :
49 daemon_reply_str(reply
, "reason", "Unknown."));
50 daemon_reply_destroy(reply
);
54 daemon_reply_destroy(reply
);
58 static int _read_mda(struct lvmcache_info
*info
,
59 struct format_type
*fmt
,
60 const struct dm_config_node
*cn
)
62 struct metadata_area_ops
*ops
;
64 dm_list_iterate_items(ops
, &fmt
->mda_ops
)
65 if (ops
->mda_import_text
&& ops
->mda_import_text(info
, cn
))
71 static struct lvmcache_info
*_pv_populate_lvmcache(
72 struct cmd_context
*cmd
, struct dm_config_node
*cn
, dev_t fallback
)
74 struct device
*device
;
79 struct dm_config_node
*mda
= NULL
;
80 struct dm_config_node
*da
= NULL
;
81 uint64_t offset
, size
;
82 struct lvmcache_info
*info
;
83 const char *pvid_txt
= dm_config_find_str(cn
->child
, "id", NULL
),
84 *vgid_txt
= dm_config_find_str(cn
->child
, "vgid", NULL
),
85 *vgname
= dm_config_find_str(cn
->child
, "vgname", NULL
),
86 *fmt_name
= dm_config_find_str(cn
->child
, "format", NULL
);
87 dev_t devt
= dm_config_find_int(cn
->child
, "device", 0);
88 uint64_t devsize
= dm_config_find_int(cn
->child
, "dev_size", 0),
89 label_sector
= dm_config_find_int(cn
->child
, "label_sector", 0);
91 struct format_type
*fmt
= fmt_name
? get_format_by_name(cmd
, fmt_name
) : NULL
;
94 log_warn("No format for PV %s. It is probably missing.", pvid_txt
);
98 device
= dev_cache_get_by_devt(devt
, cmd
->filter
);
99 if (!device
&& fallback
)
100 device
= dev_cache_get_by_devt(fallback
, cmd
->filter
);
103 log_warn("No device for PV %s.", pvid_txt
);
107 if (!pvid_txt
|| !id_read_format(&pvid
, pvid_txt
)) {
108 log_warn("Missing or ill-formatted PVID for PV: %s.", pvid_txt
);
113 id_read_format(&vgid
, vgid_txt
);
115 strcpy((char*)&vgid
, fmt
->orphan_vg_name
);
118 vgname
= fmt
->orphan_vg_name
;
120 info
= lvmcache_add(fmt
->labeller
, (const char *)&pvid
, device
,
121 vgname
, (const char *)&vgid
, 0);
123 lvmcache_get_label(info
)->sector
= label_sector
;
124 lvmcache_set_device_size(info
, devsize
);
125 lvmcache_del_das(info
);
126 lvmcache_del_mdas(info
);
129 sprintf(mda_id
, "mda%d", i
);
130 mda
= dm_config_find_node(cn
->child
, mda_id
);
132 _read_mda(info
, fmt
, mda
);
138 sprintf(da_id
, "da%d", i
);
139 da
= dm_config_find_node(cn
->child
, da_id
);
141 if (!dm_config_get_uint64(da
->child
, "offset", &offset
)) return_0
;
142 if (!dm_config_get_uint64(da
->child
, "size", &size
)) return_0
;
143 lvmcache_add_da(info
, offset
, size
);
151 struct volume_group
*lvmetad_vg_lookup(struct cmd_context
*cmd
, const char *vgname
, const char *vgid
)
153 struct volume_group
*vg
= NULL
;
156 struct format_instance
*fid
;
157 struct format_instance_ctx fic
;
158 struct dm_config_node
*top
;
160 const char *fmt_name
;
161 struct format_type
*fmt
;
162 struct dm_config_node
*pvcn
;
164 struct lvmcache_info
*info
;
170 if (!id_write_format((const struct id
*)vgid
, uuid
, sizeof(uuid
)))
172 reply
= daemon_send_simple(_lvmetad
, "vg_lookup", "uuid = %s", uuid
, NULL
);
175 log_error(INTERNAL_ERROR
"VG name required (VGID not available)");
176 reply
= daemon_send_simple(_lvmetad
, "vg_lookup", "name = %s", vgname
, NULL
);
179 if (!strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
181 top
= dm_config_find_node(reply
.cft
->root
, "metadata");
182 name
= daemon_reply_str(reply
, "name", NULL
);
184 /* fall back to lvm2 if we don't know better */
185 fmt_name
= dm_config_find_str(top
, "metadata/format", "lvm2");
186 if (!(fmt
= get_format_by_name(cmd
, fmt_name
))) {
187 log_error(INTERNAL_ERROR
188 "We do not know the format (%s) reported by lvmetad.",
193 fic
.type
= FMT_INSTANCE_MDAS
| FMT_INSTANCE_AUX_MDAS
;
194 fic
.context
.vg_ref
.vg_name
= name
;
195 fic
.context
.vg_ref
.vg_id
= vgid
;
197 if (!(fid
= fmt
->ops
->create_instance(fmt
, &fic
)))
200 pvcn
= dm_config_find_node(top
, "metadata/physical_volumes")->child
;
202 _pv_populate_lvmcache(cmd
, pvcn
, 0);
207 vg
= import_vg_from_config_tree(reply
.cft
, fid
);
209 dm_list_iterate_items(pvl
, &vg
->pvs
) {
210 if ((info
= lvmcache_info_from_pvid((const char *)&pvl
->pv
->id
, 0))) {
211 pvl
->pv
->label_sector
= lvmcache_get_label(info
)->sector
;
212 pvl
->pv
->dev
= lvmcache_device(info
);
213 lvmcache_fid_add_mdas_pv(info
, fid
);
214 } /* else probably missing */
217 lvmcache_update_vg(vg
, 0);
220 daemon_reply_destroy(reply
);
224 struct _fixup_baton
{
230 static int _fixup_ignored(struct metadata_area
*mda
, void *baton
) {
231 struct _fixup_baton
*b
= baton
;
233 mda_set_ignored(mda
, b
->ignore
);
238 int lvmetad_vg_update(struct volume_group
*vg
)
242 struct dm_hash_node
*n
;
243 struct metadata_area
*mda
;
244 char mda_id
[128], *num
;
246 struct lvmcache_info
*info
;
247 struct _fixup_baton baton
;
253 return 1; /* fake it */
255 /* TODO. This is not entirely correct, since export_vg_to_buffer
256 * adds trailing nodes to the buffer. We may need to use
257 * export_vg_to_config_tree and format the buffer ourselves. It
258 * does, however, work for now, since the garbage is well
259 * formatted and has no conflicting keys with the rest of the
261 if (!export_vg_to_buffer(vg
, &buf
)) {
262 log_error("Could not format VG metadata.");
266 reply
= daemon_send_simple(_lvmetad
, "vg_update", "vgname = %s", vg
->name
,
267 "metadata = %b", strchr(buf
, '{'),
271 if (!_lvmetad_handle_reply(reply
, "update VG", vg
->name
))
274 n
= (vg
->fid
&& vg
->fid
->metadata_areas_index
) ?
275 dm_hash_get_first(vg
->fid
->metadata_areas_index
) : NULL
;
277 mda
= dm_hash_get_data(vg
->fid
->metadata_areas_index
, n
);
278 strcpy(mda_id
, dm_hash_get_key(vg
->fid
->metadata_areas_index
, n
));
279 if ((num
= strchr(mda_id
, '_'))) {
282 if ((info
= lvmcache_info_from_pvid(mda_id
, 0))) {
283 memset(&baton
, 0, sizeof(baton
));
284 baton
.find
= atoi(num
);
285 baton
.ignore
= mda_is_ignored(mda
);
286 lvmcache_foreach_mda(info
, _fixup_ignored
, &baton
);
289 n
= dm_hash_get_next(vg
->fid
->metadata_areas_index
, n
);
292 dm_list_iterate_items(pvl
, &vg
->pvs
) {
293 /* NB. the PV fmt pointer is sometimes wrong during vgconvert */
294 if (pvl
->pv
->dev
&& !lvmetad_pv_found(pvl
->pv
->id
, pvl
->pv
->dev
,
295 vg
->fid
? vg
->fid
->fmt
: pvl
->pv
->fmt
,
296 pvl
->pv
->label_sector
, NULL
))
303 int lvmetad_vg_remove(struct volume_group
*vg
)
309 return 1; /* just fake it */
311 if (!id_write_format(&vg
->id
, uuid
, sizeof(uuid
)))
314 reply
= daemon_send_simple(_lvmetad
, "vg_remove", "uuid = %s", uuid
, NULL
);
316 return _lvmetad_handle_reply(reply
, "remove VG", vg
->name
);
319 int lvmetad_pv_lookup(struct cmd_context
*cmd
, struct id pvid
)
324 struct dm_config_node
*cn
;
329 if (!id_write_format(&pvid
, uuid
, sizeof(uuid
)))
332 reply
= daemon_send_simple(_lvmetad
, "pv_lookup", "uuid = %s", uuid
, NULL
);
334 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
335 _lvmetad_handle_reply(reply
, "lookup PVs", "");
339 cn
= dm_config_find_node(reply
.cft
->root
, "physical_volume");
340 if (!_pv_populate_lvmcache(cmd
, cn
, 0))
343 daemon_reply_destroy(reply
);
347 int lvmetad_pv_lookup_by_devt(struct cmd_context
*cmd
, dev_t device
)
351 struct dm_config_node
*cn
;
356 reply
= daemon_send_simple(_lvmetad
, "pv_lookup", "device = %d", device
, NULL
);
358 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
359 _lvmetad_handle_reply(reply
, "lookup PVs", "");
363 cn
= dm_config_find_node(reply
.cft
->root
, "physical_volume");
364 if (!_pv_populate_lvmcache(cmd
, cn
, device
))
367 daemon_reply_destroy(reply
);
371 int lvmetad_pv_list_to_lvmcache(struct cmd_context
*cmd
)
374 struct dm_config_node
*cn
;
379 reply
= daemon_send_simple(_lvmetad
, "pv_list", NULL
);
381 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
382 _lvmetad_handle_reply(reply
, "list PVs", "");
386 cn
= dm_config_find_node(reply
.cft
->root
, "physical_volumes")->child
;
388 _pv_populate_lvmcache(cmd
, cn
, 0);
392 daemon_reply_destroy(reply
);
396 int lvmetad_vg_list_to_lvmcache(struct cmd_context
*cmd
)
398 struct volume_group
*tmp
;
400 const char *vgid_txt
;
402 struct dm_config_node
*cn
;
407 reply
= daemon_send_simple(_lvmetad
, "vg_list", NULL
);
408 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
409 _lvmetad_handle_reply(reply
, "list VGs", "");
413 cn
= dm_config_find_node(reply
.cft
->root
, "volume_groups")->child
;
416 id_read_format(&vgid
, vgid_txt
);
419 /* the call to lvmetad_vg_lookup will poke the VG into lvmcache */
420 tmp
= lvmetad_vg_lookup(cmd
, NULL
, (const char*)&vgid
);
424 daemon_reply_destroy(reply
);
428 struct _print_mda_baton
{
433 static int _print_mda(struct metadata_area
*mda
, void *baton
)
436 struct _print_mda_baton
*b
= baton
;
439 if (!mda
->ops
->mda_export_text
) /* do nothing */
443 mda_txt
= mda
->ops
->mda_export_text(mda
);
444 if (!dm_asprintf(&b
->buffer
, "%s mda%i { %s }", b
->buffer
?: "", b
->i
, mda_txt
))
454 static int _print_da(struct disk_locn
*da
, void *baton
)
456 struct _print_mda_baton
*b
;
464 if (!dm_asprintf(&b
->buffer
, "%s da%i { offset = %" PRIu64
465 " size = %" PRIu64
" }",
466 b
->buffer
?: "", b
->i
, da
->offset
, da
->size
))
477 static const char *_print_mdas(struct lvmcache_info
*info
)
479 struct _print_mda_baton baton
= { .i
= 0, .buffer
= NULL
};
481 if (!lvmcache_foreach_mda(info
, &_print_mda
, &baton
))
484 if (!lvmcache_foreach_da(info
, &_print_da
, &baton
))
490 int lvmetad_pv_found(struct id pvid
, struct device
*device
, const struct format_type
*fmt
,
491 uint64_t label_sector
, struct volume_group
*vg
)
495 struct lvmcache_info
*info
;
496 const char *mdas
= NULL
;
503 if (!id_write_format(&pvid
, uuid
, sizeof(uuid
)))
506 /* FIXME A more direct route would be much preferable. */
507 if ((info
= lvmcache_info_from_pvid((const char *)&pvid
, 0)))
508 mdas
= _print_mdas(info
);
510 if (!dm_asprintf(&pvmeta
,
511 "{ device = %" PRIu64
"\n"
512 " dev_size = %" PRIu64
"\n"
514 " label_sector = %" PRIu64
"\n"
518 info
? lvmcache_device_size(info
) : 0,
519 fmt
->name
, label_sector
, uuid
, mdas
?: "")) {
520 dm_free((char *)mdas
);
524 dm_free((char *)mdas
);
528 * TODO. This is not entirely correct, since export_vg_to_buffer
529 * adds trailing garbage to the buffer. We may need to use
530 * export_vg_to_config_tree and format the buffer ourselves. It
531 * does, however, work for now, since the garbage is well
532 * formatted and has no conflicting keys with the rest of the
535 if (!export_vg_to_buffer(vg
, &buf
)) {
540 reply
= daemon_send_simple(_lvmetad
,
542 "pvmeta = %b", pvmeta
,
543 "vgname = %s", vg
->name
,
544 "metadata = %b", strchr(buf
, '{'),
547 /* There are no MDAs on this PV. */
548 reply
= daemon_send_simple(_lvmetad
,
550 "pvmeta = %b", pvmeta
,
555 return _lvmetad_handle_reply(reply
, "update PV", uuid
);
558 int lvmetad_pv_gone(dev_t device
)
564 daemon_send_simple(_lvmetad
, "pv_gone", "device = %d", device
, NULL
);
566 return _lvmetad_handle_reply(reply
, "drop PV", "");
569 int lvmetad_active(void)
571 return _using_lvmetad
;
574 void lvmetad_set_active(int active
)
576 _using_lvmetad
= active
;
580 * The following code implements pvscan --lvmetad.
583 struct _pvscan_lvmetad_baton
{
584 struct volume_group
*vg
;
585 struct format_instance
*fid
;
588 static int _pvscan_lvmetad_single(struct metadata_area
*mda
, void *baton
)
590 struct _pvscan_lvmetad_baton
*b
= baton
;
591 struct volume_group
*this = mda
->ops
->vg_read(b
->fid
, "", mda
, 1);
593 if (!b
->vg
|| this->seqno
> b
->vg
->seqno
)
601 static dev_t
_parse_devt(const char *str
)
603 char *where
= (char *) str
;
604 int major
= strtol(str
, &where
, 10);
614 minor
= strtol(str
, &where
, 10);
622 return MKDEV(major
, minor
);
625 int pvscan_lvmetad(struct cmd_context
*cmd
, int argc
, char **argv
)
629 struct lvmcache_info
*info
;
630 struct physical_volume pv
;
631 struct _pvscan_lvmetad_baton baton
;
632 /* Create a dummy instance. */
633 struct format_instance_ctx fic
= { .type
= 0 };
636 log_error("Exactly one device parameter required.");
640 if (!lvmetad_active()) {
641 log_error("Cannot proceed since lvmetad is not active.");
645 dev
= dev_cache_get(argv
[0], NULL
);
646 if (!dev
&& _parse_devt(argv
[0]) != -1)
647 dev
= dev_cache_get_by_devt(_parse_devt(argv
[0]), NULL
);
650 if (_parse_devt(argv
[0]) == -1) {
651 log_error("For devices that do not exist, we need a MAJOR:MINOR pair.");
655 if (!lvmetad_pv_gone(_parse_devt(argv
[0])))
658 log_info("Device %s not found and was wiped from lvmetad.", argv
[0]);
662 if (!label_read(dev
, &label
, 0)) {
663 log_warn("No PV label found on %s.", dev_name(dev
));
664 if (!lvmetad_pv_gone(dev
->dev
))
669 info
= (struct lvmcache_info
*) label
->info
;
670 memset(&pv
, 0, sizeof(pv
));
673 baton
.fid
= lvmcache_fmt(info
)->ops
->create_instance(lvmcache_fmt(info
),
676 lvmcache_foreach_mda(info
, _pvscan_lvmetad_single
, &baton
);
678 lvmcache_fmt(info
)->ops
->destroy_instance(baton
.fid
);
681 * NB. If this command failed and we are relying on lvmetad to have an
682 * *exact* image of the system, the lvmetad instance that went out of
683 * sync needs to be killed.
685 if (!lvmetad_pv_found(*(struct id
*)dev
->pvid
, dev
, lvmcache_fmt(info
),
686 label
->sector
, baton
.vg
))
689 release_vg(baton
.vg
);
692 release_vg(baton
.vg
);
693 /* FIXME kill lvmetad automatically if we can */
694 log_error("Update of lvmetad failed. This is a serious problem.\n "
695 "It is strongly recommended that you restart lvmetad immediately.");