| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
| |
|
| |
|
|
|
|
|
|
|
| |
The vg_strip_outdated_former_lvs iterates over the list of former LVs
we have and it shoots down the ones which are outdated.
Configuration hook to set the timeout will be in subsequent patch.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When lvremove is used together with -r|--removed switch, former LVs
are processed as well. This allows for removing former LVs from history.
For example, we have lvol1 --> lvol2 --> lvol3 thin snapshot chain at
the beginning:
$ lvs -o name,name_removed,full_ancestors,full_descendants -O removed vg
LV RLV FAncestors FDescendants
pool
lvol1 lvol2,lvol3
lvol2 lvol1 lvol3
lvol3 lvol2,lvol1
Then we remove the lvol2 which is then recorded as former LV -rlvol0:
$ lvremove -ff vg/lvol2
Logical volume "lvol2" successfully removed
$ lvs -r -o name,name_removed,full_ancestors,full_descendants -O removed vg
LV RLV FAncestors FDescendants
pool
lvol1 -rlvol0,lvol3
lvol3 -rlvol0,lvol1
-lvol2 -rlvol0 lvol1 lvol3
Without the -r|--removed switch, removed entities are not processed and
they're simply not visible to the command:
$ lvremove -ff vg/-rlvol0
Failed to find logical volume "vg/-rlvol0"
With lvremove used together with the -r|--removed switch, we can removed
items from history:
$ lvremove -r -ff vg/-rlvol0
former logical volume "rlvol0" successfully removed
The indirect origin/indirect users relation is still kept though, we
just don't see the history of what was in between there before:
$ lvs -r -o name,name_removed,full_ancestors,full_descendants -O removed vg
LV RLV FAncestors FDescendants
pool
lvol1 lvol3
lvol3 lvol1
|
|
|
|
| |
Add former_glv_remove function to add support for removing former LVs from history.
|
|
|
|
|
|
|
|
|
| |
The metadata/record_former_entities is global switch which enables or
disables recording former entities (like former LVs) in metadata.
If both metadata/record_former_entities=1 lvm.conf option and
--nohistory command switch is used at the same time, the --nohistory
prevails.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
For example, we have lvol1 --> lvol2 --> lvol3 thin snapshot chain where
lvol2 has been removed with the --nohistory option:
$ lvs -o name,name_removed,full_ancestors,full_descendants -O removed vg
LV RLV FAncestors FDescendants
pool
lvol1 lvol2,lvol3
lvol2 lvol1 lvol3
lvol3 lvol2,lvol1
$ lvremove -ff --nohistory vg/lvol2
Logical volume "lvol2" successfully removed
$ lvs -o name,name_removed,full_ancestors,full_descendants -O removed vg
LV RLV FAncestors FDescendants
pool
lvol1 lvol3
lvol3 lvol1
|
|
|
|
|
|
|
| |
When --nohistory switch is used, the LV that is removed is not recorded
in metadata as 'former LV'. We still keep the "indirect_origin" and
"indirect_glvs" relations complete though even if don't keep the former
LVs in history.
|
|
|
|
|
| |
The --nohistory switch will cause former LVs to not be recorded
in metadata on demand.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
that way
Report proper values for former LVs in lv_layout and lv_role fields.
Any former LV doesn't have any layout anymore and the role is "history".
For example:
$ lvs -r -o name,name_removed,layout,role vg
LV RLV Layout Role
-lvol2 -rlvol0 none public,history
lvol1 thin,sparse public
lvol3 thin,sparse public
pool thin,pool private
|
|
|
|
|
|
|
|
|
|
| |
Former LVs do not have any segments attached anymore - we can't report
anything that is segment-related for these volumes so do not allow
reporting segment fields while former LVs are also processed.
We could report former LVs together with segment fields if we created
dummy lv_segment for such removed volumes, but let's add this later when
someone asks for this...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Same as lv_full_ancestors, but the other way round in the ancestry chain.
For example, we have lvol1 --> lvol2 --> lvol3 thin snapshot chain where
lvol2 has been removed (we're using -O removed here to place the removed
entries at the end of the report for clarity):
$ lvs -r -o name,name_removed,ancestors,full_ancestors,descendants,full_descendants -O removed vg
LV RLV Ancestors FAncestors Descendants FDescendants
pool
lvol1 -rlvol0,lvol3
lvol3 -rlvol0,lvol1
-lvol2 -rlvol0 lvol1 lvol3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The lv_full_ancestors reporting field is just like the existing lv_ancestors
field but it also takes into account any history and indirect relations
recorded.
For example, we have lvol1 --> lvol2 --> lvol3 thin snapshot chain where
lvol2 has been removed (we're using -O removed here in the report to place
the removed entries at the end of the report for clarity):
$ lvs -r -o name,name_removed,ancestors,full_ancestors -O removed vg
LV RLV Ancestors FAncestors
pool
lvol1
lvol3 -rlvol0,lvol1
-lvol2 -rlvol0 lvol1
|
|
|
|
|
|
|
| |
All names for former LVs are prefixed with '-' character to make clear
difference between live and former LVs. The '-' can't be set by users
for LV names during lvcreate hence we never get into a conflict with
the names that user defines for live LVs.
|
|
|
|
|
| |
The 'former' state is displayed as 5th bit ("state") in the lv_attr field
and denoted by new 'f' character.
|
|
|
|
|
|
| |
The lv_former reporting field is a simple binary field that reports
whether an LV is former one ("former" value or value of "1" displayed)
or not (blank string "" or value of "0" displayed).
|
|
|
|
|
| |
When lvs command is used together with the -r|--removed switch,
all former LVs are reported as well.
|
|
|
|
| |
former LVs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When processing LVs in a VG and when the -r|--removed switch is used,
make process_each_lv_in_vg to iterate over former volumes too.
For each former LV, we use dummy struct logical_volume instance with
the "this_glv" reference set to a wrapper over proper struct
former_logical_volume representation. This makes it possible to process
former LVs just like normal live LVs (though a dummy one without any
segments and all the other fields zeroed and blank) and it also allows
for using all former LV related information via lv->this_glv->former
reference.
One can use a simple call to lv_is_former to make a difference between
live and former LV in the code which is called by process_each_* fns.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
processing_handle
This patch adds "include_former_entities" field to struct cmd_context to
make it possible for the command to switch between original funcionality
where no former entities are processed and functionality where former entities
are taken into account (and reported or processed further). The switch
between these modes is done using the '-r|--removed' switch on command
line.
The include_former_entities state is then passed to process_each_* fns
using the "include_former_entities" field within struct processing_handle.
|
| |
|
|
|
|
|
|
|
| |
with live ancestors
Interconnect former LVs in an ancestry chain and also connect the last one
with its live ancestor if it exists.
|
|
|
|
|
|
| |
Look for thin LV segment's indirect_origin field value and if found,
look for the appropriate former LV in VG's former_lvs list and passt
this former LV to attach_thin_pool fn to make the proper interconnection.
|
|
|
|
|
|
|
|
| |
indirect origin
Add support for making an interconnection between thin LV segment and
its indirect origin (which may be former or live LV) - add a new
"indirect_origin" argument to attach_pool_lv function.
|
|
|
|
|
| |
The find_former_glv is helper function that looks up former LV in
struct volume_group's former_lvs list and returns it if found.
|
|
|
|
|
| |
Import former LV list from metadata and add it to struct volume_group's
former_lvs list.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Also export former LVs when exporting LVM2 metadata,
that is the list of all former LVs in "former_logical_volumes" section
in metadata with all the properties exported and also the indirect_origin
field within LV segment if there's any.
For example, we had this thin snapshot sequence:
lvol1 --> lvol2 --> lvol3 --> lvol4,
Then by removing lvol2 and lvol3, we end up with these metadata:
vg {
...
logical_volumes {
lvol1 {
...
}
lvol4 {
segment1 {
...
indirect_origin = "-lvol3"
}
}
...
}
former_logical_volumes {
lvol2 {
id = "haUJg1-uNty-MdjT-hPV1-Em7P-Chby-ZQZ2pO"
creation_time = 1441095024 # 2015-09-01 10:10:24 +0200
removal_time = 1441095031 # 2015-09-01 10:10:31 +0200
indirect_origin = "lvol1"
}
lvol3 {
id = "RGCc5H-SmW3-etIB-TE9q-oc2e-FAal-TjcvXv"
creation_time = 1441095025 # 2015-09-01 10:10:25 +0200
removal_time = 1441095032 # 2015-09-01 10:10:32 +0200
indirect_origin = "-lvol2"
}
}
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
LVs to track history
When an LV is being removed, we create an instance of
"struct former_logical_volume" wrapped up in "struct generic_logical_volume".
All instances of "struct former_logical_volume" are then recorded in "former_lvs"
list which is part of "struct volume_group".
The "former LV" is then interconnected with "live LVs" (the ones
which are not removed yet) like this:
"g" stands for "this logical_volume is wrapped with struct generic_logical_volume"
"seg" stands for "representative segment is chosen for this logical_volume"
* Simple example:
g(liveLV1) --(indirects_glvs)--> g(formerLV2) --(indirects_glvs)--> g(liveLV3)
g(liveLV1) <--(indirect_origin)-- g(formerLV2) <--(indirect_origin)-- seg(liveLV3)
* Example with more former LVs:
g(liveLV1) --(indirects_glvs)--> g(formerLV2) --(indirects_glvs)--> g(formerLV3)--(indirects_glvs)--> g(liveLV4)
g(liveLV1) <--(indirect_origin)-- g(formerLV2) <--(indirect_origin)-- g(formerLV3) <--(indirect_origin)-- seg(liveLV4)
* Or with branches:
g(liveLV1) --(indirects_glvs)--> g(formerLV2A) --(indirects_glvs)--> g(formerLV3A) --(indirects_glvs)--> g(liveLV4A)
\
-> g(formerLV2B) --(indirects_glvs)--> g(formerLV3BA) --(indirects_glvs)--> g(liveLV4BA)
\
-> g(formerLV3BB) --(indirects_glvs)--> g(liveLV4BB)
g(liveLV1) <--(indirect_origin)-- g(formerLV2A) <--(indirect_origin)-- g(formerLV3A) <--(indirect_origin)-- seg(liveLV4A)
\
-(indirect_origin)-- g(formerLV2B) <--(indirect_origin)-- g(formerLV3BA) <--(indirect_origin)-- seg(liveLV4BA)
\
-(indirect_origin)-- g(formerLV3BB) <--(indirect_origin)-- seg(liveLV4BB)
* Or simple example when former LV is not remembered in records (compare with first "Simple example"):
g(liveLV1) --(indirects_glvs)--> g(liveLV3)
g(liveLV1) <--(indirect_origin)-- seg(liveLV3)
|
|
|
|
|
|
|
|
|
| |
The add_glv_to_indirect_glvs is a helper function that registers a volume
represented by struct generic_logical_volume instance ("glv") as an indirect
user of another volume ("origin_glv") and vice versa - it also registers the
other volume ("origin_glv") as indirect_origin of user volume ("glv").
The remove_glv_from_indirect_glvs does the opposite.
|
|
|
|
|
|
|
|
|
| |
The get_or_create_glv is a helper function that retrieves any existing
generic_logical_volume wrapper for the LV. If the wrapper does not exist
yet, it's created.
The get_org_create_glvl is the same as get_or_create_glv but it creates
the glv_list wrapper in addition so it can be added to a list.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add new structures and new fields in existing structures to support
tracking history of former LVs (the LVs which don't exist - they were
removed):
- new "struct former_logical_volume"
This structure keeps information specific to former LVs (former LV is
very reduced form of struct logical_volume + it contains a few specific
fields to track former LVs).
- new "struct generic_logical_volume"
Wrapper for "struct former_logical_volume" and "struct logical_volume"
to make it possible to handle the volume in uniform way, no matter
if it's live or former.
- new "struct glv_list"
Wrapper for "struct generic_logical_volume" so it can be added to a
list.
- new "indirect_glvs" field in "struct logical_volume"
List that stores references to all indirect users of this LV - this
interconnects live LV with former descendant LVs or even live descendant
LVs in case we're not storing history of former LVs but we still
want to keep the ancestry chain tracked even after an LV was
removed in the middle of this chain.
- new "indirect_origin" field in "struct lv_segment"
Reference to indirect origin of this segment - this interconnects
live LV (segment) with former ancestor or even live ancestor
in case we're not storing history of former LVs but we still
want to keep the ancestry chain tracked even after an LV was
removed in the middle of this chain.
- new "this_glv" field in "struct logical_volume"
This references an existing generic_logical_volume wrapper for this
LV, if used. It can be NULL if not needed - which means we're not
handling former LVs at all.
- new "former_lvs" field in "struct volume group
List of all former LVs read from VG metadata.
|
|
|
|
|
|
|
|
| |
When update fails in suspend() (sending of messages
fails because metadata space is full) call resume(),
so the locking sequence works properly for clustering.
Also failing deactivation should unlock memory.
|
|
|
|
| |
The workaround for python3 is no longer needed.
|
|
|
|
| |
Skip part of test when driver is too old.
|
|
|
|
| |
Check status has right type.
|
|
|
|
| |
Test various (D/M/F) attrs for thin-pool/thin
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Fix reporting of Fail thin-pool target status
as attr[8] letter 'F'.
Report 'needs_check' status from thin-pool target via
attr field [4] (letter 'c'/'C'), and also via CheckNeeded field.
TODO: think about better name here?
TODO: lots of prop_not_implemented_set
|
|
|
|
|
| |
When thin-pool is in failed/error state, we can't
read percentage so report invalid value.
|
|
|
|
|
|
|
|
| |
Fix parsing of 'Fail' status (using capital letter) for thin-pool.
Add also parsing of 'Error' state for thin-pool.
Add needs_check test for thin-pool.
Detect Fail state for thin.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
is marked as belonging to a VG
Ask for confirmation when using pvcreate/pvremove on a PV which is
marked as belonging to a VG, just like we do in case of a PV which
belongs to known VG:
$ pvcreate -ff /dev/sda
Really INITIALIZE physical volume "/dev/sda" that is marked as belonging to a VG [y/n]? n
/dev/sda: physical volume not initialized
$ pvremove -ff /dev/sda
Really WIPE LABELS from physical volume "/dev/sda" that is marked as belonging to a VG [y/n]? n
/dev/sda: physical volume label not removed
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
--binary
State:
$ lvs -o lv_name,lv_active_locally,lv_snapshot_invalid,lv_merge_failed vg/lvol0
LV ActLocal SnapInvalid MergeFailed
lvol0 active locally unknown unknown
Now with using --binary switch.
Before this patch (lv_snapshot_invalid and lv_merge_failed not switched into numeric value
where -1 represents 'unknown' value)
$ lvs -o lv_name,lv_active_locally,lv_snapshot_invalid,lv_merge_failed vg/lvol0 --binary
LV ActLocal SnapInvalid MergeFailed
lvol0 1 unknown unknown
With this patch applied:
$ lvs -o lv_name,lv_active_locally,lv_snapshot_invalid,lv_merge_failed vg/lvol0 --binary
LV ActLocal SnapInvalid MergeFailed
lvol0 1 -1 -1
|
|
|
|
| |
Assume that's good enough for older systems.
|
| |
|
| |
|
| |
|