mirror of
git://sourceware.org/git/lvm2.git
synced 2024-10-26 08:55:06 +03:00
Compare commits
75 Commits
e4830299ff
...
95bfcd8118
Author | SHA1 | Date | |
---|---|---|---|
|
95bfcd8118 | ||
|
708435d187 | ||
|
034b6a262c | ||
|
143545a08c | ||
|
c8a8c7286f | ||
|
5a293968ec | ||
|
43ce78e5c6 | ||
|
aa0200c3ff | ||
|
40010e3eb8 | ||
|
ebc5c0cb1d | ||
|
0fbcb3b308 | ||
|
5ec8f744d0 | ||
|
ea4daeb28e | ||
|
1363a5ffb2 | ||
|
5a3375f958 | ||
|
edfa4955d8 | ||
|
a5e3f0e6dd | ||
|
f61572eef2 | ||
|
87f68f443c | ||
|
7d48c1f6e3 | ||
|
188dd3c357 | ||
|
875012fb5d | ||
|
77332669d0 | ||
|
639fb633d3 | ||
|
9295de7cea | ||
|
2c5bf25187 | ||
|
b88cbc7f17 | ||
|
c27d6695c1 | ||
|
73c7dac1a8 | ||
|
21517c2bd5 | ||
|
1825e782cc | ||
|
956b2c568f | ||
|
c681d4e61a | ||
|
73f24443e5 | ||
|
eb4b307d0c | ||
|
dee8bc9ae4 | ||
|
d62170d646 | ||
|
668c185949 | ||
|
0852c3171d | ||
|
5b1ebed3fc | ||
|
dd856edaab | ||
|
2916a8a1f3 | ||
|
1f0530919e | ||
|
ea39c58127 | ||
|
056ad4a8f4 | ||
|
e0421ee7bf | ||
|
4929c55bc5 | ||
|
7156b4930d | ||
|
96cea466a5 | ||
|
0f793fcbca | ||
|
5666728b27 | ||
|
d121707ffa | ||
|
c19dfe11a5 | ||
|
ccd693d065 | ||
|
34b5d7f8bd | ||
|
5827c9e337 | ||
|
5d2d3c53a4 | ||
|
4dc0ee8e56 | ||
|
7c5cca600c | ||
|
fa11ef6846 | ||
|
1755ceb17c | ||
|
8fcfac7c89 | ||
|
b4156bb4de | ||
|
0179f00e0c | ||
|
89da9ae251 | ||
|
9c9953dc3e | ||
|
fd9f7d10ca | ||
|
f59fa69507 | ||
|
d8996a2a12 | ||
|
c29e3410c9 | ||
|
92158a24a5 | ||
|
2f022f5cbb | ||
|
b185578321 | ||
|
f55c949410 | ||
|
d07e273aff |
14
WHATS_NEW
14
WHATS_NEW
@ -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.
|
||||
|
@ -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
|
||||
====================================
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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"))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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?
|
||||
|
@ -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))
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)))
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
161
lib/misc/crc.c
161
lib/misc/crc.c
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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";
|
||||
|
1
libdm/.exported_symbols.DM_1_02_202
Normal file
1
libdm/.exported_symbols.DM_1_02_202
Normal file
@ -0,0 +1 @@
|
||||
dm_config_parse_only_section
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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])
|
||||
|
119
tools/toollib.c
119
tools/toollib.c
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user