1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-26 08:55:06 +03:00

Compare commits

...

75 Commits

Author SHA1 Message Date
Jack Wilsdon
95bfcd8118 libdaemon: fix suppressing stray fd warnings 2024-10-26 01:06:09 +01:00
Heinz Mauelshagen
708435d187 man: lvchange update about --syncaction being transient 2024-10-25 22:03:18 +02:00
Zdenek Kabelac
034b6a262c WHATS_NEW: update 2024-10-25 15:08:03 +02:00
Zdenek Kabelac
143545a08c lvmlockd: fix incorrect function definition
In commit 7f29afdb06 this function
was added with misplaced ';'.
2024-10-25 15:08:03 +02:00
Zdenek Kabelac
c8a8c7286f tests: add test to resize to same size
Check that 'lvresize/extend -r' resizing to the same size is
doing the fs resize.
2024-10-25 15:08:03 +02:00
Zdenek Kabelac
5a293968ec lvresize: fix regression when resizing with fs
When 'lvresize -r' is used to resize the volume, it's valid to
resize even to the same size of an LV, as the command then runs
fs-resize utility to eventually upsize the fs to the current
volume size.

Return code of such command then reflects the return value
of this fs-resize tool.

This fixes the regression introduced when the support
for option --fs was added (2.03.17).
2024-10-25 15:06:39 +02:00
Peter Rajnoha
43ce78e5c6
tests: lvresize-fs: check blkid version for lvresize with swap test 2024-10-25 13:21:57 +02:00
Peter Rajnoha
aa0200c3ff
dev-type: update comment about swap info from blkid 2024-10-25 12:53:07 +02:00
Zdenek Kabelac
40010e3eb8 clang: close file on memory alloc error path 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
ebc5c0cb1d clang: check for dirfd result 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
0fbcb3b308 clang: check segment lv is defined 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
5ec8f744d0 clang: ensure pointer is defined
Check for new_segtype and lv is defined
before dereferencing.
2024-10-25 01:26:40 +02:00
Zdenek Kabelac
ea4daeb28e cov: use 64bit arithmentic 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
1363a5ffb2 cov: ensure detached_log_lv exists before use 2024-10-25 01:26:40 +02:00
Zdenek Kabelac
5a3375f958 debug: use major:minor
Print major:minor as in other places.
2024-10-25 01:26:40 +02:00
Zdenek Kabelac
edfa4955d8 device_id: close only opened dir
After more of opendir, make sure 'dir' is closed
only when it's been opened.
2024-10-25 01:26:40 +02:00
Zdenek Kabelac
a5e3f0e6dd metadata: check for mda_device existance 2024-10-25 01:26:39 +02:00
Zdenek Kabelac
f61572eef2 dev-cache: ensure list has elements
When updating DM cache, check whether the list even has entries
before comparing it with old cached instance.
2024-10-25 01:26:39 +02:00
Zdenek Kabelac
87f68f443c metadata: fallback search without radix_tree
If we use some dummy vg struct, allow fallback
plain dm_list search.
2024-10-25 01:26:39 +02:00
Zdenek Kabelac
7d48c1f6e3 device_mapper: add omitted error message 2024-10-25 01:26:39 +02:00
Zdenek Kabelac
188dd3c357 device_mapper: check for pv before use in error msg 2024-10-25 01:26:39 +02:00
David Teigland
875012fb5d lvmlockd: enable lockopt nodelay for lockstart
Avoid the sanlock add_lockspace delay in vgchange --lockstart
by adding --lockopt nodelay.  This is for testing, and is not
safe to use in general.
2024-10-24 17:15:16 -05:00
Zdenek Kabelac
77332669d0 WHATS_NEW: update 2024-10-24 21:38:35 +02:00
long.yunjian@zte.com.cn
639fb633d3 cleanup: correct invalid function
Use proper function names in annotation

There are no fuction named print_common_options_cmd()
and print_common_options_lvm(). So, rename them to the
real function named print_usage_common_cmd() and
print_usage_common_lvm().

Signed-off-by: YunJian Long
2024-10-24 21:38:06 +02:00
Zdenek Kabelac
9295de7cea tests: do not use shell pipe for reshape_len
Tricky one - as the pipe exit codes may result into whole
test failure depending on how quick/slow command exits
are within pipeline.

So get the len without piping.
2024-10-24 21:24:26 +02:00
Zdenek Kabelac
2c5bf25187 devicesfile: move opendir after fclose
Call opendir() after new file is stored within dir,
otherwise this new file would not accounted.
2024-10-24 21:24:26 +02:00
Zdenek Kabelac
b88cbc7f17 metadata: missed lv_set_name users
Missed when introduced lv_set_name().
2024-10-24 21:24:26 +02:00
Zdenek Kabelac
c27d6695c1 lv: add lv_set_vg
To keep vg->lv_names up-to-date also for merge & split,
add function lv_set_vg() the will update also radix tree
reference for a VG.
2024-10-24 21:23:49 +02:00
Zdenek Kabelac
73c7dac1a8 WHATS_NEW: update 2024-10-24 17:38:09 +02:00
Zdenek Kabelac
21517c2bd5 metadata: use radix tree to find lv_names
Replace usage of dm_hash with radix_tree to quickly find LV name
with a vg and also index PV names with set of available PVs.
This PV index is only needed during the import, but instead
of passing 'radix_tree *' everywhere, just keep this within
a VG struct as well and once the parsing is finished, release
this PV index radix_tree.

This also makes it easier to replace this structure
in the future if needed.

lv_set_name now uses  radix_tree remove+insert to keep lv_names
tree in-sync and usable for  find_lv queries.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
1825e782cc revert "metadata: use lv_hash in segment-specific metadata parsing"
This reverts commit f42aef4706.

Going to replace dm_hash with radix_tree and use 'find_lv()'
to abstract lookup for LV with VG.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
956b2c568f metadata: use lv_set_name for raid and mirror
Use lv_set_name API also for raid and mirror LV manipulation.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
c681d4e61a metadata: add lv_set_name
Add function to set lv->name.
Also when creating empty LV, first add this LV
to linked list in a VG and just after that allocate lv name.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
73f24443e5 check_pv_segments: resolve pv name once 2024-10-24 17:38:09 +02:00
Zdenek Kabelac
eb4b307d0c log: postpone some initialization
Clear buffers when really logging.
2024-10-24 17:38:09 +02:00
Zdenek Kabelac
dee8bc9ae4 lv_manip: remove duplicate check for max lv
This check is always performed with call to link_lv_to_vg().
2024-10-24 17:37:30 +02:00
Zdenek Kabelac
d62170d646 flags: drop no longer needed header
After code refactoring, this header is not needed here anymore.
2024-10-24 17:35:33 +02:00
Zdenek Kabelac
668c185949 vg_validate: use uniq_insert
Enhance usage with uniq_insert and also try to better
utilize CPU cache and do a smaller loop for individual
hashing of lvname and separately lvid.

Also correcting usage of 'continue' within validation of
historical names as it should report as much errors
as it can within a loop.
2024-10-24 17:35:33 +02:00
Zdenek Kabelac
0852c3171d tests: unit test for uniq insert into radix_tree 2024-10-24 17:35:33 +02:00
Zdenek Kabelac
5b1ebed3fc radix_tree: add radix_tree_uniq_insert
When using radix_tree to identify duplicate entries we may
avoid to call an extra 'lookup()' prior the insert() operation
add radix_tree_uniq_insert/_ptr() that is able to report -1 if
there was already set a value for the given key.
2024-10-24 17:24:40 +02:00
Zdenek Kabelac
dd856edaab vgcfgrestore: validate complete VG
Avoid finding problems in vg_validate when restoring
invalid VG metadata as that would lead to internal error.
i.e. adding unsupported METADATA_FLAG to zero segtype
can trigger such thing.
2024-10-23 20:16:14 +02:00
Zdenek Kabelac
2916a8a1f3 read_lvflags: keep flag reading focused on flags
Previous update needed to add handling segtype within flag.c
which somewhat breaks API separition and also had bug in hanlding
actual flags.

So instead keep segtype code in _read_segtype_and_lvflags() within
import_vsn1.c and handle purly flags in read_lvflags() from const
string.
2024-10-23 20:16:14 +02:00
Zdenek Kabelac
1f0530919e export: typo with buffer zeroing
Lost '= 0' in cut & paste.
Also get rid of no longer needed 'goto' section.
2024-10-23 20:15:48 +02:00
Zdenek Kabelac
ea39c58127 export: add missed buffer initialization
Since we reduced emitting to single string list,
we need to make sure empty list are not producing
garbage strings.
2024-10-23 14:38:21 +02:00
Zdenek Kabelac
056ad4a8f4 WHATS_NEW: update 2024-10-23 14:10:46 +02:00
Zdenek Kabelac
e0421ee7bf export: change to read_segtype_and_lvflags
Instead of duplicating whole segtype string with flags and
using 2 calls read_segtype_lvflags() + get_segtype_from_string(),
merge the functionality into a single read_segtype_and_lvflags().
This allows to make only a local string copy (no allocs) and eventually
to not copy segtype string at all, when there are no flags.
2024-10-23 14:10:46 +02:00
Zdenek Kabelac
4929c55bc5 export: reduce emit_to_buffer calls
As the 'emit_to_buffer' uses relatively complex
vsnprintf() call inside, try to reduce number
of unnecessary calls and try replace some more
complex string build with a single call instead.
2024-10-23 14:10:46 +02:00
Zdenek Kabelac
7156b4930d dev-cache: enhance usability of dm cache
With existing code, the cache was working only to the 2nd. locking.
So i.e. when 'lvs' scans system with more then one VG, the caching
was effectively not working.

Update the code, so the label invalidate code is able to update DM
cache - so whenever we take a new lock - we will refresh the cache.

TODO: the refresh ATM does a very simple compare of old a new list
of cached DM device, and with the first spotted difference, it just
fallback to the full rebuild of DM cache - with large amount of active
devices this might not the most efficient way....
2024-10-23 14:10:35 +02:00
Zdenek Kabelac
96cea466a5 tests: skip test for too old sfdisk 2024-10-22 22:30:47 +02:00
Zdenek Kabelac
0f793fcbca check_lv_segment: correct last change
Previous commit 7c5cca600c
was not correctly aliging block that was checking mirrors.
2024-10-22 22:25:54 +02:00
Zdenek Kabelac
5666728b27 WHATS_NEW: update 2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d121707ffa debug: drop stack 2024-10-22 19:36:00 +02:00
Zdenek Kabelac
c19dfe11a5 debug: use just LV name for debug message
Since we detect 'debug' level after calling 'log_debug()' - all
the arguments are evaluated, so in this case display_lvname() was
preparing a string that is not used in case debugging is not enabled.

So since these string are on 'hot-path' and it's already known
which VG is being worked on, in these few cases just use lv->name.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
ccd693d065 reporting: prepare id string only for json output
When processing LVs for a command we stored  '*object_id' & '*group_id'
as printable string that was however only used with json reporting.

Refactor code so we simply store there 'struct id*' that is just
converted into printable string when json reporting is really used.

Also check for 'sigint()' right before loop processing begins which
is primary purpose of this test.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
34b5d7f8bd vg_validate: use radix_tree
Replace dm_hash with radix_tree which uses less memory
and gives same performance.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
5827c9e337 config: use dm_config_parse_only_section 2024-10-22 19:36:00 +02:00
Zdenek Kabelac
5d2d3c53a4 device_mapper: add dm_config_parse_only_section
This function call is able to setup config parser so it stops
parsing 'subsection' nodes after parsing named section node.
Only nodes at 'level' 0 will be still processed. And this nodes
are found by searching for last  \n}\n sequence from the end of
buffer   (instead of trying to analyze all the text in buffer).
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
4dc0ee8e56 export: use radix_tree for write formatter
Replace use of dm_hash with radix_tree when making PV index names.

Store just the index number itself and use pv%d for outf() string.

For lookup up a PV - use just the PV pointer itself, it's faster then
converint for it's ID to UUID format.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
7c5cca600c check_lv_segment: split into incomplete complete
Split single check_lv_segments() into 2 separate
versions so they can be called independently.
This allow to 'skip' already checked segment
check after it's been imported to VG and also
avoid another repeated checking when validating
segment with complete vg.

**
check_lv_segments_incomplete_vg()

this check just basic LV segment properties and does not
validate those requiring full VG.

**
check_lv_segments_complete_vg()

Remaining check that expects complete VG is present.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
fa11ef6846 metadata: look for LV by name with find_lv
Avoid getting dm_list reference when looking for logical_volume*.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
1755ceb17c thin: check only for profiled config vars
ATM this rather save a lot of unncessary log entries as it grabs
the global autoextend_threshold (profile == NULL) just once instead
of revealing it every time with NULL profile.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
8fcfac7c89 lv: set creation uses const string
There is no need to duplicate const string we got and keep
from uname() call.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
b4156bb4de export: limit generation of comment strings
Generate comment string only for formatter with comments.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
0179f00e0c import: check fixup mirror only when needed
Track whether import has even seen segment of LV with log_lv,
and call fixup mirror only in this case.

Also avoid repeated lookup of get_segtype_from_string for
SEG_TYPE_NAME_MIRROR.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
89da9ae251 device_mapper: increase mem pool chunk size
Use bigger memory pool chunk size and reduces amount of
memory pool extensions when handling larger metadata, but do not
make it noticable bigger when handling small ones...

Use same large value also when allocating VG memory pool.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
9c9953dc3e device_mapper: join flags checks together
Just use a single bitmask flag check and OR fields together.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
fd9f7d10ca device_mapper: query for json report once
Remember _is_json_report() check for whole function.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
f59fa69507 device_mapper: use on stack allocation
Reduce number of heap allocation calls and for smaller
locally used string, use on stack allocation.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d8996a2a12 device_mapper: store string on stack
Instead of allocating string from a pool, for shorted strings
use buffer on stack since the string after the use in _find_or_make_node()
as no longer needed.
Eventually we may enhance code also for TOK_STRING_ESCAPED and TOK_STRING,
but they appear to be unused for _section().
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
c29e3410c9 device_mapper: slight improvement of tok_match
Reduce amount of unnecessary instructions for some code paths.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
92158a24a5 device_mapper: optimize _get_token
For the most common part check for '#' when it's known it's not a space.
And also when we checked for '\n' we dont need to check again isspace().

Also help a bit more 'gcc' optimizer to grab buffer char just once and
simplify jump to next characted in the buffer when checking for token.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
2f022f5cbb device_mapper: nodes and values with strings
Avoid double dm_pool allocation call by copying string
for node name and config value directly after the end
of node/value structure.

It would be likely better to not copy these strings at all
and derefence it from the original string however that
needs futher changes in the code base.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
b185578321 crc: add newer zlib code
This code is faster when calculating crc32 checksum for larger
block areas. There is also SIMD variant present in the code,
however ATM the influence on performance of lvm2 is not that big..
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
f55c949410 crc: move static table
Move static table upward in the code so it can be shared with
another 'crc' implementation.
2024-10-22 19:36:00 +02:00
Zdenek Kabelac
d07e273aff lvmlockd: drop return 1 from void function
When compiling code without lvmlockd, the void function
lockd_free_lv_after_updatei()  should not return any value.
2024-10-22 19:15:55 +02:00
72 changed files with 1433 additions and 984 deletions

View File

@ -1,5 +1,18 @@
Version 2.03.28 -
==================
Restore fs resize call for lvresize -r on the same size LV (2.03.17).
Correct off-by-one devicesfile backup counting.
Replace use of dm_hash with radix_tree for lv names and uuids.
Refactor vg_validate with uniq_insert and better use of CPU caches.
Add radix_tree_uniq_insert.
Update DM cache when taking next VG lock instead of dropping it.
Generate json string id only for json reporting.
For vgsummary use new API call dm_config_parse_only_section().
Use radix_tree for PV names mapping.
Split check_lv_segment into separate _in/complete_vg variant.
Use find_lv instead of find_lv_in_vg when possible.
Do a mirror fixup only when mirrors with logs are imported.
Add faster crc32 calculation from zlib code for x86_64.
Fall back to direct zeroing if BLKZEROOUT fails during new LV initialization.
Version 2.03.27 - 02nd October 2024
@ -158,6 +171,7 @@ Version 2.03.17 - 10th November 2022
Switch to use mallinfo2 and use it only with glibc.
Error out in lvm shell if using a cmd argument not supported in the shell.
Fix lvm shell's lastlog command to report previous pre-command failures.
Keep libaio locked in memory in critical section.
Extend VDO and VDOPOOL without flushing and locking fs.
Add --valuesonly option to lvmconfig to print only values without keys.
Updates configure with recent autoconf tooling.

View File

@ -1,5 +1,8 @@
Version 1.02.202 -
===================
Introduce dm_config_parse_only_section to stop parsing after section.
For shorter string use on stack buffers when generating sections.
Enhance dm_config tokenizer.
Version 1.02.201 - 02nd October 2024
====================================

View File

@ -564,6 +564,13 @@ bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, un
return _insert(rt, lr.v, lr.kb, ke, rv);
}
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
{
unsigned entries = rt->nr_entries;
return radix_tree_insert(rt, key, keylen, rv) ?
((entries != rt->nr_entries) ? 1 : -1) : 0;
}
// Note the degrade functions also free the original node.
static void _degrade_to_n4(struct node16 *n16, struct value *result)
{

View File

@ -35,6 +35,10 @@ void radix_tree_destroy(struct radix_tree *rt);
unsigned radix_tree_size(struct radix_tree *rt);
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen);
// Returns: 1 success
// 0 failure during insert
// -1 key had already existing value (that was updated)
int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
// Returns the number of values removed
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len);
@ -78,6 +82,12 @@ static inline bool radix_tree_insert_ptr(struct radix_tree *rt, const void *key,
union radix_value v = { .ptr = ptr };
return radix_tree_insert(rt, key, keylen, v);
}
static inline int radix_tree_uniq_insert_ptr(struct radix_tree *rt, const void *key, size_t keylen, void *ptr)
{
union radix_value v = { .ptr = ptr };
return radix_tree_uniq_insert(rt, key, keylen, v);
}
//----------------------------------------------------------------
#endif

View File

@ -1062,14 +1062,14 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
return rv;
}
static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_only, int adopt_ok)
static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_only, int adopt_ok, int nodelay)
{
int rv;
if (ls->lm_type == LD_LM_DLM)
rv = lm_add_lockspace_dlm(ls, adopt_only, adopt_ok);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_add_lockspace_sanlock(ls, adopt_only, adopt_ok);
rv = lm_add_lockspace_sanlock(ls, adopt_only, adopt_ok, nodelay);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_add_lockspace_idm(ls, adopt_only, adopt_ok);
else
@ -2495,6 +2495,7 @@ static void *lockspace_thread_main(void *arg_in)
int adopt_only = 0;
int adopt_ok = 0;
int wait_flag = 0;
int nodelay = 0;
int retry;
int rv;
@ -2517,6 +2518,8 @@ static void *lockspace_thread_main(void *arg_in)
adopt_only = 1;
if (add_act->flags & LD_AF_ADOPT)
adopt_ok = 1;
if (add_act->flags & LD_AF_NODELAY)
nodelay = 1;
}
}
pthread_mutex_unlock(&ls->mutex);
@ -2546,7 +2549,7 @@ static void *lockspace_thread_main(void *arg_in)
* The actual lockspace join can take a while.
*/
if (!error) {
error = lm_add_lockspace(ls, add_act, adopt_only, adopt_ok);
error = lm_add_lockspace(ls, add_act, adopt_only, adopt_ok, nodelay);
log_debug("S %s lm_add_lockspace done %d", ls->name, error);
@ -4545,6 +4548,8 @@ static uint32_t str_to_opts(const char *str)
flags |= LD_AF_ENABLE;
if (strstr(str, "disable"))
flags |= LD_AF_DISABLE;
if (strstr(str, "nodelay"))
flags |= LD_AF_NODELAY;
/* FIXME: parse the flag values properly */
if (strstr(str, "adopt_only"))

View File

@ -113,6 +113,7 @@ struct client {
#define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
#define LD_AF_NODELAY 0x00400000
/*
* Number of times to repeat a lock request after
@ -510,7 +511,7 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay);
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry,
@ -561,7 +562,7 @@ static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay)
{
return -1;
}
@ -630,7 +631,7 @@ static inline int lm_is_running_sanlock(void)
return 0;
}
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes)
{
return -1;
}

View File

@ -24,6 +24,9 @@
#include "sanlock_admin.h"
#include "sanlock_resource.h"
/* FIXME: copied from sanlock header until the sanlock update is more widespread */
#define SANLK_ADD_NODELAY 0x00000002
#include <stddef.h>
#include <poll.h>
#include <errno.h>
@ -1594,9 +1597,10 @@ fail:
return ret;
}
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
uint32_t flags = 0;
int rv;
if (daemon_test) {
@ -1604,7 +1608,10 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
goto out;
}
rv = sanlock_add_lockspace_timeout(&lms->ss, 0, sanlock_io_timeout);
if (nodelay)
flags |= SANLK_ADD_NODELAY;
rv = sanlock_add_lockspace_timeout(&lms->ss, flags, sanlock_io_timeout);
if (rv == -EEXIST && (adopt_ok || adopt_only)) {
/* We could alternatively just skip the sanlock call for adopt. */
log_debug("S %s add_lockspace_san adopt found ls", ls->name);

View File

@ -2034,6 +2034,7 @@ struct dm_config_tree *dm_config_create(void);
struct dm_config_tree *dm_config_from_string(const char *config_settings);
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section);
void *dm_config_get_custom(struct dm_config_tree *cft);
void dm_config_set_custom(struct dm_config_tree *cft, void *custom);

View File

@ -53,6 +53,8 @@ struct parser {
int no_dup_node_check; /* whether to disable dup node checking */
const char *key; /* last obtained key */
unsigned ignored_creation_time;
unsigned section_indent;
const char *stop_after_section;
};
struct config_output {
@ -70,7 +72,8 @@ static struct dm_config_value *_value(struct parser *p);
static struct dm_config_value *_type(struct parser *p);
static int _match_aux(struct parser *p, int t);
static struct dm_config_value *_create_value(struct dm_pool *mem);
static struct dm_config_node *_create_node(struct dm_pool *mem);
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len);
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len);
static char *_dup_tok(struct parser *p);
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
@ -84,20 +87,24 @@ static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
} \
} while(0)
/* match token */
static int _tok_match(const char *str, const char *b, const char *e)
{
while (*str && (b != e)) {
if (*str++ != *b++)
while (b < e) {
if (!*str ||
(*str != *b))
return 0;
++str;
++b;
}
return !(*str || (b != e));
return !*str; /* token is matching for \0 end */
}
struct dm_config_tree *dm_config_create(void)
{
struct dm_config_tree *cft;
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
struct dm_pool *mem = dm_pool_create("config", 63 * 1024);
if (!mem) {
log_error("Failed to allocate config pool.");
@ -171,7 +178,8 @@ static struct dm_config_node *_config_reverse(struct dm_config_node *head)
return middle;
}
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end, int no_dup_node_check)
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end,
int no_dup_node_check, const char *section)
{
/* TODO? if (start == end) return 1; */
@ -182,6 +190,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
.fb = start,
.fe = end,
.line = 1,
.stop_after_section = section,
.no_dup_node_check = no_dup_node_check
};
@ -196,12 +205,23 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 0);
return _do_dm_config_parse(cft, start, end, 0, NULL);
}
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 1);
return _do_dm_config_parse(cft, start, end, 1, NULL);
}
/*
* Stop parsing more sections after given section is parsed.
* Only non-section config nodes are then still parsed.
* It can be useful, when parsing i.e. lvm2 metadata and only physical_volumes config node is needed.
* This function is automatically running without_dup_node_check.
*/
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section)
{
return _do_dm_config_parse(cft, start, end, 1, section);
}
struct dm_config_tree *dm_config_from_string(const char *config_settings)
@ -467,23 +487,33 @@ int dm_config_write_node_out(const struct dm_config_node *cn,
/*
* parser
*/
static char *_dup_string_tok(struct parser *p)
static const char *_string_tok(struct parser *p, size_t *len)
{
char *str;
ptrdiff_t d = p->te - p->tb;
p->tb++, p->te--; /* strip "'s */
if (p->te < p->tb) {
if (d < 2) {
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): "
"expected a string token.",
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!(str = _dup_tok(p)))
*len = (size_t)(d - 2); /* strip "'s */
return p->tb + 1;
}
static char *_dup_string_tok(struct parser *p)
{
const char *tok;
size_t len;
char *str;
if (!(tok = _string_tok(p, &len)))
return_NULL;
p->te++;
if (!(str = _dup_token(p->mem, tok, tok + len)))
return_NULL;
return str;
}
@ -505,10 +535,9 @@ static struct dm_config_node *_make_node(struct dm_pool *mem,
{
struct dm_config_node *n;
if (!(n = _create_node(mem)))
if (!(n = _create_node(mem, key_b, key_e - key_b)))
return_NULL;
n->key = _dup_token(mem, key_b, key_e);
if (parent) {
n->parent = parent;
n->sib = parent->child;
@ -578,6 +607,8 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
struct dm_config_node *root;
struct dm_config_value *value;
char *str;
size_t len;
char buf[8192];
if (p->t == TOK_STRING_ESCAPED) {
if (!(str = _dup_string_tok(p)))
@ -591,9 +622,16 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_STRING);
} else {
if (!(str = _dup_tok(p)))
return_NULL;
len = p->te - p->tb;
if (len < (sizeof(buf) - 1)) {
/* Use stack for smaller string */
str = buf;
memcpy(str, p->tb, len);
str[len] = '\0';
} else {
if (!(str = _dup_tok(p)))
return_NULL;
}
match(TOK_IDENTIFIER);
}
@ -607,12 +645,28 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
return_NULL;
if (p->t == TOK_SECTION_B) {
if (p->stop_after_section)
++p->section_indent;
match(TOK_SECTION_B);
while (p->t != TOK_SECTION_E) {
if (!(_section(p, root)))
return_NULL;
}
match(TOK_SECTION_E);
if (p->stop_after_section && (--p->section_indent == 1)) {
if (!strcmp(str, p->stop_after_section)) {
/* Found stopping section name -> parsing is finished.
* Now try to find the sequence "\n}\n" from end of b
* parsed buffer to continue filling remaining nodes */
for (p->te = p->fe - 1; p->te > p->tb; --p->te)
if ((p->te[-2] == '\n') &&
(p->te[-1] == '}') &&
(p->te[ 0] == '\n')) {
p->t = TOK_SECTION_E;
break;
}
}
}
} else {
match(TOK_EQ);
p->key = root->key;
@ -669,16 +723,14 @@ static struct dm_config_value *_value(struct parser *p)
static struct dm_config_value *_type(struct parser *p)
{
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
struct dm_config_value *v = _create_value(p->mem);
char *str;
if (!v) {
log_error("Failed to allocate type value");
return NULL;
}
struct dm_config_value *v;
const char *str;
size_t len;
switch (p->t) {
case TOK_INT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_INT;
errno = 0;
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
@ -699,6 +751,8 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_FLOAT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_FLOAT;
errno = 0;
v->v.f = strtod(p->tb, NULL); /* FIXME: check error */
@ -710,31 +764,31 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_STRING:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
match(TOK_STRING);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
match(TOK_STRING);
}
break;
case TOK_STRING_BARE:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_tok(p)))
return_NULL;
match(TOK_STRING_BARE);
if ((v = _create_str_value(p->mem, p->tb, p->te - p->tb))) {
v->type = DM_CFG_STRING;
match(TOK_STRING_BARE);
}
break;
case TOK_STRING_ESCAPED:
v->type = DM_CFG_STRING;
if (!(str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
dm_unescape_double_quotes(str);
v->v.str = str;
match(TOK_STRING_ESCAPED);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
dm_unescape_double_quotes((char*)v->v.str);
match(TOK_STRING_ESCAPED);
}
break;
default:
@ -742,6 +796,12 @@ static struct dm_config_value *_type(struct parser *p)
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!v) {
log_error("Failed to allocate type value.");
return NULL;
}
return v;
}
@ -759,60 +819,52 @@ static int _match_aux(struct parser *p, int t)
*/
static void _get_token(struct parser *p, int tok_prev)
{
int values_allowed = 0;
/* Should next token be interpreted as value instead of identifier? */
const int values_allowed = (tok_prev == TOK_EQ ||
tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA);
const char *te;
char c;
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe || !*p->tb) {
if (p->tb == p->fe ||
!((c = *p->tb))) {
p->t = TOK_EOF;
return;
}
/* Should next token be interpreted as value instead of identifier? */
if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA)
values_allowed = 1;
p->t = TOK_INT; /* fudge so the fall through for
floats works */
te = p->te + 1; /* next character */
te = p->te;
switch (*te) {
switch (c) {
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
te++;
break;
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
te++;
break;
case '[':
p->t = TOK_ARRAY_B;
te++;
break;
case ']':
p->t = TOK_ARRAY_E;
te++;
break;
case ',':
p->t = TOK_COMMA;
te++;
break;
case '=':
p->t = TOK_EQ;
te++;
break;
case '"':
p->t = TOK_STRING_ESCAPED;
te++;
while ((te != p->fe) && (*te) && (*te != '"')) {
if ((*te == '\\') && (te + 1 != p->fe) &&
*(te + 1))
@ -826,7 +878,6 @@ static void _get_token(struct parser *p, int tok_prev)
case '\'':
p->t = TOK_STRING;
te++;
while ((te != p->fe) && (*te) && (*te != '\''))
te++;
@ -850,7 +901,7 @@ static void _get_token(struct parser *p, int tok_prev)
case '+':
case '-':
if (values_allowed) {
while (++te != p->fe) {
for (; te != p->fe; ++te) {
if (!isdigit((int) *te)) {
if (*te == '.') {
if (p->t != TOK_FLOAT) {
@ -867,10 +918,10 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((te != p->fe) && (*te) && !isspace(*te) &&
(*te != '#') && (*te != '=') &&
(*te != SECTION_B_CHAR) &&
(*te != SECTION_E_CHAR))
while ((te != p->fe) && ((c = *te)) && !isspace(c) &&
(c != '#') && (c != '=') &&
(c != SECTION_B_CHAR) &&
(c != SECTION_E_CHAR))
te++;
if (values_allowed)
p->t = TOK_STRING_BARE;
@ -883,16 +934,19 @@ static void _get_token(struct parser *p, int tok_prev)
static void _eat_space(struct parser *p)
{
while (p->tb != p->fe) {
if (*p->te == '#')
if (!isspace(*p->te)) {
if (*p->te != '#')
break;
while ((p->te != p->fe) && (*p->te != '\n') && (*p->te))
++p->te;
}
else if (!isspace(*p->te))
break;
while ((p->te != p->fe) && isspace(*p->te)) {
while (p->te != p->fe) {
if (*p->te == '\n')
++p->line;
else if (!isspace(*p->te))
break;
++p->te;
}
@ -908,9 +962,44 @@ static struct dm_config_value *_create_value(struct dm_pool *mem)
return dm_pool_zalloc(mem, sizeof(struct dm_config_value));
}
static struct dm_config_node *_create_node(struct dm_pool *mem)
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len)
{
return dm_pool_zalloc(mem, sizeof(struct dm_config_node));
struct dm_config_value *cv;
char *str_buf;
if (!(cv = dm_pool_alloc(mem, sizeof(struct dm_config_value) + str_len + 1)))
return_NULL;
memset(cv, 0, sizeof(*cv));
if (str) {
str_buf = (char *)(cv + 1);
memcpy(str_buf, str, str_len);
str_buf[str_len] = '\0';
cv->v.str = str_buf;
}
return cv;
}
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len)
{
struct dm_config_node *cn;
char *key_buf;
if (!(cn = dm_pool_alloc(mem, sizeof(struct dm_config_node) + key_len + 1)))
return_NULL;
memset(cn, 0, sizeof(*cn));
if (key) {
key_buf = (char *)(cn + 1);
memcpy(key_buf, key, key_len);
key_buf[key_len] = '\0';
cn->key = key_buf;
}
return cn;
}
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e)
@ -1327,19 +1416,20 @@ static struct dm_config_value *_clone_config_value(struct dm_pool *mem,
{
struct dm_config_value *new_cv;
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
if (v->type == DM_CFG_STRING) {
if (!(new_cv = _create_str_value(mem, v->v.str, strlen(v->v.str)))) {
log_error("Failed to clone string config value.");
return NULL;
}
} else {
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
}
new_cv->v = v->v;
}
new_cv->type = v->type;
if (v->type == DM_CFG_STRING) {
if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) {
log_error("Failed to clone config string value.");
return NULL;
}
} else
new_cv->v = v->v;
if (v->next && !(new_cv->next = _clone_config_value(mem, v->next)))
return_NULL;
@ -1356,16 +1446,11 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
return NULL;
}
if (!(new_cn = _create_node(mem))) {
if (!(new_cn = _create_node(mem, cn->key, cn->key ? strlen(cn->key) : 0))) {
log_error("Failed to clone config node.");
return NULL;
}
if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) {
log_error("Failed to clone config node key.");
return NULL;
}
new_cn->id = cn->id;
if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) ||
@ -1385,14 +1470,11 @@ struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const c
{
struct dm_config_node *cn;
if (!(cn = _create_node(cft->mem))) {
if (!(cn = _create_node(cft->mem, key, strlen(key)))) {
log_error("Failed to create config node.");
return NULL;
}
if (!(cn->key = dm_pool_strdup(cft->mem, key))) {
log_error("Failed to create config node's key.");
return NULL;
}
cn->parent = NULL;
cn->v = NULL;

View File

@ -4371,9 +4371,10 @@ static int _row_compare(const void *a, const void *b)
for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
sfa = (*rowa->sort_fields)[cnt];
sfb = (*rowb->sort_fields)[cnt];
if ((sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_SIZE) ||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_TIME)) {
if (sfa->props->flags &
((DM_REPORT_FIELD_TYPE_NUMBER) |
(DM_REPORT_FIELD_TYPE_SIZE) |
(DM_REPORT_FIELD_TYPE_TIME))) {
const uint64_t numa =
*(const uint64_t *) sfa->sort_value;
const uint64_t numb =
@ -4484,6 +4485,7 @@ static const char *_get_field_id(struct dm_report *rh, struct dm_report_field *f
static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field *field)
{
char buf_local[8192];
char *field_id;
int32_t width;
uint32_t align;
@ -4491,25 +4493,26 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
size_t buf_size = 0;
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
if (!(field_id = strdup(_get_field_id(rh, field)))) {
log_error("dm_report: Failed to copy field name");
buf_size = strlen(_get_field_id(rh, field)) + 1;
if (buf_size >= sizeof(buf_local)) {
/* for field names our buf_local should be enough */
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
field_id = buf_local;
memcpy(field_id, _get_field_id(rh, field), buf_size);
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
free(field_id);
return 0;
}
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
free(field_id);
return 0;
}
free(field_id);
if (!dm_pool_grow_object(rh->mem, STANDARD_PAIR, 1)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
@ -4532,7 +4535,10 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
/* Including trailing '\0'! */
buf_size = width + 1;
if (!(buf = malloc(buf_size))) {
if (buf_size < sizeof(buf_local))
/* Use local buffer on stack for smaller strings */
buf = buf_local;
else if (!(buf = malloc(buf_size))) {
log_error("dm_report: Could not allocate memory for output line buffer.");
return 0;
}
@ -4574,10 +4580,12 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
}
}
free(buf);
if (buf != buf_local)
free(buf);
return 1;
bad:
free(buf);
if (buf != buf_local)
free(buf);
return 0;
}
@ -4847,6 +4855,7 @@ static int _output_as_columns(struct dm_report *rh)
struct dm_report_field *field;
struct dm_list *last_rowh;
int do_field_delim;
int is_json_report = _is_json_report(rh);
char *line;
/* If headings not printed yet, calculate field widths and print them */
@ -4866,7 +4875,7 @@ static int _output_as_columns(struct dm_report *rh)
return 0;
}
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_START, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;
@ -4881,7 +4890,7 @@ static int _output_as_columns(struct dm_report *rh)
continue;
if (do_field_delim) {
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0) ||
!dm_pool_grow_object(rh->mem, JSON_SPACE, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
@ -4903,7 +4912,7 @@ static int _output_as_columns(struct dm_report *rh)
dm_list_del(&field->list);
}
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_END, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;

View File

@ -202,9 +202,7 @@ static int _settings_text_export(const struct lv_segment *seg,
}
static int _cache_pool_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
struct logical_volume *data_lv, *meta_lv;
const char *str = NULL;
@ -213,7 +211,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Cache data not specified in");
if (!(str = dm_config_find_str(sn, "data", NULL)))
return SEG_LOG_ERROR("Cache data must be a string in");
if (!(data_lv = dm_hash_lookup(lv_hash, str)))
if (!(data_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache data in", str);
@ -221,7 +219,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Cache metadata not specified in");
if (!(str = dm_config_find_str(sn, "metadata", NULL)))
return SEG_LOG_ERROR("Cache metadata must be a string in");
if (!(meta_lv = dm_hash_lookup(lv_hash, str)))
if (!(meta_lv = find_lv(seg->lv->vg, str)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache metadata in", str);
@ -439,9 +437,7 @@ static const struct segtype_handler _cache_pool_ops = {
};
static int _cache_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
struct logical_volume *pool_lv, *origin_lv;
const char *name;
@ -451,7 +447,7 @@ static int _cache_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("cache_pool not specified in");
if (!(name = dm_config_find_str(sn, "cache_pool", NULL)))
return SEG_LOG_ERROR("cache_pool must be a string in");
if (!(pool_lv = dm_hash_lookup(lv_hash, name)))
if (!(pool_lv = find_lv(seg->lv->vg, name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache_pool in", name);
@ -459,7 +455,7 @@ static int _cache_text_import(struct lv_segment *seg,
return SEG_LOG_ERROR("Cache origin not specified in");
if (!(name = dm_config_find_str(sn, "origin", NULL)))
return SEG_LOG_ERROR("Cache origin must be a string in");
if (!(origin_lv = dm_hash_lookup(lv_hash, name)))
if (!(origin_lv = find_lv(seg->lv->vg, name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"cache origin in", name);
if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))

View File

@ -483,7 +483,7 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
int checksum_only, int no_dup_node_check, int only_pv_summary)
{
char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
int namelen = 0;
@ -573,7 +573,10 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (!checksum_only) {
fe = fb + size + size2;
if (no_dup_node_check) {
if (!dm_config_parse_without_dup_node_check(cft, fb, fe))
if (only_pv_summary) {
if (!dm_config_parse_only_section(cft, fb, fe, "physical_volumes"))
goto_out;
} else if (!dm_config_parse_without_dup_node_check(cft, fb, fe))
goto_out;
} else {
if (!dm_config_parse(cft, fb, fe))
@ -635,7 +638,7 @@ int config_file_read_from_file(struct dm_config_tree *cft)
cf->dev = &fake_dev;
r = config_file_read_fd(cft, cf->dev, DEV_IO_MDA_CONTENT, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0, 0, 0);
(checksum_fn_t) NULL, 0, 0, 0, 0);
free((void*)alias->str);
free((void*)alias);

View File

@ -243,7 +243,7 @@ struct dm_config_tree *config_open(config_source_t source, const char *filename,
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
int skip_parse, int no_dup_node_check);
int skip_parse, int no_dup_node_check, int only_pv_summary);
int config_file_read_from_file(struct dm_config_tree *cft);
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
struct cmd_context *cmd);

View File

@ -1281,11 +1281,13 @@ void dm_devs_cache_destroy(void)
_cache.use_dm_devs_cache = 0;
if (_cache.dm_devnos) {
log_debug_cache("Destroying DM devno cache.");
radix_tree_destroy(_cache.dm_devnos);
_cache.dm_devnos = NULL;
}
if (_cache.dm_uuids) {
log_debug_cache("Destroying DM uuid cache.");
radix_tree_destroy(_cache.dm_uuids);
_cache.dm_uuids = NULL;
}
@ -1293,23 +1295,67 @@ void dm_devs_cache_destroy(void)
dm_device_list_destroy(&_cache.dm_devs);
}
/*
* Updates cached trees with active DM devices.
*
* TODO:
* For large amount of active devices it might be useful
* to update existing trees - especially when there is high
* chance the set of active devices is nearly the same).
* However its not so trivial, so just make it a TODO.
* And do only an easy 1:1 match or full rebuild.
*/
int dm_devs_cache_update(void)
{
struct dm_active_device *dm_dev;
struct dm_active_device *dm_dev, *dm_dev_new;
unsigned devs_features;
uint32_t d;
struct dm_list *dm_devs_new, *l;
int cache_changed = 0;
dm_devs_cache_destroy();
if (!get_dm_active_devices(NULL, &_cache.dm_devs, &devs_features))
if (!get_dm_active_devices(NULL, &dm_devs_new, &devs_features))
return 1;
if (!(devs_features & DM_DEVICE_LIST_HAS_UUID)) {
/* Cache unusable with older kernels without UUIDs in LIST */
dm_device_list_destroy(&_cache.dm_devs);
dm_device_list_destroy(&dm_devs_new);
return 1;
}
if (_cache.dm_devs) {
/* Compare existing cached list with a new one.
* When there is any mismatch, just rebuild whole cache */
if ((l = dm_list_first(dm_devs_new))) {
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
dm_dev_new = dm_list_item(l, struct dm_active_device);
if ((dm_dev->devno != dm_dev_new->devno) ||
strcmp(dm_dev->uuid, dm_dev_new->uuid)) {
log_debug_cache("Mismatching UUID or devno found %s %u:%u %s %u:%u.",
dm_dev->uuid, MAJOR(dm_dev->devno), MINOR(dm_dev->devno),
dm_dev_new->uuid, MAJOR(dm_dev_new->devno), MINOR(dm_dev_new->devno));
cache_changed = 1;
break;
}
if (!(l = dm_list_next(dm_devs_new, l))) {
if (dm_list_next(_cache.dm_devs, &dm_dev->list))
cache_changed = 1; /* old cached list still with entries */
break;
}
}
} else
cache_changed = 1;
if (!cache_changed) {
log_debug_cache("Preserving DM cache.");
dm_device_list_destroy(&dm_devs_new);
return 1;
}
dm_devs_cache_destroy();
}
_cache.dm_devs = dm_devs_new;
/* _cache.dm_devs entries are referenced by radix trees */
/* TODO: if _cache.dm_devs list is small, then skip the
@ -1320,6 +1366,7 @@ int dm_devs_cache_update(void)
return_0; // FIXME
}
log_debug_cache("Creating DM cache for devno and uuid.");
/* Insert every active DM device into radix trees */
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
d = _shuffle_devno(dm_dev->devno);
@ -1344,6 +1391,8 @@ void dm_devs_cache_label_invalidate(struct cmd_context *cmd)
struct dm_active_device *dm_dev;
struct device *dev;
dm_devs_cache_update();
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
if (dm_dev->uuid &&
strncmp(dm_dev->uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1) == 0) {

View File

@ -604,14 +604,14 @@ static int _has_gpt_partition_table(struct device *dev)
/* the gpt table is always written using LE on disk */
if (le64_to_cpu(gpt_header.magic) != PART_GPT_MAGIC)
return_0;
return 0;
entries_start = le64_to_cpu(gpt_header.part_entries_lba) * lbs;
nr_entries = le32_to_cpu(gpt_header.nr_part_entries);
sz_entry = le32_to_cpu(gpt_header.sz_part_entry);
for (i = 0; i < nr_entries; i++) {
if (!dev_read_bytes(dev, entries_start + i * sz_entry,
if (!dev_read_bytes(dev, entries_start + (uint64_t)i * sz_entry,
sizeof(gpt_part_entry), &gpt_part_entry))
return_0;
@ -1005,8 +1005,8 @@ int fs_get_blkid(const char *pathname, struct fs_info *fsi)
fsi->fs_last_byte = fssize;
/*
* For swap, there's no FSLASTBLOCK reported by blkid. We do have FSSIZE reported though.
* The last block is then calculated as:
* For swap, FSLASTBLOCK is reported by blkid since v2.41 so use that directly.
* Otherwise, we do have FSSIZE reported since v2.39. Then. then last block is calculated as:
* FSSIZE (== size of the usable swap area) + FSBLOCKSIZE (== size of the swap header)
*/
if (!strcmp(fsi->fstype, "swap"))

View File

@ -1359,7 +1359,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
{
struct dirent *de;
struct dirent **namelist = NULL;
DIR *dir;
DIR *dir = NULL;
FILE *fp = NULL;
struct tm *tm;
char dirpath[PATH_MAX];
@ -1389,11 +1389,6 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
stack;
return;
}
if (!(dir = opendir(dirpath))) {
log_sys_debug("opendir", dirpath);
return;
}
tm = localtime(tp);
strftime(datetime_str, sizeof(datetime_str), "%Y%m%d.%H%M%S", tm);
@ -1427,6 +1422,12 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
fp = NULL;
log_debug("Wrote backup %s", path);
/* Open dir after backup file is written, so it can be accounted */
if (!(dir = opendir(dirpath))) {
log_sys_debug("opendir", dirpath);
return;
}
/* Possibly remove old backup files per configurable limit on backup files. */
while ((de = readdir(dir))) {
@ -1511,7 +1512,7 @@ out:
if (fp && fclose(fp))
stack;
if (closedir(dir))
if (dir && closedir(dir))
log_sys_debug("closedir", dirpath);
}

View File

@ -542,6 +542,8 @@ int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
break;
}
}
if (!check_lv_segments_complete_vg(lvl->lv))
goto_out;
}
missing_pvs = vg_missing_pv_count(vg);

View File

@ -25,6 +25,7 @@
#include "lib/commands/toolcontext.h"
#include "lib/device/device_id.h"
#include "libdaemon/client/config-util.h"
#include "base/data-struct/radix-tree.h"
#include <stdarg.h>
#include <time.h>
@ -53,8 +54,7 @@ typedef int (*nl_fn) (struct formatter * f);
* exporting the vg, ie. writing it to a file.
*/
struct formatter {
struct dm_pool *mem; /* pv names allocated from here */
struct dm_hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
struct radix_tree *pv_idx; /* dev_name id -> pv_name (eg, pv1) */
union {
FILE *fp; /* where we're writing to */
@ -71,6 +71,7 @@ struct formatter {
int indent; /* current level of indentation */
int error;
int header; /* 1 => comments at start; 0 => end */
int with_comment; /* 1 => prepare comment sting */
};
static struct utsname _utsname;
@ -273,8 +274,11 @@ int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
va_list ap;
int r;
if (!_sectors_to_units(size, buffer, sizeof(buffer)))
return 0;
if (f->with_comment) {
if (!_sectors_to_units(size, buffer, sizeof(buffer)))
return 0;
} else
buffer[0] = 0;
_out_with_comment(f, buffer, fmt, ap);
@ -363,11 +367,11 @@ static int _print_flag_config(struct formatter *f, uint64_t status, enum pv_vg_l
if (!print_flags(buffer, sizeof(buffer), type, STATUS_FLAG, status))
return_0;
outf(f, "status = %s", buffer);
outf(f, "status = [%s]", buffer);
if (!print_flags(buffer, sizeof(buffer), type, COMPATIBLE_FLAG, status))
return_0;
outf(f, "flags = %s", buffer);
outf(f, "flags = [%s]", buffer);
return 1;
}
@ -390,28 +394,19 @@ static char *_alloc_printed_str_list(struct dm_list *list)
return NULL;
}
if (!emit_to_buffer(&buf, &size, "["))
goto_bad;
buffer[0] = 0;
dm_list_iterate_items(sl, list) {
if (!first) {
if (!emit_to_buffer(&buf, &size, ", "))
goto_bad;
} else
first = 0;
if (!emit_to_buffer(&buf, &size, "\"%s\"", sl->str))
goto_bad;
if (!emit_to_buffer(&buf, &size, "%s\"%s\"",
(!first) ? ", " : "",
sl->str)) {
free(buffer);
return_NULL;
}
first = 0;
}
if (!emit_to_buffer(&buf, &size, "]"))
goto_bad;
return buffer;
bad:
free(buffer);
return_NULL;
}
static int _out_list(struct formatter *f, struct dm_list *list,
@ -422,7 +417,7 @@ static int _out_list(struct formatter *f, struct dm_list *list,
if (!dm_list_empty(list)) {
if (!(buffer = _alloc_printed_str_list(list)))
return_0;
if (!out_text(f, "%s = %s", list_name, buffer)) {
if (!out_text(f, "%s = [%s]", list_name, buffer)) {
free(buffer);
return_0;
}
@ -496,29 +491,18 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
return 1;
}
/*
* Get the pv%d name from the formatters hash
* table.
*/
static const char *_get_pv_name_from_uuid(struct formatter *f, char *uuid)
/* Get the pv index %d name from the formatters radix tree. */
static int _get_pv_idx(const struct formatter *f, const struct physical_volume *pv)
{
const char *pv_name = dm_hash_lookup(f->pv_names, uuid);
union radix_value idx;
if (!pv_name)
log_error(INTERNAL_ERROR "PV name for uuid %s missing from text metadata export hash table.",
uuid);
if (!pv || !radix_tree_lookup(f->pv_idx, &pv, sizeof(pv), &idx)) {
log_error(INTERNAL_ERROR "PV name for %s missing in metadata export radix tree.",
(pv) ? pv_dev_name(pv) : "");
return -1;
}
return pv_name;
}
static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
{
char uuid[64] __attribute__((aligned(8)));
if (!pv || !id_write_format(&pv->id, uuid, sizeof(uuid)))
return_NULL;
return _get_pv_name_from_uuid(f, uuid);
return (int) idx.n;
}
static int _print_pvs(struct formatter *f, struct volume_group *vg)
@ -526,7 +510,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
struct pv_list *pvl;
struct physical_volume *pv;
char buffer[PATH_MAX * 2];
const char *name;
int idx;
const char *idtype, *idname;
outf(f, "physical_volumes {");
@ -538,11 +522,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
return_0;
if (!(name = _get_pv_name_from_uuid(f, buffer)))
if ((idx = _get_pv_idx(f, pv)) < 0)
return_0;
outnl(f);
outf(f, "%s {", name);
outf(f, "pv%d {", idx);
_inc_indent(f);
outf(f, "id = \"%s\"", buffer);
@ -626,8 +610,8 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *type)
{
const char *name;
unsigned int s;
int idx;
struct physical_volume *pv;
outnl(f);
@ -643,11 +627,11 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
s, type, display_lvname(seg->lv));
return 0;
}
if (!(name = _get_pv_name(f, pv)))
if ((idx = _get_pv_idx(f, pv)) < 0)
return_0;
outf(f, "\"%s\", %u%s", name,
outf(f, "\"pv%d\", %u%s", idx,
seg_pe(seg, s),
(s == seg->area_count - 1) ? "" : ",");
break;
@ -696,10 +680,14 @@ static int _print_timestamp(struct formatter *f,
struct tm *local_tm;
if (ts) {
strncpy(buf, "# ", buf_size);
if (!(local_tm = localtime(&ts)) ||
!strftime(buf + 2, buf_size - 2,
"%Y-%m-%d %T %z", local_tm))
if (f->with_comment) {
/* generate timestamp only for commented output */
strncpy(buf, "# ", buf_size);
if (!(local_tm = localtime(&ts)) ||
!strftime(buf + 2, buf_size - 2,
"%Y-%m-%d %T %z", local_tm))
buf[0] = 0;
} else
buf[0] = 0;
outfc(f, buf, "%s = " FMTu64, name, (uint64_t) ts);
@ -850,25 +838,19 @@ static int _alloc_printed_indirect_descendants(struct dm_list *indirect_glvs, ch
return 0;
}
buf = *buffer;
if (!emit_to_buffer(&buf, &buf_size, "["))
goto_bad;
buf[0] = 0;
dm_list_iterate_items(user_glvl, indirect_glvs) {
if (user_glvl->glv->is_historical)
continue;
if (!first) {
if (!emit_to_buffer(&buf, &buf_size, ", "))
goto_bad;
} else
first = 0;
if (!emit_to_buffer(&buf, &buf_size, "\"%s\"", user_glvl->glv->live->name))
if (!emit_to_buffer(&buf, &buf_size, "%s\"%s\"",
(!first) ? ", " : "",
user_glvl->glv->live->name))
goto_bad;
}
if (!emit_to_buffer(&buf, &buf_size, "]"))
goto_bad;
first = 0;
}
return 1;
bad:
@ -907,7 +889,7 @@ static int _print_historical_lv_with_descendants(struct formatter *f, struct his
}
if (descendants_buffer)
outf(f, "descendants = %s", descendants_buffer);
outf(f, "descendants = [%s]", descendants_buffer);
_dec_indent(f);
outf(f, "}");
@ -954,35 +936,22 @@ static int _print_historical_lvs(struct formatter *f, struct volume_group *vg)
* 'pv2' etc. This function builds a hash table
* to enable a quick lookup from device -> name.
*/
static int _build_pv_names(struct formatter *f, struct volume_group *vg)
static int _build_pv_idx(struct formatter *f, struct volume_group *vg)
{
int count = 0;
union radix_value count = { 0 };
struct pv_list *pvl;
struct physical_volume *pv;
char buffer[32], *name;
char uuid[64];
if (!(f->mem = dm_pool_create("text pv_names", 512)))
return_0;
if (!(f->pv_names = dm_hash_create(115)))
if (!(f->pv_idx = radix_tree_create(NULL, NULL)))
return_0;
dm_list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
/* FIXME But skip if there's already an LV called pv%d ! */
if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
return_0;
if (!(name = dm_pool_strdup(f->mem, buffer)))
return_0;
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
return_0;
if (!dm_hash_insert(f->pv_names, uuid, name))
if (!radix_tree_insert(f->pv_idx, &pv, sizeof(pv), count))
return_0;
count.n++;
}
return 1;
@ -993,7 +962,7 @@ static int _text_vg_export(struct formatter *f,
{
int r = 0;
if (!_build_pv_names(f, vg))
if (!_build_pv_idx(f, vg))
goto_out;
if (f->header && !_print_header(vg->cmd, f, desc))
@ -1029,14 +998,9 @@ static int _text_vg_export(struct formatter *f,
r = 1;
out:
if (f->mem) {
dm_pool_destroy(f->mem);
f->mem = NULL;
}
if (f->pv_names) {
dm_hash_destroy(f->pv_names);
f->pv_names = NULL;
if (f->pv_idx) {
radix_tree_destroy(f->pv_idx);
f->pv_idx = NULL;
}
return r;
@ -1049,6 +1013,7 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
.indent = 0,
.header = 1,
.out_with_comment = &_out_with_comment_file,
.with_comment = 1,
.nl = &_nl_file,
.data.fp = fp,
};

View File

@ -144,8 +144,8 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
if (!(flags = _get_flags(type)))
return_0;
if (!emit_to_buffer(&buffer, &size, "["))
return_0;
if (size)
buffer[0] = 0;
for (f = 0; flags[f].mask; f++) {
if (status & flags[f].mask) {
@ -158,21 +158,14 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
if (!flags[f].description)
continue;
if (!first) {
if (!emit_to_buffer(&buffer, &size, ", "))
return_0;
} else
first = 0;
if (!emit_to_buffer(&buffer, &size, "\"%s\"",
if (!emit_to_buffer(&buffer, &size, "%s\"%s\"",
(!first) ? ", " : "",
flags[f].description))
return_0;
first = 0;
}
}
if (!emit_to_buffer(&buffer, &size, "]"))
return_0;
if (status)
log_warn(INTERNAL_ERROR "Metadata inconsistency: "
"Not all flags successfully exported.");
@ -238,51 +231,39 @@ int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm
/*
* 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.
* Returns 0 and prints warning for an UNKNOWN flag.
*
* Note: using these segtype status flags instead of actual
* status flags ensures wanted incompatibility.
*/
int read_segtype_lvflags(uint64_t *status, char *segtype_str)
int read_lvflags(uint64_t *status, const char *flags_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;
const char *delim;
size_t len;
unsigned i;
do {
flag = delim;
if ((delim = strchr(delim, '+')))
*delim++ = '\0';
if ((delim = strchr(flags_str, '+')))
len = delim - flags_str;
else
len = strlen(flags_str);
for (i = 0; flags[i].description; i++)
for (i = 0; flags[i].kind; ++i)
if ((flags[i].kind & SEGTYPE_FLAG) &&
!strcmp(flags[i].description, flag)) {
!strncmp(flags_str, flags[i].description, len) &&
!flags[i].description[len]) {
*status |= flags[i].mask;
break;
break; /* Found matching flag */
}
} while (delim && flags[i].description); /* Till no more flags in type appear */
if (!flags[i].kind) {
log_warn("WARNING: Unrecognised flag(s) %s.", flags_str);
return 0; /* Unknown flag is incompatible */
}
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);
flags_str = delim + 1;
} while (delim); /* Till no more flags in type appear */
return 1;
}

View File

@ -67,7 +67,7 @@ int print_flags(char *buffer, size_t size, enum pv_vg_lv_e type, int mask, uint6
int read_flags(uint64_t *status, enum pv_vg_lv_e type, int mask, const struct dm_config_value *cv);
int print_segtype_lvflags(char *buffer, size_t size, uint64_t status);
int read_segtype_lvflags(uint64_t *status, char *segtype_str);
int read_lvflags(uint64_t *status, const char *flags_str);
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf, uint32_t *alloc_size);

View File

@ -61,7 +61,7 @@ int text_read_metadata_summary(const struct format_type *fmt,
if (!config_file_read_fd(cft, dev, reason, offset, size,
offset2, size2, checksum_fn,
vgsummary->mda_checksum,
checksum_only, 1)) {
checksum_only, 1, 1)) {
log_warn("WARNING: invalid metadata text from %s at %llu.",
dev_name(dev), (unsigned long long)offset);
goto out;
@ -156,7 +156,7 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
if (!config_file_read_fd(cft, dev, MDA_CONTENT_REASON(primary_mda), offset, size,
offset2, size2, checksum_fn, checksum,
skip_parse, 1)) {
skip_parse, 1, 0)) {
log_warn("WARNING: couldn't read volume group metadata from %s.", dev_name(dev));
goto out;
}

View File

@ -26,6 +26,7 @@
#include "lib/format_text/text_import.h"
#include "lib/config/defaults.h"
#include "lib/datastruct/str_list.h"
#include "base/data-struct/radix-tree.h"
typedef int (*section_fn) (struct cmd_context *cmd,
struct format_type *fmt,
@ -34,9 +35,7 @@ typedef int (*section_fn) (struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *pvn,
const struct dm_config_node *vgn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash);
const struct dm_config_node *vgn);
#define _read_int32(root, path, result) \
dm_config_get_uint32(root, path, (uint32_t *) (result))
@ -180,9 +179,7 @@ static int _read_pv(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *pvn,
const struct dm_config_node *vgn __attribute__((unused)),
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash __attribute__((unused)))
const struct dm_config_node *vgn __attribute__((unused)))
{
struct physical_volume *pv;
struct pv_list *pvl;
@ -200,8 +197,8 @@ static int _read_pv(struct cmd_context *cmd,
* Add the pv to the pv hash for quick lookup when we read
* the lv segments.
*/
if (!dm_hash_insert(pv_hash, pvn->key, pv))
return_0;
if (!radix_tree_insert_ptr(vg->pv_names, pvn->key, strlen(pvn->key), pv))
return_0;
if (!(pvn = pvn->child)) {
log_error("Empty pv section.");
@ -310,9 +307,7 @@ static int _read_pvsummary(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *pvn,
const struct dm_config_node *vgn __attribute__((unused)),
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash __attribute__((unused)))
const struct dm_config_node *vgn __attribute__((unused)))
{
struct physical_volume *pv;
struct pv_list *pvl;
@ -371,13 +366,31 @@ static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
dm_list_add(&lv->segments, &seg->list);
}
static struct segment_type *_read_segtype_and_lvflags(struct cmd_context *cmd,
uint64_t *status,
const char *segtype_str)
{
char buffer[128]; /* just for segtype name */
const char *str;
size_t len;
if ((str = strchr(segtype_str, '+')))
if (read_lvflags(status, ++str)) {
len = str - segtype_str - 1;
len = min(len, sizeof(buffer) - 1);
memcpy(buffer, segtype_str, len);
buffer[len] = 0;
segtype_str = buffer;
}
return get_segtype_from_string(cmd, segtype_str);
}
static int _read_segment(struct cmd_context *cmd,
struct format_type *fmt,
struct format_instance *fid,
struct dm_pool *mem,
struct logical_volume *lv, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
struct logical_volume *lv, const struct dm_config_node *sn)
{
uint32_t area_count = 0u;
struct lv_segment *seg;
@ -386,7 +399,6 @@ static int _read_segment(struct cmd_context *cmd,
uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
struct segment_type *segtype;
const char *segtype_str;
char *segtype_with_flags;
if (!sn_child) {
log_error("Empty segment section.");
@ -418,24 +430,12 @@ static int _read_segment(struct cmd_context *cmd,
return 0;
}
/* Locally duplicate to parse out status flag bits */
if (!(segtype_with_flags = dm_pool_strdup(mem, segtype_str))) {
log_error("Cannot duplicate segtype string.");
if (!(segtype = _read_segtype_and_lvflags(cmd, &lv->status, segtype_str))) {
log_error("Couldn't read segtype %s for logical volume %s.",
segtype_str, display_lvname(lv));
return 0;
}
if (!read_segtype_lvflags(&lv->status, segtype_with_flags)) {
log_error("Couldn't read segtype for logical volume %s.",
display_lvname(lv));
return 0;
}
if (!(segtype = get_segtype_from_string(cmd, segtype_with_flags)))
return_0;
/* Can drop temporary string here as nothing has allocated from VGMEM meanwhile */
dm_pool_free(mem, segtype_with_flags);
if (segtype->ops->text_import_area_count &&
!segtype->ops->text_import_area_count(sn_child, &area_count))
return_0;
@ -450,7 +450,7 @@ static int _read_segment(struct cmd_context *cmd,
}
if (seg->segtype->ops->text_import &&
!seg->segtype->ops->text_import(seg, sn_child, pv_hash, lv_hash))
!seg->segtype->ops->text_import(seg, sn_child))
return_0;
/* Optional tags */
@ -485,7 +485,7 @@ static int _read_segment(struct cmd_context *cmd,
}
int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
const struct dm_config_value *cv, struct dm_hash_table *pv_hash,
const struct dm_config_value *cv,
uint64_t status)
{
unsigned int s;
@ -517,7 +517,7 @@ int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
}
/* FIXME Cope if LV not yet read in */
if ((pv = dm_hash_lookup(pv_hash, cv->v.str))) {
if ((pv = find_pv_by_pv_name(seg->lv->vg, cv->v.str))) {
if (!set_lv_segment_area_pv(seg, s, pv, (uint32_t) cv->next->v.i))
return_0;
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
@ -551,9 +551,7 @@ static int _read_segments(struct cmd_context *cmd,
struct format_type *fmt,
struct format_instance *fid,
struct dm_pool *mem,
struct logical_volume *lv, const struct dm_config_node *lvn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
struct logical_volume *lv, const struct dm_config_node *lvn)
{
const struct dm_config_node *sn;
int count = 0, seg_count;
@ -564,7 +562,7 @@ static int _read_segments(struct cmd_context *cmd,
* All sub-sections are assumed to be segments.
*/
if (!sn->v) {
if (!_read_segment(cmd, fmt, fid, mem, lv, sn, pv_hash, lv_hash))
if (!_read_segment(cmd, fmt, fid, mem, lv, sn))
return_0;
count++;
@ -591,7 +589,7 @@ static int _read_segments(struct cmd_context *cmd,
/*
* Check there are no gaps or overlaps in the lv.
*/
if (!check_lv_segments(lv, 0))
if (!check_lv_segments_incomplete_vg(lv))
return_0;
/*
@ -610,9 +608,7 @@ static int _read_lvnames(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *lvn,
const struct dm_config_node *vgn __attribute__((unused)),
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *vgn __attribute__((unused)))
{
struct logical_volume *lv;
const char *str;
@ -626,10 +622,11 @@ static int _read_lvnames(struct cmd_context *cmd,
if (!link_lv_to_vg(vg, lv))
return_0;
if (!(lv->name = dm_pool_strdup(mem, lvn->key)))
if (!(str = dm_pool_strdup(mem, lvn->key)) ||
!lv_set_name(lv, str))
return_0;
log_debug_metadata("Importing logical volume %s.", display_lvname(lv));
log_debug_metadata("Importing logical volume %s.", lv->name);
if (!(lvn = lvn->child)) {
log_error("Empty logical volume section for %s.",
@ -734,9 +731,6 @@ static int _read_lvnames(struct cmd_context *cmd,
return 0;
}
if (!dm_hash_insert(lv_hash, lv->name, lv))
return_0;
if (timestamp && !lv_set_creation(lv, hostname, timestamp))
return_0;
@ -769,9 +763,7 @@ static int _read_historical_lvnames(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *hlvn,
const struct dm_config_node *vgn __attribute__((unused)),
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash __attribute__((unused)))
const struct dm_config_node *vgn __attribute__((unused)))
{
struct generic_logical_volume *glv;
struct glv_list *glvl;
@ -842,9 +834,7 @@ static int _read_historical_lvnames_interconnections(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *hlvn,
const struct dm_config_node *vgn __attribute__((unused)),
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash __attribute__((unused)))
const struct dm_config_node *vgn __attribute__((unused)))
{
const char *historical_lv_name, *origin_name = NULL;
struct generic_logical_volume *glv, *origin_glv, *descendant_glv;
@ -956,13 +946,11 @@ static int _read_lvsegs(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *lvn,
const struct dm_config_node *vgn __attribute__((unused)),
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
const struct dm_config_node *vgn __attribute__((unused)))
{
struct logical_volume *lv;
if (!(lv = dm_hash_lookup(lv_hash, lvn->key))) {
if (!(lv = find_lv(vg, lvn->key))) {
log_error("Lost logical volume reference %s", lvn->key);
return 0;
}
@ -981,7 +969,7 @@ static int _read_lvsegs(struct cmd_context *cmd,
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
if (!_read_segments(cmd, fmt, fid, mem, lv, lvn, pv_hash, lv_hash))
if (!_read_segments(cmd, fmt, fid, mem, lv, lvn))
return_0;
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
@ -1022,8 +1010,6 @@ static int _read_sections(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_vgsummary *vgsummary,
const struct dm_config_node *vgn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash,
int optional)
{
const struct dm_config_node *n;
@ -1038,7 +1024,7 @@ static int _read_sections(struct cmd_context *cmd,
}
for (n = n->child; n; n = n->sib) {
if (!fn(cmd, (struct format_type *)fmt, fid, mem, vg, vgsummary, n, vgn, pv_hash, lv_hash))
if (!fn(cmd, (struct format_type *)fmt, fid, mem, vg, vgsummary, n, vgn))
return_0;
}
@ -1055,7 +1041,6 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
const struct dm_config_value *cv;
const char *str, *format_str, *system_id;
struct volume_group *vg;
struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL;
uint64_t vgstatus;
/* skip any top-level values */
@ -1073,20 +1058,20 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
mem = vg->vgmem;
/*
* The pv hash memorizes the pv section names -> pv
* The pv_names memorizes the pv section names -> pv
* structures.
*/
if (!(pv_hash = dm_hash_create(59))) {
log_error("Couldn't create pv hash table.");
if (!(vg->pv_names = radix_tree_create(NULL, NULL))) {
log_error("Couldn't create pv_names radix tree.");
goto bad;
}
/*
* The lv hash memorizes the lv section names -> lv
* The lv_names radix_tree memorizes the lv section names -> lv
* structures.
*/
if (!(lv_hash = dm_hash_create(1023))) {
log_error("Couldn't create lv hash table.");
if (!(vg->lv_names = radix_tree_create(NULL, NULL))) {
log_error("Couldn't create lv_names radix tree.");
goto bad;
}
@ -1205,7 +1190,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
if (!_read_sections(cmd, fmt, fid, mem, "physical_volumes", _read_pv, vg, NULL,
vgn, pv_hash, lv_hash, 0)) {
vgn, 0)) {
log_error("Couldn't find all physical volumes for volume "
"group %s.", vg->name);
goto bad;
@ -1219,57 +1204,54 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
if (!_read_sections(cmd, fmt, fid, mem, "logical_volumes", _read_lvnames, vg, NULL,
vgn, pv_hash, lv_hash, 1)) {
vgn, 1)) {
log_error("Couldn't read all logical volume names for volume "
"group %s.", vg->name);
goto bad;
}
if (!_read_sections(cmd, fmt, fid, mem, "historical_logical_volumes", _read_historical_lvnames, vg, NULL,
vgn, pv_hash, lv_hash, 1)) {
vgn, 1)) {
log_error("Couldn't read all historical logical volumes for volume "
"group %s.", vg->name);
goto bad;
}
if (!_read_sections(cmd, fmt, fid, mem, "logical_volumes", _read_lvsegs, vg, NULL,
vgn, pv_hash, lv_hash, 1)) {
vgn, 1)) {
log_error("Couldn't read all logical volumes for "
"volume group %s.", vg->name);
goto bad;
}
if (!_read_sections(cmd, fmt, fid, mem, "historical_logical_volumes", _read_historical_lvnames_interconnections,
vg, NULL, vgn, pv_hash, lv_hash, 1)) {
vg, NULL, vgn, 1)) {
log_error("Couldn't read all removed logical volume interconnections "
"for volume group %s.", vg->name);
goto bad;
}
if (!fixup_imported_mirrors(vg)) {
if (vg->fixup_imported_mirrors &&
!fixup_imported_mirrors(vg)) {
log_error("Failed to fixup mirror pointers after import for "
"volume group %s.", vg->name);
goto bad;
}
dm_hash_destroy(pv_hash);
dm_hash_destroy(lv_hash);
if (fid)
vg_set_fid(vg, fid);
if (vg->pv_names) {
radix_tree_destroy(vg->pv_names);
vg->pv_names = NULL; /* PV names are no longer valid outside of _read_vg() */
}
/*
* Finished.
*/
return vg;
bad:
if (pv_hash)
dm_hash_destroy(pv_hash);
if (lv_hash)
dm_hash_destroy(lv_hash);
release_vg(vg);
return NULL;
}
@ -1353,7 +1335,7 @@ static int _read_vgsummary(const struct format_type *fmt, const struct dm_config
}
if (!_read_sections(fmt->cmd, NULL, NULL, mem, "physical_volumes", _read_pvsummary, NULL, vgsummary,
vgn, NULL, NULL, 0)) {
vgn, 0)) {
log_debug("Couldn't read pv summaries");
}

View File

@ -23,7 +23,6 @@ struct lv_segment;
struct dm_config_node;
int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
const struct dm_config_value *cv, struct dm_hash_table *pv_hash,
uint64_t status);
const struct dm_config_value *cv, uint64_t status);
#endif

View File

@ -36,9 +36,7 @@ static void _integrity_display(const struct lv_segment *seg)
}
static int _integrity_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
struct integrity_settings *set;
struct logical_volume *origin_lv = NULL;
@ -59,7 +57,7 @@ static int _integrity_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "origin", &origin_name))
return SEG_LOG_ERROR("origin must be a string in");
if (!(origin_lv = dm_hash_lookup(lv_hash, origin_name)))
if (!(origin_lv = find_lv(seg->lv->vg, origin_name)))
return SEG_LOG_ERROR("Unknown LV specified for integrity origin %s in", origin_name);
if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
@ -104,7 +102,7 @@ static int _integrity_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "meta_dev", &meta_dev))
return SEG_LOG_ERROR("meta_dev must be a string in");
if (!(meta_lv = dm_hash_lookup(lv_hash, meta_dev)))
if (!(meta_lv = find_lv(seg->lv->vg, meta_dev)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for integrity in", meta_dev);
}

View File

@ -330,7 +330,6 @@ int vg_write_lock_held(void)
int sync_local_dev_names(struct cmd_context* cmd)
{
dm_devs_cache_destroy();
memlock_unlock(cmd);
fs_unlock();
return 1;

View File

@ -1407,6 +1407,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists
{
char uuid[64] __attribute__((aligned(8)));
const char *opts = NULL;
char opt_buf[64] = {};
daemon_reply reply;
uint32_t lockd_flags = 0;
int host_id = 0;
@ -1428,10 +1429,15 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists
return 0;
}
if (cmd->lockopt & LOCKOPT_ADOPTLS)
opts = "adopt_only";
else if (cmd->lockopt & LOCKOPT_ADOPT)
opts = "adopt";
if ((cmd->lockopt & LOCKOPT_NODELAY) ||
(cmd->lockopt & LOCKOPT_ADOPTLS) ||
(cmd->lockopt & LOCKOPT_ADOPT)) {
dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s",
(cmd->lockopt & LOCKOPT_NODELAY) ? "nodelay," : "",
(cmd->lockopt & LOCKOPT_ADOPTLS) ? "adopt_only" : "",
(cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : "");
opts = opt_buf;
}
log_debug("lockd start VG %s lock_type %s",
vg->name, vg->lock_type ? vg->lock_type : "empty");
@ -3266,7 +3272,7 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
} else if (seg_is_thin(lp)) {
if ((seg_is_thin_volume(lp) && !lp->create_pool) ||
(!seg_is_thin_volume(lp) && lp->origin_name)) {
struct lv_list *lvl;
struct logical_volume *thin_pool_lv;
/*
* Creating a new thin lv or snapshot. These lvs do not get
@ -3275,11 +3281,11 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
*/
log_debug("lockd_init_lv thin %s locking thin pool", display_lvname(lv));
if (!(lvl = find_lv_in_vg(vg, lp->pool_name))) {
if (!(thin_pool_lv = find_lv(vg, lp->pool_name))) {
log_error("Failed to find thin pool %s/%s", vg->name, lp->pool_name);
return 0;
}
if (!lockd_lv(cmd, lvl->lv, "ex", 0)) {
if (!lockd_lv(cmd, thin_pool_lv, "ex", 0)) {
log_error("Failed to lock thin pool %s/%s", vg->name, lp->pool_name);
return 0;
}
@ -3308,7 +3314,7 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
}
} else if (seg_is_vdo(lp)) {
struct lv_list *lvl;
struct logical_volume *vdo_pool_lv;
/*
* A vdo lv is being created in a vdo pool. The vdo lv does
@ -3316,12 +3322,12 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
* the vdo pool needs to be locked to create a vdo lv in it.
*/
if (!(lvl = find_lv_in_vg(vg, lp->pool_name))) {
if (!(vdo_pool_lv = find_lv(vg, lp->pool_name))) {
log_error("Failed to find vdo pool %s/%s", vg->name, lp->pool_name);
return 0;
}
if (!lockd_lv(cmd, lvl->lv, "ex", LDLV_PERSISTENT)) {
if (!lockd_lv(cmd, vdo_pool_lv, "ex", LDLV_PERSISTENT)) {
log_error("Failed to lock vdo pool %s/%s", vg->name, lp->pool_name);
return 0;
}
@ -3797,6 +3803,8 @@ void lockd_lockopt_get_flags(const char *str, uint32_t *flags)
*flags |= LOCKOPT_ADOPTLV;
else if (!strcmp(argv[i], "adopt"))
*flags |= LOCKOPT_ADOPT;
else if (!strcmp(argv[i], "nodelay"))
*flags |= LOCKOPT_NODELAY;
else
log_warn("Ignoring unknown lockopt value: %s", argv[i]);
}

View File

@ -54,6 +54,7 @@
#define LOCKOPT_ADOPTVG 0x00000800
#define LOCKOPT_ADOPTLV 0x00001000
#define LOCKOPT_ADOPT 0x00002000
#define LOCKOPT_NODELAY 0x00004000
#ifdef LVMLOCKD_SUPPORT
@ -273,7 +274,6 @@ static inline int lockd_free_lv_after_update(struct cmd_context *cmd, struct vol
static inline void lockd_free_removed_lvs(struct cmd_context *cmd, struct volume_group *vg, int remove_success)
{
return 1;
}
static inline const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple)

View File

@ -539,7 +539,7 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
{
va_list ap;
char buf[1024], message[4096];
char time_prefix[32] = "";
char time_prefix[32];
const char *command_prefix = NULL;
int n;
const char *trformat; /* Translated format string */
@ -690,15 +690,12 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
}
#endif
time_prefix[0] = '\0';
if (!logged_via_report && ((verbose_level() >= level) && !_log_suppress)) {
if (verbose_level() > _LOG_DEBUG) {
memset(buf, 0, sizeof(buf));
if (!_debug_output_fields || (_debug_output_fields & LOG_DEBUG_FIELD_TIME)) {
if (!time_prefix[0])
_set_time_prefix(time_prefix, sizeof(time_prefix));
else
time_prefix[0] = '\0';
}
if (!_debug_output_fields || (_debug_output_fields & LOG_DEBUG_FIELD_COMMAND))
@ -713,8 +710,6 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
(void) dm_snprintf(buf, sizeof(buf), "%s%s",
time_prefix, command_prefix ?: "");
} else {
memset(buf, 0, sizeof(buf));
/* without -vvvv, command[pid] is controlled by config settings */
(void) dm_snprintf(buf, sizeof(buf), "%s", log_command_info());
@ -763,8 +758,6 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
if (!_debug_file_fields || (_debug_file_fields & LOG_DEBUG_FIELD_TIME)) {
if (!time_prefix[0])
_set_time_prefix(time_prefix, sizeof(time_prefix));
else
time_prefix[0] = '\0';
}
if (!_debug_file_fields || (_debug_file_fields & LOG_DEBUG_FIELD_COMMAND))
@ -862,13 +855,13 @@ void log_set_report_object_type(log_report_object_type_t object_type)
_log_report.object_type = object_type;
}
void log_set_report_object_group_and_group_id(const char *group, const char *id)
void log_set_report_object_group_and_group_id(const char *group, const struct id *id)
{
_log_report.object_group = group;
_log_report.object_group_id = id;
}
void log_set_report_object_name_and_id(const char *name, const char *id)
void log_set_report_object_name_and_id(const char *name, const struct id *id)
{
_log_report.object_name = name;
_log_report.object_id = id;

View File

@ -106,9 +106,9 @@ typedef struct log_report {
log_report_context_t context;
log_report_object_type_t object_type;
const char *object_name;
const char *object_id;
const struct id *object_id;
const char *object_group;
const char *object_group_id;
const struct id *object_group_id;
} log_report_t;
#define LOG_STATUS_NAME "status"
@ -121,8 +121,8 @@ void log_restore_report_state(log_report_t log_report);
void log_set_report(struct dm_report *report);
void log_set_report_context(log_report_context_t context);
void log_set_report_object_type(log_report_object_type_t object_type);
void log_set_report_object_group_and_group_id(const char *group, const char *group_id);
void log_set_report_object_name_and_id(const char *name, const char *id);
void log_set_report_object_group_and_group_id(const char *group, const struct id *group_id);
void log_set_report_object_name_and_id(const char *name, const struct id *id);
const char *log_get_report_context_name(log_report_context_t context);
const char *log_get_report_object_type_name(log_report_object_type_t object_type);

View File

@ -21,6 +21,7 @@
#include "lib/metadata/segtype.h"
#include "lib/datastruct/str_list.h"
#include "lib/locking/lvmlockd.h"
#include "base/data-struct/radix-tree.h"
#include <time.h>
#include <sys/utsname.h>
@ -1568,11 +1569,50 @@ int lv_set_creation(struct logical_volume *lv,
_utsinit = 1;
}
hostname = _utsname.nodename;
lv->hostname = _utsname.nodename;
} else
lv->hostname = dm_pool_strdup(lv->vg->vgmem, hostname);
lv->timestamp = timestamp ? : (uint64_t) time(NULL);
return 1;
}
/*
* As we keep now vg->lv_names for quick looking of an LV by name
* when the LV name is changed, we need to also update our lookup tree
*/
int lv_set_name(struct logical_volume *lv, const char *lv_name)
{
if (lv->vg->lv_names && lv->name &&
!radix_tree_remove(lv->vg->lv_names, lv->name, strlen(lv->name))) {
log_error("Cannot remove from lv_names LV %s", lv->name);
return 0;
}
lv->hostname = dm_pool_strdup(lv->vg->vgmem, hostname);
lv->timestamp = timestamp ? : (uint64_t) time(NULL);
lv->name = lv_name; /* NULL -> LV is removed from tree */
if (lv->vg->lv_names && lv->name &&
!radix_tree_insert_ptr(lv->vg->lv_names, lv->name, strlen(lv->name), lv)) {
log_error("Cannot insert to lv_names LV %s", lv->name);
return 0;
}
return 1;
}
int lv_set_vg(struct logical_volume *lv, struct volume_group *vg)
{
const char *lv_name;
if (lv->vg != vg) {
lv_name = lv->name;
if (!lv_set_name(lv, NULL))
return_0; /* drop from existing VG radix_tree */
lv->vg = vg;
if (!lv_set_name(lv, lv_name))
return_0;
}
return 1;
}

View File

@ -153,6 +153,8 @@ char *lvseg_kernel_discards_dup(struct dm_pool *mem, const struct lv_segment *se
/* LV modification functions */
int lv_set_creation(struct logical_volume *lv,
const char *hostname, uint64_t timestamp);
int lv_set_name(struct logical_volume *lv, const char *lv_name);
int lv_set_vg(struct logical_volume *lv, struct volume_group *vg);
int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
enum activation_change activate);

View File

@ -32,6 +32,7 @@
#include "lib/label/label.h"
#include "lib/misc/lvm-signal.h"
#include "lib/device/filesystem.h"
#include "base/data-struct/radix-tree.h"
#ifdef HAVE_BLKZEROOUT
#include <sys/ioctl.h>
@ -868,7 +869,7 @@ int add_seg_to_segs_using_this_lv(struct logical_volume *lv,
}
log_very_verbose("Adding %s:" FMTu32 " as an user of %s.",
display_lvname(seg->lv), seg->le, display_lvname(lv));
seg->lv->name, seg->le, lv->name);
if (!(sl = dm_pool_zalloc(lv->vg->vgmem, sizeof(*sl)))) {
log_error("Failed to allocate segment list.");
@ -1303,8 +1304,7 @@ int set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
uint64_t status)
{
log_very_verbose("Stack %s:" FMTu32 "[" FMTu32 "] on LV %s:" FMTu32 ".",
display_lvname(seg->lv), seg->le, area_num,
display_lvname(lv), le);
seg->lv->name, seg->le, area_num, lv->name, le);
if (area_num >= seg->area_count) {
log_error(INTERNAL_ERROR "Try to set to high area number (%u >= %u) for LV %s.",
@ -1581,7 +1581,7 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
return_0;
}
if (seg_is_thin_pool(seg)) {
if (seg_is_thin_pool(seg) && seg_lv(seg, 0)) {
/* For some segtypes the size may differ between the segment size and its layered LV
* i.e. thin-pool and tdata.
*
@ -1834,6 +1834,11 @@ int historical_glv_remove(struct generic_logical_volume *glv)
*/
int lv_remove(struct logical_volume *lv)
{
if (!lv) {
log_error(INTERNAL_ERROR "Cannot remove undefined LV.");
return 0;
}
if (lv_is_historical(lv))
return historical_glv_remove(lv->this_glv);
@ -4655,7 +4660,8 @@ static int _rename_single_lv(struct logical_volume *lv, char *new_name)
return 0;
}
lv->name = new_name;
if (!lv_set_name(lv, new_name))
return_0;
return 1;
}
@ -4878,7 +4884,8 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
return_0;
/* rename main LV */
lv->name = lv_names.new;
if (!lv_set_name(lv, lv_names.new))
return_0;
if (lv_is_cow(lv))
lv = origin_from_cow(lv);
@ -6643,6 +6650,7 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
int is_active = 0;
int activated = 0;
int activated_checksize = 0;
int resize_fs = !strncmp(lp->fsopt, "resize", 6);
int status;
int ret = 0;
@ -6881,9 +6889,10 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
/*
* No resizing is needed.
*/
if ((main_size_matches && meta_size_matches) ||
(main_size_matches && !lv_meta) ||
(meta_size_matches && !lv_main)) {
if (!resize_fs &&
((main_size_matches && meta_size_matches) ||
(main_size_matches && !lv_meta) ||
(meta_size_matches && !lv_main))) {
log_error("No size change.");
return 0;
}
@ -7096,11 +7105,18 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
goto end_main;
if (!_lv_resize_volume(lv_main, lp, lp->pvh))
goto_out;
if (!lp->size_changed)
goto_out;
if (!lv_update_and_reload(lv_top))
goto_out;
log_debug("Resized %s to %u extents.", display_lvname(lv_main), lp->extents);
if (!lp->size_changed) {
if (!resize_fs)
goto_out;
/* Even when the new volume size does NOT change, command still should resize
* the filesystem, we still run filesystem resize tool to eventually
* match the volume size. Return code of command then reflects the result
* of such operation thus it's valid to 'lvresize -f -Lsamesize vg/lv' */
} else {
if (!lv_update_and_reload(lv_top))
goto_out;
log_debug("Resized %s to %u extents.", display_lvname(lv_main), lp->extents);
}
end_main:
@ -7308,11 +7324,9 @@ struct logical_volume *lv_create_empty(const char *name,
struct format_instance *fi = vg->fid;
struct logical_volume *lv;
char dname[NAME_LEN];
const char *lv_name;
int historical;
if (vg_max_lv_reached(vg))
stack;
if (strstr(name, "%d") &&
!(name = generate_lv_name(vg, name, dname, sizeof(dname)))) {
log_error("Failed to generate unique name for the new "
@ -7332,7 +7346,11 @@ struct logical_volume *lv_create_empty(const char *name,
if (!(lv = alloc_lv(vg->vgmem)))
return_NULL;
if (!(lv->name = dm_pool_strdup(vg->vgmem, name)))
if (!link_lv_to_vg(vg, lv))
goto_bad;
if (!(lv_name = dm_pool_strdup(vg->vgmem, name)) ||
!lv_set_name(lv, lv_name))
goto_bad;
lv->status = status;
@ -7346,9 +7364,6 @@ struct logical_volume *lv_create_empty(const char *name,
if (lvid)
lv->lvid = *lvid;
if (!link_lv_to_vg(vg, lv))
goto_bad;
if (!lv_set_creation(lv, NULL, 0))
goto_bad;

View File

@ -605,14 +605,106 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
}
}
int check_lv_segments_complete_vg(struct logical_volume *lv)
{
struct lv_segment *seg, *seg2;
unsigned seg_count = 0, external_lv_found = 0;
uint32_t s;
struct seg_list *sl;
int error_count = 0;
dm_list_iterate_items(seg, &lv->segments) {
seg_count++;
_check_lv_segment(lv, seg, seg_count, &error_count);
for (s = 0; s < seg->area_count; s++) {
if ((seg_type(seg, s) == AREA_LV) &&
seg_lv(seg, s) &&
lv_is_mirror_image(seg_lv(seg, s)) &&
(!(seg2 = find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))) ||
find_mirror_seg(seg2) != seg)) {
log_error("LV %s: segment %u mirror "
"image %u missing mirror ptr",
lv->name, seg_count, s);
inc_error_count;
}
if (seg_is_mirrored(seg) && !seg_is_raid(seg) &&
seg_type(seg, s) == AREA_LV && seg_lv(seg, s) &&
seg_lv(seg, s)->le_count != seg->area_len) {
log_error("LV %s: mirrored LV segment %u has "
"wrong size %u (should be %u).",
lv->name, s, seg_lv(seg, s)->le_count,
seg->area_len);
inc_error_count;
}
}
}
/* Check LV flags match first segment type */
if ((seg_count != 1) &&
(lv_is_cache(lv) ||
lv_is_cache_pool(lv) ||
lv_is_raid(lv) ||
lv_is_snapshot(lv) ||
lv_is_thin_pool(lv) ||
lv_is_thin_volume(lv))) {
log_error("LV %s must have exactly one segment.",
lv->name);
inc_error_count;
}
if (lv_is_pool_data(lv) &&
(!(seg2 = first_seg(lv)) || !(seg2 = find_pool_seg(seg2)) ||
seg2->area_count != 1 || seg_type(seg2, 0) != AREA_LV ||
seg_lv(seg2, 0) != lv)) {
log_error("LV %s: segment 1 pool data LV does not point back to same LV",
lv->name);
inc_error_count;
}
if (lv_is_thin_pool_metadata(lv) && !strstr(lv->name, "_tmeta")) {
log_error("LV %s: thin pool metadata LV does not use _tmeta.",
lv->name);
inc_error_count;
} else if (lv_is_cache_pool_metadata(lv) && !strstr(lv->name, "_cmeta")) {
log_error("LV %s: cache pool metadata LV does not use _cmeta.",
lv->name);
inc_error_count;
}
if (lv_is_external_origin(lv)) {
/* Validation of external origin counter */
dm_list_iterate_items(sl, &lv->segs_using_this_lv)
if (sl->seg->external_lv == lv)
external_lv_found++;
if (lv->external_count != external_lv_found) {
log_error("LV %s: external origin count does not match.",
lv->name);
inc_error_count;
}
if (lv->status & LVM_WRITE) {
log_error("LV %s: external origin can't be writable.",
lv->name);
inc_error_count;
}
}
out:
return !error_count;
}
/*
* Verify that an LV's segments are consecutive, complete and don't overlap.
*/
int check_lv_segments(struct logical_volume *lv, int complete_vg)
int check_lv_segments_incomplete_vg(struct logical_volume *lv)
{
struct lv_segment *seg, *seg2;
uint32_t le = 0;
unsigned seg_count = 0, seg_found, external_lv_found = 0;
unsigned seg_count = 0, seg_found;
uint32_t data_rimage_count, s;
struct seg_list *sl;
struct glv_list *glvl;
@ -653,9 +745,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
}
if (complete_vg)
_check_lv_segment(lv, seg, seg_count, &error_count);
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_UNASSIGNED) {
log_error("LV %s: segment %u has unassigned "
@ -681,16 +770,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count;
}
if (complete_vg && seg_lv(seg, s) &&
lv_is_mirror_image(seg_lv(seg, s)) &&
(!(seg2 = find_seg_by_le(seg_lv(seg, s),
seg_le(seg, s))) ||
find_mirror_seg(seg2) != seg)) {
log_error("LV %s: segment %u mirror "
"image %u missing mirror ptr",
lv->name, seg_count, s);
inc_error_count;
}
/* FIXME I don't think this ever holds?
if (seg_le(seg, s) != le) {
@ -722,16 +801,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
}
if (complete_vg &&
seg_is_mirrored(seg) && !seg_is_raid(seg) &&
seg_type(seg, s) == AREA_LV &&
seg_lv(seg, s)->le_count != seg->area_len) {
log_error("LV %s: mirrored LV segment %u has "
"wrong size %u (should be %u).",
lv->name, s, seg_lv(seg, s)->le_count,
seg->area_len);
inc_error_count;
}
}
le += seg->len;
@ -802,10 +871,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
lv->name);
inc_error_count;
}
/* Validation of external origin counter */
if (seg->external_lv == lv)
external_lv_found++;
}
dm_list_iterate_items(glvl, &lv->indirect_glvs) {
@ -827,53 +892,6 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
}
}
/* Check LV flags match first segment type */
if (complete_vg) {
if ((seg_count != 1) &&
(lv_is_cache(lv) ||
lv_is_cache_pool(lv) ||
lv_is_raid(lv) ||
lv_is_snapshot(lv) ||
lv_is_thin_pool(lv) ||
lv_is_thin_volume(lv))) {
log_error("LV %s must have exactly one segment.",
lv->name);
inc_error_count;
}
if (lv_is_pool_data(lv) &&
(!(seg2 = first_seg(lv)) || !(seg2 = find_pool_seg(seg2)) ||
seg2->area_count != 1 || seg_type(seg2, 0) != AREA_LV ||
seg_lv(seg2, 0) != lv)) {
log_error("LV %s: segment 1 pool data LV does not point back to same LV",
lv->name);
inc_error_count;
}
if (lv_is_thin_pool_metadata(lv) && !strstr(lv->name, "_tmeta")) {
log_error("LV %s: thin pool metadata LV does not use _tmeta.",
lv->name);
inc_error_count;
} else if (lv_is_cache_pool_metadata(lv) && !strstr(lv->name, "_cmeta")) {
log_error("LV %s: cache pool metadata LV does not use _cmeta.",
lv->name);
inc_error_count;
}
if (lv_is_external_origin(lv)) {
if (lv->external_count != external_lv_found) {
log_error("LV %s: external origin count does not match.",
lv->name);
inc_error_count;
}
if (lv->status & LVM_WRITE) {
log_error("LV %s: external origin can't be writable.",
lv->name);
inc_error_count;
}
}
}
out:
return !error_count;
}

View File

@ -34,6 +34,7 @@
#include "lib/config/defaults.h"
#include "lib/locking/lvmlockd.h"
#include "lib/notify/lvmnotify.h"
#include "base/data-struct/radix-tree.h"
#include <time.h>
#include <math.h>
@ -1670,8 +1671,12 @@ struct logical_volume *find_lv_in_vg_by_lvid(const struct volume_group *vg,
struct logical_volume *find_lv(const struct volume_group *vg,
const char *lv_name)
{
struct lv_list *lvl = find_lv_in_vg(vg, lv_name);
return lvl ? lvl->lv : NULL;
if (!vg->lv_names) {
struct lv_list *lvl = find_lv_in_vg(vg, lv_name);
return lvl ? lvl->lv : NULL;
}
return radix_tree_lookup_ptr(vg->lv_names, lv_name, strlen(lv_name));
}
struct generic_logical_volume *find_historical_glv(const struct volume_group *vg,
@ -1733,6 +1738,16 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL;
}
struct physical_volume *find_pv_by_pv_name(struct volume_group *vg, const char *pv_name)
{
if (!vg->pv_names) {
log_error(INTERNAL_ERROR "Cannot find pv name %s outside of _read_vg()", pv_name);
return NULL;
}
return radix_tree_lookup_ptr(vg->pv_names, pv_name, strlen(pv_name));
}
/* Find segment at a given logical extent in an LV */
struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le)
{
@ -2116,12 +2131,12 @@ void lv_calculate_readahead(const struct logical_volume *lv, uint32_t *read_ahea
}
struct validate_hash {
struct dm_hash_table *lvname;
struct dm_hash_table *historical_lvname;
struct dm_hash_table *lvid;
struct dm_hash_table *historical_lvid;
struct dm_hash_table *pvid;
struct dm_hash_table *lv_lock_args;
struct radix_tree *lvname;
struct radix_tree *historical_lvname;
struct radix_tree *lvid;
struct radix_tree *historical_lvid;
struct radix_tree *pvid;
struct radix_tree *lv_lock_args;
};
/*
@ -2139,7 +2154,7 @@ static int _lv_validate_references_single(struct logical_volume *lv, void *data)
unsigned s;
int r = 1;
if (lv != dm_hash_lookup_binary(vhash->lvid, &lv->lvid.id[1],
if (lv != radix_tree_lookup_ptr(vhash->lvid, &lv->lvid.id[1],
sizeof(lv->lvid.id[1]))) {
log_error(INTERNAL_ERROR
"Referenced LV %s not listed in VG %s.",
@ -2153,7 +2168,7 @@ static int _lv_validate_references_single(struct logical_volume *lv, void *data)
continue;
pv = seg_pv(lvseg, s);
/* look up the reference in vg->pvs */
if (pv != dm_hash_lookup_binary(vhash->pvid, &pv->id,
if (pv != radix_tree_lookup_ptr(vhash->pvid, &pv->id,
sizeof(pv->id))) {
log_error(INTERNAL_ERROR
"Referenced PV %s not listed in VG %s.",
@ -2252,7 +2267,7 @@ int vg_validate(struct volume_group *vg)
struct dm_str_list *sl;
char uuid[64] __attribute__((aligned(8)));
char uuid2[64] __attribute__((aligned(8)));
int r = 1;
int r = 1, rt;
unsigned hidden_lv_count = 0, lv_count = 0, lv_visible_count = 0;
unsigned pv_count = 0;
unsigned num_snapshots = 0;
@ -2274,7 +2289,7 @@ int vg_validate(struct volume_group *vg)
}
/* FIXME Also check there's no data/metadata overlap */
if (!(vhash.pvid = dm_hash_create(vg->pv_count))) {
if (!(vhash.pvid = radix_tree_create(NULL, NULL))) {
log_error("Failed to allocate pvid hash.");
return 0;
}
@ -2306,8 +2321,14 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
if (dm_hash_lookup_binary(vhash.pvid, &pvl->pv->id,
sizeof(pvl->pv->id))) {
if (1 != (rt = radix_tree_uniq_insert_ptr(vhash.pvid, &pvl->pv->id,
sizeof(pvl->pv->id), pvl->pv))) {
r = 0;
if (!rt) {
log_error("Failed to store pvid.");
goto out;
}
if (!id_write_format(&pvl->pv->id, uuid,
sizeof(uuid)))
stack;
@ -2315,7 +2336,6 @@ int vg_validate(struct volume_group *vg)
"%s detected for %s in %s.",
uuid, pv_dev_name(pvl->pv),
vg->name);
r = 0;
}
dm_list_iterate_items(sl, &pvl->pv->tags)
@ -2324,13 +2344,6 @@ int vg_validate(struct volume_group *vg)
pv_dev_name(pvl->pv), sl->str);
r = 0;
}
if (!dm_hash_insert_binary(vhash.pvid, &pvl->pv->id,
sizeof(pvl->pv->id), pvl->pv)) {
log_error("Failed to hash pvid.");
r = 0;
break;
}
}
@ -2399,7 +2412,7 @@ int vg_validate(struct volume_group *vg)
}
}
if (!check_lv_segments(lvl->lv, 0)) {
if (!check_lv_segments_incomplete_vg(lvl->lv)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.",
lvl->lv->name);
r = 0;
@ -2453,57 +2466,55 @@ int vg_validate(struct volume_group *vg)
if (!r)
goto out;
if (!(vhash.lvname = dm_hash_create(lv_count))) {
if (!(vhash.lvname = radix_tree_create(NULL, NULL))) {
log_error("Failed to allocate lv_name hash");
r = 0;
goto out;
}
if (!(vhash.lvid = dm_hash_create(lv_count))) {
if (!(vhash.lvid = radix_tree_create(NULL, NULL))) {
log_error("Failed to allocate uuid hash");
r = 0;
goto out;
}
dm_list_iterate_items(lvl, &vg->lvs) {
if (dm_hash_lookup(vhash.lvname, lvl->lv->name)) {
/* For best CPU cache utilization do a separate pass for lvname and lvid */
dm_list_iterate_items(lvl, &vg->lvs)
if (1 != (rt = radix_tree_uniq_insert_ptr(vhash.lvname, lvl->lv->name,
strlen(lvl->lv->name), lvl))) {
r = 0;
if (!rt) {
log_error("Failed to store lvname.");
goto out;
}
log_error(INTERNAL_ERROR
"Duplicate LV name %s detected in %s.",
lvl->lv->name, vg->name);
r = 0;
}
if (dm_hash_lookup_binary(vhash.lvid, &lvl->lv->lvid.id[1],
sizeof(lvl->lv->lvid.id[1]))) {
dm_list_iterate_items(lvl, &vg->lvs)
if (1 != (rt = radix_tree_uniq_insert_ptr(vhash.lvid, &lvl->lv->lvid.id[1],
sizeof(lvl->lv->lvid.id[1]), lvl->lv))) {
r = 0;
if (!rt) {
log_error("Failed to store lvid.");
goto out;
}
if (!id_write_format(&lvl->lv->lvid.id[1], uuid,
sizeof(uuid)))
stack;
log_error(INTERNAL_ERROR "Duplicate LV id "
"%s detected for %s in %s.",
log_error(INTERNAL_ERROR "Duplicate LV id %s detected for %s in %s.",
uuid, lvl->lv->name, vg->name);
r = 0;
}
if (!check_lv_segments(lvl->lv, 1)) {
dm_list_iterate_items(lvl, &vg->lvs)
if (!check_lv_segments_complete_vg(lvl->lv)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.",
lvl->lv->name);
r = 0;
}
if (!dm_hash_insert(vhash.lvname, lvl->lv->name, lvl)) {
log_error("Failed to hash lvname.");
r = 0;
break;
}
if (!dm_hash_insert_binary(vhash.lvid, &lvl->lv->lvid.id[1],
sizeof(lvl->lv->lvid.id[1]), lvl->lv)) {
log_error("Failed to hash lvid.");
r = 0;
break;
}
}
if (!_lv_postorder_vg(vg, _lv_validate_references_single, &vhash)) {
stack;
r = 0;
@ -2546,7 +2557,7 @@ int vg_validate(struct volume_group *vg)
if (vg_max_lv_reached(vg))
stack;
if (!(vhash.lv_lock_args = dm_hash_create(lv_count))) {
if (!(vhash.lv_lock_args = radix_tree_create(NULL, NULL))) {
log_error("Failed to allocate lv_lock_args hash");
r = 0;
goto out;
@ -2641,13 +2652,15 @@ int vg_validate(struct volume_group *vg)
}
if (!strcmp(vg->lock_type, "sanlock")) {
if (dm_hash_lookup(vhash.lv_lock_args, lvl->lv->lock_args)) {
if (radix_tree_lookup_ptr(vhash.lv_lock_args, lvl->lv->lock_args,
strlen(lvl->lv->lock_args))) {
log_error(INTERNAL_ERROR "LV %s has duplicate lock_args %s.",
display_lvname(lvl->lv), lvl->lv->lock_args);
r = 0;
}
if (!dm_hash_insert(vhash.lv_lock_args, lvl->lv->lock_args, lvl)) {
if (!radix_tree_insert_ptr(vhash.lv_lock_args, lvl->lv->lock_args,
strlen(lvl->lv->lock_args), lvl)) {
log_error("Failed to hash lvname.");
r = 0;
}
@ -2671,19 +2684,19 @@ int vg_validate(struct volume_group *vg)
}
}
if (!(vhash.historical_lvname = dm_hash_create(dm_list_size(&vg->historical_lvs)))) {
if (!(vhash.historical_lvname = radix_tree_create(NULL, NULL))) {
r = 0;
goto_out;
}
if (!(vhash.historical_lvid = dm_hash_create(dm_list_size(&vg->historical_lvs)))) {
r = 0;
goto_out;
}
if (!(vhash.historical_lvid = radix_tree_create(NULL, NULL))) {
r = 0;
goto_out;
}
dm_list_iterate_items(glvl, &vg->historical_lvs) {
if (!glvl->glv->is_historical) {
log_error(INTERNAL_ERROR "LV %s/%s appearing in VG's historical list is not a historical LV",
log_error(INTERNAL_ERROR "LV %s/%s appearing in VG's historical list is not a historical LV.",
vg->name, glvl->glv->live->name);
r = 0;
continue;
@ -2692,7 +2705,7 @@ int vg_validate(struct volume_group *vg)
hlv = glvl->glv->historical;
if (hlv->vg != vg) {
log_error(INTERNAL_ERROR "Historical LV %s points to different VG %s while it is listed in VG %s",
log_error(INTERNAL_ERROR "Historical LV %s points to different VG %s while it is listed in VG %s.",
hlv->name, hlv->vg->name, vg->name);
r = 0;
continue;
@ -2706,62 +2719,57 @@ int vg_validate(struct volume_group *vg)
log_error(INTERNAL_ERROR "Historical LV %s has VG UUID %s but its VG %s has UUID %s",
hlv->name, uuid, hlv->vg->name, uuid2);
r = 0;
continue;
}
if (dm_hash_lookup_binary(vhash.historical_lvid, &hlv->lvid.id[1], sizeof(hlv->lvid.id[1]))) {
if (!id_write_format(&hlv->lvid.id[1], uuid,sizeof(uuid)))
stack;
log_error(INTERNAL_ERROR "Duplicate historical LV id %s detected for %s in %s",
uuid, hlv->name, vg->name);
r = 0;
}
if (dm_hash_lookup(vhash.historical_lvname, hlv->name)) {
log_error(INTERNAL_ERROR "Duplicate historical LV name %s detected in %s", hlv->name, vg->name);
r = 0;
continue;
}
if (!dm_hash_insert(vhash.historical_lvname, hlv->name, hlv)) {
log_error("Failed to hash historical LV name");
r = 0;
break;
}
if (1 != (rt = radix_tree_uniq_insert_ptr(vhash.historical_lvname, hlv->name,
strlen(hlv->name), hlv))) {
r = 0;
if (!rt) {
log_error("Failed to store historical LV name.");
goto out;
}
log_error(INTERNAL_ERROR "Duplicate historical LV name %s detected in %s.",
hlv->name, vg->name);
}
if (!dm_hash_insert_binary(vhash.historical_lvid, &hlv->lvid.id[1], sizeof(hlv->lvid.id[1]), hlv)) {
log_error("Failed to hash historical LV id");
r = 0;
break;
}
if (1 != (rt = radix_tree_uniq_insert_ptr(vhash.historical_lvid, &hlv->lvid.id[1],
sizeof(hlv->lvid.id[1]), hlv))) {
r = 0;
if (!rt) {
log_error("Failed to store historical LV id.");
goto out;
}
if (!id_write_format(&hlv->lvid.id[1], uuid,sizeof(uuid)))
stack;
log_error(INTERNAL_ERROR "Duplicate historical LV id %s detected for %s in %s.",
uuid, hlv->name, vg->name);
}
if (dm_hash_lookup(vhash.lvname, hlv->name)) {
log_error(INTERNAL_ERROR "Name %s appears as live and historical LV at the same time in VG %s",
if (radix_tree_lookup_ptr(vhash.lvname, hlv->name, strlen(hlv->name))) {
log_error(INTERNAL_ERROR "Name %s appears as live and historical LV at the same time in VG %s.",
hlv->name, vg->name);
r = 0;
continue;
}
if (!hlv->indirect_origin && dm_list_empty(&hlv->indirect_glvs)) {
log_error(INTERNAL_ERROR "Historical LV %s is not part of any LV chain in VG %s", hlv->name, vg->name);
log_error(INTERNAL_ERROR "Historical LV %s is not part of any LV chain in VG %s.",
hlv->name, vg->name);
r = 0;
continue;
}
}
out:
if (vhash.lvid)
dm_hash_destroy(vhash.lvid);
radix_tree_destroy(vhash.lvid);
if (vhash.lvname)
dm_hash_destroy(vhash.lvname);
radix_tree_destroy(vhash.lvname);
if (vhash.historical_lvid)
dm_hash_destroy(vhash.historical_lvid);
radix_tree_destroy(vhash.historical_lvid);
if (vhash.historical_lvname)
dm_hash_destroy(vhash.historical_lvname);
radix_tree_destroy(vhash.historical_lvname);
if (vhash.pvid)
dm_hash_destroy(vhash.pvid);
radix_tree_destroy(vhash.pvid);
if (vhash.lv_lock_args)
dm_hash_destroy(vhash.lv_lock_args);
radix_tree_destroy(vhash.lv_lock_args);
return r;
}
@ -3020,11 +3028,14 @@ int vg_write(struct volume_group *vg)
/* Write to each copy of the metadata area */
dm_list_iterate_items(mda, &vg->fid->metadata_areas_in_use) {
mda_dev = mda_get_device(mda);
if (mda->status & MDA_FAILED)
continue;
if (!(mda_dev = mda_get_device(mda))) {
log_warn("WARNING: mda without device.");
continue;
}
/*
* When the scan and vg_read find old metadata in an mda, they
* leave the info struct in lvmcache, and leave the mda in
@ -5071,17 +5082,9 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
goto bad;
}
dm_list_iterate_items(lvl, &vg->lvs) {
if (!check_lv_segments(lvl->lv, 0)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name);
failure |= FAILED_INTERNAL_ERROR;
goto bad;
}
}
dm_list_iterate_items(lvl, &vg->lvs) {
/* Checks that cross-reference other LVs. */
if (!check_lv_segments(lvl->lv, 1)) {
if (!check_lv_segments_complete_vg(lvl->lv)) {
log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name);
failure |= FAILED_INTERNAL_ERROR;
goto bad;

View File

@ -35,7 +35,7 @@
#define MIN_PE_SIZE (8192L >> SECTOR_SHIFT) /* 8 KB in sectors - format1 only */
#define MAX_PE_SIZE (16L * 1024L * (1024L >> SECTOR_SHIFT) * 1024L) /* format1 only */
#define MIRROR_LOG_OFFSET 2 /* sectors */
#define VG_MEMPOOL_CHUNK 10240 /* in bytes, hint only */
#define VG_MEMPOOL_CHUNK 63000 /* in bytes, hint only */
/*
* Ceiling(n / sz)
@ -395,6 +395,7 @@ struct logical_volume *find_lv_in_vg_by_lvid(const struct volume_group *vg,
/* FIXME Merge these functions with ones above */
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
struct physical_volume *find_pv_by_pv_name(struct volume_group *vg, const char *pv_name);
struct pv_list *find_pv_in_pv_list(const struct dm_list *pl,
const struct physical_volume *pv);
@ -418,11 +419,10 @@ const char *strip_dir(const char *vg_name, const char *dev_dir);
struct logical_volume *alloc_lv(struct dm_pool *mem);
/*
* Checks that an lv has no gaps or overlapping segments.
* Set complete_vg to perform additional VG level checks.
*/
int check_lv_segments(struct logical_volume *lv, int complete_vg);
/* Checks that an lv has no gaps or overlapping segments. */
int check_lv_segments_incomplete_vg(struct logical_volume *lv);
/* Aditional VG level checks on lv segment. */
int check_lv_segments_complete_vg(struct logical_volume *lv);
/*
* Does every LV segment have the same number of stripes?

View File

@ -596,6 +596,7 @@ static int _split_mirror_images(struct logical_volume *lv,
struct lv_list *lvl;
struct cmd_context *cmd = lv->vg->cmd;
char layer_name[NAME_LEN], format[NAME_LEN];
const char *lv_name;
int act;
if (!lv_is_mirrored(lv)) {
@ -662,8 +663,8 @@ static int _split_mirror_images(struct logical_volume *lv,
return 0;
}
new_lv->name = dm_pool_strdup(lv->vg->vgmem, split_name);
if (!new_lv->name) {
if (!(lv_name = dm_pool_strdup(lv->vg->vgmem, split_name)) ||
!lv_set_name(new_lv, lv_name)) {
log_error("Unable to rename newly split LV.");
return 0;
}
@ -699,7 +700,8 @@ static int _split_mirror_images(struct logical_volume *lv,
display_lvname(new_lv));
return 0;
}
if (!(sub_lv->name = dm_pool_strdup(lv->vg->vgmem, layer_name))) {
if (!(lv_name = dm_pool_strdup(lv->vg->vgmem, layer_name)) ||
!lv_set_name(sub_lv, lv_name)) {
log_error("Unable to allocate memory.");
return 0;
}
@ -991,7 +993,11 @@ static int _remove_mirror_images(struct logical_volume *lv,
/* Mirror with only 1 area is 'in sync'. */
if (new_area_count == 1 && is_temporary_mirror_layer(lv)) {
detached_log_lv = detach_mirror_log(mirrored_seg);
if (!(detached_log_lv = detach_mirror_log(mirrored_seg))) {
log_error("Cannot detach mirror log from %s..",
display_lvname(mirrored_seg->lv));
return 0;
}
if (!_init_mirror_log(lv->vg->cmd,
(struct logical_volume*)lv_lock_holder(mirrored_seg->lv),
detached_log_lv,
@ -1367,11 +1373,12 @@ int fixup_imported_mirrors(struct volume_group *vg)
{
struct lv_list *lvl;
struct lv_segment *seg;
const struct segment_type *mirror_segtype =
get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_MIRROR);
dm_list_iterate_items(lvl, &vg->lvs) {
dm_list_iterate_items(seg, &lvl->lv->segments) {
if (seg->segtype !=
get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_MIRROR))
if (seg->segtype != mirror_segtype)
continue;
if (seg->log_lv && !add_seg_to_segs_using_this_lv(seg->log_lv, seg))

View File

@ -398,9 +398,11 @@ int check_pv_segments(struct volume_group *vg)
uint32_t start_pe, alloced;
uint32_t pv_count = 0, free_count = 0, extent_count = 0;
int ret = 1;
const char *pv_devname;
dm_list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
pv_devname = pv_dev_name(pv);
segno = 0;
start_pe = 0;
alloced = 0;
@ -411,7 +413,7 @@ int check_pv_segments(struct volume_group *vg)
/* FIXME Remove this next line eventually */
log_debug_alloc("%s %u: %6u %6u: %s(%u:%u)",
pv_dev_name(pv), segno++, peg->pe, peg->len,
pv_devname, segno++, peg->pe, peg->len,
peg->lvseg ? peg->lvseg->lv->name : "NULL",
peg->lvseg ? peg->lvseg->le : 0, s);
/* FIXME Add details here on failure instead */

View File

@ -913,6 +913,7 @@ static char *_generate_raid_name(struct logical_volume *lv,
static int _shift_and_rename_image_components(struct lv_segment *seg)
{
uint32_t s, missing;
const char *lv_name;
/*
* All LVs must be properly named for their index before
@ -943,13 +944,15 @@ static int _shift_and_rename_image_components(struct lv_segment *seg)
display_lvname(seg_lv(seg, s)), missing);
/* Alter rmeta name */
if (!(seg_metalv(seg, s)->name = _generate_raid_name(seg->lv, "rmeta", s - missing))) {
if (!(lv_name = _generate_raid_name(seg->lv, "rmeta", s - missing)) ||
!lv_set_name(seg_metalv(seg, s), lv_name)) {
log_error("Memory allocation failed.");
return 0;
}
/* Alter rimage name */
if (!(seg_lv(seg, s)->name = _generate_raid_name(seg->lv, "rimage", s - missing))) {
if (!(lv_name = _generate_raid_name(seg->lv, "rimage", s - missing)) ||
!lv_set_name(seg_lv(seg, s), lv_name)) {
log_error("Memory allocation failed.");
return 0;
}
@ -2703,17 +2706,20 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
if (seg_is_linear(seg)) {
struct dm_list *l;
struct lv_list *lvl_tmp;
const char *lv_name;
dm_list_iterate(l, &data_lvs) {
if (l == dm_list_last(&data_lvs)) {
lvl = dm_list_item(l, struct lv_list);
if (!(lvl->lv->name = _generate_raid_name(lv, "rimage", count)))
if (!(lv_name = _generate_raid_name(lv, "rimage", count)) ||
!lv_set_name(lvl->lv, lv_name))
return_0;
continue;
}
lvl = dm_list_item(l, struct lv_list);
lvl_tmp = dm_list_item(l->n, struct lv_list);
lvl->lv->name = lvl_tmp->lv->name;
if (!lv_set_name(lvl->lv, lvl_tmp->lv->name))
return_0;
}
}
@ -2902,6 +2908,7 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
{
struct logical_volume *data_lv = seg_lv(seg, idx);
struct logical_volume *meta_lv = seg_metalv(seg, idx);
const char *data_lv_name, *meta_lv_name;
log_very_verbose("Extracting image components %s and %s from %s.",
display_lvname(data_lv),
@ -2921,10 +2928,12 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
seg_type(seg, idx) = AREA_UNASSIGNED;
seg_metatype(seg, idx) = AREA_UNASSIGNED;
if (!(data_lv->name = _generate_raid_name(data_lv, "extracted", -1)))
if (!(data_lv_name = _generate_raid_name(data_lv, "extracted", -1)) ||
!(meta_lv_name = _generate_raid_name(meta_lv, "extracted", -1)))
return_0;
if (!(meta_lv->name = _generate_raid_name(meta_lv, "extracted", -1)))
if (!lv_set_name(data_lv, data_lv_name) ||
!lv_set_name(meta_lv, meta_lv_name))
return_0;
*extracted_rmeta = meta_lv;
@ -3413,7 +3422,8 @@ int lv_raid_split(struct logical_volume *lv, int yes, const char *split_name,
/* Get first item */
lvl = (struct lv_list *) dm_list_first(&data_list);
lvl->lv->name = split_name;
if (!lv_set_name(lvl->lv, split_name))
return_0;
if (lv->vg->lock_type && !strcmp(lv->vg->lock_type, "dlm"))
lvl->lv->lock_args = lv->lock_args;
@ -3579,7 +3589,6 @@ int lv_raid_merge(struct logical_volume *image_lv)
{
uint32_t s;
char *p, *lv_name;
struct lv_list *lvl;
struct logical_volume *lv;
struct logical_volume *meta_lv = NULL;
struct lv_segment *seg;
@ -3601,17 +3610,16 @@ int lv_raid_merge(struct logical_volume *image_lv)
}
*p = '\0'; /* lv_name is now that of top-level RAID */
if (!(lvl = find_lv_in_vg(vg, lv_name))) {
if (!(lv = find_lv(vg, lv_name))) {
log_error("Unable to find containing RAID array for %s.",
display_lvname(image_lv));
return 0;
}
/* Ensure primary LV is not active elsewhere. */
if (!lockd_lv(vg->cmd, lvl->lv, "ex", 0))
if (!lockd_lv(vg->cmd, lv, "ex", 0))
return_0;
lv = lvl->lv;
seg = first_seg(lv);
for (s = 0; s < seg->area_count; ++s)
if (seg_lv(seg, s) == image_lv)
@ -3782,6 +3790,7 @@ static int _extract_image_component_error_seg(struct lv_segment *seg,
int set_error_seg)
{
struct logical_volume *lv;
const char *lv_name;
switch (type) {
case RAID_META:
@ -3808,7 +3817,10 @@ static int _extract_image_component_error_seg(struct lv_segment *seg,
if (!remove_seg_from_segs_using_this_lv(lv, seg))
return_0;
if (!(lv->name = _generate_raid_name(lv, "extracted", -1)))
if (!(lv_name = _generate_raid_name(lv, "extracted", -1)))
return_0;
if (!lv_set_name(lv, lv_name))
return_0;
if (set_error_seg && !replace_lv_with_error_segment(lv))
@ -4140,7 +4152,8 @@ static int _convert_mirror_to_raid1(struct logical_volume *lv,
if (!(new_name = _generate_raid_name(lv, "rimage", s)))
return_0;
log_debug_metadata("Renaming %s to %s.", seg_lv(seg, s)->name, new_name);
seg_lv(seg, s)->name = new_name;
if (!lv_set_name(seg_lv(seg, s), new_name))
return_0;
seg_lv(seg, s)->status &= ~MIRROR_IMAGE;
seg_lv(seg, s)->status |= RAID_IMAGE;
}
@ -5078,6 +5091,7 @@ static int _rename_area_lvs(struct logical_volume *lv, const char *suffix)
size_t sz = sizeof("rimage") - 1 + (suffix ? strlen(suffix) : 0) + 1;
char *sfx[SLV_COUNT] = { NULL, NULL };
struct lv_segment *seg = first_seg(lv);
const char *lv_name;
/* Create _generate_raid_name() suffixes w/ or w/o passed in @suffix */
for (s = 0; s < SLV_COUNT; s++)
@ -5087,10 +5101,12 @@ static int _rename_area_lvs(struct logical_volume *lv, const char *suffix)
/* Change names (temporarily) to be able to shift numerical name suffixes */
for (s = 0; s < seg->area_count; s++) {
if (!(seg_lv(seg, s)->name = _generate_raid_name(lv, sfx[0], s)))
if (!(lv_name = _generate_raid_name(lv, sfx[0], s)) ||
!lv_set_name(seg_lv(seg, s), lv_name))
return_0;
if (seg->meta_areas &&
!(seg_metalv(seg, s)->name = _generate_raid_name(lv, sfx[1], s)))
(!(lv_name = _generate_raid_name(lv, sfx[1], s)) ||
!lv_set_name(seg_metalv(seg, s), lv_name)))
return_0;
}
@ -6089,9 +6105,13 @@ static int _log_prohibited_option(const struct lv_segment *seg_from,
if (seg_from->segtype == new_segtype)
log_error("%s not allowed when converting %s LV %s.",
opt_str, lvseg_name(seg_from), display_lvname(seg_from->lv));
else
else if (new_segtype)
log_error("%s not allowed for LV %s when converting from %s to %s.",
opt_str, display_lvname(seg_from->lv), lvseg_name(seg_from), new_segtype->name);
else {
log_error(INTERNAL_ERROR "New segtype is not defined.");
return 0;
}
return 1;
}
@ -7113,8 +7133,9 @@ skip_alloc:
struct logical_volume *lv_image = seg_lv(raid_seg, s);
struct logical_volume *lv_rmeta = seg_metalv(raid_seg, s);
lv_rmeta->name = tmp_names[s];
lv_image->name = tmp_names[sd];
if (!lv_set_name(lv_rmeta, tmp_names[s]) ||
!lv_set_name(lv_image, tmp_names[sd]))
return_0;
if (lv_is_integrity(lv_image)) {
struct logical_volume *lv_imeta;
@ -7133,7 +7154,9 @@ skip_alloc:
stack;
continue;
}
lv_imeta->name = tmp_name_dup;
if (!lv_set_name(lv_imeta, tmp_name_dup))
return_0;
if (dm_snprintf(tmp_name_buf, NAME_LEN, "%s_iorig", lv_image->name) < 0) {
stack;
@ -7143,7 +7166,9 @@ skip_alloc:
stack;
continue;
}
lv_iorig->name = tmp_name_dup;
if (!lv_set_name(lv_iorig, tmp_name_dup))
return_0;
}
}
}

View File

@ -254,9 +254,7 @@ struct segtype_handler {
int (*text_import_area_count) (const struct dm_config_node * sn,
uint32_t *area_count);
int (*text_import) (struct lv_segment * seg,
const struct dm_config_node * sn,
struct dm_hash_table * pv_hash,
struct dm_hash_table * lv_hash);
const struct dm_config_node * sn);
int (*merge_segments) (struct lv_segment * seg1,
struct lv_segment * seg2);
int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,

View File

@ -354,8 +354,9 @@ int thin_pool_check_overprovisioning(const struct logical_volume *lv)
struct cmd_context *cmd = lv->vg->cmd;
const char *txt = "";
uint64_t thinsum = 0, poolsum = 0, sz = ~0;
int threshold, max_threshold = 0;
int percent, min_percent = 100;
int threshold, def_threshold, max_threshold = 0;
int percent, def_percent, min_percent = 100;
struct profile *profile;
int more_pools = 0;
/* When passed thin volume, check related pool first */
@ -373,15 +374,26 @@ int thin_pool_check_overprovisioning(const struct logical_volume *lv)
return 1; /* All thins fit into this thin pool */
}
def_threshold = find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG,
NULL);
def_percent = find_config_tree_int(cmd, activation_thin_pool_autoextend_percent_CFG,
NULL);
/* Sum all thins and all thin pools in VG */
dm_list_iterate_items(lvl, &lv->vg->lvs) {
if (!lv_is_thin_pool(lvl->lv))
continue;
threshold = find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG,
lv_config_profile(lvl->lv));
percent = find_config_tree_int(cmd, activation_thin_pool_autoextend_percent_CFG,
lv_config_profile(lvl->lv));
if ((profile = lv_config_profile(lvl->lv))) {
threshold = find_config_tree_int(cmd, activation_thin_pool_autoextend_threshold_CFG,
profile);
percent = find_config_tree_int(cmd, activation_thin_pool_autoextend_percent_CFG,
profile);
} else {
threshold = def_threshold;
percent = def_percent;
}
if (threshold > max_threshold)
max_threshold = threshold;
if (percent < min_percent)

View File

@ -544,8 +544,10 @@ struct logical_volume *convert_vdo_lv(struct logical_volume *lv,
return_NULL;
/* Also swap naming, so the passed in LV keeps the passed-in name */
vdo_lv->name = lv->name;
lv->name = lvc.lv_name;
tmp_lv.name = lv->name;
lv_set_name(lv, NULL);
lv_set_name(vdo_lv, tmp_lv.name);
lv_set_name(lv, lvc.lv_name);
/* Swap segment referencing */
if (!remove_seg_from_segs_using_this_lv(lv, first_seg(lv)))

View File

@ -19,6 +19,7 @@
#include "lib/activate/activate.h"
#include "lib/commands/toolcontext.h"
#include "lib/format_text/archiver.h"
#include "base/data-struct/radix-tree.h"
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
const char *vg_name)
@ -76,6 +77,13 @@ static void _free_vg(struct volume_group *vg)
if (vg->committed_cft)
config_destroy(vg->committed_cft);
if (vg->lv_names)
radix_tree_destroy(vg->lv_names);
if (vg->pv_names)
radix_tree_destroy(vg->pv_names);
dm_pool_destroy(vg->vgmem);
}
@ -129,6 +137,12 @@ int unlink_lv_from_vg(struct logical_volume *lv)
dm_list_move(&lv->vg->removed_lvs, &lvl->list);
lv->status |= LV_REMOVED;
/* lv->lv_name stays valid for historical LV usage
* So just remove the name from active lv_names */
if (lv->vg->lv_names &&
!radix_tree_remove(lv->vg->lv_names, lv->name, strlen(lv->name)))
stack;
return 1;
}

View File

@ -46,6 +46,7 @@ struct volume_group {
unsigned needs_backup : 1;
unsigned needs_write_and_commit : 1;
unsigned needs_lockd_free_lvs : 1;
unsigned fixup_imported_mirrors : 1;
uint32_t write_count; /* count the number of vg_write calls */
uint32_t buffer_size_hint; /* hint with buffer size of parsed VG */
@ -63,6 +64,9 @@ struct volume_group {
struct profile *profile;
uint64_t status;
struct radix_tree *lv_names; /* maintained tree for LV names within VG */
struct radix_tree *pv_names; /* PV names used for metadata import */
struct id id;
const char *name;
const char *old_name; /* Set during vgrename and vgcfgrestore */

View File

@ -162,7 +162,8 @@ static void _rename_detached_cvol(struct cmd_context *cmd, struct logical_volume
return;
}
lv_fast->name = cvol_name_dup;
if (!lv_set_name(lv_fast, cvol_name_dup))
stack;
}
static int _lv_detach_writecache_cachevol_inactive(struct logical_volume *lv, int noflush)

View File

@ -73,9 +73,7 @@ static int _mirrored_text_import_area_count(const struct dm_config_node *sn, uin
return 1;
}
static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn)
{
const struct dm_config_value *cv;
const char *logname = NULL;
@ -103,13 +101,14 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_
}
if (dm_config_get_str(sn, "mirror_log", &logname)) {
if (!(seg->log_lv = dm_hash_lookup(lv_hash, logname))) {
if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) {
log_error("Unrecognised mirror log in "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
return 0;
}
seg->log_lv->status |= MIRROR_LOG;
seg->log_lv->vg->fixup_imported_mirrors = 1;
}
if (logname && !seg->region_size) {
@ -126,7 +125,7 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_
return 0;
}
return text_import_areas(seg, sn, cv, pv_hash, MIRROR_IMAGE);
return text_import_areas(seg, sn, cv, MIRROR_IMAGE);
}
static int _mirrored_text_export(const struct lv_segment *seg, struct formatter *f)

View File

@ -18,6 +18,130 @@
#include "lib/misc/crc.h"
#include "lib/mm/xlate.h"
/*
* CRC-32 byte lookup table generated by crc_gen.c
*
* Precomputed lookup table for CRC computed with 0xedb88320 polynomial.
*/
static const uint32_t _crctab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
#ifdef __x86_64__
/*
* Note that the CRC-32 checksum is merely used for error detection in
* transmission and storage. It is not intended to guard against the malicious
* modification of files (i.e., it is not a cryptographic hash). !!!
*
* This code is based on zlib code from:
*
* https://github.com/vlastavesely/crc32sum
* https://github.com/chromium/chromium/blob/master/third_party/zlib/
*
* SPDX-License-Identifier: GPL-2.0
*/
/*
* ATM Use this code only for X86_64 arch where it was tested
* TODO: check if it speeds also non X86_64 arch
*/
static unsigned int _crc32_lookup[16][256] = { 0 };
static void _initialise_crc32(void)
{
unsigned int i, j;
if (_crc32_lookup[0][1])
return;
for (i = 0; i < 256; i++)
_crc32_lookup[0][i] = _crctab[i];
for (i = 0; i < 256; i++)
for (j = 1; j < 16; j++)
_crc32_lookup[j][i] = (_crc32_lookup[j - 1][i] >> 8) ^
_crc32_lookup[0][_crc32_lookup[j - 1][i] & 0xff];
}
#ifndef DEBUG_CRC32
uint32_t calc_crc(uint32_t initial, const uint8_t *buf, uint32_t size)
#else
static uint32_t _calc_crc_new(uint32_t initial, const uint8_t *buf, uint32_t size)
#endif
{
const uint32_t *ptr = (const uint32_t *) buf;
uint32_t a, b, c, d;
uint32_t crc = initial;
_initialise_crc32();
for (;size >= 16; size -= 16) {
a = xlate32(*ptr++) ^ crc;
b = xlate32(*ptr++);
c = xlate32(*ptr++);
d = xlate32(*ptr++);
crc = _crc32_lookup[ 0][(d >> 24) & 0xff] ^
_crc32_lookup[ 1][(d >> 16) & 0xff] ^
_crc32_lookup[ 2][(d >> 8) & 0xff] ^
_crc32_lookup[ 3][ d & 0xff] ^
_crc32_lookup[ 4][(c >> 24) & 0xff] ^
_crc32_lookup[ 5][(c >> 16) & 0xff] ^
_crc32_lookup[ 6][(c >> 8) & 0xff] ^
_crc32_lookup[ 7][ c & 0xff] ^
_crc32_lookup[ 8][(b >> 24) & 0xff] ^
_crc32_lookup[ 9][(b >> 16) & 0xff] ^
_crc32_lookup[10][(b >> 8) & 0xff] ^
_crc32_lookup[11][ b & 0xff] ^
_crc32_lookup[12][(a >> 24) & 0xff] ^
_crc32_lookup[13][(a >> 16) & 0xff] ^
_crc32_lookup[14][(a >> 8) & 0xff] ^
_crc32_lookup[15][ a & 0xff];
}
buf = (const uint8_t *) ptr;
while (size--)
crc = _crc32_lookup[0][((unsigned char) crc ^ *(buf++))] ^ (crc >> 8);
return crc;
}
#else // __x86_64__
/* Calculate an endian-independent CRC of supplied buffer */
#ifndef DEBUG_CRC32
uint32_t calc_crc(uint32_t initial, const uint8_t *buf, uint32_t size)
@ -25,41 +149,6 @@ uint32_t calc_crc(uint32_t initial, const uint8_t *buf, uint32_t size)
static uint32_t _calc_crc_new(uint32_t initial, const uint8_t *buf, uint32_t size)
#endif
{
/* CRC-32 byte lookup table generated by crc_gen.c */
static const uint32_t _crctab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
const uint32_t *start = (const uint32_t *) buf;
const uint32_t *end = (const uint32_t *) (buf + (size & 0xfffffffc));
uint32_t crc = initial;
@ -84,6 +173,8 @@ static uint32_t _calc_crc_new(uint32_t initial, const uint8_t *buf, uint32_t siz
return crc;
}
#endif // __x86_64__
#ifdef DEBUG_CRC32
static uint32_t _calc_crc_old(uint32_t initial, const uint8_t *buf, uint32_t size)
{

View File

@ -70,8 +70,7 @@ static int _raid_text_import_area_count(const struct dm_config_node *sn,
static int _raid_text_import_areas(struct lv_segment *seg,
const struct dm_config_node *sn,
const struct dm_config_value *cv,
struct dm_hash_table *lv_hash)
const struct dm_config_value *cv)
{
unsigned int s;
struct logical_volume *lv;
@ -89,7 +88,7 @@ static int _raid_text_import_areas(struct lv_segment *seg,
}
/* Metadata device comes first. */
if (!(lv = dm_hash_lookup(lv_hash, cv->v.str))) {
if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
log_error("Couldn't find volume '%s' for segment '%s'.",
cv->v.str ? : "NULL", seg_name);
return 0;
@ -107,7 +106,7 @@ static int _raid_text_import_areas(struct lv_segment *seg,
}
/* Data device comes second */
if (!(lv = dm_hash_lookup(lv_hash, cv->v.str))) {
if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
log_error("Couldn't find volume '%s' for segment '%s'.",
cv->v.str ? : "NULL", seg_name);
return 0;
@ -129,9 +128,7 @@ static int _raid_text_import_areas(struct lv_segment *seg,
}
static int _raid_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
const struct dm_config_value *cv;
const struct {
@ -173,7 +170,7 @@ static int _raid_text_import(struct lv_segment *seg,
return 0;
}
if (!_raid_text_import_areas(seg, sn, cv, lv_hash)) {
if (!_raid_text_import_areas(seg, sn, cv)) {
log_error("Failed to import RAID component pairs.");
return 0;
}

View File

@ -2622,13 +2622,12 @@ static struct logical_volume *_lv_for_raid_image_seg(const struct lv_segment *se
p = strchr(p + 5, '_');
if (p) {
struct lv_list *lvl;
struct logical_volume *lv;
*p = '\0';
if ((lvl = find_lv_in_vg(seg->lv->vg, lv_name)) &&
seg_is_reshapable_raid(first_seg(lvl->lv)))
return lvl->lv;
if ((lv = find_lv(seg->lv->vg, lv_name)) &&
seg_is_reshapable_raid(first_seg(lv)))
return lv;
}
}
}
@ -4637,15 +4636,26 @@ int report_devtypes(void *handle)
int report_cmdlog(void *handle, const char *type, const char *context,
const char *object_type_name, const char *object_name,
const char *object_id, const char *object_group,
const char *object_group_id, const char *msg,
const struct id *object_id, const char *object_group,
const struct id *object_group_id, const char *msg,
int current_errno, int ret_code)
{
char object_uuid[64] __attribute__((aligned(8))) = { 0 };
char object_group_uuid[64] __attribute__((aligned(8))) = { 0 };
struct cmd_log_item log_item = {_log_seqnum++, type, context, object_type_name,
object_name ? : "", object_id ? : "",
object_group ? : "", object_group_id ? : "",
object_name ? : "", object_uuid,
object_group ? : "", object_group_uuid,
msg ? : "", current_errno, ret_code};
if (object_id &&
!id_write_format(object_id, object_uuid, sizeof(object_uuid)))
stack;
if (object_group_id &&
!id_write_format(object_group_id, object_group_uuid, sizeof(object_group_uuid)))
stack;
if (handle)
return dm_report_object(handle, &log_item);

View File

@ -117,8 +117,8 @@ int report_object(void *handle, int selection_only, const struct volume_group *v
int report_devtypes(void *handle);
int report_cmdlog(void *handle, const char *type, const char *context,
const char *object_type_name, const char *object_name,
const char *object_id, const char *object_group,
const char *object_group_id, const char *msg,
const struct id *object_id, const char *object_group,
const struct id *object_group_id, const char *msg,
int current_errno, int ret_code);
void report_reset_cmdlog_seqnum(void);
#define REPORT_OBJECT_CMDLOG_NAME "status"

View File

@ -34,10 +34,7 @@ static const char *_snap_target_name(const struct lv_segment *seg,
return lvseg_name(seg);
}
static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node *sn)
{
uint32_t chunk_size;
struct logical_volume *org, *cow;
@ -72,11 +69,11 @@ static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node
if (!(org_name = dm_config_find_str(sn, "origin", NULL)))
return SEG_LOG_ERROR("Snapshot origin must be a string in");
if (!(cow = dm_hash_lookup(lv_hash, cow_name)))
if (!(cow = find_lv(seg->lv->vg, cow_name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"snapshot cow store in", cow_name);
if (!(org = dm_hash_lookup(lv_hash, org_name)))
if (!(org = find_lv(seg->lv->vg, org_name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for "
"snapshot origin in", org_name);

View File

@ -69,9 +69,7 @@ static int _striped_text_import_area_count(const struct dm_config_node *sn, uint
return 1;
}
static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn)
{
const struct dm_config_value *cv;
@ -90,7 +88,7 @@ static int _striped_text_import(struct lv_segment *seg, const struct dm_config_n
seg->area_len /= seg->area_count;
return text_import_areas(seg, sn, cv, pv_hash, 0);
return text_import_areas(seg, sn, cv, 0);
}
static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)

View File

@ -53,8 +53,7 @@ static void _thin_pool_display(const struct lv_segment *seg)
static int _thin_pool_add_message(struct lv_segment *seg,
const char *key,
const struct dm_config_node *sn,
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
const char *lv_name = NULL;
struct logical_volume *lv = NULL;
@ -63,7 +62,7 @@ static int _thin_pool_add_message(struct lv_segment *seg,
/* Message must have only one from: create, delete */
if (dm_config_get_str(sn, "create", &lv_name)) {
if (!(lv = dm_hash_lookup(lv_hash, lv_name)))
if (!(lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown LV %s for create message in",
lv_name);
/* FIXME: switch to _SNAP later, if the created LV has an origin */
@ -80,9 +79,7 @@ static int _thin_pool_add_message(struct lv_segment *seg,
}
static int _thin_pool_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
const char *lv_name;
struct logical_volume *pool_data_lv, *pool_metadata_lv;
@ -93,13 +90,13 @@ static int _thin_pool_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "metadata", &lv_name))
return SEG_LOG_ERROR("Metadata must be a string in");
if (!(pool_metadata_lv = dm_hash_lookup(lv_hash, lv_name)))
if (!(pool_metadata_lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown metadata %s in", lv_name);
if (!dm_config_get_str(sn, "pool", &lv_name))
return SEG_LOG_ERROR("Pool must be a string in");
if (!(pool_data_lv = dm_hash_lookup(lv_hash, lv_name)))
if (!(pool_data_lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown pool %s in", lv_name);
if (!attach_pool_data_lv(seg, pool_data_lv))
@ -143,7 +140,7 @@ static int _thin_pool_text_import(struct lv_segment *seg,
/* Read messages */
for (; sn; sn = sn->sib)
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child, lv_hash))
if (!(sn->v) && !_thin_pool_add_message(seg, sn->key, sn->child))
return_0;
return 1;
@ -469,9 +466,7 @@ static void _thin_display(const struct lv_segment *seg)
}
static int _thin_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
const char *lv_name;
struct logical_volume *pool_lv, *origin = NULL, *external_lv = NULL, *merge_lv = NULL;
@ -480,7 +475,7 @@ static int _thin_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "thin_pool", &lv_name))
return SEG_LOG_ERROR("Thin pool must be a string in");
if (!(pool_lv = dm_hash_lookup(lv_hash, lv_name)))
if (!(pool_lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown thin pool %s in", lv_name);
if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id))
@ -490,14 +485,14 @@ static int _thin_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "origin", &lv_name))
return SEG_LOG_ERROR("Origin must be a string in");
if (!(origin = dm_hash_lookup(lv_hash, lv_name)))
if (!(origin = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown origin %s in", lv_name);
}
if (dm_config_has_node(sn, "merge")) {
if (!dm_config_get_str(sn, "merge", &lv_name))
return SEG_LOG_ERROR("Merge lv must be a string in");
if (!(merge_lv = dm_hash_lookup(lv_hash, lv_name)))
if (!(merge_lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown merge lv %s in", lv_name);
}
@ -512,7 +507,7 @@ static int _thin_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "external_origin", &lv_name))
return SEG_LOG_ERROR("External origin must be a string in");
if (!(external_lv = dm_hash_lookup(lv_hash, lv_name)))
if (!(external_lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown external origin %s in", lv_name);
}

View File

@ -19,9 +19,7 @@
#include "lib/format_text/text_export.h"
#include "lib/config/config.h"
static int _unknown_text_import(struct lv_segment *seg, const struct dm_config_node *sn,
struct dm_hash_table *pv_hash,
struct dm_hash_table *lv_hash)
static int _unknown_text_import(struct lv_segment *seg, const struct dm_config_node *sn)
{
struct dm_config_node *new, *last = NULL, *head = NULL;
const struct dm_config_node *current;

View File

@ -74,9 +74,7 @@ static void _vdo_display(const struct lv_segment *seg)
}
static int _vdo_text_import(struct lv_segment *seg,
const struct dm_config_node *n,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *n)
{
struct logical_volume *vdo_pool_lv;
const char *str;
@ -85,7 +83,7 @@ static int _vdo_text_import(struct lv_segment *seg,
if (!dm_config_has_node(n, "vdo_pool") ||
!(str = dm_config_find_str(n, "vdo_pool", NULL)))
return _bad_field("vdo_pool");
if (!(vdo_pool_lv = dm_hash_lookup(lv_hash, str))) {
if (!(vdo_pool_lv = find_lv(seg->lv->vg, str))) {
log_error("Unknown VDO pool logical volume %s.", str);
return 0;
}
@ -207,9 +205,7 @@ static int _vdo_pool_text_import_area_count(const struct dm_config_node *sn __at
}
static int _vdo_pool_text_import(struct lv_segment *seg,
const struct dm_config_node *n,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *n)
{
struct dm_vdo_target_params *vtp = &seg->vdo_params;
struct logical_volume *data_lv;
@ -218,7 +214,7 @@ static int _vdo_pool_text_import(struct lv_segment *seg,
if (!dm_config_has_node(n, "data") ||
!(str = dm_config_find_str(n, "data", NULL)))
return _bad_field("data");
if (!(data_lv = dm_hash_lookup(lv_hash, str))) {
if (!(data_lv = find_lv(seg->lv->vg, str))) {
log_error("Unknown logical volume %s.", str);
return 0;
}

View File

@ -39,9 +39,7 @@ static void _writecache_display(const struct lv_segment *seg)
}
static int _writecache_text_import(struct lv_segment *seg,
const struct dm_config_node *sn,
struct dm_hash_table *pv_hash __attribute__((unused)),
struct dm_hash_table *lv_hash)
const struct dm_config_node *sn)
{
struct logical_volume *origin_lv = NULL;
struct logical_volume *fast_lv;
@ -54,7 +52,7 @@ static int _writecache_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "origin", &origin_name))
return SEG_LOG_ERROR("origin must be a string in");
if (!(origin_lv = dm_hash_lookup(lv_hash, origin_name)))
if (!(origin_lv = find_lv(seg->lv->vg, origin_name)))
return SEG_LOG_ERROR("Unknown LV specified for writecache origin %s in", origin_name);
if (!set_lv_segment_area_lv(seg, 0, origin_lv, 0, 0))
@ -66,7 +64,7 @@ static int _writecache_text_import(struct lv_segment *seg,
if (!dm_config_get_str(sn, "writecache", &fast_name))
return SEG_LOG_ERROR("writecache must be a string in");
if (!(fast_lv = dm_hash_lookup(lv_hash, fast_name)))
if (!(fast_lv = find_lv(seg->lv->vg, fast_name)))
return SEG_LOG_ERROR("Unknown logical volume %s specified for writecache in",
fast_name);

View File

@ -104,16 +104,15 @@ static void _daemon_close_descriptor(int fd, unsigned suppress_warnings,
* Note: when 'from_fd' is set to -1, unused 'custom_fds' must use same value!
*
* command: print command name with warning message
* suppress_warning: whether to print warning messages
* suppress_warnings: whether to print warning messages
* above_fd: close all descriptors above this descriptor
* custom_fds: preserve descriptors from this set of descriptors
*/
static int daemon_close_stray_fds(const char *command, int suppress_warning,
static int daemon_close_stray_fds(const char *command, int suppress_warnings,
int from_fd, const struct custom_fds *custom_fds)
{
struct rlimit rlim;
int fd;
unsigned suppress_warnings = 0;
pid_t ppid = getppid();
char parent_cmdline[64];
static const char _fd_dir[] = DEFAULT_PROC_DIR "/self/fd";

View File

@ -0,0 +1 @@
dm_config_parse_only_section

View File

@ -141,6 +141,7 @@ static int _is_open_in_pid(pid_t pid, const char *path)
char link_buf[PATH_MAX];
DIR *pid_d = NULL;
ssize_t len;
int df;
if (pid == getpid())
return 0;
@ -169,7 +170,8 @@ static int _is_open_in_pid(pid_t pid, const char *path)
while ((pid_dp = readdir(pid_d)) != NULL) {
if (pid_dp->d_name[0] == '.')
continue;
if ((len = readlinkat(dirfd(pid_d), pid_dp->d_name, link_buf,
if (((df = dirfd(pid_d)) < 0) ||
(len = readlinkat(df, pid_dp->d_name, link_buf,
(sizeof(link_buf) - 1))) < 0) {
log_error("readlink failed for " DEFAULT_PROC_DIR
"/%d/fd/.", pid);

View File

@ -406,7 +406,7 @@ static int _parse_file(struct dm_task *dmt, const char *file)
buffer_size = LINE_SIZE;
if (!(buffer = malloc(buffer_size))) {
log_error("Failed to malloc line buffer.");
return 0;
goto out;
}
while (fgets(buffer, (int) buffer_size, fp))
@ -419,12 +419,11 @@ static int _parse_file(struct dm_task *dmt, const char *file)
r = 1;
out:
memset(buffer, 0, buffer_size);
#ifndef HAVE_GETLINE
free(buffer);
#else
free(buffer);
#endif
if (buffer) {
memset(buffer, 0, buffer_size);
free(buffer);
}
if (file && fclose(fp))
log_sys_debug("fclose", file);

View File

@ -3537,6 +3537,7 @@ struct dm_config_tree *dm_config_create(void);
struct dm_config_tree *dm_config_from_string(const char *config_settings);
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end);
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section);
void *dm_config_get_custom(struct dm_config_tree *cft);
void dm_config_set_custom(struct dm_config_tree *cft, void *custom);

View File

@ -53,6 +53,8 @@ struct parser {
int no_dup_node_check; /* whether to disable dup node checking */
const char *key; /* last obtained key */
unsigned ignored_creation_time;
unsigned section_indent;
const char *stop_after_section;
};
struct config_output {
@ -70,7 +72,8 @@ static struct dm_config_value *_value(struct parser *p);
static struct dm_config_value *_type(struct parser *p);
static int _match_aux(struct parser *p, int t);
static struct dm_config_value *_create_value(struct dm_pool *mem);
static struct dm_config_node *_create_node(struct dm_pool *mem);
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len);
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len);
static char *_dup_tok(struct parser *p);
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
@ -84,20 +87,24 @@ static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
} \
} while(0)
/* match token */
static int _tok_match(const char *str, const char *b, const char *e)
{
while (*str && (b != e)) {
if (*str++ != *b++)
while (b < e) {
if (!*str ||
(*str != *b))
return 0;
++str;
++b;
}
return !(*str || (b != e));
return !*str; /* token is matching for \0 end */
}
struct dm_config_tree *dm_config_create(void)
{
struct dm_config_tree *cft;
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
struct dm_pool *mem = dm_pool_create("config", 63 * 1024);
if (!mem) {
log_error("Failed to allocate config pool.");
@ -171,7 +178,8 @@ static struct dm_config_node *_config_reverse(struct dm_config_node *head)
return middle;
}
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end, int no_dup_node_check)
static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end,
int no_dup_node_check, const char *section)
{
/* TODO? if (start == end) return 1; */
@ -182,6 +190,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
.fb = start,
.fe = end,
.line = 1,
.stop_after_section = section,
.no_dup_node_check = no_dup_node_check
};
@ -196,12 +205,23 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 0);
return _do_dm_config_parse(cft, start, end, 0, NULL);
}
int dm_config_parse_without_dup_node_check(struct dm_config_tree *cft, const char *start, const char *end)
{
return _do_dm_config_parse(cft, start, end, 1);
return _do_dm_config_parse(cft, start, end, 1, NULL);
}
/*
* Stop parsing more sections after given section is parsed.
* Only non-section config nodes are then still parsed.
* It can be useful, when parsing i.e. lvm2 metadata and only physical_volumes config node is needed.
* This function is automatically running without_dup_node_check.
*/
int dm_config_parse_only_section(struct dm_config_tree *cft, const char *start, const char *end, const char *section)
{
return _do_dm_config_parse(cft, start, end, 1, section);
}
struct dm_config_tree *dm_config_from_string(const char *config_settings)
@ -467,23 +487,33 @@ int dm_config_write_node_out(const struct dm_config_node *cn,
/*
* parser
*/
static char *_dup_string_tok(struct parser *p)
static const char *_string_tok(struct parser *p, size_t *len)
{
char *str;
ptrdiff_t d = p->te - p->tb;
p->tb++, p->te--; /* strip "'s */
if (p->te < p->tb) {
if (d < 2) {
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): "
"expected a string token.",
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!(str = _dup_tok(p)))
*len = (size_t)(d - 2); /* strip "'s */
return p->tb + 1;
}
static char *_dup_string_tok(struct parser *p)
{
const char *tok;
size_t len;
char *str;
if (!(tok = _string_tok(p, &len)))
return_NULL;
p->te++;
if (!(str = _dup_token(p->mem, tok, tok + len)))
return_NULL;
return str;
}
@ -505,10 +535,9 @@ static struct dm_config_node *_make_node(struct dm_pool *mem,
{
struct dm_config_node *n;
if (!(n = _create_node(mem)))
if (!(n = _create_node(mem, key_b, key_e - key_b)))
return_NULL;
n->key = _dup_token(mem, key_b, key_e);
if (parent) {
n->parent = parent;
n->sib = parent->child;
@ -578,6 +607,8 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
struct dm_config_node *root;
struct dm_config_value *value;
char *str;
size_t len;
char buf[8192];
if (p->t == TOK_STRING_ESCAPED) {
if (!(str = _dup_string_tok(p)))
@ -591,9 +622,16 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_STRING);
} else {
if (!(str = _dup_tok(p)))
return_NULL;
len = p->te - p->tb;
if (len < (sizeof(buf) - 1)) {
/* Use stack for smaller string */
str = buf;
memcpy(str, p->tb, len);
str[len] = '\0';
} else {
if (!(str = _dup_tok(p)))
return_NULL;
}
match(TOK_IDENTIFIER);
}
@ -607,12 +645,28 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
return_NULL;
if (p->t == TOK_SECTION_B) {
if (p->stop_after_section)
++p->section_indent;
match(TOK_SECTION_B);
while (p->t != TOK_SECTION_E) {
if (!(_section(p, root)))
return_NULL;
}
match(TOK_SECTION_E);
if (p->stop_after_section && (--p->section_indent == 1)) {
if (!strcmp(str, p->stop_after_section)) {
/* Found stopping section name -> parsing is finished.
* Now try to find the sequence "\n}\n" from end of b
* parsed buffer to continue filling remaining nodes */
for (p->te = p->fe - 1; p->te > p->tb; --p->te)
if ((p->te[-2] == '\n') &&
(p->te[-1] == '}') &&
(p->te[ 0] == '\n')) {
p->t = TOK_SECTION_E;
break;
}
}
}
} else {
match(TOK_EQ);
p->key = root->key;
@ -669,16 +723,14 @@ static struct dm_config_value *_value(struct parser *p)
static struct dm_config_value *_type(struct parser *p)
{
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
struct dm_config_value *v = _create_value(p->mem);
char *str;
if (!v) {
log_error("Failed to allocate type value");
return NULL;
}
struct dm_config_value *v;
const char *str;
size_t len;
switch (p->t) {
case TOK_INT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_INT;
errno = 0;
v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */
@ -699,6 +751,8 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_FLOAT:
if (!(v = _create_value(p->mem)))
break;
v->type = DM_CFG_FLOAT;
errno = 0;
v->v.f = strtod(p->tb, NULL); /* FIXME: check error */
@ -710,31 +764,31 @@ static struct dm_config_value *_type(struct parser *p)
break;
case TOK_STRING:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
match(TOK_STRING);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
match(TOK_STRING);
}
break;
case TOK_STRING_BARE:
v->type = DM_CFG_STRING;
if (!(v->v.str = _dup_tok(p)))
return_NULL;
match(TOK_STRING_BARE);
if ((v = _create_str_value(p->mem, p->tb, p->te - p->tb))) {
v->type = DM_CFG_STRING;
match(TOK_STRING_BARE);
}
break;
case TOK_STRING_ESCAPED:
v->type = DM_CFG_STRING;
if (!(str = _dup_string_tok(p)))
if (!(str = _string_tok(p, &len)))
return_NULL;
dm_unescape_double_quotes(str);
v->v.str = str;
match(TOK_STRING_ESCAPED);
if ((v = _create_str_value(p->mem, str, len))) {
v->type = DM_CFG_STRING;
dm_unescape_double_quotes((char*)v->v.str);
match(TOK_STRING_ESCAPED);
}
break;
default:
@ -742,6 +796,12 @@ static struct dm_config_value *_type(struct parser *p)
p->tb - p->fb + 1, p->line);
return NULL;
}
if (!v) {
log_error("Failed to allocate type value.");
return NULL;
}
return v;
}
@ -759,60 +819,52 @@ static int _match_aux(struct parser *p, int t)
*/
static void _get_token(struct parser *p, int tok_prev)
{
int values_allowed = 0;
/* Should next token be interpreted as value instead of identifier? */
const int values_allowed = (tok_prev == TOK_EQ ||
tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA);
const char *te;
char c;
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe || !*p->tb) {
if (p->tb == p->fe ||
!((c = *p->tb))) {
p->t = TOK_EOF;
return;
}
/* Should next token be interpreted as value instead of identifier? */
if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B ||
tok_prev == TOK_COMMA)
values_allowed = 1;
p->t = TOK_INT; /* fudge so the fall through for
floats works */
te = p->te + 1; /* next character */
te = p->te;
switch (*te) {
switch (c) {
case SECTION_B_CHAR:
p->t = TOK_SECTION_B;
te++;
break;
case SECTION_E_CHAR:
p->t = TOK_SECTION_E;
te++;
break;
case '[':
p->t = TOK_ARRAY_B;
te++;
break;
case ']':
p->t = TOK_ARRAY_E;
te++;
break;
case ',':
p->t = TOK_COMMA;
te++;
break;
case '=':
p->t = TOK_EQ;
te++;
break;
case '"':
p->t = TOK_STRING_ESCAPED;
te++;
while ((te != p->fe) && (*te) && (*te != '"')) {
if ((*te == '\\') && (te + 1 != p->fe) &&
*(te + 1))
@ -826,7 +878,6 @@ static void _get_token(struct parser *p, int tok_prev)
case '\'':
p->t = TOK_STRING;
te++;
while ((te != p->fe) && (*te) && (*te != '\''))
te++;
@ -850,7 +901,7 @@ static void _get_token(struct parser *p, int tok_prev)
case '+':
case '-':
if (values_allowed) {
while (++te != p->fe) {
for (; te != p->fe; ++te) {
if (!isdigit((int) *te)) {
if (*te == '.') {
if (p->t != TOK_FLOAT) {
@ -867,10 +918,10 @@ static void _get_token(struct parser *p, int tok_prev)
default:
p->t = TOK_IDENTIFIER;
while ((te != p->fe) && (*te) && !isspace(*te) &&
(*te != '#') && (*te != '=') &&
(*te != SECTION_B_CHAR) &&
(*te != SECTION_E_CHAR))
while ((te != p->fe) && ((c = *te)) && !isspace(c) &&
(c != '#') && (c != '=') &&
(c != SECTION_B_CHAR) &&
(c != SECTION_E_CHAR))
te++;
if (values_allowed)
p->t = TOK_STRING_BARE;
@ -883,16 +934,19 @@ static void _get_token(struct parser *p, int tok_prev)
static void _eat_space(struct parser *p)
{
while (p->tb != p->fe) {
if (*p->te == '#')
if (!isspace(*p->te)) {
if (*p->te != '#')
break;
while ((p->te != p->fe) && (*p->te != '\n') && (*p->te))
++p->te;
}
else if (!isspace(*p->te))
break;
while ((p->te != p->fe) && isspace(*p->te)) {
while (p->te != p->fe) {
if (*p->te == '\n')
++p->line;
else if (!isspace(*p->te))
break;
++p->te;
}
@ -908,9 +962,44 @@ static struct dm_config_value *_create_value(struct dm_pool *mem)
return dm_pool_zalloc(mem, sizeof(struct dm_config_value));
}
static struct dm_config_node *_create_node(struct dm_pool *mem)
static struct dm_config_value *_create_str_value(struct dm_pool *mem, const char *str, size_t str_len)
{
return dm_pool_zalloc(mem, sizeof(struct dm_config_node));
struct dm_config_value *cv;
char *str_buf;
if (!(cv = dm_pool_alloc(mem, sizeof(struct dm_config_value) + str_len + 1)))
return_NULL;
memset(cv, 0, sizeof(*cv));
if (str) {
str_buf = (char *)(cv + 1);
memcpy(str_buf, str, str_len);
str_buf[str_len] = '\0';
cv->v.str = str_buf;
}
return cv;
}
static struct dm_config_node *_create_node(struct dm_pool *mem, const char *key, size_t key_len)
{
struct dm_config_node *cn;
char *key_buf;
if (!(cn = dm_pool_alloc(mem, sizeof(struct dm_config_node) + key_len + 1)))
return_NULL;
memset(cn, 0, sizeof(*cn));
if (key) {
key_buf = (char *)(cn + 1);
memcpy(key_buf, key, key_len);
key_buf[key_len] = '\0';
cn->key = key_buf;
}
return cn;
}
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e)
@ -1327,19 +1416,20 @@ static struct dm_config_value *_clone_config_value(struct dm_pool *mem,
{
struct dm_config_value *new_cv;
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
if (v->type == DM_CFG_STRING) {
if (!(new_cv = _create_str_value(mem, v->v.str, strlen(v->v.str)))) {
log_error("Failed to clone string config value.");
return NULL;
}
} else {
if (!(new_cv = _create_value(mem))) {
log_error("Failed to clone config value.");
return NULL;
}
new_cv->v = v->v;
}
new_cv->type = v->type;
if (v->type == DM_CFG_STRING) {
if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) {
log_error("Failed to clone config string value.");
return NULL;
}
} else
new_cv->v = v->v;
if (v->next && !(new_cv->next = _clone_config_value(mem, v->next)))
return_NULL;
@ -1356,16 +1446,11 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
return NULL;
}
if (!(new_cn = _create_node(mem))) {
if (!(new_cn = _create_node(mem, cn->key, cn->key ? strlen(cn->key) : 0))) {
log_error("Failed to clone config node.");
return NULL;
}
if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) {
log_error("Failed to clone config node key.");
return NULL;
}
new_cn->id = cn->id;
if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) ||
@ -1385,14 +1470,11 @@ struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const c
{
struct dm_config_node *cn;
if (!(cn = _create_node(cft->mem))) {
if (!(cn = _create_node(cft->mem, key, strlen(key)))) {
log_error("Failed to create config node.");
return NULL;
}
if (!(cn->key = dm_pool_strdup(cft->mem, key))) {
log_error("Failed to create config node's key.");
return NULL;
}
cn->parent = NULL;
cn->v = NULL;

View File

@ -4369,9 +4369,10 @@ static int _row_compare(const void *a, const void *b)
for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
sfa = (*rowa->sort_fields)[cnt];
sfb = (*rowb->sort_fields)[cnt];
if ((sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_SIZE) ||
(sfa->props->flags & DM_REPORT_FIELD_TYPE_TIME)) {
if (sfa->props->flags &
((DM_REPORT_FIELD_TYPE_NUMBER) |
(DM_REPORT_FIELD_TYPE_SIZE) |
(DM_REPORT_FIELD_TYPE_TIME))) {
const uint64_t numa =
*(const uint64_t *) sfa->sort_value;
const uint64_t numb =
@ -4482,6 +4483,7 @@ static const char *_get_field_id(struct dm_report *rh, struct dm_report_field *f
static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field *field)
{
char buf_local[8192];
char *field_id;
int32_t width;
uint32_t align;
@ -4489,25 +4491,26 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
size_t buf_size = 0;
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
if (!(field_id = strdup(_get_field_id(rh, field)))) {
log_error("dm_report: Failed to copy field name");
buf_size = strlen(_get_field_id(rh, field)) + 1;
if (buf_size >= sizeof(buf_local)) {
/* for field names our buf_local should be enough */
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
}
field_id = buf_local;
memcpy(field_id, _get_field_id(rh, field), buf_size);
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
dm_free(field_id);
return 0;
}
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
dm_free(field_id);
return 0;
}
dm_free(field_id);
if (!dm_pool_grow_object(rh->mem, STANDARD_PAIR, 1)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
return 0;
@ -4530,7 +4533,10 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
/* Including trailing '\0'! */
buf_size = width + 1;
if (!(buf = dm_malloc(buf_size))) {
if (buf_size < sizeof(buf_local))
/* Use local buffer on stack for smaller strings */
buf = buf_local;
else if (!(buf = dm_malloc(buf_size))) {
log_error("dm_report: Could not allocate memory for output line buffer.");
return 0;
}
@ -4572,10 +4578,12 @@ static int _output_field_basic_fmt(struct dm_report *rh, struct dm_report_field
}
}
dm_free(buf);
if (buf != buf_local)
dm_free(buf);
return 1;
bad:
dm_free(buf);
if (buf != buf_local)
dm_free(buf);
return 0;
}
@ -4845,6 +4853,7 @@ static int _output_as_columns(struct dm_report *rh)
struct dm_report_field *field;
struct dm_list *last_rowh;
int do_field_delim;
int is_json_report = _is_json_report(rh);
char *line;
/* If headings not printed yet, calculate field widths and print them */
@ -4864,7 +4873,7 @@ static int _output_as_columns(struct dm_report *rh)
return 0;
}
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_START, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;
@ -4879,7 +4888,7 @@ static int _output_as_columns(struct dm_report *rh)
continue;
if (do_field_delim) {
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0) ||
!dm_pool_grow_object(rh->mem, JSON_SPACE, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
@ -4901,7 +4910,7 @@ static int _output_as_columns(struct dm_report *rh)
dm_list_del(&field->list);
}
if (_is_json_report(rh)) {
if (is_json_report) {
if (!dm_pool_grow_object(rh->mem, JSON_OBJECT_END, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;

View File

@ -922,6 +922,8 @@ blocks in the array and check for discrepancies
(mismatches between mirrors or incorrect parity values).
\fBcheck\fP will count but not correct discrepancies.
\fBrepair\fP will correct discrepancies.
Mind that these synchronization actions are transient and have to be restarted
after a system failure/reboot or a configuration change to the RaidLV.
See \fBlvs\fP(8) for reporting discrepancies found or repaired.
.
.HP

View File

@ -85,9 +85,11 @@ function _get_size
local data_stripes=$3
local reshape_len rimagesz
# Get any reshape size in sectors
reshape_len=$(lvs --noheadings -aoname,reshapelen --unit s $vg/${lv}_rimage_0|head -1|cut -d ']' -f2)
reshape_len=$(echo ${reshape_len/S}|xargs)
# Get any reshape size in sectors
# avoid using pipes as exit codes may cause test failure
reshape_len="$(lvs --noheadings --nosuffix -aoreshapelen --unit s $vg/${lv}_rimage_0)"
# drop everything past 'S'
reshape_len="$(echo ${reshape_len/S*}|xargs)"
# Get rimage size - reshape length
rimagesz=$(($(blockdev --getsz /dev/mapper/${vg}-${lv}_rimage_0) - $reshape_len))

View File

@ -137,11 +137,24 @@ mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
# so exit 0 test here, if the feature is not present
blkid -p "$DM_DEV_DIR/$vg/$lv" | grep FSLASTBLOCK || exit 0
# existence of FSLASTBLOCK gives assumption on having 'new enough' blkid
FSSIZE="$(blkid -p -o udev --match-tag FSSIZE "$DM_DEV_DIR/$vg/$lv")"
FSSIZE=${FSSIZE/*=}
# lvextend, ext4, active, mounted,
df --output=size "$mount_dir" |tee df1
lvextend -L+5M $vg/$lv
check lv_field $vg/$lv lv_size "25.00m"
# here the filesystem should be resize to match 25M and must not fail
lvextend -r -L25M $vg/$lv
NEW_FSSIZE="$(blkid -p -o udev --match-tag FSSIZE "$DM_DEV_DIR/$vg/$lv")"
NEW_FSSIZE=${NEW_FSSIZE/*=}
test "$NEW_FSSIZE" -gt "$FSSIZE" ||
die "Filesystem should be extended"
# lvextend, ext4, active, mounted, no --fs setting is same as --fs ignore
df --output=size "$mount_dir" |tee df1
dd if=/dev/zero of="$mount_dir/zeros1" bs=1M count=8 oflag=direct
lvextend -L+10M $vg/$lv
lvextend -L+5M $vg/$lv
check lv_field $vg/$lv lv_size "30.00m"
# with no --fs used, the fs size should be the same
df --output=size "$mount_dir" |tee df2
@ -661,21 +674,24 @@ lvremove -f $vg
lvcreate -n $lv -L 16M $vg
mkswap /dev/$vg/$lv
# lvreduce not allowed if LV size < swap size
not lvreduce --fs checksize -L8m $vg/$lv
check lv_field $vg/$lv lv_size "16.00m"
# FSSIZE reported since util-linux/blkid v2.39 and later only
blkid -p "$DM_DEV_DIR/$vg/$lv" | grep FSSIZE && {
# lvreduce not allowed if LV size < swap size
not lvreduce --fs checksize -L8m $vg/$lv
check lv_field $vg/$lv lv_size "16.00m"
# lvreduce not allowed if LV size < swap size,
# even with --fs resize, this is not supported
not lvreduce --fs resize $vg/$lv
check lv_field $vg/$lv lv_size "16.00m"
# lvreduce not allowed if LV size < swap size,
# even with --fs resize, this is not supported
not lvreduce --fs resize $vg/$lv
check lv_field $vg/$lv lv_size "16.00m"
# lvextend allowed if LV size > swap size
lvextend -L32m $vg/$lv
check lv_field $vg/$lv lv_size "32.00m"
# lvextend allowed if LV size > swap size
lvextend -L32m $vg/$lv
check lv_field $vg/$lv lv_size "32.00m"
# lvreduce allowed if LV size == swap size
lvreduce -L16m $vg/$lv
check lv_field $vg/$lv lv_size "16.00m"
# lvreduce allowed if LV size == swap size
lvreduce -L16m $vg/$lv
check lv_field $vg/$lv lv_size "16.00m"
}
vgremove -ff $vg

View File

@ -25,7 +25,7 @@ pvcreate_on_dev_with_part_table() {
local type=$2
# pvcreate passes on empty partition table
echo "label:$type" | sfdisk "$dev"
echo "label:$type" | sfdisk "$dev" || skip "sfdisk does not support lable:$type"
pvcreate -y "$dev"
pvremove "$dev"

View File

@ -1,5 +1,5 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
@ -9,7 +9,7 @@
// 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
#include "units.h"
#include "base/data-struct/radix-tree.h"
#include "base/memory/container_of.h"
@ -348,7 +348,7 @@ static void test_remove_prefix(void *fixture)
T_ASSERT(radix_tree_is_well_formed(rt));
// remove keys in a sub range
// remove keys in a sub range
k[0] = 21;
T_ASSERT_EQUAL(radix_tree_remove_prefix(rt, k, 1), count);
T_ASSERT(radix_tree_is_well_formed(rt));
@ -542,7 +542,7 @@ static void test_remove_calls_dtr(void *fixture)
}
T_ASSERT(radix_tree_is_well_formed(rt));
// double check
for (i = 0; i < DTR_COUNT; i++) {
uint8_t *k = keys + (i * 3);
@ -597,7 +597,7 @@ static void test_destroy_calls_dtr(void *fixture)
T_ASSERT(radix_tree_is_well_formed(rt));
}
radix_tree_destroy(rt);
T_ASSERT(c.c == DTR_COUNT);
for (i = 0; i < DTR_COUNT; i++)
@ -810,6 +810,37 @@ static void test_bcache_scenario3(void *fixture)
#include "test/unit/rt_case1.c"
}
static bool _uniq_visit(struct radix_tree_iterator *it,
const void *key, size_t keylen, union radix_value v)
{
struct visitor *vt = container_of(it, struct visitor, it);
T_ASSERT_EQUAL(v.n, 2); // always expecting value == 2
vt->count++;
return true;
}
static void test_uniq_insert(void *fixture)
{
struct radix_tree *rt = fixture;
struct visitor vt = { .it.visit = _uniq_visit };
uint8_t k[6] = "test1";
uint8_t l[6] = "test2";
union radix_value v1 = { .n = 1 };
union radix_value v2 = { .n = 2 };
T_ASSERT(radix_tree_insert(rt, k, sizeof(k), v1));
T_ASSERT(radix_tree_insert(rt, k, sizeof(k), v1));
T_ASSERT_EQUAL(radix_tree_uniq_insert(rt, k, sizeof(k), v2), -1);
T_ASSERT(radix_tree_uniq_insert(rt, l, sizeof(l), v1));
T_ASSERT_EQUAL(radix_tree_uniq_insert(rt, l, sizeof(l), v2), -1);
T_ASSERT(radix_tree_is_well_formed(rt));
radix_tree_iterate(rt, NULL, 0, &vt.it);
T_ASSERT_EQUAL(radix_tree_size(rt), vt.count);
}
//----------------------------------------------------------------
#define T(path, desc, fn) register_test(ts, "/base/data-struct/radix-tree/" path, desc, fn)
@ -846,6 +877,7 @@ void radix_tree_tests(struct dm_list *all_tests)
T("bcache-scenario", "A specific series of keys from a bcache scenario", test_bcache_scenario);
T("bcache-scenario-2", "A second series of keys from a bcache scenario", test_bcache_scenario2);
T("bcache-scenario-3", "A third series of keys from a bcache scenario", test_bcache_scenario3);
T("uniq-insert", "Test insert with test for uniq key", test_uniq_insert);
dm_list_add(all_tests, &ts->list);
}

View File

@ -864,6 +864,8 @@ arg(syncaction_ARG, '\0', "syncaction", syncaction_VAL, 0, 0,
"(mismatches between mirrors or incorrect parity values).\n"
"\\fBcheck\\fP will count but not correct discrepancies.\n"
"\\fBrepair\\fP will correct discrepancies.\n"
"Mind that these synchronization actions are transient and have to be restarted\n"
"after a system failure/reboot or a configuration change to the RaidLV.\n"
"See \\fBlvs\\fP(8) for reporting discrepancies found or repaired.\n")
arg(sysinit_ARG, '\0', "sysinit", 0, 0, 0,

View File

@ -1851,7 +1851,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
/*
* Skip common lvm options in lvm_all which
* are printed at the end under "Common options for lvm"
* see print_common_options_lvm()
* see print_usage_common_lvm()
*/
if (_is_lvm_all_opt(opt_enum))
@ -1863,7 +1863,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
* cname->common_options (options common
* to all variants), which are printed at
* the end under "Common options for command"
* see print_common_options_cmd()
* see print_usage_common_cmd()
*/
if (cna && (cna->variants > 1) && cna->common_options[opt_enum])
@ -1891,7 +1891,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
/*
* Skip common lvm options in lvm_all which
* are printed at the end under "Common options for lvm"
* see print_common_options_lvm()
* see print_usage_common_lvm()
*/
if (_is_lvm_all_opt(opt_enum))
@ -1903,7 +1903,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
* cname->common_options (options common
* to all variants), which are printed at
* the end under "Common options for command"
* see print_common_options_cmd()
* see print_usage_common_cmd()
*/
if (cna && (cna->variants > 1) && cna->common_options[opt_enum])

View File

@ -2306,6 +2306,11 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
* FIXME If one_vgname, only proceed if exactly one VG matches tags or selection.
*/
dm_list_iterate_items(vgnl, vgnameids_to_process) {
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
vg_name = vgnl->vg_name;
vg_uuid = vgnl->vgid;
skip = 0;
@ -2315,16 +2320,11 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
uuid[0] = '\0';
if (is_orphan_vg(vg_name)) {
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_ORPHAN);
log_set_report_object_name_and_id(vg_name + sizeof(VG_ORPHANS), uuid);
log_set_report_object_name_and_id(vg_name + sizeof(VG_ORPHANS), NULL);
} else {
if (vg_uuid && !id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid)))
stack;
log_set_report_object_name_and_id(vg_name, uuid);
}
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
log_set_report_object_name_and_id(vg_name, (const struct id*)vg_uuid);
}
log_very_verbose("Processing VG %s %s", vg_name, uuid);
@ -3382,8 +3382,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
process_single_lv_fn_t process_single_lv)
{
log_report_t saved_log_report_state = log_get_report_state();
char lv_uuid[64] __attribute__((aligned(8)));
char vg_uuid[64] __attribute__((aligned(8)));
int ret_max = ECMD_PROCESSED;
int ret = 0;
int whole_selected = 0;
@ -3396,9 +3394,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
int lv_arg_pos;
struct lv_list *lvl;
struct dm_str_list *sl;
struct dm_list final_lvs;
DM_LIST_INIT(final_lvs);
struct lv_list *final_lvl;
struct dm_list found_arg_lvnames;
DM_LIST_INIT(found_arg_lvnames);
struct glv_list *glvl, *tglvl;
int do_report_ret_code = 1;
@ -3406,13 +3404,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LV);
vg_uuid[0] = '\0';
if (!id_write_format(&vg->id, vg_uuid, sizeof(vg_uuid)))
stack;
dm_list_init(&final_lvs);
dm_list_init(&found_arg_lvnames);
if (tags_in && !dm_list_empty(tags_in))
tags_supplied = 1;
@ -3436,20 +3427,16 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
(tags_supplied && str_list_match_list(tags_in, &vg->tags, NULL)))
process_all = 1;
log_set_report_object_group_and_group_id(vg->name, vg_uuid);
log_set_report_object_group_and_group_id(vg->name, &vg->id);
dm_list_iterate_items(lvl, &vg->lvs) {
lv_uuid[0] = '\0';
if (!id_write_format(&lvl->lv->lvid.id[1], lv_uuid, sizeof(lv_uuid)))
stack;
log_set_report_object_name_and_id(lvl->lv->name, lv_uuid);
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
log_set_report_object_name_and_id(lvl->lv->name, &lvl->lv->lvid.id[1]);
if (lv_is_snapshot(lvl->lv))
continue;
@ -3519,7 +3506,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
if (!process_lv)
continue;
log_very_verbose("Adding %s to the list of LVs to be processed.", display_lvname(lvl->lv));
log_very_verbose("Adding %s to the list of LVs to be processed.", lvl->lv->name);
if (!(final_lvl = dm_pool_zalloc(cmd->mem, sizeof(struct lv_list)))) {
log_error("Failed to allocate final LV list item.");
@ -3543,16 +3530,13 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
label_scan_invalidate_lvs(cmd, &final_lvs);
dm_list_iterate_items(lvl, &final_lvs) {
lv_uuid[0] = '\0';
if (!id_write_format(&lvl->lv->lvid.id[1], lv_uuid, sizeof(lv_uuid)))
stack;
log_set_report_object_name_and_id(lvl->lv->name, lv_uuid);
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
log_set_report_object_name_and_id(lvl->lv->name, &lvl->lv->lvid.id[1]);
/*
* FIXME: Once we have index over vg->removed_lvs, check directly
* LV presence there and remove LV_REMOVE flag/lv_is_removed fn
@ -3618,17 +3602,14 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
_historical_lv.vg = vg;
dm_list_iterate_items_safe(glvl, tglvl, &vg->historical_lvs) {
lv_uuid[0] = '\0';
if (!id_write_format(&glvl->glv->historical->lvid.id[1], lv_uuid, sizeof(lv_uuid)))
stack;
log_set_report_object_name_and_id(glvl->glv->historical->name, lv_uuid);
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
log_set_report_object_name_and_id(glvl->glv->historical->name,
&glvl->glv->historical->lvid.id[1]);
if (glvl->glv->historical->fresh)
continue;
@ -4007,6 +3988,11 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_VG);
dm_list_iterate_items(vgnl, vgnameids_to_process) {
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
vg_name = vgnl->vg_name;
vg_uuid = vgnl->vgid;
skip = 0;
@ -4017,12 +4003,7 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag
if (vg_uuid && !id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid)))
stack;
log_set_report_object_name_and_id(vg_name, uuid);
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
log_set_report_object_name_and_id(vg_name, (const struct id*)vg_uuid);
/*
* arg_lvnames contains some elements that are just "vgname"
@ -4500,7 +4481,6 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
process_single_pv_fn_t process_single_pv)
{
log_report_t saved_log_report_state = log_get_report_state();
char pv_uuid[64] __attribute__((aligned(8)));
char vg_uuid[64] __attribute__((aligned(8)));
int handle_supplied = handle != NULL;
struct physical_volume *pv;
@ -4530,22 +4510,19 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
}
if (!is_orphan_vg(vg->name))
log_set_report_object_group_and_group_id(vg->name, vg_uuid);
log_set_report_object_group_and_group_id(vg->name, &vg->id);
dm_list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
pv_name = pv_dev_name(pv);
pv_uuid[0]='\0';
if (!id_write_format(&pv->id, pv_uuid, sizeof(pv_uuid)))
stack;
log_set_report_object_name_and_id(pv_name, pv_uuid);
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
pv = pvl->pv;
pv_name = pv_dev_name(pv);
log_set_report_object_name_and_id(pv_name, &pv->id);
process_pv = process_all_pvs;
dil = NULL;
@ -4640,7 +4617,6 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags,
process_single_pv_fn_t process_single_pv)
{
log_report_t saved_log_report_state = log_get_report_state();
char uuid[64] __attribute__((aligned(8)));
struct volume_group *vg;
struct volume_group *error_vg;
struct vgnameid_list *vgnl;
@ -4658,25 +4634,22 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t read_flags,
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_VG);
dm_list_iterate_items(vgnl, all_vgnameids) {
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
vg_name = vgnl->vg_name;
vg_uuid = vgnl->vgid;
skip = 0;
notfound = 0;
is_lockd = lvmcache_vg_is_lockd_type(cmd, vg_name, vg_uuid);
uuid[0] = '\0';
if (is_orphan_vg(vg_name)) {
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_ORPHAN);
log_set_report_object_name_and_id(vg_name + sizeof(VG_ORPHANS), uuid);
log_set_report_object_name_and_id(vg_name + sizeof(VG_ORPHANS), NULL);
} else {
if (vg_uuid && !id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid)))
stack;
log_set_report_object_name_and_id(vg_name, uuid);
}
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
log_set_report_object_name_and_id(vg_name, (const struct id*)vg_uuid);
}
do_lockd:
if (is_lockd && !lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
@ -4882,8 +4855,6 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
process_single_pv_fn_t process_single_pv)
{
log_report_t saved_log_report_state = log_get_report_state();
char pv_uuid[64] __attribute__((aligned(8)));
char vg_uuid[64] __attribute__((aligned(8)));
int whole_selected = 0;
int ret_max = ECMD_PROCESSED;
int ret;
@ -4892,25 +4863,17 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_PV);
vg_uuid[0] = '\0';
if (!id_write_format(&vg->id, vg_uuid, sizeof(vg_uuid)))
stack;
if (!is_orphan_vg(vg->name))
log_set_report_object_group_and_group_id(vg->name, vg_uuid);
log_set_report_object_group_and_group_id(vg->name, &vg->id);
dm_list_iterate_items(pvl, &vg->pvs) {
pv_uuid[0] = '\0';
if (!id_write_format(&pvl->pv->id, pv_uuid, sizeof(pv_uuid)))
stack;
log_set_report_object_name_and_id(pv_dev_name(pvl->pv), pv_uuid);
if (sigint_caught()) {
ret_max = ECMD_FAILED;
goto_out;
}
log_set_report_object_name_and_id(pv_dev_name(pvl->pv), &pvl->pv->id);
ret = process_single_pv(cmd, vg, pvl->pv, handle);
_update_selection_result(handle, &whole_selected);
if (ret != ECMD_PROCESSED)

View File

@ -156,7 +156,8 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
}
dm_list_iterate_items(lvl1, &vg_from->lvs) {
lvl1->lv->vg = vg_to;
if (!lv_set_vg(lvl1->lv, vg_to))
goto_bad;
lvl1->lv->lvid.id[0] = lvl1->lv->vg->id;
}

View File

@ -49,7 +49,8 @@ static int _lv_tree_move(struct dm_list *lvh,
*lvht = dm_list_next(lvh, lvh);
dm_list_move(&vg_to->lvs, lvh);
lv->vg = vg_to;
if (!lv_set_vg(lv, vg_to))
return_0;
lv->lvid.id[0] = lv->vg->id;
if (seg)