| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
| |
|
|
|
|
|
|
| |
The vg_strip_outdated_dead_lvs iterates over the list of dead LVs
we have and it shoots down the ones which are outdated. The
configuration hook to set the timeout will be in subsequent patch.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When lvremove is used together with -r|--removed switch, dead LVs
are processed as well. This allows for removing dead 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 dead 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
Dead 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 dead_glv_remove function to add support for removing dead LVs from history.
|
|
|
|
|
|
|
|
|
| |
The metadata/record_removed_entities is a global switch which enables or
disables recording removed entities (like dead LVs) in metadata.
If both metadata/record_removed_entities=1 lvm.conf option and
--nohistory command switch is used at the same time, the --nohistory
has higher priority.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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. We still keep the "indirect_origin" and "indirect_users"
relations complete though even if don't keep the dead LVs in history.
|
|
|
|
|
| |
The --nohistory switch will cause removed LVs to not be recorded
in metadata on demand.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
that way
Report proper values for dead LVs in lv_layout and lv_role fields.
Any dead LV doesn't have any layout anymore of course and the role
is set to "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
|
|
|
|
|
|
|
|
|
|
|
|
| |
same time
Removed entries 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 dead LVs are also processed.
We could report removed entries 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 dead LVs are prefixed with '-' character to make a clear
difference between live and dead LVs. The '-' can't be set by users as
LV names directly hence we never get into a conflict with the names that
user defines for live LVs.
For example:
$ lvs -r -o name,name_removed,lv_attr vg/-rlvol0
LV RLV Attr
-lvol2 -rlvol0 ----r-----
|
|
|
|
|
| |
The removed state is displayed as 5th bit ("state") in the lv_attr field
and denoted by new "r" character.
|
|
|
|
|
|
| |
The lv_removed reporting field is a simple binary field that reports
whether an LV is removed ("removed" 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 the dead LVs are reported as well.
|
|
|
|
| |
dead LVs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When processing LVs in a VG and when the -r|--removed switch is used,
make process_each_lv_in_vg to iterate over dead volumes too.
For each dead LV, we use a dummy struct logical_volume instance with
the "this_glv" reference set to a wrapper over proper struct
dead_logical_volume representation. This makes it possible to process
dead LV 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 dead LV related information via lv->this_glv->dead
reference.
One can use a simple call to lv_is_dead to make a difference between
live and dead LV in the code which is called by process_each_* fns.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
processing_handle
This patch adds "include_dead_entities" field to struct cmd_context to
make it possible for the command to switch between original funcionality
where no dead entities are processed and functionality where dead 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_dead_entities state is then passed to process_each_* fns
using the "include_dead_entities" field within struct processing_handle.
|
| |
|
|
|
|
|
|
|
| |
live ancestors
Interconnect dead 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 dead LV in VG's dead_lvs list and pass this
dead 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 dead or live LV) - add a new
"indirect_origin" argument to attach_pool_lv function.
|
|
|
|
|
| |
The find_dead_glv is a helper function that looks up dead LV in
struct volume_group's dead_lvs list and returns it if found.
|
|
|
|
|
| |
Import dead LV list from metadata and add it to struct volume_group's
dead_lvs list.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Also export dead LVs when exporting LVM2 metadata,
that is the list of all dead LVs in "removed_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 = "-rlvol1"
}
}
...
}
removed_logical_volumes {
rlvol0 {
id = "haUJg1-uNty-MdjT-hPV1-Em7P-Chby-ZQZ2pO"
name = "lvol2"
creation_time = 1441095024 # 2015-09-01 10:10:24 +0200
removal_time = 1441095031 # 2015-09-01 10:10:31 +0200
indirect_origin = "lvol1"
}
rlvol1 {
id = "RGCc5H-SmW3-etIB-TE9q-oc2e-FAal-TjcvXv"
name = "lvol3"
creation_time = 1441095025 # 2015-09-01 10:10:25 +0200
removal_time = 1441095032 # 2015-09-01 10:10:32 +0200
indirect_origin = "-rlvol0"
}
}
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
LVs to track history
When an LV is being removed, we create an instance of
"struct dead_logical_volume" wrapped up in "struct generic_logical_volume".
All instances of "struct dead_logical_volume" are then recorded in "dead_lvs"
list which is part of "struct volume_group".
The "dead 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) --(indirect_users)--> g(deadLV2) --(indirect_users)--> g(liveLV3)
g(liveLV1) <--(indirect_origin)-- g(deadLV2) <--(indirect_origin)-- seg(liveLV3)
* Example with more dead LVs:
g(liveLV1) --(indirect_users)--> g(deadLV2) --(indirect_users)--> g(deadLV3)--(indirect_users)--> g(liveLV4)
g(liveLV1) <--(indirect_origin)-- g(deadLV2) <--(indirect_origin)-- g(deadLV3) <--(indirect_origin)-- seg(liveLV4)
* Or with branches:
g(liveLV1) --(indirect_users)--> g(deadLV2A) --(indirect_users)--> g(deadLV3A) --(indirect_users)--> g(liveLV4A)
\
-> g(deadLV2B) --(indirect_users)--> g(deadLV3BA) --(indirect_users)--> g(liveLV4BA)
\
-> g(deadLV3BB) --(indirect_users)--> g(liveLV4BB)
g(liveLV1) <--(indirect_origin)-- g(deadLV2A) <--(indirect_origin)-- g(deadLV3A) <--(indirect_origin)-- seg(liveLV4A)
\
-(indirect_origin)-- g(deadLV2B) <--(indirect_origin)-- g(deadLV3BA) <--(indirect_origin)-- seg(liveLV4BA)
\
-(indirect_origin)-- g(deadLV3BB) <--(indirect_origin)-- seg(liveLV4BB)
* Or simple example when dead LV is not remembered in records (compare with first "Simple example"):
g(liveLV1) --(indirect_users)--> g(liveLV3)
g(liveLV1) <--(indirect_origin)-- seg(liveLV3)
|
|
|
|
|
|
|
|
|
|
|
|
| |
removed_glv_from_indirect_user_list fns
The add_glv_to_indirect_user_list is a helper function that registers
a volume represented by struct generic_logical_volume instance ("user_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 ("user_glv").
The remove_glv_from_indirect_user_list 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.
|
|
|
|
|
|
|
|
| |
Dead LVs have generated name "rlvolN" where N is the number that is
assigned automatically so the name is unique in the VG.
This is exactly the same naming scheme as used for automatic naming
for live LV names, but it has the "r" prefix in addition.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add new structures and new fields in existing structures to support
tracking of dead LVs:
- new "struct dead_logical_volume"
This structure keeps information specific to dead LVs (it's actually
very reduced form of struct logical_volume + it contains a few specific
fields to track dead LVs).
- new "struct generic_logical_volume"
Wrapper for "struct dead_logical_volume" and "struct logical_volume"
to make it possible to handle the volume in uniform way, no matter
if it's alive or dead.
- new "struct glv_list"
Wrapper for "struct generic_logical_volume" so it can be added to a
list.
- new "indirect_users" field in "struct logical_volume"
List that stores references to all indirect users of this LV - this
interconnects live LV with dead descendants or even live descendants
in case we're not storing history of dead LVs.
- new "indirect_origin" field in "struct lv_segment"
Reference to indirect origin of this segment - this interconnects
live LV (segment) with dead ancestor or even live ancestor in case
we're not storing history of dead LVs.
- new "this_glv" field in "struct logical_volume"
This references an existing generic_logical_volume wrapper for this
LV, if used.
- new "dead_lvs" field in "struct volume group
List of all dead LVs read from VG metadata.
|
|
|
|
|
|
|
|
|
| |
We already do check for suspended devs within udev rules where
the pvscan is to update lvmetad. So the check for suspended devs
in "pre-lvmetad" chain is not useful here - remove it - it may
be a source of hardly to detect races anyway (if udev rule detects
the device is not suspended and then the pvscan instance sees the
dev as suspended, we may end up not reacting to the event properly).
|
|
|
|
|
|
|
|
|
|
|
|
| |
lvm1 and pool label
lvm1 and pool format do not support bootloader areas and we need to
remove any existing associated bootloader areas when we read lvm1 and
pool labels.
This has its importance if we're converting from one format to another
and we're reusing lvmcache in long-running commands (e.g. clvmd or lvm
shell) and we need to make lvmcache consistent and valid for current format.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
external_device_info_source="udev" and blkid<2.20
Non-dm devices have ID_PART_TABLE_TYPE variable exported in
udev db from blkid scan for *both* whole devices and partitions.
We used ID_PART_ENTRY_DISK in addition to decide whether this
is the whole device or partition and then we filtered out only
whole devices where the partition table really is.
However, ID_PART_ENTRY_DISK was added in blkid 2.20 so we need
to use a different set of variables to decide on whole devices
and partitions on systems where older blkid is still used.
Now, we use ID_PART_TABLE_TYPE to detect that there's something
related to partitioning with this device and we use DEVTYPE variable
instead to decide between whole device (DEVTYPE="disk") and partition
(DEVTYPE="partition").
For dm devices it's simpler, we have ID_PART_TABLE_TYPE variable\
set in udev db for whole devices. It's not set for partitions,
hence we don't need more variable in addition to make the decision
on whole device vs. partition (dm devices do not have regular
partitions, hence DEVTYPE can't be used anyway, it's always set
to "disk" for whole disks and partitions).
|
|
|
|
|
| |
When built without dlm or sanlock support, don't
attempt to adopt locks from that lm.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add "size" and "size_seqno" to struct device to cache device's size
and also to control its lifetime - the cached value is valid as long
as the global _dev_size_seqno is equal to the device's size_seqno,
otherwise we need to get the size again and cache the new value.
This patch also adds new dev_size_seqno_inc() fn for the appropriate
parts of the code to increment current global value of _dev_size_seqno
and hence to cause all currently cached values for device sizes to
be invalidated.
The device size is now cached because we're planning to reuse this
information for further checks and we want to avoid checking it more
than necessary to save resources.
|
|
|
|
|
| |
The debug message appeared even when lvmlockd was not used,
and the lockd operation was simply being skipped.
|
|
|
|
| |
PV uuid change
|
|
|
|
|
| |
Commit 2304286f68debd4755b44fa8b779b762142bfada
missed to add function prototype.
|
|
|
|
|
|
|
| |
Fix regression caused by c9f021de0b4d2c873ef5b97d17c602d0380359fd.
This commit actually transfered real-action (e.g. device removal)
into the next loop which has however missed to check for break.
So add check for break also there.
|
|
|
|
|
|
|
| |
When creating a list in 'context of command' - use proper mempool.
vg->vgmem is mempool related to VG metadata - and can be eventually
locked read-only when VG struct is shared.
|
|
|
|
|
| |
Hmm rpmlint suggest fsf is using a different address these days,
so lets keep it up-to-date
|