1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/lib/format_text/flags.c

306 lines
7.8 KiB
C
Raw Normal View History

/*
2008-01-30 17:00:02 +03:00
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
lvconvert: add infrastructure for RaidLV reshaping support In order to support striped raid5/6/10 LV reshaping (change of LV type, stripesize or number of legs), this patch introduces infrastructure prerequisites to be used by raid_manip.c extensions in followup patches. This base is needed for allocation of out-of-place reshape space required by the MD raid personalities to avoid writing over data in-place when reading off the current RAID layout or number of legs and writing out the new layout or to a different number of legs (i.e. restripe) Changes: - add members reshape_len to 'struct lv_segment' to store out-of-place reshape length per component rimage - add member data_copies to struct lv_segment to support more than 2 raid10 data copies - make alloc_lv_segment() aware of both reshape_len and data_copies - adjust all alloc_lv_segment() callers to the new API - add functions to retrieve the current data offset (needed for out-of-place reshaping space allocation) and the devices count from the kernel - make libdm deptree code aware of reshape_len - add LV flags for disk add/remove reshaping - support import/export of the new 'struct lv_segment' members - enhance lv_extend/_lv_reduce to cope with reshape_len - add seg_is_*/segtype_is_* macros related to reshaping - add target version check for reshaping - grow rebuilds/writemostly bitmaps to 246 bit to support kernel maximal - enhance libdm deptree code to support data_offset (out-of-place reshaping) and delta_disk (legs add/remove reshaping) target arguments Related: rhbz834579 Related: rhbz1191935 Related: rhbz1191978
2017-02-24 02:50:00 +03:00
* Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
*
2004-03-30 23:35:44 +04:00
* 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.
2004-03-30 23:35:44 +04:00
*
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "lib/metadata/metadata.h"
#include "import-export.h"
#include "lib/misc/lvm-string.h"
/*
* Bitsets held in the 'status' flags get
* converted into arrays of strings.
*/
struct flag {
const uint64_t mask;
const char *description;
int kind;
};
2010-01-07 17:47:57 +03:00
static const struct flag _vg_flags[] = {
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
{RESIZEABLE_VG, "RESIZEABLE", STATUS_FLAG},
{PVMOVE, "PVMOVE", STATUS_FLAG},
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
{LVM_WRITE_LOCKED, "WRITE_LOCKED", COMPATIBLE_FLAG},
Add metadata-based autoactivation property for VG and LV The autoactivation property can be specified in lvcreate or vgcreate for new LVs/VGs, and the property can be changed by lvchange or vgchange for existing LVs/VGs. --setautoactivation y|n enables|disables autoactivation of a VG or LV. Autoactivation is enabled by default, which is consistent with past behavior. The disabled state is stored as a new flag in the VG metadata, and the absence of the flag allows autoactivation. If autoactivation is disabled for the VG, then no LVs in the VG will be autoactivated (the LV autoactivation property will have no effect.) When autoactivation is enabled for the VG, then autoactivation can be controlled on individual LVs. The state of this property can be reported for LVs/VGs using the "-o autoactivation" option in lvs/vgs commands, which will report "enabled", or "" for the disabled state. Previous versions of lvm do not recognize this property. Since autoactivation is enabled by default, the disabled setting will have no effect in older lvm versions. If the VG is modified by older lvm versions, the disabled state will also be dropped from the metadata. The autoactivation property is an alternative to using the lvm.conf auto_activation_volume_list, which is still applied to to VGs/LVs in addition to the new property. If VG or LV autoactivation is disabled either in metadata or in auto_activation_volume_list, it will not be autoactivated. An autoactivation command will silently skip activating an LV when the autoactivation property is disabled. To determine the effective autoactivation behavior for a specific LV, multiple settings would need to be checked: the VG autoactivation property, the LV autoactivation property, the auto_activation_volume_list. The "activation skip" property would also be relevant, since it applies to both normal and auto activation.
2021-04-02 01:20:00 +03:00
{NOAUTOACTIVATE, "NOAUTOACTIVATE", COMPATIBLE_FLAG},
{CLUSTERED, "CLUSTERED", STATUS_FLAG},
{SHARED, "SHARED", STATUS_FLAG},
{PARTIAL_VG, NULL, 0},
{PRECOMMITTED, NULL, 0},
{ARCHIVED_VG, NULL, 0},
{0, NULL, 0}
};
2010-01-07 17:47:57 +03:00
static const struct flag _pv_flags[] = {
{ALLOCATABLE_PV, "ALLOCATABLE", STATUS_FLAG},
{EXPORTED_VG, "EXPORTED", STATUS_FLAG},
{MISSING_PV, "MISSING", COMPATIBLE_FLAG},
{MISSING_PV, "MISSING", STATUS_FLAG},
{PV_MOVED_VG, NULL, 0},
{UNLABELLED_PV, NULL, 0},
{0, NULL, 0}
};
2010-01-07 17:47:57 +03:00
static const struct flag _lv_flags[] = {
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
{LVM_WRITE_LOCKED, "WRITE_LOCKED", COMPATIBLE_FLAG},
{FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
{VISIBLE_LV, "VISIBLE", STATUS_FLAG},
{PVMOVE, "PVMOVE", STATUS_FLAG},
{LOCKED, "LOCKED", STATUS_FLAG},
{LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG},
{LV_REBUILD, "REBUILD", STATUS_FLAG},
{LV_RESHAPE, "RESHAPE", SEGTYPE_FLAG},
{LV_RESHAPE_DATA_OFFSET, "RESHAPE_DATA_OFFSET", SEGTYPE_FLAG},
{LV_RESHAPE_DELTA_DISKS_PLUS, "RESHAPE_DELTA_DISKS_PLUS", SEGTYPE_FLAG},
{LV_RESHAPE_DELTA_DISKS_MINUS, "RESHAPE_DELTA_DISKS_MINUS", SEGTYPE_FLAG},
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", SEGTYPE_FLAG},
RAID: Add writemostly/writebehind support for RAID1 'lvchange' is used to alter a RAID 1 logical volume's write-mostly and write-behind characteristics. The '--writemostly' parameter takes a PV as an argument with an optional trailing character to specify whether to set ('y'), unset ('n'), or toggle ('t') the value. If no trailing character is given, it will set the flag. Synopsis: lvchange [--writemostly <PV>:{t|y|n}] [--writebehind <count>] vg/lv Example: lvchange --writemostly /dev/sdb1:y --writebehind 512 vg/raid1_lv The last character in the 'lv_attr' field is used to show whether a device has the WriteMostly flag set. It is signified with a 'w'. If the device has failed, the 'p'artial flag has priority. Example ("nosync" raid1 with mismatch_cnt and writemostly): [~]# lvs -a --segment vg LV VG Attr #Str Type SSize raid1 vg Rwi---r-m 2 raid1 500.00m [raid1_rimage_0] vg Iwi---r-- 1 linear 500.00m [raid1_rimage_1] vg Iwi---r-w 1 linear 500.00m [raid1_rmeta_0] vg ewi---r-- 1 linear 4.00m [raid1_rmeta_1] vg ewi---r-- 1 linear 4.00m Example (raid1 with mismatch_cnt, writemostly - but failed drive): [~]# lvs -a --segment vg LV VG Attr #Str Type SSize raid1 vg rwi---r-p 2 raid1 500.00m [raid1_rimage_0] vg Iwi---r-- 1 linear 500.00m [raid1_rimage_1] vg Iwi---r-p 1 linear 500.00m [raid1_rmeta_0] vg ewi---r-- 1 linear 4.00m [raid1_rmeta_1] vg ewi---r-p 1 linear 4.00m A new reportable field has been added for writebehind as well. If write-behind has not been set or the LV is not RAID1, the field will be blank. Example (writebehind is set): [~]# lvs -a -o name,attr,writebehind vg LV Attr WBehind lv rwi-a-r-- 512 [lv_rimage_0] iwi-aor-w [lv_rimage_1] iwi-aor-- [lv_rmeta_0] ewi-aor-- [lv_rmeta_1] ewi-aor-- Example (writebehind is not set): [~]# lvs -a -o name,attr,writebehind vg LV Attr WBehind lv rwi-a-r-- [lv_rimage_0] iwi-aor-w [lv_rimage_1] iwi-aor-- [lv_rmeta_0] ewi-aor-- [lv_rmeta_1] ewi-aor--
2013-04-15 22:59:46 +04:00
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
activation: add support for skipping activation of selected LVs Also add -k/--setactivationskip y/n and -K/--ignoreactivationskip options to lvcreate. The --setactivationskip y sets the flag in metadata for an LV to skip the LV during activation. Also, the newly created LV is not activated. Thin snapsots have this flag set automatically if not specified directly by the --setactivationskip y/n option. The --ignoreactivationskip overrides the activation skip flag set in metadata for an LV (just for the run of the command - the flag is not changed in metadata!) A few examples for the lvcreate with the new options: (non-thin snap LV => skip flag not set in MDA + LV activated) raw/~ $ lvcreate -l1 vg Logical volume "lvol0" created raw/~ $ lvs -o lv_name,attr vg/lvol0 LV Attr lvol0 -wi-a---- (non-thin snap LV + -ky => skip flag set in MDA + LV not activated) raw/~ $ lvcreate -l1 -ky vg Logical volume "lvol1" created raw/~ $ lvs -o lv_name,attr vg/lvol1 LV Attr lvol1 -wi------ (non-thin snap LV + -ky + -K => skip flag set in MDA + LV activated) raw/~ $ lvcreate -l1 -ky -K vg Logical volume "lvol2" created raw/~ $ lvs -o lv_name,attr vg/lvol2 LV Attr lvol2 -wi-a---- (thin snap LV => skip flag set in MDA (default behaviour) + LV not activated) raw/~ $ lvcreate -L100M -T vg/pool -V 1T -n thin_lv Logical volume "thin_lv" created raw/~ $ lvcreate -s vg/thin_lv -n thin_snap Logical volume "thin_snap" created raw/~ $ lvs -o name,attr vg LV Attr pool twi-a-tz- thin_lv Vwi-a-tz- thin_snap Vwi---tz- (thin snap LV + -K => skip flag set in MDA (default behaviour) + LV activated) raw/~ $ lvcreate -s vg/thin_lv -n thin_snap -K Logical volume "thin_snap" created raw/~ $ lvs -o name,attr vg/thin_lv LV Attr thin_lv Vwi-a-tz- (thins snap LV + -kn => no skip flag in MDA (default behaviour overridden) + LV activated) [0] raw/~ # lvcreate -s vg/thin_lv -n thin_snap -kn Logical volume "thin_snap" created [0] raw/~ # lvs -o name,attr vg/thin_snap LV Attr thin_snap Vwi-a-tz-
2013-07-10 16:06:50 +04:00
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
Add metadata-based autoactivation property for VG and LV The autoactivation property can be specified in lvcreate or vgcreate for new LVs/VGs, and the property can be changed by lvchange or vgchange for existing LVs/VGs. --setautoactivation y|n enables|disables autoactivation of a VG or LV. Autoactivation is enabled by default, which is consistent with past behavior. The disabled state is stored as a new flag in the VG metadata, and the absence of the flag allows autoactivation. If autoactivation is disabled for the VG, then no LVs in the VG will be autoactivated (the LV autoactivation property will have no effect.) When autoactivation is enabled for the VG, then autoactivation can be controlled on individual LVs. The state of this property can be reported for LVs/VGs using the "-o autoactivation" option in lvs/vgs commands, which will report "enabled", or "" for the disabled state. Previous versions of lvm do not recognize this property. Since autoactivation is enabled by default, the disabled setting will have no effect in older lvm versions. If the VG is modified by older lvm versions, the disabled state will also be dropped from the metadata. The autoactivation property is an alternative to using the lvm.conf auto_activation_volume_list, which is still applied to to VGs/LVs in addition to the new property. If VG or LV autoactivation is disabled either in metadata or in auto_activation_volume_list, it will not be autoactivated. An autoactivation command will silently skip activating an LV when the autoactivation property is disabled. To determine the effective autoactivation behavior for a specific LV, multiple settings would need to be checked: the VG autoactivation property, the LV autoactivation property, the auto_activation_volume_list. The "activation skip" property would also be relevant, since it applies to both normal and auto activation.
2021-04-02 01:20:00 +03:00
{LV_NOAUTOACTIVATE, "NOAUTOACTIVATE", COMPATIBLE_FLAG},
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
thin: improve 16g support for thin pool metadata Initial support for thin-pool used slightly smaller max size 15.81GiB for thin-pool metadata. However the real limit later settled at 15.88GiB (difference is ~64MiB - 16448 4K blocks). lvm2 could not simply increase the size as it has been using hard cropping of the loaded metadata device to avoid warnings printing warning of kernel when the size was bigger (i.e. due to bigger extent_size). This patch adds the new lvm.conf configurable setting: allocation/thin_pool_crop_metadata which defaults to 0 -> no crop of metadata beyond 15.81GiB. Only user with these sizes of metadata will be affected. Without cropping lvm2 now limits metadata allocation size to 15.88GiB. Any space beyond is currently not used by thin-pool target. Even if i.e. bigger LV is used for metadata via lvconvert, or allocated bigger because of to large extent size. With cropping enabled (=1) lvm2 preserves the old limitation 15.81GiB and should allow to work in the evironement with older lvm2 tools (i.e. older distribution). Thin-pool metadata with size bigger then 15.81G is now using CROP_METADATA flag within lvm2 metadata, so older lvm2 recognizes an incompatible thin-pool and cannot activate such pool! Users should use uncropped version as it is not suffering from various issues between thin_repair results and allocated metadata LV as thin_repair limit is 15.88GiB Users should use cropping only when really needed! Patch also better handles resize of thin-pool metadata and prevents resize beoyond usable size 15.88GiB. Resize beyond 15.81GiB automatically switches pool to no-crop version. Even with existing bigger thin-pool metadata command 'lvextend -l+1 vg/pool_tmeta' does the change. Patch gives better controls 'coverted' metadata LV and reports less confusing message during conversion. Patch set also moves the code for updating min/max into pool_manip.c for better sharing with cache_pool code.
2021-01-12 19:59:29 +03:00
{LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
{LV_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG},
{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG},
{LV_NOSCAN, NULL, 0},
activation: flag temporary LVs internally Add LV_TEMPORARY flag for LVs with limited existence during command execution. Such LVs are temporary in way that they need to be activated, some action done and then removed immediately. Such LVs are just like any normal LV - the only difference is that they are removed during LVM command execution. This is also the case for LVs representing future pool metadata spare LVs which we need to initialize by using the usual LV before they are declared as pool metadata spare. We can optimize some other parts like udev to do a better job if it knows that the LV is temporary and any processing on it is just useless. This flag is orthogonal to LV_NOSCAN flag introduced recently as LV_NOSCAN flag is primarily used to mark an LV for the scanning to be avoided before the zeroing of the device happens. The LV_TEMPORARY flag makes a difference between a full-fledged LV visible in the system and the LV just used as a temporary overlay for some action that needs to be done on underlying PVs. For example: lvcreate --thinpool POOL --zero n -L 1G vg - first, the usual LV is created to do a clean up for pool metadata spare. The LV is activated, zeroed, deactivated. - between "activated" and "zeroed" stage, the LV_NOSCAN flag is used to avoid any scanning in udev - betwen "zeroed" and "deactivated" stage, we need to avoid the WATCH udev rule, but since the LV is just a usual LV, we can't make a difference. The LV_TEMPORARY internal LV flag helps here. If we create the LV with this flag, the DM_UDEV_DISABLE_DISK_RULES and DM_UDEV_DISABLE_OTHER_RULES flag are set (just like as it is with "invisible" and non-top-level LVs) - udev is directed to skip WATCH rule use. - if the LV_TEMPORARY flag was not used, there would normally be a WATCH event generated once the LV is closed after "zeroed" stage. This will make problems with immediated deactivation that follows.
2013-10-23 16:06:39 +04:00
{LV_TEMPORARY, NULL, 0},
{POOL_METADATA_SPARE, NULL, 0},
2015-03-05 23:00:44 +03:00
{LOCKD_SANLOCK_LV, NULL, 0},
{RAID, NULL, 0},
{RAID_META, NULL, 0},
{RAID_IMAGE, NULL, 0},
{MIRROR, NULL, 0},
{MIRROR_IMAGE, NULL, 0},
{MIRROR_LOG, NULL, 0},
{MIRRORED, NULL, 0},
{VIRTUAL, NULL, 0},
{SNAPSHOT, NULL, 0},
{MERGING, NULL, 0},
{CONVERTING, NULL, 0},
{PARTIAL_LV, NULL, 0},
{POSTORDER_FLAG, NULL, 0},
{VIRTUAL_ORIGIN, NULL, 0},
{THIN_VOLUME, NULL, 0},
{THIN_POOL, NULL, 0},
{THIN_POOL_DATA, NULL, 0},
{THIN_POOL_METADATA, NULL, 0},
{CACHE, NULL, 0},
{CACHE_POOL, NULL, 0},
{CACHE_POOL_DATA, NULL, 0},
{CACHE_POOL_METADATA, NULL, 0},
{LV_VDO, NULL, 0},
{LV_VDO_POOL, NULL, 0},
{LV_VDO_POOL_DATA, NULL, 0},
{WRITECACHE, NULL, 0},
Allow dm-integrity to be used for raid images dm-integrity stores checksums of the data written to an LV, and returns an error if data read from the LV does not match the previously saved checksum. When used on raid images, dm-raid will correct the error by reading the block from another image, and the device user sees no error. The integrity metadata (checksums) are stored on an internal LV allocated by lvm for each linear image. The internal LV is allocated on the same PV as the image. Create a raid LV with an integrity layer over each raid image (for raid levels 1,4,5,6,10): lvcreate --type raidN --raidintegrity y [options] Add an integrity layer to images of an existing raid LV: lvconvert --raidintegrity y LV Remove the integrity layer from images of a raid LV: lvconvert --raidintegrity n LV Settings Use --raidintegritymode journal|bitmap (journal is default) to configure the method used by dm-integrity to ensure crash consistency. Initialization When integrity is added to an LV, the kernel needs to initialize the integrity metadata/checksums for all blocks in the LV. The data corruption checking performed by dm-integrity will only operate on areas of the LV that are already initialized. The progress of integrity initialization is reported by the "syncpercent" LV reporting field (and under the Cpy%Sync lvs column.) Example: create a raid1 LV with integrity: $ lvcreate --type raid1 -m1 --raidintegrity y -n rr -L1G foo Creating integrity metadata LV rr_rimage_0_imeta with size 12.00 MiB. Logical volume "rr_rimage_0_imeta" created. Creating integrity metadata LV rr_rimage_1_imeta with size 12.00 MiB. Logical volume "rr_rimage_1_imeta" created. Logical volume "rr" created. $ lvs -a foo LV VG Attr LSize Origin Cpy%Sync rr foo rwi-a-r--- 1.00g 4.93 [rr_rimage_0] foo gwi-aor--- 1.00g [rr_rimage_0_iorig] 41.02 [rr_rimage_0_imeta] foo ewi-ao---- 12.00m [rr_rimage_0_iorig] foo -wi-ao---- 1.00g [rr_rimage_1] foo gwi-aor--- 1.00g [rr_rimage_1_iorig] 39.45 [rr_rimage_1_imeta] foo ewi-ao---- 12.00m [rr_rimage_1_iorig] foo -wi-ao---- 1.00g [rr_rmeta_0] foo ewi-aor--- 4.00m [rr_rmeta_1] foo ewi-aor--- 4.00m
2019-11-21 01:07:27 +03:00
{INTEGRITY, NULL, 0},
{INTEGRITY_METADATA, NULL, 0},
2014-11-11 17:13:00 +03:00
{LV_PENDING_DELETE, NULL, 0}, /* FIXME Display like COMPATIBLE_FLAG */
metadata: process_each_lv_in_vg: get the list of LVs to process first, then do the processing This avoids a problem in which we're using selection on LV list - we need to do the selection on initial state and not on any intermediary state as we process LVs one by one - some of the relations among LVs can be gone during this processing. For example, processing one LV can cause the other LVs to lose the relation to this LV and hence they're not selectable anymore with the original selection criteria as it would be if we did selection on inital state. A perfect example is with thin snapshots: $ lvs -o lv_name,origin,layout,role vg LV Origin Layout Role lvol1 thin,sparse public,origin,thinorigin,multithinorigin lvol2 lvol1 thin,sparse public,snapshot,thinsnapshot lvol3 lvol1 thin,sparse public,snapshot,thinsnapshot pool thin,pool private $ lvremove -ff -S 'lv_name=lvol1 || origin=lvol1' Logical volume "lvol1" successfully removed The lvremove command above was supposed to remove lvol1 as well as all its snapshots which have origin=lvol1. It failed to do so, because once we removed the origin lvol1, the lvol2 and lvol3 which were snapshots before are not snapshots anymore - the relations change as we're processing these LVs one by one. If we do the selection first and then execute any concrete actions on these LVs (which is what this patch does), the behaviour is correct then - the selection is done on the *initial state*: $ lvremove -ff -S 'lv_name=lvol1 || origin=lvol1' Logical volume "lvol1" successfully removed Logical volume "lvol2" successfully removed Logical volume "lvol3" successfully removed Similarly for all the other situations in which relations among LVs are being changed by processing the LVs one by one. This patch also introduces LV_REMOVED internal LV status flag to mark removed LVs so they're not processed further when we iterate over collected list of LVs to be processed. Previously, when we iterated directly over vg->lvs list to process the LVs, we relied on the fact that once the LV is removed, it is also removed from the vg->lvs list we're iterating over. But that was incorrect as we shouldn't remove LVs from the list during one iteration while we're iterating over that exact list (dm_list_iterate_items safe can handle only one removal at one iteration anyway, so it can't be used here).
2015-03-16 19:10:21 +03:00
{LV_REMOVED, NULL, 0},
{0, NULL, 0}
};
static const struct flag *_get_flags(enum pv_vg_lv_e type)
{
switch (type) {
case VG_FLAGS:
return _vg_flags;
case PV_FLAGS:
return _pv_flags;
case LV_FLAGS:
return _lv_flags;
}
log_error(INTERNAL_ERROR "Unknown flag set requested.");
return NULL;
}
/*
* Converts a bitset to an array of string values,
* using one of the tables defined at the top of
* the file.
*/
int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint64_t status)
{
2001-12-31 18:14:44 +03:00
int f, first = 1;
2010-01-07 17:47:57 +03:00
const struct flag *flags;
2008-01-30 16:19:47 +03:00
if (!(flags = _get_flags(type)))
return_0;
2003-09-18 00:35:57 +04:00
if (!emit_to_buffer(&buffer, &size, "["))
return_0;
for (f = 0; flags[f].mask; f++) {
if (status & flags[f].mask) {
2004-05-05 22:15:47 +04:00
status &= ~flags[f].mask;
if (mask != flags[f].kind)
continue;
2004-05-05 22:15:47 +04:00
/* Internal-only flag? */
if (!flags[f].description)
continue;
2001-12-20 14:52:54 +03:00
if (!first) {
2003-09-18 00:35:57 +04:00
if (!emit_to_buffer(&buffer, &size, ", "))
return_0;
2001-12-20 14:52:54 +03:00
} else
first = 0;
2004-05-05 22:15:47 +04:00
if (!emit_to_buffer(&buffer, &size, "\"%s\"",
flags[f].description))
return_0;
}
}
2003-09-18 00:35:57 +04:00
if (!emit_to_buffer(&buffer, &size, "]"))
return_0;
if (status)
log_warn(INTERNAL_ERROR "Metadata inconsistency: "
"Not all flags successfully exported.");
return 1;
}
int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm_config_value *cv)
{
unsigned f;
uint64_t s = UINT64_C(0);
2010-01-07 17:47:57 +03:00
const struct flag *flags;
2008-01-30 16:19:47 +03:00
if (!(flags = _get_flags(type)))
return_0;
if (cv->type == DM_CFG_EMPTY_ARRAY)
2002-11-18 17:04:08 +03:00
goto out;
2002-11-18 17:04:08 +03:00
while (cv) {
if (cv->type != DM_CFG_STRING) {
log_error("Status value is not a string.");
2002-11-18 17:04:08 +03:00
return 0;
}
/*
* For a short time CACHE_VOL was a STATUS_FLAG, then it
* was changed to COMPATIBLE_FLAG, so we want to read it
* from either place.
*/
if (type == LV_FLAGS && !strcmp(cv->v.str, "CACHE_VOL"))
mask = (STATUS_FLAG | COMPATIBLE_FLAG);
for (f = 0; flags[f].description; f++) {
if ((flags[f].kind & mask) &&
!strcmp(flags[f].description, cv->v.str)) {
2002-11-18 17:04:08 +03:00
s |= flags[f].mask;
break;
}
}
if (type == VG_FLAGS && !strcmp(cv->v.str, "PARTIAL")) {
/*
* Exception: We no longer write this flag out, but it
* might be encountered in old backup files, so restore
* it in that case. It is never part of live metadata
* though, so only vgcfgrestore needs to be concerned
* by this case.
*/
s |= PARTIAL_VG;
} else if (!flags[f].description && (mask & STATUS_FLAG)) {
log_error("Unknown status flag '%s'.", cv->v.str);
2002-11-18 17:04:08 +03:00
return 0;
}
2002-11-18 17:04:08 +03:00
cv = cv->next;
}
2002-11-18 17:04:08 +03:00
out:
*status |= s;
return 1;
}
/*
* Parse extra status flags from segment "type" string.
* These flags are seen as INCOMPATIBLE by any older lvm2 code.
* All flags separated by '+' are trimmed from passed string.
* All UNKNOWN flags will again cause the "UNKNOWN" segtype.
*
* Note: using these segtype status flags instead of actual
* status flags ensures wanted incompatiblity.
*/
int read_segtype_lvflags(uint64_t *status, char *segtype_str)
{
unsigned i;
const struct flag *flags = _lv_flags;
char *delim;
char *flag, *buffer, *str;
if (!(str = strchr(segtype_str, '+')))
return 1; /* No flags */
if (!(buffer = strdup(str + 1))) {
log_error("Cannot duplicate segment string.");
return 0;
}
delim = buffer;
do {
flag = delim;
if ((delim = strchr(delim, '+')))
*delim++ = '\0';
for (i = 0; flags[i].description; i++)
if ((flags[i].kind & SEGTYPE_FLAG) &&
!strcmp(flags[i].description, flag)) {
*status |= flags[i].mask;
break;
}
} while (delim && flags[i].description); /* Till no more flags in type appear */
if (!flags[i].description)
/* Unknown flag is incompatible - returns unmodified segtype_str */
log_warn("WARNING: Unrecognised flag %s in segment type %s.",
flag, segtype_str);
else
*str = '\0'; /* Cut away 1st. '+' */
free(buffer);
return 1;
}
int print_segtype_lvflags(char *buffer, size_t size, uint64_t status)
{
unsigned i;
const struct flag *flags = _lv_flags;
buffer[0] = 0;
for (i = 0; flags[i].mask; i++)
if ((flags[i].kind & SEGTYPE_FLAG) &&
(status & flags[i].mask) &&
!emit_to_buffer(&buffer, &size, "+%s",
flags[i].description))
return 0;
return 1;
}