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("WARNING: Failed to connect to lvmetad: %s. Falling back to internal 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.
44
* If found is set, *found indicates whether or not device exists,
45
* and missing device is not treated as an error.
47
static int _lvmetad_handle_reply(daemon_reply reply, const char *action, const char *object,
51
log_error("Request to %s %s%sin lvmetad gave response %s.",
52
action, object, *object ? " " : "", strerror(reply.error));
57
if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
63
/* Unknown device permitted? */
64
if (found && !strcmp(daemon_reply_str(reply, "response", ""), "unknown")) {
65
log_very_verbose("Request to %s %s%sin lvmetad did not find object.",
66
action, object, *object ? " " : "");
71
log_error("Request to %s %s%sin lvmetad gave response %s. Reason: %s",
72
action, object, *object ? " " : "",
73
daemon_reply_str(reply, "response", "<missing>"),
74
daemon_reply_str(reply, "reason", "<missing>"));
79
static int _read_mda(struct lvmcache_info *info,
80
struct format_type *fmt,
81
const struct dm_config_node *cn)
83
struct metadata_area_ops *ops;
85
dm_list_iterate_items(ops, &fmt->mda_ops)
86
if (ops->mda_import_text && ops->mda_import_text(info, cn))
92
static struct lvmcache_info *_pv_populate_lvmcache(
93
struct cmd_context *cmd, struct dm_config_node *cn, dev_t fallback)
95
struct device *device;
100
struct dm_config_node *mda = NULL;
101
struct dm_config_node *da = NULL;
102
uint64_t offset, size;
103
struct lvmcache_info *info;
104
const char *pvid_txt = dm_config_find_str(cn->child, "id", NULL),
105
*vgid_txt = dm_config_find_str(cn->child, "vgid", NULL),
106
*vgname = dm_config_find_str(cn->child, "vgname", NULL),
107
*fmt_name = dm_config_find_str(cn->child, "format", NULL);
108
dev_t devt = dm_config_find_int(cn->child, "device", 0);
109
uint64_t devsize = dm_config_find_int64(cn->child, "dev_size", 0),
110
label_sector = dm_config_find_int64(cn->child, "label_sector", 0);
112
struct format_type *fmt = fmt_name ? get_format_by_name(cmd, fmt_name) : NULL;
115
log_error("PV %s not recognised. Is the device missing?", pvid_txt);
119
device = dev_cache_get_by_devt(devt, cmd->filter);
120
if (!device && fallback)
121
device = dev_cache_get_by_devt(fallback, cmd->filter);
124
log_error("No device found for PV %s.", pvid_txt);
128
if (!pvid_txt || !id_read_format(&pvid, pvid_txt)) {
129
log_error("Missing or ill-formatted PVID for PV: %s.", pvid_txt);
134
id_read_format(&vgid, vgid_txt);
136
strcpy((char*)&vgid, fmt->orphan_vg_name);
139
vgname = fmt->orphan_vg_name;
141
info = lvmcache_add(fmt->labeller, (const char *)&pvid, device,
142
vgname, (const char *)&vgid, 0);
144
lvmcache_get_label(info)->sector = label_sector;
145
lvmcache_set_device_size(info, devsize);
146
lvmcache_del_das(info);
147
lvmcache_del_mdas(info);
150
sprintf(mda_id, "mda%d", i);
151
mda = dm_config_find_node(cn->child, mda_id);
153
_read_mda(info, fmt, mda);
159
sprintf(da_id, "da%d", i);
160
da = dm_config_find_node(cn->child, da_id);
162
if (!dm_config_get_uint64(da->child, "offset", &offset)) return_0;
163
if (!dm_config_get_uint64(da->child, "size", &size)) return_0;
164
lvmcache_add_da(info, offset, size);
172
struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgname, const char *vgid)
174
struct volume_group *vg = NULL;
177
struct format_instance *fid;
178
struct format_instance_ctx fic;
179
struct dm_config_node *top;
181
const char *fmt_name;
182
struct format_type *fmt;
183
struct dm_config_node *pvcn;
185
struct lvmcache_info *info;
191
if (!id_write_format((const struct id*)vgid, uuid, sizeof(uuid)))
193
reply = daemon_send_simple(_lvmetad, "vg_lookup", "uuid = %s", uuid, NULL);
196
log_error(INTERNAL_ERROR "VG name required (VGID not available)");
197
reply = daemon_send_simple(_lvmetad, "vg_lookup", "name = %s", vgname, NULL);
200
if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
202
top = dm_config_find_node(reply.cft->root, "metadata");
203
name = daemon_reply_str(reply, "name", NULL);
205
/* fall back to lvm2 if we don't know better */
206
fmt_name = dm_config_find_str(top, "metadata/format", "lvm2");
207
if (!(fmt = get_format_by_name(cmd, fmt_name))) {
208
log_error(INTERNAL_ERROR
209
"We do not know the format (%s) reported by lvmetad.",
214
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
215
fic.context.vg_ref.vg_name = name;
216
fic.context.vg_ref.vg_id = vgid;
218
if (!(fid = fmt->ops->create_instance(fmt, &fic)))
221
if ((pvcn = dm_config_find_node(top, "metadata/physical_volumes")))
222
for (pvcn = pvcn->child; pvcn; pvcn = pvcn->sib)
223
_pv_populate_lvmcache(cmd, pvcn, 0);
226
if (!(vg = import_vg_from_config_tree(reply.cft, fid)))
229
dm_list_iterate_items(pvl, &vg->pvs) {
230
if ((info = lvmcache_info_from_pvid((const char *)&pvl->pv->id, 0))) {
231
pvl->pv->label_sector = lvmcache_get_label(info)->sector;
232
pvl->pv->dev = lvmcache_device(info);
233
if (!lvmcache_fid_add_mdas_pv(info, fid)) {
235
goto_out; /* FIXME error path */
237
} /* else probably missing */
240
lvmcache_update_vg(vg, 0);
244
daemon_reply_destroy(reply);
249
struct _fixup_baton {
255
static int _fixup_ignored(struct metadata_area *mda, void *baton) {
256
struct _fixup_baton *b = baton;
258
mda_set_ignored(mda, b->ignore);
263
int lvmetad_vg_update(struct volume_group *vg)
267
struct dm_hash_node *n;
268
struct metadata_area *mda;
269
char mda_id[128], *num;
271
struct lvmcache_info *info;
272
struct _fixup_baton baton;
278
return 1; /* fake it */
280
/* TODO. This is not entirely correct, since export_vg_to_buffer
281
* adds trailing nodes to the buffer. We may need to use
282
* export_vg_to_config_tree and format the buffer ourselves. It
283
* does, however, work for now, since the garbage is well
284
* formatted and has no conflicting keys with the rest of the
286
if (!export_vg_to_buffer(vg, &buf)) {
287
log_error("Could not format VG metadata.");
291
reply = daemon_send_simple(_lvmetad, "vg_update", "vgname = %s", vg->name,
292
"metadata = %b", strchr(buf, '{'), NULL);
295
if (!_lvmetad_handle_reply(reply, "update VG", vg->name, NULL)) {
296
daemon_reply_destroy(reply);
300
daemon_reply_destroy(reply);
302
n = (vg->fid && vg->fid->metadata_areas_index) ?
303
dm_hash_get_first(vg->fid->metadata_areas_index) : NULL;
305
mda = dm_hash_get_data(vg->fid->metadata_areas_index, n);
306
strcpy(mda_id, dm_hash_get_key(vg->fid->metadata_areas_index, n));
307
if ((num = strchr(mda_id, '_'))) {
310
if ((info = lvmcache_info_from_pvid(mda_id, 0))) {
311
memset(&baton, 0, sizeof(baton));
312
baton.find = atoi(num);
313
baton.ignore = mda_is_ignored(mda);
314
lvmcache_foreach_mda(info, _fixup_ignored, &baton);
317
n = dm_hash_get_next(vg->fid->metadata_areas_index, n);
320
dm_list_iterate_items(pvl, &vg->pvs) {
321
/* NB. the PV fmt pointer is sometimes wrong during vgconvert */
322
if (pvl->pv->dev && !lvmetad_pv_found(pvl->pv->id, pvl->pv->dev,
323
vg->fid ? vg->fid->fmt : pvl->pv->fmt,
324
pvl->pv->label_sector, NULL))
331
int lvmetad_vg_remove(struct volume_group *vg)
338
return 1; /* just fake it */
340
if (!id_write_format(&vg->id, uuid, sizeof(uuid)))
343
reply = daemon_send_simple(_lvmetad, "vg_remove", "uuid = %s", uuid, NULL);
345
result = _lvmetad_handle_reply(reply, "remove VG", vg->name, NULL);
347
daemon_reply_destroy(reply);
352
int lvmetad_pv_lookup(struct cmd_context *cmd, struct id pvid, int *found)
357
struct dm_config_node *cn;
362
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
365
reply = daemon_send_simple(_lvmetad, "pv_lookup", "uuid = %s", uuid, NULL);
367
if (!_lvmetad_handle_reply(reply, "lookup PV", "", found))
370
if (found && !*found)
373
if (!(cn = dm_config_find_node(reply.cft->root, "physical_volume")))
375
else if (!_pv_populate_lvmcache(cmd, cn, 0))
382
daemon_reply_destroy(reply);
387
int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *found)
391
struct dm_config_node *cn;
396
reply = daemon_send_simple(_lvmetad, "pv_lookup", "device = %d", dev->dev, NULL);
398
if (!_lvmetad_handle_reply(reply, "lookup PV", dev_name(dev), found))
401
if (found && !*found)
404
cn = dm_config_find_node(reply.cft->root, "physical_volume");
405
if (!cn || !_pv_populate_lvmcache(cmd, cn, dev->dev))
412
daemon_reply_destroy(reply);
416
int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
419
struct dm_config_node *cn;
424
reply = daemon_send_simple(_lvmetad, "pv_list", NULL);
426
if (!_lvmetad_handle_reply(reply, "list PVs", "", NULL)) {
427
daemon_reply_destroy(reply);
431
if ((cn = dm_config_find_node(reply.cft->root, "physical_volumes")))
432
for (cn = cn->child; cn; cn = cn->sib)
433
_pv_populate_lvmcache(cmd, cn, 0);
435
daemon_reply_destroy(reply);
440
int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
442
struct volume_group *tmp;
444
const char *vgid_txt;
446
struct dm_config_node *cn;
451
reply = daemon_send_simple(_lvmetad, "vg_list", NULL);
453
if (!_lvmetad_handle_reply(reply, "list VGs", "", NULL)) {
454
daemon_reply_destroy(reply);
458
if ((cn = dm_config_find_node(reply.cft->root, "volume_groups")))
459
for (cn = cn->child; cn; cn = cn->sib) {
461
if (!id_read_format(&vgid, vgid_txt)) {
466
/* the call to lvmetad_vg_lookup will poke the VG into lvmcache */
467
tmp = lvmetad_vg_lookup(cmd, NULL, (const char*)&vgid);
471
daemon_reply_destroy(reply);
475
struct _print_mda_baton {
480
static int _print_mda(struct metadata_area *mda, void *baton)
483
struct _print_mda_baton *b = baton;
486
if (!mda->ops->mda_export_text) /* do nothing */
490
mda_txt = mda->ops->mda_export_text(mda);
491
if (!dm_asprintf(&b->buffer, "%s mda%i { %s }", b->buffer ?: "", b->i, mda_txt))
501
static int _print_da(struct disk_locn *da, void *baton)
503
struct _print_mda_baton *b;
511
if (!dm_asprintf(&b->buffer, "%s da%i { offset = %" PRIu64
512
" size = %" PRIu64 " }",
513
b->buffer ?: "", b->i, da->offset, da->size))
524
static const char *_print_mdas(struct lvmcache_info *info)
526
struct _print_mda_baton baton = { .i = 0, .buffer = NULL };
528
if (!lvmcache_foreach_mda(info, &_print_mda, &baton))
531
if (!lvmcache_foreach_da(info, &_print_da, &baton))
537
int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_type *fmt,
538
uint64_t label_sector, struct volume_group *vg)
542
struct lvmcache_info *info;
543
const char *mdas = NULL;
551
if (!id_write_format(&pvid, uuid, sizeof(uuid)))
554
/* FIXME A more direct route would be much preferable. */
555
if ((info = lvmcache_info_from_pvid((const char *)&pvid, 0)))
556
mdas = _print_mdas(info);
558
if (!dm_asprintf(&pvmeta,
559
"{ device = %" PRIu64 "\n"
560
" dev_size = %" PRIu64 "\n"
562
" label_sector = %" PRIu64 "\n"
566
info ? lvmcache_device_size(info) : 0,
567
fmt->name, label_sector, uuid, mdas ?: "")) {
568
dm_free((char *)mdas);
572
dm_free((char *)mdas);
576
* TODO. This is not entirely correct, since export_vg_to_buffer
577
* adds trailing garbage to the buffer. We may need to use
578
* export_vg_to_config_tree and format the buffer ourselves. It
579
* does, however, work for now, since the garbage is well
580
* formatted and has no conflicting keys with the rest of the
583
if (!export_vg_to_buffer(vg, &buf)) {
588
reply = daemon_send_simple(_lvmetad,
590
"pvmeta = %b", pvmeta,
591
"vgname = %s", vg->name,
592
"metadata = %b", strchr(buf, '{'),
595
/* There are no MDAs on this PV. */
596
reply = daemon_send_simple(_lvmetad,
598
"pvmeta = %b", pvmeta,
604
result = _lvmetad_handle_reply(reply, "update PV", uuid, NULL);
605
daemon_reply_destroy(reply);
610
int lvmetad_pv_gone(dev_t device, const char *pv_name)
618
daemon_reply reply = daemon_send_simple(_lvmetad, "pv_gone", "device = %d", device, NULL);
620
result = _lvmetad_handle_reply(reply, "drop PV", pv_name, &found);
621
/* We don't care whether or not the daemon had the PV cached. */
623
daemon_reply_destroy(reply);
628
int lvmetad_pv_gone_by_dev(struct device *dev)
630
return lvmetad_pv_gone(dev->dev, dev_name(dev));
633
int lvmetad_active(void)
635
return _using_lvmetad;
638
void lvmetad_set_active(int active)
640
_using_lvmetad = active;
644
* The following code implements pvscan --cache.
647
struct _pvscan_lvmetad_baton {
648
struct volume_group *vg;
649
struct format_instance *fid;
652
static int _pvscan_lvmetad_single(struct metadata_area *mda, void *baton)
654
struct _pvscan_lvmetad_baton *b = baton;
655
struct volume_group *this = mda->ops->vg_read(b->fid, "", mda, 1);
657
/* FIXME Also ensure contents match etc. */
658
if (!b->vg || this->seqno > b->vg->seqno)
666
int pvscan_lvmetad_single(struct cmd_context *cmd, struct device *dev)
669
struct lvmcache_info *info;
670
struct physical_volume pv;
671
struct _pvscan_lvmetad_baton baton;
672
/* Create a dummy instance. */
673
struct format_instance_ctx fic = { .type = 0 };
675
if (!lvmetad_active()) {
676
log_error("Cannot proceed since lvmetad is not active.");
680
if (!label_read(dev, &label, 0)) {
681
log_print("No PV label found on %s.", dev_name(dev));
682
if (!lvmetad_pv_gone_by_dev(dev))
687
info = (struct lvmcache_info *) label->info;
688
memset(&pv, 0, sizeof(pv));
691
baton.fid = lvmcache_fmt(info)->ops->create_instance(lvmcache_fmt(info),
694
lvmcache_foreach_mda(info, _pvscan_lvmetad_single, &baton);
696
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
699
* NB. If this command failed and we are relying on lvmetad to have an
700
* *exact* image of the system, the lvmetad instance that went out of
701
* sync needs to be killed.
703
if (!lvmetad_pv_found(*(struct id *)dev->pvid, dev, lvmcache_fmt(info),
704
label->sector, baton.vg)) {
705
release_vg(baton.vg);
709
release_vg(baton.vg);
713
/* FIXME kill lvmetad automatically if we can */
714
log_error("Update of lvmetad failed. This is a serious problem.\n "
715
"It is strongly recommended that you restart lvmetad immediately.");