lvmcache.c revision 1.1.1.2 1 1.1 haad /* $NetBSD: lvmcache.c,v 1.1.1.2 2009/02/18 11:16:52 haad Exp $ */
2 1.1 haad
3 1.1 haad /*
4 1.1 haad * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 1.1 haad * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
6 1.1 haad *
7 1.1 haad * This file is part of LVM2.
8 1.1 haad *
9 1.1 haad * This copyrighted material is made available to anyone wishing to use,
10 1.1 haad * modify, copy, or redistribute it subject to the terms and conditions
11 1.1 haad * of the GNU Lesser General Public License v.2.1.
12 1.1 haad *
13 1.1 haad * You should have received a copy of the GNU Lesser General Public License
14 1.1 haad * along with this program; if not, write to the Free Software Foundation,
15 1.1 haad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 1.1 haad */
17 1.1 haad
18 1.1 haad #include "lib.h"
19 1.1 haad #include "lvmcache.h"
20 1.1 haad #include "toolcontext.h"
21 1.1 haad #include "dev-cache.h"
22 1.1 haad #include "locking.h"
23 1.1 haad #include "metadata.h"
24 1.1 haad #include "filter.h"
25 1.1 haad #include "memlock.h"
26 1.1 haad #include "str_list.h"
27 1.1 haad #include "format-text.h"
28 1.1 haad #include "format_pool.h"
29 1.1 haad #include "format1.h"
30 1.1 haad
31 1.1 haad static struct dm_hash_table *_pvid_hash = NULL;
32 1.1 haad static struct dm_hash_table *_vgid_hash = NULL;
33 1.1 haad static struct dm_hash_table *_vgname_hash = NULL;
34 1.1 haad static struct dm_hash_table *_lock_hash = NULL;
35 1.1 haad static struct dm_list _vginfos;
36 1.1 haad static int _scanning_in_progress = 0;
37 1.1 haad static int _has_scanned = 0;
38 1.1 haad static int _vgs_locked = 0;
39 1.1 haad static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */
40 1.1 haad
41 1.1 haad int lvmcache_init(void)
42 1.1 haad {
43 1.1 haad dm_list_init(&_vginfos);
44 1.1 haad
45 1.1 haad if (!(_vgname_hash = dm_hash_create(128)))
46 1.1 haad return 0;
47 1.1 haad
48 1.1 haad if (!(_vgid_hash = dm_hash_create(128)))
49 1.1 haad return 0;
50 1.1 haad
51 1.1 haad if (!(_pvid_hash = dm_hash_create(128)))
52 1.1 haad return 0;
53 1.1 haad
54 1.1 haad if (!(_lock_hash = dm_hash_create(128)))
55 1.1 haad return 0;
56 1.1 haad
57 1.1 haad if (_vg_global_lock_held)
58 1.1 haad lvmcache_lock_vgname(VG_GLOBAL, 0);
59 1.1 haad
60 1.1 haad return 1;
61 1.1 haad }
62 1.1 haad
63 1.1 haad /* Volume Group metadata cache functions */
64 1.1 haad static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
65 1.1 haad {
66 1.1 haad if (!vginfo || !vginfo->vgmetadata)
67 1.1 haad return;
68 1.1 haad
69 1.1 haad dm_free(vginfo->vgmetadata);
70 1.1 haad
71 1.1 haad vginfo->vgmetadata = NULL;
72 1.1 haad
73 1.1 haad log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
74 1.1 haad }
75 1.1 haad
76 1.1 haad static void _store_metadata(struct lvmcache_vginfo *vginfo,
77 1.1 haad struct volume_group *vg, unsigned precommitted)
78 1.1 haad {
79 1.1 haad int size;
80 1.1 haad
81 1.1 haad if (vginfo->vgmetadata)
82 1.1 haad _free_cached_vgmetadata(vginfo);
83 1.1 haad
84 1.1 haad if (!(size = export_vg_to_buffer(vg, &vginfo->vgmetadata))) {
85 1.1 haad stack;
86 1.1 haad return;
87 1.1 haad }
88 1.1 haad
89 1.1 haad vginfo->precommitted = precommitted;
90 1.1 haad
91 1.1 haad log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
92 1.1 haad size, precommitted ? ", precommitted" : "");
93 1.1 haad }
94 1.1 haad
95 1.1 haad static void _update_cache_info_lock_state(struct lvmcache_info *info,
96 1.1 haad int locked,
97 1.1 haad int *cached_vgmetadata_valid)
98 1.1 haad {
99 1.1 haad int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
100 1.1 haad
101 1.1 haad /*
102 1.1 haad * Cache becomes invalid whenever lock state changes unless
103 1.1 haad * exclusive VG_GLOBAL is held (i.e. while scanning).
104 1.1 haad */
105 1.1 haad if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
106 1.1 haad info->status |= CACHE_INVALID;
107 1.1 haad *cached_vgmetadata_valid = 0;
108 1.1 haad }
109 1.1 haad
110 1.1 haad if (locked)
111 1.1 haad info->status |= CACHE_LOCKED;
112 1.1 haad else
113 1.1 haad info->status &= ~CACHE_LOCKED;
114 1.1 haad }
115 1.1 haad
116 1.1 haad static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
117 1.1 haad int locked)
118 1.1 haad {
119 1.1 haad struct lvmcache_info *info;
120 1.1 haad int cached_vgmetadata_valid = 1;
121 1.1 haad
122 1.1 haad dm_list_iterate_items(info, &vginfo->infos)
123 1.1 haad _update_cache_info_lock_state(info, locked,
124 1.1 haad &cached_vgmetadata_valid);
125 1.1 haad
126 1.1 haad if (!cached_vgmetadata_valid)
127 1.1 haad _free_cached_vgmetadata(vginfo);
128 1.1 haad }
129 1.1 haad
130 1.1 haad static void _update_cache_lock_state(const char *vgname, int locked)
131 1.1 haad {
132 1.1 haad struct lvmcache_vginfo *vginfo;
133 1.1 haad
134 1.1 haad if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
135 1.1 haad return;
136 1.1 haad
137 1.1 haad _update_cache_vginfo_lock_state(vginfo, locked);
138 1.1 haad }
139 1.1 haad
140 1.1 haad static void _drop_metadata(const char *vgname)
141 1.1 haad {
142 1.1 haad struct lvmcache_vginfo *vginfo;
143 1.1 haad struct lvmcache_info *info;
144 1.1 haad
145 1.1 haad if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
146 1.1 haad return;
147 1.1 haad
148 1.1 haad /*
149 1.1 haad * Invalidate cached PV labels.
150 1.1 haad * If cached precommitted metadata exists that means we
151 1.1 haad * already invalidated the PV labels (before caching it)
152 1.1 haad * and we must not do it again.
153 1.1 haad */
154 1.1 haad
155 1.1 haad if (!vginfo->precommitted)
156 1.1 haad dm_list_iterate_items(info, &vginfo->infos)
157 1.1 haad info->status |= CACHE_INVALID;
158 1.1 haad
159 1.1 haad _free_cached_vgmetadata(vginfo);
160 1.1 haad }
161 1.1 haad
162 1.1 haad void lvmcache_drop_metadata(const char *vgname)
163 1.1 haad {
164 1.1 haad /* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
165 1.1 haad if (!strcmp(vgname, VG_ORPHANS)) {
166 1.1 haad _drop_metadata(FMT_TEXT_ORPHAN_VG_NAME);
167 1.1 haad _drop_metadata(FMT_LVM1_ORPHAN_VG_NAME);
168 1.1 haad _drop_metadata(FMT_POOL_ORPHAN_VG_NAME);
169 1.1 haad
170 1.1 haad /* Indicate that PVs could now be missing from the cache */
171 1.1 haad init_full_scan_done(0);
172 1.1 haad } else if (!vgname_is_locked(VG_GLOBAL))
173 1.1 haad _drop_metadata(vgname);
174 1.1 haad }
175 1.1 haad
176 1.1 haad void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
177 1.1 haad {
178 1.1 haad if (!_lock_hash && !lvmcache_init()) {
179 1.1 haad log_error("Internal cache initialisation failed");
180 1.1 haad return;
181 1.1 haad }
182 1.1 haad
183 1.1 haad if (dm_hash_lookup(_lock_hash, vgname))
184 1.1 haad log_error("Internal error: Nested locking attempted on VG %s.",
185 1.1 haad vgname);
186 1.1 haad
187 1.1 haad if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
188 1.1 haad log_error("Cache locking failure for %s", vgname);
189 1.1 haad
190 1.1 haad _update_cache_lock_state(vgname, 1);
191 1.1 haad
192 1.1 haad if (strcmp(vgname, VG_GLOBAL))
193 1.1 haad _vgs_locked++;
194 1.1 haad }
195 1.1 haad
196 1.1 haad int vgname_is_locked(const char *vgname)
197 1.1 haad {
198 1.1 haad if (!_lock_hash)
199 1.1 haad return 0;
200 1.1 haad
201 1.1 haad return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
202 1.1 haad }
203 1.1 haad
204 1.1 haad void lvmcache_unlock_vgname(const char *vgname)
205 1.1 haad {
206 1.1 haad if (!dm_hash_lookup(_lock_hash, vgname))
207 1.1 haad log_error("Internal error: Attempt to unlock unlocked VG %s.",
208 1.1 haad vgname);
209 1.1 haad
210 1.1 haad _update_cache_lock_state(vgname, 0);
211 1.1 haad
212 1.1 haad dm_hash_remove(_lock_hash, vgname);
213 1.1 haad
214 1.1 haad /* FIXME Do this per-VG */
215 1.1 haad if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked)
216 1.1 haad dev_close_all();
217 1.1 haad }
218 1.1 haad
219 1.1 haad int vgs_locked(void)
220 1.1 haad {
221 1.1 haad return _vgs_locked;
222 1.1 haad }
223 1.1 haad
224 1.1 haad static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
225 1.1 haad struct lvmcache_info *info)
226 1.1 haad {
227 1.1 haad if (!vginfo)
228 1.1 haad return;
229 1.1 haad
230 1.1 haad info->vginfo = vginfo;
231 1.1 haad dm_list_add(&vginfo->infos, &info->list);
232 1.1 haad }
233 1.1 haad
234 1.1 haad static void _vginfo_detach_info(struct lvmcache_info *info)
235 1.1 haad {
236 1.1 haad if (!dm_list_empty(&info->list)) {
237 1.1 haad dm_list_del(&info->list);
238 1.1 haad dm_list_init(&info->list);
239 1.1 haad }
240 1.1 haad
241 1.1 haad info->vginfo = NULL;
242 1.1 haad }
243 1.1 haad
244 1.1 haad /* If vgid supplied, require a match. */
245 1.1 haad struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
246 1.1 haad {
247 1.1 haad struct lvmcache_vginfo *vginfo;
248 1.1 haad
249 1.1 haad if (!vgname)
250 1.1 haad return vginfo_from_vgid(vgid);
251 1.1 haad
252 1.1 haad if (!_vgname_hash)
253 1.1 haad return NULL;
254 1.1 haad
255 1.1 haad if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
256 1.1 haad return NULL;
257 1.1 haad
258 1.1 haad if (vgid)
259 1.1 haad do
260 1.1 haad if (!strncmp(vgid, vginfo->vgid, ID_LEN))
261 1.1 haad return vginfo;
262 1.1 haad while ((vginfo = vginfo->next));
263 1.1 haad
264 1.1 haad return vginfo;
265 1.1 haad }
266 1.1 haad
267 1.1 haad const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
268 1.1 haad {
269 1.1 haad struct lvmcache_vginfo *vginfo;
270 1.1 haad struct lvmcache_info *info;
271 1.1 haad struct label *label;
272 1.1 haad struct dm_list *devh, *tmp;
273 1.1 haad struct dm_list devs;
274 1.1 haad struct device_list *devl;
275 1.1 haad char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
276 1.1 haad
277 1.1 haad if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
278 1.1 haad return NULL;
279 1.1 haad
280 1.1 haad /* This function is normally called before reading metadata so
281 1.1 haad * we check cached labels here. Unfortunately vginfo is volatile. */
282 1.1 haad dm_list_init(&devs);
283 1.1 haad dm_list_iterate_items(info, &vginfo->infos) {
284 1.1 haad if (!(devl = dm_malloc(sizeof(*devl)))) {
285 1.1 haad log_error("device_list element allocation failed");
286 1.1 haad return NULL;
287 1.1 haad }
288 1.1 haad devl->dev = info->dev;
289 1.1 haad dm_list_add(&devs, &devl->list);
290 1.1 haad }
291 1.1 haad
292 1.1 haad memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
293 1.1 haad
294 1.1 haad dm_list_iterate_safe(devh, tmp, &devs) {
295 1.1 haad devl = dm_list_item(devh, struct device_list);
296 1.1 haad label_read(devl->dev, &label, UINT64_C(0));
297 1.1 haad dm_list_del(&devl->list);
298 1.1 haad dm_free(devl);
299 1.1 haad }
300 1.1 haad
301 1.1 haad /* If vginfo changed, caller needs to rescan */
302 1.1 haad if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
303 1.1 haad strncmp(vginfo->vgid, vgid_found, ID_LEN))
304 1.1 haad return NULL;
305 1.1 haad
306 1.1 haad return vginfo->fmt;
307 1.1 haad }
308 1.1 haad
309 1.1 haad struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
310 1.1 haad {
311 1.1 haad struct lvmcache_vginfo *vginfo;
312 1.1 haad char id[ID_LEN + 1] __attribute((aligned(8)));
313 1.1 haad
314 1.1 haad if (!_vgid_hash || !vgid)
315 1.1 haad return NULL;
316 1.1 haad
317 1.1 haad /* vgid not necessarily NULL-terminated */
318 1.1 haad strncpy(&id[0], vgid, ID_LEN);
319 1.1 haad id[ID_LEN] = '\0';
320 1.1 haad
321 1.1 haad if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
322 1.1 haad return NULL;
323 1.1 haad
324 1.1 haad return vginfo;
325 1.1 haad }
326 1.1 haad
327 1.1 haad const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
328 1.1 haad {
329 1.1 haad struct lvmcache_vginfo *vginfo;
330 1.1 haad const char *vgname = NULL;
331 1.1 haad
332 1.1 haad if ((vginfo = vginfo_from_vgid(vgid)))
333 1.1 haad vgname = vginfo->vgname;
334 1.1 haad
335 1.1 haad if (mem && vgname)
336 1.1 haad return dm_pool_strdup(mem, vgname);
337 1.1 haad
338 1.1 haad return vgname;
339 1.1 haad }
340 1.1 haad
341 1.1 haad static int _info_is_valid(struct lvmcache_info *info)
342 1.1 haad {
343 1.1 haad if (info->status & CACHE_INVALID)
344 1.1 haad return 0;
345 1.1 haad
346 1.1 haad /*
347 1.1 haad * The caller must hold the VG lock to manipulate metadata.
348 1.1 haad * In a cluster, remote nodes sometimes read metadata in the
349 1.1 haad * knowledge that the controlling node is holding the lock.
350 1.1 haad * So if the VG appears to be unlocked here, it should be safe
351 1.1 haad * to use the cached value.
352 1.1 haad */
353 1.1 haad if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
354 1.1 haad return 1;
355 1.1 haad
356 1.1 haad if (!(info->status & CACHE_LOCKED))
357 1.1 haad return 0;
358 1.1 haad
359 1.1 haad return 1;
360 1.1 haad }
361 1.1 haad
362 1.1 haad static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
363 1.1 haad {
364 1.1 haad struct lvmcache_info *info;
365 1.1 haad
366 1.1 haad /* Invalid if any info is invalid */
367 1.1 haad dm_list_iterate_items(info, &vginfo->infos)
368 1.1 haad if (!_info_is_valid(info))
369 1.1 haad return 0;
370 1.1 haad
371 1.1 haad return 1;
372 1.1 haad }
373 1.1 haad
374 1.1 haad /* vginfo is invalid if it does not contain at least one valid info */
375 1.1 haad static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
376 1.1 haad {
377 1.1 haad struct lvmcache_info *info;
378 1.1 haad
379 1.1 haad dm_list_iterate_items(info, &vginfo->infos)
380 1.1 haad if (_info_is_valid(info))
381 1.1 haad return 0;
382 1.1 haad
383 1.1 haad return 1;
384 1.1 haad }
385 1.1 haad
386 1.1 haad /*
387 1.1 haad * If valid_only is set, data will only be returned if the cached data is
388 1.1 haad * known still to be valid.
389 1.1 haad */
390 1.1 haad struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
391 1.1 haad {
392 1.1 haad struct lvmcache_info *info;
393 1.1 haad char id[ID_LEN + 1] __attribute((aligned(8)));
394 1.1 haad
395 1.1 haad if (!_pvid_hash || !pvid)
396 1.1 haad return NULL;
397 1.1 haad
398 1.1 haad strncpy(&id[0], pvid, ID_LEN);
399 1.1 haad id[ID_LEN] = '\0';
400 1.1 haad
401 1.1 haad if (!(info = dm_hash_lookup(_pvid_hash, id)))
402 1.1 haad return NULL;
403 1.1 haad
404 1.1 haad if (valid_only && !_info_is_valid(info))
405 1.1 haad return NULL;
406 1.1 haad
407 1.1 haad return info;
408 1.1 haad }
409 1.1 haad
410 1.1 haad static void _rescan_entry(struct lvmcache_info *info)
411 1.1 haad {
412 1.1 haad struct label *label;
413 1.1 haad
414 1.1 haad if (info->status & CACHE_INVALID)
415 1.1 haad label_read(info->dev, &label, UINT64_C(0));
416 1.1 haad }
417 1.1 haad
418 1.1 haad static int _scan_invalid(void)
419 1.1 haad {
420 1.1 haad dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
421 1.1 haad
422 1.1 haad return 1;
423 1.1 haad }
424 1.1 haad
425 1.1 haad int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
426 1.1 haad {
427 1.1 haad struct label *label;
428 1.1 haad struct dev_iter *iter;
429 1.1 haad struct device *dev;
430 1.1 haad struct format_type *fmt;
431 1.1 haad
432 1.1 haad int r = 0;
433 1.1 haad
434 1.1 haad /* Avoid recursion when a PVID can't be found! */
435 1.1 haad if (_scanning_in_progress)
436 1.1 haad return 0;
437 1.1 haad
438 1.1 haad _scanning_in_progress = 1;
439 1.1 haad
440 1.1 haad if (!_vgname_hash && !lvmcache_init()) {
441 1.1 haad log_error("Internal cache initialisation failed");
442 1.1 haad goto out;
443 1.1 haad }
444 1.1 haad
445 1.1 haad if (_has_scanned && !full_scan) {
446 1.1 haad r = _scan_invalid();
447 1.1 haad goto out;
448 1.1 haad }
449 1.1 haad
450 1.1 haad if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
451 1.1 haad log_error("dev_iter creation failed");
452 1.1 haad goto out;
453 1.1 haad }
454 1.1 haad
455 1.1 haad while ((dev = dev_iter_get(iter)))
456 1.1 haad label_read(dev, &label, UINT64_C(0));
457 1.1 haad
458 1.1 haad dev_iter_destroy(iter);
459 1.1 haad
460 1.1 haad _has_scanned = 1;
461 1.1 haad
462 1.1 haad /* Perform any format-specific scanning e.g. text files */
463 1.1 haad dm_list_iterate_items(fmt, &cmd->formats) {
464 1.1 haad if (fmt->ops->scan && !fmt->ops->scan(fmt))
465 1.1 haad goto out;
466 1.1 haad }
467 1.1 haad
468 1.1 haad r = 1;
469 1.1 haad
470 1.1 haad out:
471 1.1 haad _scanning_in_progress = 0;
472 1.1 haad
473 1.1 haad return r;
474 1.1 haad }
475 1.1 haad
476 1.1 haad struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
477 1.1 haad {
478 1.1 haad struct lvmcache_vginfo *vginfo;
479 1.1 haad struct volume_group *vg;
480 1.1 haad struct format_instance *fid;
481 1.1 haad
482 1.1 haad if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
483 1.1 haad return NULL;
484 1.1 haad
485 1.1 haad if (!_vginfo_is_valid(vginfo))
486 1.1 haad return NULL;
487 1.1 haad
488 1.1 haad /*
489 1.1 haad * Don't return cached data if either:
490 1.1 haad * (i) precommitted metadata is requested but we don't have it cached
491 1.1 haad * - caller should read it off disk;
492 1.1 haad * (ii) live metadata is requested but we have precommitted metadata cached
493 1.1 haad * and no devices are suspended so caller may read it off disk.
494 1.1 haad *
495 1.1 haad * If live metadata is requested but we have precommitted metadata cached
496 1.1 haad * and devices are suspended, we assume this precommitted metadata has
497 1.1 haad * already been preloaded and committed so it's OK to return it as live.
498 1.1 haad * Note that we do not clear the PRECOMMITTED flag.
499 1.1 haad */
500 1.1 haad if ((precommitted && !vginfo->precommitted) ||
501 1.1 haad (!precommitted && vginfo->precommitted && !memlock()))
502 1.1 haad return NULL;
503 1.1 haad
504 1.1 haad if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
505 1.1 haad vginfo->vgname,
506 1.1 haad vgid, NULL)))
507 1.1 haad return_NULL;
508 1.1 haad
509 1.1 haad if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, fid)) ||
510 1.1 haad !vg_validate(vg)) {
511 1.1 haad _free_cached_vgmetadata(vginfo);
512 1.1 haad return_NULL;
513 1.1 haad }
514 1.1 haad
515 1.1 haad log_debug("Using cached %smetadata for VG %s.",
516 1.1 haad vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
517 1.1 haad
518 1.1 haad return vg;
519 1.1 haad }
520 1.1 haad
521 1.1 haad struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
522 1.1 haad {
523 1.1 haad struct dm_list *vgids;
524 1.1 haad struct lvmcache_vginfo *vginfo;
525 1.1 haad
526 1.1 haad lvmcache_label_scan(cmd, full_scan);
527 1.1 haad
528 1.1 haad if (!(vgids = str_list_create(cmd->mem))) {
529 1.1 haad log_error("vgids list allocation failed");
530 1.1 haad return NULL;
531 1.1 haad }
532 1.1 haad
533 1.1 haad dm_list_iterate_items(vginfo, &_vginfos) {
534 1.1 haad if (!str_list_add(cmd->mem, vgids,
535 1.1 haad dm_pool_strdup(cmd->mem, vginfo->vgid))) {
536 1.1 haad log_error("strlist allocation failed");
537 1.1 haad return NULL;
538 1.1 haad }
539 1.1 haad }
540 1.1 haad
541 1.1 haad return vgids;
542 1.1 haad }
543 1.1 haad
544 1.1 haad struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
545 1.1 haad {
546 1.1 haad struct dm_list *vgnames;
547 1.1 haad struct lvmcache_vginfo *vginfo;
548 1.1 haad
549 1.1 haad lvmcache_label_scan(cmd, full_scan);
550 1.1 haad
551 1.1 haad if (!(vgnames = str_list_create(cmd->mem))) {
552 1.1 haad log_error("vgnames list allocation failed");
553 1.1 haad return NULL;
554 1.1 haad }
555 1.1 haad
556 1.1 haad dm_list_iterate_items(vginfo, &_vginfos) {
557 1.1 haad if (!str_list_add(cmd->mem, vgnames,
558 1.1 haad dm_pool_strdup(cmd->mem, vginfo->vgname))) {
559 1.1 haad log_error("strlist allocation failed");
560 1.1 haad return NULL;
561 1.1 haad }
562 1.1 haad }
563 1.1 haad
564 1.1 haad return vgnames;
565 1.1 haad }
566 1.1 haad
567 1.1 haad struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
568 1.1 haad const char *vgid)
569 1.1 haad {
570 1.1 haad struct dm_list *pvids;
571 1.1 haad struct lvmcache_vginfo *vginfo;
572 1.1 haad struct lvmcache_info *info;
573 1.1 haad
574 1.1 haad if (!(pvids = str_list_create(cmd->mem))) {
575 1.1 haad log_error("pvids list allocation failed");
576 1.1 haad return NULL;
577 1.1 haad }
578 1.1 haad
579 1.1 haad if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
580 1.1 haad return pvids;
581 1.1 haad
582 1.1 haad dm_list_iterate_items(info, &vginfo->infos) {
583 1.1 haad if (!str_list_add(cmd->mem, pvids,
584 1.1 haad dm_pool_strdup(cmd->mem, info->dev->pvid))) {
585 1.1 haad log_error("strlist allocation failed");
586 1.1 haad return NULL;
587 1.1 haad }
588 1.1 haad }
589 1.1 haad
590 1.1 haad return pvids;
591 1.1 haad }
592 1.1 haad
593 1.1 haad struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
594 1.1 haad {
595 1.1 haad struct label *label;
596 1.1 haad struct lvmcache_info *info;
597 1.1 haad
598 1.1 haad /* Already cached ? */
599 1.1 haad if ((info = info_from_pvid((char *) pvid, 0))) {
600 1.1 haad if (label_read(info->dev, &label, UINT64_C(0))) {
601 1.1 haad info = (struct lvmcache_info *) label->info;
602 1.1 haad if (id_equal(pvid, (struct id *) &info->dev->pvid))
603 1.1 haad return info->dev;
604 1.1 haad }
605 1.1 haad }
606 1.1 haad
607 1.1 haad lvmcache_label_scan(cmd, 0);
608 1.1 haad
609 1.1 haad /* Try again */
610 1.1 haad if ((info = info_from_pvid((char *) pvid, 0))) {
611 1.1 haad if (label_read(info->dev, &label, UINT64_C(0))) {
612 1.1 haad info = (struct lvmcache_info *) label->info;
613 1.1 haad if (id_equal(pvid, (struct id *) &info->dev->pvid))
614 1.1 haad return info->dev;
615 1.1 haad }
616 1.1 haad }
617 1.1 haad
618 1.1 haad if (memlock())
619 1.1 haad return NULL;
620 1.1 haad
621 1.1 haad lvmcache_label_scan(cmd, 2);
622 1.1 haad
623 1.1 haad /* Try again */
624 1.1 haad if ((info = info_from_pvid((char *) pvid, 0))) {
625 1.1 haad if (label_read(info->dev, &label, UINT64_C(0))) {
626 1.1 haad info = (struct lvmcache_info *) label->info;
627 1.1 haad if (id_equal(pvid, (struct id *) &info->dev->pvid))
628 1.1 haad return info->dev;
629 1.1 haad }
630 1.1 haad }
631 1.1 haad
632 1.1 haad return NULL;
633 1.1 haad }
634 1.1 haad
635 1.1 haad static int _free_vginfo(struct lvmcache_vginfo *vginfo)
636 1.1 haad {
637 1.1 haad struct lvmcache_vginfo *primary_vginfo, *vginfo2;
638 1.1 haad int r = 1;
639 1.1 haad
640 1.1 haad _free_cached_vgmetadata(vginfo);
641 1.1 haad
642 1.1 haad vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
643 1.1 haad
644 1.1 haad if (vginfo == primary_vginfo) {
645 1.1 haad dm_hash_remove(_vgname_hash, vginfo->vgname);
646 1.1 haad if (vginfo->next && !dm_hash_insert(_vgname_hash, vginfo->vgname,
647 1.1 haad vginfo->next)) {
648 1.1 haad log_error("_vgname_hash re-insertion for %s failed",
649 1.1 haad vginfo->vgname);
650 1.1 haad r = 0;
651 1.1 haad }
652 1.1 haad } else do
653 1.1 haad if (vginfo2->next == vginfo) {
654 1.1 haad vginfo2->next = vginfo->next;
655 1.1 haad break;
656 1.1 haad }
657 1.1 haad while ((vginfo2 = primary_vginfo->next));
658 1.1 haad
659 1.1 haad if (vginfo->vgname)
660 1.1 haad dm_free(vginfo->vgname);
661 1.1 haad
662 1.1 haad if (vginfo->creation_host)
663 1.1 haad dm_free(vginfo->creation_host);
664 1.1 haad
665 1.1 haad if (*vginfo->vgid && _vgid_hash &&
666 1.1 haad vginfo_from_vgid(vginfo->vgid) == vginfo)
667 1.1 haad dm_hash_remove(_vgid_hash, vginfo->vgid);
668 1.1 haad
669 1.1 haad dm_list_del(&vginfo->list);
670 1.1 haad
671 1.1 haad dm_free(vginfo);
672 1.1 haad
673 1.1 haad return r;
674 1.1 haad }
675 1.1 haad
676 1.1 haad /*
677 1.1 haad * vginfo must be info->vginfo unless info is NULL
678 1.1 haad */
679 1.1 haad static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
680 1.1 haad {
681 1.1 haad if (info)
682 1.1 haad _vginfo_detach_info(info);
683 1.1 haad
684 1.1 haad /* vginfo still referenced? */
685 1.1 haad if (!vginfo || is_orphan_vg(vginfo->vgname) ||
686 1.1 haad !dm_list_empty(&vginfo->infos))
687 1.1 haad return 1;
688 1.1 haad
689 1.1 haad if (!_free_vginfo(vginfo))
690 1.1 haad return_0;
691 1.1 haad
692 1.1 haad return 1;
693 1.1 haad }
694 1.1 haad
695 1.1 haad /* Unused
696 1.1 haad void lvmcache_del(struct lvmcache_info *info)
697 1.1 haad {
698 1.1 haad if (info->dev->pvid[0] && _pvid_hash)
699 1.1 haad dm_hash_remove(_pvid_hash, info->dev->pvid);
700 1.1 haad
701 1.1 haad _drop_vginfo(info, info->vginfo);
702 1.1 haad
703 1.1 haad info->label->labeller->ops->destroy_label(info->label->labeller,
704 1.1 haad info->label);
705 1.1 haad dm_free(info);
706 1.1 haad
707 1.1 haad return;
708 1.1 haad } */
709 1.1 haad
710 1.1 haad static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
711 1.1 haad {
712 1.1.1.2 haad /*
713 1.1.1.2 haad * Nothing to do if already stored with same pvid.
714 1.1.1.2 haad */
715 1.1.1.2 haad if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
716 1.1.1.2 haad !strcmp(info->dev->pvid, pvid))
717 1.1 haad return 1;
718 1.1.1.2 haad if (*info->dev->pvid)
719 1.1 haad dm_hash_remove(_pvid_hash, info->dev->pvid);
720 1.1 haad strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
721 1.1 haad if (!dm_hash_insert(_pvid_hash, pvid, info)) {
722 1.1 haad log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
723 1.1 haad return 0;
724 1.1 haad }
725 1.1 haad
726 1.1 haad return 1;
727 1.1 haad }
728 1.1 haad
729 1.1 haad /*
730 1.1 haad * vginfo must be info->vginfo unless info is NULL (orphans)
731 1.1 haad */
732 1.1 haad static int _lvmcache_update_vgid(struct lvmcache_info *info,
733 1.1 haad struct lvmcache_vginfo *vginfo,
734 1.1 haad const char *vgid)
735 1.1 haad {
736 1.1 haad if (!vgid || !vginfo ||
737 1.1 haad !strncmp(vginfo->vgid, vgid, ID_LEN))
738 1.1 haad return 1;
739 1.1 haad
740 1.1 haad if (vginfo && *vginfo->vgid)
741 1.1 haad dm_hash_remove(_vgid_hash, vginfo->vgid);
742 1.1 haad if (!vgid) {
743 1.1 haad log_debug("lvmcache: %s: clearing VGID", info ? dev_name(info->dev) : vginfo->vgname);
744 1.1 haad return 1;
745 1.1 haad }
746 1.1 haad
747 1.1 haad strncpy(vginfo->vgid, vgid, ID_LEN);
748 1.1 haad vginfo->vgid[ID_LEN] = '\0';
749 1.1 haad if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) {
750 1.1 haad log_error("_lvmcache_update: vgid hash insertion failed: %s",
751 1.1 haad vginfo->vgid);
752 1.1 haad return 0;
753 1.1 haad }
754 1.1 haad
755 1.1 haad if (!is_orphan_vg(vginfo->vgname))
756 1.1 haad log_debug("lvmcache: %s: setting %s VGID to %s",
757 1.1 haad dev_name(info->dev), vginfo->vgname,
758 1.1 haad vginfo->vgid);
759 1.1 haad
760 1.1 haad return 1;
761 1.1 haad }
762 1.1 haad
763 1.1 haad static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
764 1.1 haad uint32_t vgstatus, const char *creation_host,
765 1.1 haad struct lvmcache_vginfo *primary_vginfo)
766 1.1 haad {
767 1.1 haad struct lvmcache_vginfo *last_vginfo = primary_vginfo;
768 1.1 haad char uuid_primary[64] __attribute((aligned(8)));
769 1.1 haad char uuid_new[64] __attribute((aligned(8)));
770 1.1 haad int use_new = 0;
771 1.1 haad
772 1.1 haad /* Pre-existing VG takes precedence. Unexported VG takes precedence. */
773 1.1 haad if (primary_vginfo) {
774 1.1 haad if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
775 1.1 haad return_0;
776 1.1 haad
777 1.1 haad if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
778 1.1 haad sizeof(uuid_primary)))
779 1.1 haad return_0;
780 1.1 haad
781 1.1 haad /*
782 1.1 haad * If Primary not exported, new exported => keep
783 1.1 haad * Else Primary exported, new not exported => change
784 1.1 haad * Else Primary has hostname for this machine => keep
785 1.1 haad * Else Primary has no hostname, new has one => change
786 1.1 haad * Else New has hostname for this machine => change
787 1.1 haad * Else Keep primary.
788 1.1 haad */
789 1.1 haad if (!(primary_vginfo->status & EXPORTED_VG) &&
790 1.1 haad (vgstatus & EXPORTED_VG))
791 1.1 haad log_error("WARNING: Duplicate VG name %s: "
792 1.1 haad "Existing %s takes precedence over "
793 1.1 haad "exported %s", new_vginfo->vgname,
794 1.1 haad uuid_primary, uuid_new);
795 1.1 haad else if ((primary_vginfo->status & EXPORTED_VG) &&
796 1.1 haad !(vgstatus & EXPORTED_VG)) {
797 1.1 haad log_error("WARNING: Duplicate VG name %s: "
798 1.1 haad "%s takes precedence over exported %s",
799 1.1 haad new_vginfo->vgname, uuid_new,
800 1.1 haad uuid_primary);
801 1.1 haad use_new = 1;
802 1.1 haad } else if (primary_vginfo->creation_host &&
803 1.1 haad !strcmp(primary_vginfo->creation_host,
804 1.1 haad primary_vginfo->fmt->cmd->hostname))
805 1.1 haad log_error("WARNING: Duplicate VG name %s: "
806 1.1 haad "Existing %s (created here) takes precedence "
807 1.1 haad "over %s", new_vginfo->vgname, uuid_primary,
808 1.1 haad uuid_new);
809 1.1 haad else if (!primary_vginfo->creation_host && creation_host) {
810 1.1 haad log_error("WARNING: Duplicate VG name %s: "
811 1.1 haad "%s (with creation_host) takes precedence over %s",
812 1.1 haad new_vginfo->vgname, uuid_new,
813 1.1 haad uuid_primary);
814 1.1 haad use_new = 1;
815 1.1 haad } else if (creation_host &&
816 1.1 haad !strcmp(creation_host,
817 1.1 haad primary_vginfo->fmt->cmd->hostname)) {
818 1.1 haad log_error("WARNING: Duplicate VG name %s: "
819 1.1 haad "%s (created here) takes precedence over %s",
820 1.1 haad new_vginfo->vgname, uuid_new,
821 1.1 haad uuid_primary);
822 1.1 haad use_new = 1;
823 1.1 haad }
824 1.1 haad
825 1.1 haad if (!use_new) {
826 1.1 haad while (last_vginfo->next)
827 1.1 haad last_vginfo = last_vginfo->next;
828 1.1 haad last_vginfo->next = new_vginfo;
829 1.1 haad return 1;
830 1.1 haad }
831 1.1 haad
832 1.1 haad dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
833 1.1 haad }
834 1.1 haad
835 1.1 haad if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
836 1.1 haad log_error("cache_update: vg hash insertion failed: %s",
837 1.1 haad new_vginfo->vgname);
838 1.1 haad return 0;
839 1.1 haad }
840 1.1 haad
841 1.1 haad if (primary_vginfo)
842 1.1 haad new_vginfo->next = primary_vginfo;
843 1.1 haad
844 1.1 haad return 1;
845 1.1 haad }
846 1.1 haad
847 1.1 haad static int _lvmcache_update_vgname(struct lvmcache_info *info,
848 1.1 haad const char *vgname, const char *vgid,
849 1.1 haad uint32_t vgstatus, const char *creation_host,
850 1.1 haad const struct format_type *fmt)
851 1.1 haad {
852 1.1 haad struct lvmcache_vginfo *vginfo, *primary_vginfo, *orphan_vginfo;
853 1.1 haad struct lvmcache_info *info2, *info3;
854 1.1 haad char mdabuf[32];
855 1.1 haad // struct lvmcache_vginfo *old_vginfo, *next;
856 1.1 haad
857 1.1 haad if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
858 1.1 haad return 1;
859 1.1 haad
860 1.1 haad /* Remove existing vginfo entry */
861 1.1 haad if (info)
862 1.1 haad _drop_vginfo(info, info->vginfo);
863 1.1 haad
864 1.1 haad /* Get existing vginfo or create new one */
865 1.1 haad if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
866 1.1 haad /*** FIXME - vginfo ends up duplicated instead of renamed.
867 1.1 haad // Renaming? This lookup fails.
868 1.1 haad if ((vginfo = vginfo_from_vgid(vgid))) {
869 1.1 haad next = vginfo->next;
870 1.1 haad old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
871 1.1 haad if (old_vginfo == vginfo) {
872 1.1 haad dm_hash_remove(_vgname_hash, old_vginfo->vgname);
873 1.1 haad if (old_vginfo->next) {
874 1.1 haad if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
875 1.1 haad log_error("vg hash re-insertion failed: %s",
876 1.1 haad old_vginfo->vgname);
877 1.1 haad return 0;
878 1.1 haad }
879 1.1 haad }
880 1.1 haad } else do {
881 1.1 haad if (old_vginfo->next == vginfo) {
882 1.1 haad old_vginfo->next = vginfo->next;
883 1.1 haad break;
884 1.1 haad }
885 1.1 haad } while ((old_vginfo = old_vginfo->next));
886 1.1 haad vginfo->next = NULL;
887 1.1 haad
888 1.1 haad dm_free(vginfo->vgname);
889 1.1 haad if (!(vginfo->vgname = dm_strdup(vgname))) {
890 1.1 haad log_error("cache vgname alloc failed for %s", vgname);
891 1.1 haad return 0;
892 1.1 haad }
893 1.1 haad
894 1.1 haad // Rename so can assume new name does not already exist
895 1.1 haad if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
896 1.1 haad log_error("vg hash re-insertion failed: %s",
897 1.1 haad vginfo->vgname);
898 1.1 haad return 0;
899 1.1 haad }
900 1.1 haad } else {
901 1.1 haad ***/
902 1.1 haad if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
903 1.1 haad log_error("lvmcache_update_vgname: list alloc failed");
904 1.1 haad return 0;
905 1.1 haad }
906 1.1 haad memset(vginfo, 0, sizeof(*vginfo));
907 1.1 haad if (!(vginfo->vgname = dm_strdup(vgname))) {
908 1.1 haad dm_free(vginfo);
909 1.1 haad log_error("cache vgname alloc failed for %s", vgname);
910 1.1 haad return 0;
911 1.1 haad }
912 1.1 haad dm_list_init(&vginfo->infos);
913 1.1 haad
914 1.1 haad /*
915 1.1 haad * If we're scanning and there's an invalidated entry, remove it.
916 1.1 haad * Otherwise we risk bogus warnings of duplicate VGs.
917 1.1 haad */
918 1.1 haad while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
919 1.1 haad _scanning_in_progress && _vginfo_is_invalid(primary_vginfo))
920 1.1 haad dm_list_iterate_items_safe(info2, info3, &primary_vginfo->infos) {
921 1.1 haad orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
922 1.1 haad _drop_vginfo(info2, primary_vginfo);
923 1.1 haad _vginfo_attach_info(orphan_vginfo, info2);
924 1.1 haad if (info2->mdas.n)
925 1.1 haad sprintf(mdabuf, " with %u mdas",
926 1.1 haad dm_list_size(&info2->mdas));
927 1.1 haad else
928 1.1 haad mdabuf[0] = '\0';
929 1.1 haad log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
930 1.1 haad dev_name(info2->dev),
931 1.1 haad vgname, orphan_vginfo->vgid[0] ? " (" : "",
932 1.1 haad orphan_vginfo->vgid[0] ? orphan_vginfo->vgid : "",
933 1.1 haad orphan_vginfo->vgid[0] ? ")" : "", mdabuf);
934 1.1 haad }
935 1.1 haad
936 1.1 haad if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
937 1.1 haad primary_vginfo)) {
938 1.1 haad dm_free(vginfo->vgname);
939 1.1 haad dm_free(vginfo);
940 1.1 haad return 0;
941 1.1 haad }
942 1.1 haad /* Ensure orphans appear last on list_iterate */
943 1.1 haad if (is_orphan_vg(vgname))
944 1.1 haad dm_list_add(&_vginfos, &vginfo->list);
945 1.1 haad else
946 1.1 haad dm_list_add_h(&_vginfos, &vginfo->list);
947 1.1 haad /***
948 1.1 haad }
949 1.1 haad ***/
950 1.1 haad }
951 1.1 haad
952 1.1 haad if (info)
953 1.1 haad _vginfo_attach_info(vginfo, info);
954 1.1 haad else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
955 1.1 haad return_0;
956 1.1 haad
957 1.1 haad _update_cache_vginfo_lock_state(vginfo, vgname_is_locked(vgname));
958 1.1 haad
959 1.1 haad /* FIXME Check consistency of list! */
960 1.1 haad vginfo->fmt = fmt;
961 1.1 haad
962 1.1 haad if (info) {
963 1.1 haad if (info->mdas.n)
964 1.1 haad sprintf(mdabuf, " with %u mdas", dm_list_size(&info->mdas));
965 1.1 haad else
966 1.1 haad mdabuf[0] = '\0';
967 1.1 haad log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
968 1.1 haad dev_name(info->dev),
969 1.1 haad vgname, vginfo->vgid[0] ? " (" : "",
970 1.1 haad vginfo->vgid[0] ? vginfo->vgid : "",
971 1.1 haad vginfo->vgid[0] ? ")" : "", mdabuf);
972 1.1 haad } else
973 1.1 haad log_debug("lvmcache: initialised VG %s", vgname);
974 1.1 haad
975 1.1 haad return 1;
976 1.1 haad }
977 1.1 haad
978 1.1 haad static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
979 1.1 haad const char *creation_host)
980 1.1 haad {
981 1.1 haad if (!info || !info->vginfo)
982 1.1 haad return 1;
983 1.1 haad
984 1.1 haad if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
985 1.1 haad log_debug("lvmcache: %s: VG %s %s exported",
986 1.1 haad dev_name(info->dev), info->vginfo->vgname,
987 1.1 haad vgstatus & EXPORTED_VG ? "now" : "no longer");
988 1.1 haad
989 1.1 haad info->vginfo->status = vgstatus;
990 1.1 haad
991 1.1 haad if (!creation_host)
992 1.1 haad return 1;
993 1.1 haad
994 1.1 haad if (info->vginfo->creation_host && !strcmp(creation_host,
995 1.1 haad info->vginfo->creation_host))
996 1.1 haad return 1;
997 1.1 haad
998 1.1 haad if (info->vginfo->creation_host)
999 1.1 haad dm_free(info->vginfo->creation_host);
1000 1.1 haad
1001 1.1 haad if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
1002 1.1 haad log_error("cache creation host alloc failed for %s",
1003 1.1 haad creation_host);
1004 1.1 haad return 0;
1005 1.1 haad }
1006 1.1 haad
1007 1.1 haad log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
1008 1.1 haad dev_name(info->dev), info->vginfo->vgname, creation_host);
1009 1.1 haad
1010 1.1 haad return 1;
1011 1.1 haad }
1012 1.1 haad
1013 1.1 haad int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
1014 1.1 haad {
1015 1.1 haad if (!_lock_hash && !lvmcache_init()) {
1016 1.1 haad log_error("Internal cache initialisation failed");
1017 1.1 haad return 0;
1018 1.1 haad }
1019 1.1 haad
1020 1.1 haad return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
1021 1.1 haad }
1022 1.1 haad
1023 1.1 haad int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
1024 1.1 haad const char *vgname, const char *vgid,
1025 1.1 haad uint32_t vgstatus, const char *creation_host)
1026 1.1 haad {
1027 1.1 haad if (!vgname && !info->vginfo) {
1028 1.1 haad log_error("Internal error: NULL vgname handed to cache");
1029 1.1 haad /* FIXME Remove this */
1030 1.1 haad vgname = info->fmt->orphan_vg_name;
1031 1.1 haad vgid = vgname;
1032 1.1 haad }
1033 1.1 haad
1034 1.1 haad /* If PV without mdas is already in a real VG, don't make it orphan */
1035 1.1 haad if (is_orphan_vg(vgname) && info->vginfo && !dm_list_size(&info->mdas) &&
1036 1.1 haad !is_orphan_vg(info->vginfo->vgname) && memlock())
1037 1.1 haad return 1;
1038 1.1 haad
1039 1.1 haad /* If moving PV from orphan to real VG, always mark it valid */
1040 1.1 haad if (!is_orphan_vg(vgname))
1041 1.1 haad info->status &= ~CACHE_INVALID;
1042 1.1 haad
1043 1.1 haad if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
1044 1.1 haad creation_host, info->fmt) ||
1045 1.1 haad !_lvmcache_update_vgid(info, info->vginfo, vgid) ||
1046 1.1 haad !_lvmcache_update_vgstatus(info, vgstatus, creation_host))
1047 1.1 haad return_0;
1048 1.1 haad
1049 1.1 haad return 1;
1050 1.1 haad }
1051 1.1 haad
1052 1.1 haad int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
1053 1.1 haad {
1054 1.1 haad struct pv_list *pvl;
1055 1.1 haad struct lvmcache_info *info;
1056 1.1 haad struct lvmcache_vginfo *vginfo;
1057 1.1 haad char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
1058 1.1 haad
1059 1.1 haad pvid_s[sizeof(pvid_s) - 1] = '\0';
1060 1.1 haad
1061 1.1 haad dm_list_iterate_items(pvl, &vg->pvs) {
1062 1.1 haad strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
1063 1.1 haad /* FIXME Could pvl->pv->dev->pvid ever be different? */
1064 1.1 haad if ((info = info_from_pvid(pvid_s, 0)) &&
1065 1.1 haad !lvmcache_update_vgname_and_id(info, vg->name,
1066 1.1 haad (char *) &vg->id,
1067 1.1 haad vg->status, NULL))
1068 1.1 haad return_0;
1069 1.1 haad }
1070 1.1 haad
1071 1.1 haad /* store text representation of vg to cache */
1072 1.1 haad if (vg->cmd->current_settings.cache_vgmetadata &&
1073 1.1 haad (vginfo = vginfo_from_vgname(vg->name, NULL)))
1074 1.1 haad _store_metadata(vginfo, vg, precommitted);
1075 1.1 haad
1076 1.1 haad return 1;
1077 1.1 haad }
1078 1.1 haad
1079 1.1 haad struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
1080 1.1 haad struct device *dev,
1081 1.1 haad const char *vgname, const char *vgid,
1082 1.1 haad uint32_t vgstatus)
1083 1.1 haad {
1084 1.1 haad struct label *label;
1085 1.1 haad struct lvmcache_info *existing, *info;
1086 1.1 haad char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
1087 1.1 haad
1088 1.1 haad if (!_vgname_hash && !lvmcache_init()) {
1089 1.1 haad log_error("Internal cache initialisation failed");
1090 1.1 haad return NULL;
1091 1.1 haad }
1092 1.1 haad
1093 1.1 haad strncpy(pvid_s, pvid, sizeof(pvid_s));
1094 1.1 haad pvid_s[sizeof(pvid_s) - 1] = '\0';
1095 1.1 haad
1096 1.1 haad if (!(existing = info_from_pvid(pvid_s, 0)) &&
1097 1.1 haad !(existing = info_from_pvid(dev->pvid, 0))) {
1098 1.1 haad if (!(label = label_create(labeller)))
1099 1.1 haad return_NULL;
1100 1.1 haad if (!(info = dm_malloc(sizeof(*info)))) {
1101 1.1 haad log_error("lvmcache_info allocation failed");
1102 1.1 haad label_destroy(label);
1103 1.1 haad return NULL;
1104 1.1 haad }
1105 1.1 haad memset(info, 0, sizeof(*info));
1106 1.1 haad
1107 1.1 haad label->info = info;
1108 1.1 haad info->label = label;
1109 1.1 haad dm_list_init(&info->list);
1110 1.1 haad info->dev = dev;
1111 1.1 haad } else {
1112 1.1 haad if (existing->dev != dev) {
1113 1.1 haad /* Is the existing entry a duplicate pvid e.g. md ? */
1114 1.1 haad if (MAJOR(existing->dev->dev) == md_major() &&
1115 1.1 haad MAJOR(dev->dev) != md_major()) {
1116 1.1 haad log_very_verbose("Ignoring duplicate PV %s on "
1117 1.1 haad "%s - using md %s",
1118 1.1 haad pvid, dev_name(dev),
1119 1.1 haad dev_name(existing->dev));
1120 1.1 haad return NULL;
1121 1.1 haad } else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
1122 1.1 haad !dm_is_dm_major(MAJOR(dev->dev))) {
1123 1.1 haad log_very_verbose("Ignoring duplicate PV %s on "
1124 1.1 haad "%s - using dm %s",
1125 1.1 haad pvid, dev_name(dev),
1126 1.1 haad dev_name(existing->dev));
1127 1.1 haad return NULL;
1128 1.1 haad } else if (MAJOR(existing->dev->dev) != md_major() &&
1129 1.1 haad MAJOR(dev->dev) == md_major())
1130 1.1 haad log_very_verbose("Duplicate PV %s on %s - "
1131 1.1 haad "using md %s", pvid,
1132 1.1 haad dev_name(existing->dev),
1133 1.1 haad dev_name(dev));
1134 1.1 haad else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
1135 1.1 haad dm_is_dm_major(MAJOR(dev->dev)))
1136 1.1 haad log_very_verbose("Duplicate PV %s on %s - "
1137 1.1 haad "using dm %s", pvid,
1138 1.1 haad dev_name(existing->dev),
1139 1.1 haad dev_name(dev));
1140 1.1 haad /* FIXME If both dm, check dependencies */
1141 1.1 haad //else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
1142 1.1 haad //dm_is_dm_major(MAJOR(dev->dev)))
1143 1.1 haad //
1144 1.1.1.2 haad else if (!strcmp(pvid_s, existing->dev->pvid))
1145 1.1 haad log_error("Found duplicate PV %s: using %s not "
1146 1.1 haad "%s", pvid, dev_name(dev),
1147 1.1 haad dev_name(existing->dev));
1148 1.1 haad }
1149 1.1.1.2 haad if (strcmp(pvid_s, existing->dev->pvid))
1150 1.1.1.2 haad log_debug("Updating pvid cache to %s (%s) from %s (%s)",
1151 1.1.1.2 haad pvid_s, dev_name(dev),
1152 1.1.1.2 haad existing->dev->pvid, dev_name(existing->dev));
1153 1.1 haad /* Switch over to new preferred device */
1154 1.1 haad existing->dev = dev;
1155 1.1 haad info = existing;
1156 1.1 haad /* Has labeller changed? */
1157 1.1 haad if (info->label->labeller != labeller) {
1158 1.1 haad label_destroy(info->label);
1159 1.1 haad if (!(info->label = label_create(labeller)))
1160 1.1 haad /* FIXME leaves info without label! */
1161 1.1 haad return_NULL;
1162 1.1 haad info->label->info = info;
1163 1.1 haad }
1164 1.1 haad label = info->label;
1165 1.1 haad }
1166 1.1 haad
1167 1.1 haad info->fmt = (const struct format_type *) labeller->private;
1168 1.1 haad info->status |= CACHE_INVALID;
1169 1.1 haad
1170 1.1 haad if (!_lvmcache_update_pvid(info, pvid_s)) {
1171 1.1 haad if (!existing) {
1172 1.1 haad dm_free(info);
1173 1.1 haad label_destroy(label);
1174 1.1 haad }
1175 1.1 haad return NULL;
1176 1.1 haad }
1177 1.1 haad
1178 1.1 haad if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
1179 1.1 haad if (!existing) {
1180 1.1 haad dm_hash_remove(_pvid_hash, pvid_s);
1181 1.1 haad strcpy(info->dev->pvid, "");
1182 1.1 haad dm_free(info);
1183 1.1 haad label_destroy(label);
1184 1.1 haad }
1185 1.1 haad return NULL;
1186 1.1 haad }
1187 1.1 haad
1188 1.1 haad return info;
1189 1.1 haad }
1190 1.1 haad
1191 1.1 haad static void _lvmcache_destroy_entry(struct lvmcache_info *info)
1192 1.1 haad {
1193 1.1 haad _vginfo_detach_info(info);
1194 1.1 haad strcpy(info->dev->pvid, "");
1195 1.1 haad label_destroy(info->label);
1196 1.1 haad dm_free(info);
1197 1.1 haad }
1198 1.1 haad
1199 1.1 haad static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
1200 1.1 haad {
1201 1.1 haad struct lvmcache_vginfo *next;
1202 1.1 haad
1203 1.1 haad do {
1204 1.1 haad next = vginfo->next;
1205 1.1 haad if (!_free_vginfo(vginfo))
1206 1.1 haad stack;
1207 1.1 haad } while ((vginfo = next));
1208 1.1 haad }
1209 1.1 haad
1210 1.1 haad static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
1211 1.1 haad {
1212 1.1 haad char *vgname;
1213 1.1 haad
1214 1.1 haad if (!dm_hash_get_data(_lock_hash, n))
1215 1.1 haad return;
1216 1.1 haad
1217 1.1 haad vgname = dm_hash_get_key(_lock_hash, n);
1218 1.1 haad
1219 1.1 haad if (!strcmp(vgname, VG_GLOBAL))
1220 1.1 haad _vg_global_lock_held = 1;
1221 1.1 haad else
1222 1.1 haad log_error("Internal error: Volume Group %s was not unlocked",
1223 1.1 haad dm_hash_get_key(_lock_hash, n));
1224 1.1 haad }
1225 1.1 haad
1226 1.1 haad void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
1227 1.1 haad {
1228 1.1 haad struct dm_hash_node *n;
1229 1.1 haad log_verbose("Wiping internal VG cache");
1230 1.1 haad
1231 1.1 haad _has_scanned = 0;
1232 1.1 haad
1233 1.1 haad if (_vgid_hash) {
1234 1.1 haad dm_hash_destroy(_vgid_hash);
1235 1.1 haad _vgid_hash = NULL;
1236 1.1 haad }
1237 1.1 haad
1238 1.1 haad if (_pvid_hash) {
1239 1.1 haad dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
1240 1.1 haad dm_hash_destroy(_pvid_hash);
1241 1.1 haad _pvid_hash = NULL;
1242 1.1 haad }
1243 1.1 haad
1244 1.1 haad if (_vgname_hash) {
1245 1.1 haad dm_hash_iter(_vgname_hash,
1246 1.1 haad (dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
1247 1.1 haad dm_hash_destroy(_vgname_hash);
1248 1.1 haad _vgname_hash = NULL;
1249 1.1 haad }
1250 1.1 haad
1251 1.1 haad if (_lock_hash) {
1252 1.1 haad dm_hash_iterate(n, _lock_hash)
1253 1.1 haad _lvmcache_destroy_lockname(n);
1254 1.1 haad dm_hash_destroy(_lock_hash);
1255 1.1 haad _lock_hash = NULL;
1256 1.1 haad }
1257 1.1 haad
1258 1.1 haad if (!dm_list_empty(&_vginfos))
1259 1.1 haad log_error("Internal error: _vginfos list should be empty");
1260 1.1 haad dm_list_init(&_vginfos);
1261 1.1 haad
1262 1.1 haad if (retain_orphans)
1263 1.1 haad init_lvmcache_orphans(cmd);
1264 1.1 haad }
1265