2 #include "toolcontext.h"
7 #include "lvmetad-client.h"
8 #include "format-text.h" // TODO for disk_locn, used as a DA representation
11 static int _using_lvmetad
= 0;
12 static daemon_handle _lvmetad
;
14 void lvmetad_init(void)
16 const char *socket
= getenv("LVM_LVMETAD_SOCKET");
17 if (_using_lvmetad
) { /* configured by the toolcontext */
18 _lvmetad
= lvmetad_open(socket
?: DEFAULT_RUN_DIR
"/lvmetad.socket");
19 if (_lvmetad
.socket_fd
< 0) {
20 log_warn("Failed to connect to lvmetad. Falling back to scanning.");
27 * Helper; evaluate the reply from lvmetad, check for errors, print diagnostics
28 * and return a summary success/failure exit code. Frees up the reply resources
31 static int _lvmetad_handle_reply(daemon_reply reply
, const char *action
, const char *object
) {
32 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
33 log_error("Request to %s %s in lvmetad has failed. Reason: %s",
34 action
, object
, reply
.error
? strerror(reply
.error
) :
35 daemon_reply_str(reply
, "reason", "Unknown."));
36 daemon_reply_destroy(reply
);
40 daemon_reply_destroy(reply
);
44 static int _read_mda(struct lvmcache_info
*info
,
45 struct format_type
*fmt
,
46 const struct dm_config_node
*cn
)
48 struct metadata_area_ops
*ops
;
49 struct metadata_area
*mda
= NULL
;
50 dm_list_iterate_items(ops
, &fmt
->mda_ops
) {
51 if (ops
->mda_import_text
&& ops
->mda_import_text(info
, cn
))
57 static struct lvmcache_info
*_pv_populate_lvmcache(
58 struct cmd_context
*cmd
, struct dm_config_node
*cn
, dev_t fallback
)
60 const char *pvid_txt
= dm_config_find_str(cn
->child
, "id", NULL
),
61 *vgid_txt
= dm_config_find_str(cn
->child
, "vgid", NULL
),
62 *vgname
= dm_config_find_str(cn
->child
, "vgname", NULL
),
63 *fmt_name
= dm_config_find_str(cn
->child
, "format", NULL
);
64 dev_t devt
= dm_config_find_int(cn
->child
, "device", 0);
65 uint64_t devsize
= dm_config_find_int(cn
->child
, "dev_size", 0),
66 label_sector
= dm_config_find_int(cn
->child
, "label_sector", 0);
68 struct format_type
*fmt
= fmt_name
? get_format_by_name(cmd
, fmt_name
) : NULL
;
71 log_warn("No format for PV %s. It is probably missing.", pvid_txt
);
75 struct device
*device
= dev_cache_get_by_devt(devt
, cmd
->filter
);
78 if (!device
&& fallback
)
79 device
= dev_cache_get_by_devt(fallback
, cmd
->filter
);
82 log_warn("No device for PV %s.", pvid_txt
);
86 if (!pvid_txt
|| !id_read_format(&pvid
, pvid_txt
)) {
87 log_warn("Missing or ill-formatted PVID for PV: %s.", pvid_txt
);
92 id_read_format(&vgid
, vgid_txt
);
94 strcpy((char*)&vgid
, fmt
->orphan_vg_name
);
97 vgname
= fmt
->orphan_vg_name
;
99 struct lvmcache_info
*info
=
100 lvmcache_add(fmt
->labeller
, (const char *)&pvid
, device
,
101 vgname
, (const char *)&vgid
, 0);
103 lvmcache_get_label(info
)->sector
= label_sector
;
104 lvmcache_set_device_size(info
, devsize
);
105 lvmcache_del_das(info
);
106 lvmcache_del_mdas(info
);
109 struct dm_config_node
*mda
= NULL
;
112 sprintf(mda_id
, "mda%d", i
);
113 mda
= dm_config_find_node(cn
->child
, mda_id
);
115 _read_mda(info
, fmt
, mda
);
120 struct dm_config_node
*da
= NULL
;
123 sprintf(da_id
, "da%d", i
);
124 da
= dm_config_find_node(cn
->child
, da_id
);
126 uint64_t offset
, size
;
127 if (!dm_config_get_uint64(da
->child
, "offset", &offset
)) return_0
;
128 if (!dm_config_get_uint64(da
->child
, "size", &size
)) return_0
;
129 lvmcache_add_da(info
, offset
, size
);
137 struct volume_group
*lvmetad_vg_lookup(struct cmd_context
*cmd
, const char *vgname
, const char *vgid
)
142 struct volume_group
*vg
= NULL
;
146 id_write_format((struct id
*)vgid
, uuid
, 64);
147 reply
= daemon_send_simple(_lvmetad
, "vg_lookup", "uuid = %s", uuid
, NULL
);
150 log_error(INTERNAL_ERROR
"VG name required (VGID not available)");
151 reply
= daemon_send_simple(_lvmetad
, "vg_lookup", "name = %s", vgname
, NULL
);
154 if (!strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
156 struct dm_config_node
*top
= dm_config_find_node(reply
.cft
->root
, "metadata");
157 const char *name
= daemon_reply_str(reply
, "name", NULL
);
159 struct format_instance
*fid
;
160 struct format_instance_ctx fic
;
162 /* fall back to lvm2 if we don't know better */
163 const char *fmt_name
= dm_config_find_str(top
, "metadata/format", "lvm2");
164 struct format_type
*fmt
= get_format_by_name(cmd
, fmt_name
);
166 log_error(INTERNAL_ERROR
167 "We do not know the format (%s) reported by lvmetad.",
172 fic
.type
= FMT_INSTANCE_MDAS
| FMT_INSTANCE_AUX_MDAS
;
173 fic
.context
.vg_ref
.vg_name
= name
;
174 fic
.context
.vg_ref
.vg_id
= vgid
;
176 if (!(fid
= fmt
->ops
->create_instance(fmt
, &fic
)))
179 struct dm_config_node
*pvcn
=
180 dm_config_find_node(top
, "metadata/physical_volumes")->child
;
182 _pv_populate_lvmcache(cmd
, pvcn
, 0);
187 vg
= import_vg_from_config_tree(reply
.cft
, fid
);
190 dm_list_iterate_items(pvl
, &vg
->pvs
) {
191 struct lvmcache_info
*info
=
192 lvmcache_info_from_pvid((const char *)&pvl
->pv
->id
, 0);
194 pvl
->pv
->label_sector
= lvmcache_get_label(info
)->sector
;
195 pvl
->pv
->dev
= lvmcache_device(info
);
196 lvmcache_fid_add_mdas_pv(info
, fid
);
197 } /* else probably missing */
200 lvmcache_update_vg(vg
, 0);
203 daemon_reply_destroy(reply
);
207 struct _fixup_baton
{
213 static int _fixup_ignored(struct metadata_area
*mda
, void *baton
) {
214 struct _fixup_baton
*b
= baton
;
216 mda_set_ignored(mda
, b
->ignore
);
221 int lvmetad_vg_update(struct volume_group
*vg
)
227 return 1; /* fake it */
229 /* TODO. This is not entirely correct, since export_vg_to_buffer
230 * adds trailing nodes to the buffer. We may need to use
231 * export_vg_to_config_tree and format the buffer ourselves. It
232 * does, however, work for now, since the garbage is well
233 * formatted and has no conflicting keys with the rest of the
235 if (!export_vg_to_buffer(vg
, &buf
)) {
236 log_error("Could not format VG metadata.");
242 reply
= daemon_send_simple(_lvmetad
, "vg_update", "vgname = %s", vg
->name
,
243 "metadata = %b", strchr(buf
, '{'),
246 if (!_lvmetad_handle_reply(reply
, "update VG", vg
->name
))
249 struct dm_hash_node
*n
= (vg
->fid
&& vg
->fid
->metadata_areas_index
) ?
250 dm_hash_get_first(vg
->fid
->metadata_areas_index
) : NULL
;
252 struct metadata_area
*mda
= dm_hash_get_data(vg
->fid
->metadata_areas_index
, n
);
253 char mda_id
[128], *num
;
254 strcpy(mda_id
, dm_hash_get_key(vg
->fid
->metadata_areas_index
, n
));
255 if ((num
= strchr(mda_id
, '_'))) {
258 struct lvmcache_info
*info
=
259 lvmcache_info_from_pvid(mda_id
, 0);
260 struct _fixup_baton baton
= { .i
= 0, .find
= atoi(num
),
261 .ignore
= mda_is_ignored(mda
) };
263 lvmcache_foreach_mda(info
, _fixup_ignored
, &baton
);
265 n
= dm_hash_get_next(vg
->fid
->metadata_areas_index
, n
);
269 dm_list_iterate_items(pvl
, &vg
->pvs
) {
270 /* NB. the PV fmt pointer is sometimes wrong during vgconvert */
271 if (pvl
->pv
->dev
&& !lvmetad_pv_found(pvl
->pv
->id
, pvl
->pv
->dev
,
272 vg
->fid
? vg
->fid
->fmt
: pvl
->pv
->fmt
,
273 pvl
->pv
->label_sector
, NULL
))
280 int lvmetad_vg_remove(struct volume_group
*vg
)
283 return 1; /* just fake it */
285 id_write_format(&vg
->id
, uuid
, 64);
287 daemon_send_simple(_lvmetad
, "vg_remove", "uuid = %s", uuid
, NULL
);
289 return _lvmetad_handle_reply(reply
, "remove VG", vg
->name
);
292 int lvmetad_pv_lookup(struct cmd_context
*cmd
, struct id pvid
)
299 id_write_format(&pvid
, uuid
, 64);
302 daemon_send_simple(_lvmetad
, "pv_lookup", "uuid = %s", uuid
, NULL
);
304 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
305 _lvmetad_handle_reply(reply
, "lookup PVs", "");
309 struct dm_config_node
*cn
= dm_config_find_node(reply
.cft
->root
, "physical_volume");
310 if (!_pv_populate_lvmcache(cmd
, cn
, 0))
313 daemon_reply_destroy(reply
);
317 int lvmetad_pv_lookup_by_devt(struct cmd_context
*cmd
, dev_t device
)
325 daemon_send_simple(_lvmetad
, "pv_lookup", "device = %d", device
, NULL
);
327 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
328 _lvmetad_handle_reply(reply
, "lookup PVs", "");
332 struct dm_config_node
*cn
= dm_config_find_node(reply
.cft
->root
, "physical_volume");
333 if (!_pv_populate_lvmcache(cmd
, cn
, device
))
336 daemon_reply_destroy(reply
);
340 int lvmetad_pv_list_to_lvmcache(struct cmd_context
*cmd
)
346 daemon_send_simple(_lvmetad
, "pv_list", NULL
);
348 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
349 _lvmetad_handle_reply(reply
, "list PVs", "");
353 struct dm_config_node
*cn
= dm_config_find_node(reply
.cft
->root
, "physical_volumes")->child
;
355 _pv_populate_lvmcache(cmd
, cn
, 0);
359 daemon_reply_destroy(reply
);
363 int lvmetad_vg_list_to_lvmcache(struct cmd_context
*cmd
)
369 daemon_send_simple(_lvmetad
, "vg_list", NULL
);
371 if (reply
.error
|| strcmp(daemon_reply_str(reply
, "response", ""), "OK")) {
372 _lvmetad_handle_reply(reply
, "list VGs", "");
376 struct dm_config_node
*cn
= dm_config_find_node(reply
.cft
->root
, "volume_groups")->child
;
379 const char *vgid_txt
= cn
->key
,
380 *name
= dm_config_find_str(cn
->child
, "name", NULL
);
381 id_read_format(&vgid
, vgid_txt
);
385 /* the call to lvmetad_vg_lookup will poke the VG into lvmcache */
386 struct volume_group
*tmp
= lvmetad_vg_lookup(cmd
, NULL
, (const char*)&vgid
);
390 daemon_reply_destroy(reply
);
394 struct _print_mda_baton
{
399 static int _print_mda(struct metadata_area
*mda
, void *baton
)
402 struct _print_mda_baton
*b
= baton
;
404 if (!mda
->ops
->mda_export_text
) /* do nothing */
407 char *buf
= b
->buffer
;
408 char *mda_txt
= mda
->ops
->mda_export_text(mda
);
409 if (!dm_asprintf(&b
->buffer
, "%s mda%i { %s }", b
->buffer
?: "", b
->i
, mda_txt
))
419 static int _print_da(struct disk_locn
*da
, void *baton
)
424 struct _print_mda_baton
*b
= baton
;
426 char *buf
= b
->buffer
;
427 if (!dm_asprintf(&b
->buffer
, "%s da%i { offset = %lld size = %lld }",
428 b
->buffer
?: "", b
->i
, da
->offset
, da
->size
))
438 static const char *_print_mdas(struct lvmcache_info
*info
)
440 struct _print_mda_baton baton
= { .i
= 0, .buffer
= NULL
};
441 if (!lvmcache_foreach_mda(info
, &_print_mda
, &baton
))
444 if (!lvmcache_foreach_da(info
, &_print_da
, &baton
))
449 int lvmetad_pv_found(struct id pvid
, struct device
*device
, const struct format_type
*fmt
,
450 uint64_t label_sector
, struct volume_group
*vg
)
457 id_write_format(&pvid
, uuid
, 64);
459 /* FIXME A more direct route would be much preferable. */
460 struct lvmcache_info
*info
= lvmcache_info_from_pvid((const char *)&pvid
, 0);
461 const char *mdas
= NULL
;
463 mdas
= _print_mdas(info
);
466 if (!dm_asprintf(&pvmeta
,
470 " label_sector = %lld\n"
473 "}", device
->dev
, info
? lvmcache_device_size(info
) : 0,
474 fmt
->name
, label_sector
, uuid
, mdas
?: ""))
482 * TODO. This is not entirely correct, since export_vg_to_buffer
483 * adds trailing garbage to the buffer. We may need to use
484 * export_vg_to_config_tree and format the buffer ourselves. It
485 * does, however, work for now, since the garbage is well
486 * formatted and has no conflicting keys with the rest of the
489 export_vg_to_buffer(vg
, &buf
);
490 reply
= daemon_send_simple(_lvmetad
,
492 "pvmeta = %b", pvmeta
,
493 "vgname = %s", vg
->name
,
494 "metadata = %b", strchr(buf
, '{'),
497 /* There are no MDAs on this PV. */
498 reply
= daemon_send_simple(_lvmetad
,
500 "pvmeta = %b", pvmeta
,
505 return _lvmetad_handle_reply(reply
, "update PV", uuid
);
508 int lvmetad_pv_gone(dev_t device
)
511 daemon_send_simple(_lvmetad
, "pv_gone", "device = %d", device
, NULL
);
513 return _lvmetad_handle_reply(reply
, "drop PV", "");
518 return _using_lvmetad
;
521 void lvmetad_set_active(int active
)
523 _using_lvmetad
= active
;
527 * The following code implements pvscan --lvmetad.
530 struct _pvscan_lvmetad_baton
{
531 struct volume_group
*vg
;
532 struct format_instance
*fid
;
535 static int _pvscan_lvmetad_single(struct metadata_area
*mda
, void *baton
)
537 struct _pvscan_lvmetad_baton
*b
= baton
;
538 struct volume_group
*this = mda
->ops
->vg_read(b
->fid
, "", mda
);
539 if ((this && !b
->vg
) || this->seqno
> b
->vg
->seqno
)
541 else release_vg(this);
545 static dev_t
_parse_devt(const char *str
) { /* Oh. */
546 char *where
= (char *) str
;
547 int major
= strtol(str
, &where
, 10);
554 int minor
= strtol(str
, &where
, 10);
560 return MKDEV(major
, minor
);
563 int pvscan_lvmetad(struct cmd_context
*cmd
, int argc
, char **argv
)
566 log_error("Exactly one device parameter required.");
570 if (!lvmetad_active()) {
571 log_error("Cannot proceed since lvmetad is not active.");
575 struct device
*dev
= dev_cache_get(argv
[0], NULL
);
576 if (!dev
&& _parse_devt(argv
[0]) != -1)
577 dev
= dev_cache_get_by_devt(_parse_devt(argv
[0]), NULL
);
580 if (_parse_devt(argv
[0]) == -1) {
581 log_error("For devices that do not exist, we need a MAJOR:MINOR pair.");
585 if (!lvmetad_pv_gone(_parse_devt(argv
[0])))
588 log_info("Device %s not found and was wiped from lvmetad.", argv
[0]);
593 if (!label_read(dev
, &label
, 0)) {
594 log_warn("No PV label found on %s.", dev_name(dev
));
595 if (!lvmetad_pv_gone(dev
->dev
))
600 struct lvmcache_info
*info
= (struct lvmcache_info
*) label
->info
;
601 struct physical_volume pv
;
602 memset(&pv
, 0, sizeof(pv
));
604 struct _pvscan_lvmetad_baton baton
;
607 /* Create a dummy instance. */
608 struct format_instance_ctx fic
= { .type
= 0 };
610 lvmcache_fmt(info
)->ops
->create_instance(lvmcache_fmt(info
), &fic
);
611 struct metadata_area
*mda
;
613 lvmcache_foreach_mda(info
, _pvscan_lvmetad_single
, &baton
);
616 * NB. If this command failed and we are relying on lvmetad to have an
617 * *exact* image of the system, the lvmetad instance that went out of
618 * sync needs to be killed.
620 if (!lvmetad_pv_found(*(struct id
*)dev
->pvid
, dev
, lvmcache_fmt(info
),
621 label
->sector
, baton
.vg
))
624 release_vg(baton
.vg
);
627 release_vg(baton
.vg
);
628 /* FIXME kill lvmetad automatically if we can */
629 log_error("Update of lvmetad failed. This is a serious problem.\n "
630 "It is strongly recommended that you restart lvmetad immediately.");