mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
03b0a78640
It's possible for an LVM LV to use a device during activation which then differs from device which LVM assumes based on metadata later on. For example, such device mismatch can occur if LVM doesn't have complete view of devices during activation or if filters are misbehaving or they're incorrectly set during activation. This patch adds code that can detect this mismatch by creating VG UUID and LV UUID index while scanning devices for device cache. The VG UUID index maps VG UUID to a device list. Each device in the list has a device layered above as a holder which is an LVM LV device and for which we know the VG UUID (and similarly for LV UUID index). We can acquire VG and LV UUID by reading /sys/block/<dm_dev_name>/dm/uuid. So these indices represent the actual state of PV device use in the system by LVs and then we compare that to what LVM assumes based on metadata. For example: [0] fedora/~ # lsblk /dev/sdq /dev/sdr /dev/sds /dev/sdt NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdq 65:0 0 104M 0 disk |-vg-lvol0 253:2 0 200M 0 lvm `-mpath_dev1 253:3 0 104M 0 mpath sdr 65:16 0 104M 0 disk `-mpath_dev1 253:3 0 104M 0 mpath sds 65:32 0 104M 0 disk |-vg-lvol0 253:2 0 200M 0 lvm `-mpath_dev2 253:4 0 104M 0 mpath sdt 65:48 0 104M 0 disk `-mpath_dev2 253:4 0 104M 0 mpath In this case the vg-lvol0 is mapped onto sdq and sds becauset this is what was available and seen during activation. Then later on, sdr and sdt appeared and mpath devices were created out of sdq+sdr (mpath_dev1) and sds+sdt (mpath_dev2). Now, LVM assumes (correctly) that mpath_dev1 and mpath_dev2 are the PVs that should be used, not the mpath components (sdq/sdr, sds/sdt). [0] fedora/~ # pvs Found duplicate PV xSUix1GJ2SK82ACFuKzFLAQi8xMfFxnO: using /dev/mapper/mpath_dev1 not /dev/sdq Using duplicate PV /dev/mapper/mpath_dev1 from subsystem DM, replacing /dev/sdq Found duplicate PV MvHyMVabtSqr33AbkUrobq1LjP8oiTRm: using /dev/mapper/mpath_dev2 not /dev/sds Using duplicate PV /dev/mapper/mpath_dev2 from subsystem DM, ignoring /dev/sds WARNING: Device mismatch detected for vg/lvol0 which is accessing /dev/sdq, /dev/sds instead of /dev/mapper/mpath_dev1, /dev/mapper/mpath_dev2. PV VG Fmt Attr PSize PFree /dev/mapper/mpath_dev1 vg lvm2 a-- 100.00m 0 /dev/mapper/mpath_dev2 vg lvm2 a-- 100.00m 0
74 lines
2.1 KiB
C
74 lines
2.1 KiB
C
/*
|
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
|
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
|
*
|
|
* This file is part of LVM2.
|
|
*
|
|
* This copyrighted material is made available to anyone wishing to use,
|
|
* modify, copy, or redistribute it subject to the terms and conditions
|
|
* of the GNU Lesser General Public License v.2.1.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef _LVM_DEV_CACHE_H
|
|
#define _LVM_DEV_CACHE_H
|
|
|
|
#include "device.h"
|
|
#include "lvm-wrappers.h"
|
|
|
|
/*
|
|
* predicate for devices.
|
|
*/
|
|
struct dev_filter {
|
|
int (*passes_filter) (struct dev_filter * f, struct device * dev);
|
|
void (*destroy) (struct dev_filter * f);
|
|
void (*wipe) (struct dev_filter * f);
|
|
int (*dump) (struct dev_filter * f, int merge_existing);
|
|
void *private;
|
|
unsigned use_count;
|
|
};
|
|
|
|
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid);
|
|
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid);
|
|
|
|
/*
|
|
* The global device cache.
|
|
*/
|
|
struct cmd_context;
|
|
int dev_cache_init(struct cmd_context *cmd);
|
|
int dev_cache_exit(void);
|
|
/*
|
|
* Returns number of open devices.
|
|
*/
|
|
int dev_cache_check_for_open_devices(void);
|
|
|
|
/* Trigger(1) or avoid(0) a scan */
|
|
void dev_cache_scan(int do_scan);
|
|
int dev_cache_has_scanned(void);
|
|
void dev_cache_full_scan(struct dev_filter *f);
|
|
|
|
int dev_cache_add_dir(const char *path);
|
|
int dev_cache_add_loopfile(const char *path);
|
|
__attribute__((nonnull(1)))
|
|
struct device *dev_cache_get(const char *name, struct dev_filter *f);
|
|
|
|
// TODO
|
|
struct device *dev_cache_get_by_devt(dev_t device, struct dev_filter *f);
|
|
|
|
void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev);
|
|
|
|
/*
|
|
* Object for iterating through the cache.
|
|
*/
|
|
struct dev_iter;
|
|
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
|
|
void dev_iter_destroy(struct dev_iter *iter);
|
|
struct device *dev_iter_get(struct dev_iter *iter);
|
|
|
|
void dev_reset_error_count(struct cmd_context *cmd);
|
|
|
|
#endif
|