master - RAID: Fix problems with creating, extending and converting large RAID LVs
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=886656e4ac5e5c...
Commit: 886656e4ac5e5c932d9fbe60d18c063136288a38
Parent: 662a2122f6224b5404d9f1276868bc3069766c49
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Thu Sep 27 16:51:22 2012 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Thu Sep 27 16:51:22 2012 -0500
RAID: Fix problems with creating, extending and converting large RAID LVs
MD's bitmaps can handle 2^21 regions at most. The RAID code has always
used a region_size of 1024 sectors. That means the size of a RAID LV was
limited to 1TiB. (The user can adjust the region_size when creating a
RAID LV, which can affect the maximum size.) Thus, creating, extending or
converting to a RAID LV greater than 1TiB would result in a failure to
load the new device-mapper table.
Again, the size of the RAID LV is not limited by how much space is allocated
for the metadata area, but by the limitations of the MD bitmap. Therefore,
we must adjust the 'region_size' to ensure that the number of regions does
not exceed the limit. I've added code to do this when extending a RAID LV
(which covers 'create' and 'extend' operations) and when up-converting -
specifically from linear to RAID1.
---
WHATS_NEW | 1 +
lib/metadata/lv_manip.c | 12 +++++++-
lib/metadata/raid_manip.c | 6 ++++
test/shell/lvcreate-large.sh | 65 ++++++++++++++++++++++++++++++++++++------
4 files changed, 74 insertions(+), 10 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 448f306..dc62d77 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.98 -
=================================
+ Fix inability to create, extend or convert to a large (> 1TiB) RAID LV.
Add (p)artial attribute to lvs.
Don't try to issue discards to a missing PV to avoid segfault.
Prevent lvremove from removing LVs that have any part missing.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 6c62bb3..f2d99b8 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -2660,7 +2660,17 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
seg->area_len += extents;
seg->len += extents;
lv->le_count += extents;
- lv->size += (uint64_t) extents *lv->vg->extent_size;
+ lv->size += (uint64_t) extents * lv->vg->extent_size;
+
+ /*
+ * The MD bitmap is limited to being able to track 2^21 regions.
+ * The region_size must be adjusted to meet that criteria.
+ */
+ while (seg_is_raid(seg) && (seg->region_size < (lv->size / (1 << 21)))) {
+ seg->region_size *= 2;
+ log_very_verbose("Forced to adjust RAID region_size to %uS",
+ seg->region_size);
+ }
return 1;
}
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 0266013..98a7db3 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -731,6 +731,12 @@ static int _raid_add_images(struct logical_volume *lv,
seg = first_seg(lv);
seg_lv(seg, 0)->status |= RAID_IMAGE | LVM_READ | LVM_WRITE;
seg->region_size = RAID_REGION_SIZE;
+ /* MD's bitmap is limited to tracking 2^21 regions */
+ while (seg->region_size < (lv->size / (1 << 21))) {
+ seg->region_size *= 2;
+ log_very_verbose("Setting RAID1 region_size to %uS",
+ seg->region_size);
+ }
seg->segtype = get_segtype_from_string(lv->vg->cmd, "raid1");
if (!seg->segtype)
return_0;
diff --git a/test/shell/lvcreate-large.sh b/test/shell/lvcreate-large.sh
index b61ccca..127b434 100644
--- a/test/shell/lvcreate-large.sh
+++ b/test/shell/lvcreate-large.sh
@@ -13,28 +13,75 @@
. lib/test
-aux prepare_vg 4
+aux prepare_vg 5
-lvcreate -s -l 100%FREE -n $lv $vg --virtualsize 1024T
+lvcreate -s -l 20%FREE -n $lv1 $vg --virtualsize 256T
+lvcreate -s -l 20%FREE -n $lv2 $vg --virtualsize 256T
+lvcreate -s -l 20%FREE -n $lv3 $vg --virtualsize 256T
+lvcreate -s -l 20%FREE -n $lv4 $vg --virtualsize 256T
+lvcreate -s -l 20%FREE -n $lv5 $vg --virtualsize 256T
#FIXME this should be 1024T
#check lv_field $vg/$lv size "128.00m"
aux lvmconf 'devices/filter = [ "a/dev\/mapper\/.*$/", "a/dev\/LVMTEST/", "r/.*/" ]'
-pvcreate $DM_DEV_DIR/$vg/$lv
-vgcreate -c n $vg1 $DM_DEV_DIR/$vg/$lv
+pvcreate $DM_DEV_DIR/$vg/$lv[12345]
+vgcreate -c n $vg1 $DM_DEV_DIR/$vg/$lv[12345]
lvcreate -l 100%FREE -n $lv1 $vg1
-check lv_field $vg1/$lv1 size "1024.00t"
+check lv_field $vg1/$lv1 size "1.25p"
lvresize -f -l 72%VG $vg1/$lv1
-check lv_field $vg1/$lv1 size "737.28t"
+check lv_field $vg1/$lv1 size "921.60t"
lvremove -ff $vg1/$lv1
lvcreate -l 100%VG -n $lv1 $vg1
-check lv_field $vg1/$lv1 size "1024.00t"
+check lv_field $vg1/$lv1 size "1.25p"
lvresize -f -l 72%VG $vg1/$lv1
-check lv_field $vg1/$lv1 size "737.28t"
+check lv_field $vg1/$lv1 size "921.60t"
lvremove -ff $vg1/$lv1
-lvremove -ff $vg/$lv
+if aux target_at_least dm-raid 1 1 0; then
+ # bz837927 START
+
+ #
+ # Create large RAID LVs
+ #
+ # We need '--nosync' or our virtual devices won't work
+ lvcreate --type raid1 -m 1 -L 200T -n $lv1 $vg1 --nosync
+ check lv_field $vg1/$lv1 size "200.00t"
+ lvremove -ff $vg1
+
+ lvcreate --type raid10 -m 1 -i 2 -L 200T -n $lv1 $vg1 --nosync
+ check lv_field $vg1/$lv1 size "200.00t"
+ lvremove -ff $vg1
+
+ for segtype in raid4 raid5 raid6; do
+ lvcreate --type $segtype -i 3 -L 750T -n $lv1 $vg1 --nosync
+ check lv_field $vg1/$lv1 size "750.00t"
+ lvremove -ff $vg1
+ done
+
+ #
+ # Convert large linear to RAID1 (belong in different test script?)
+ #
+ lvcreate -L 200T -n $lv1 $vg1
+ # Need to deactivate or the up-convert will start sync'ing
+ lvchange -an $vg1/$lv1
+ lvconvert --type raid1 -m 1 $vg1/$lv1
+ check lv_field $vg1/$lv1 size "200.00t"
+ lvremove -ff $vg1
+
+ #
+ # Extending large RAID LV (belong in different script?)
+ #
+ lvcreate --type raid1 -m 1 -L 200T -n $lv1 $vg1 --nosync
+ check lv_field $vg1/$lv1 size "200.00t"
+ lvextend -L +200T $vg1/$lv1
+ check lv_field $vg1/$lv1 size "400.00t"
+ lvremove -ff $vg1
+
+ # bz837927 END
+fi
+
+lvremove -ff $vg
11 years, 2 months
master - libdaemon: Split daemon-shared.[hc] into daemon-io.[hc] and config-util.[hc].
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=662a2122f6224b...
Commit: 662a2122f6224b5404d9f1276868bc3069766c49
Parent: 4ece923a4b8a38fd794ac1cc83d887747db6edda
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 26 14:44:03 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
libdaemon: Split daemon-shared.[hc] into daemon-io.[hc] and config-util.[hc].
---
daemons/lvmetad/lvmetad-core.c | 3 +-
include/.symlinks.in | 3 +-
lib/cache/lvmetad.h | 2 +-
libdaemon/client/Makefile.in | 2 +-
libdaemon/client/config-util.c | 288 ++++++++++++++++++++++++++++++
libdaemon/client/config-util.h | 58 ++++++
libdaemon/client/daemon-client.c | 4 +-
libdaemon/client/daemon-io.c | 99 ++++++++++
libdaemon/client/daemon-io.h | 30 +++
libdaemon/client/daemon-shared.c | 365 --------------------------------------
libdaemon/client/daemon-shared.h | 66 -------
libdaemon/server/daemon-server.c | 3 +-
12 files changed, 486 insertions(+), 437 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 6c2303d..0c39a77 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -15,7 +15,8 @@
#define _XOPEN_SOURCE 500 /* pthread */
#include "configure.h"
-#include "daemon-shared.h"
+#include "daemon-io.h"
+#include "config-util.h"
#include "daemon-server.h"
#include "daemon-log.h"
diff --git a/include/.symlinks.in b/include/.symlinks.in
index bd0eba7..e94ff84 100644
--- a/include/.symlinks.in
+++ b/include/.symlinks.in
@@ -61,7 +61,8 @@
@top_srcdir(a)/lib/report/report.h
@top_srcdir(a)/lib/uuid/uuid.h
@top_srcdir(a)/libdaemon/client/daemon-client.h
-@top_srcdir(a)/libdaemon/client/daemon-shared.h
+@top_srcdir(a)/libdaemon/client/daemon-io.h
+@top_srcdir(a)/libdaemon/client/config-util.h
@top_srcdir(a)/libdm/libdevmapper.h
@top_srcdir(a)/libdm/misc/dm-ioctl.h
@top_srcdir(a)/libdm/misc/dm-logging.h
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index 60110a0..10c4b13 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -15,7 +15,7 @@
#ifndef _LVM_METAD_H
#define _LVM_METAD_H
-#include "daemon-shared.h" // XXX
+#include "config-util.h"
struct volume_group;
struct cmd_context;
diff --git a/libdaemon/client/Makefile.in b/libdaemon/client/Makefile.in
index 4d8c436..d608816 100644
--- a/libdaemon/client/Makefile.in
+++ b/libdaemon/client/Makefile.in
@@ -15,6 +15,6 @@ top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
LIB_STATIC = libdaemonclient.a
-SOURCES = daemon-shared.c daemon-client.c
+SOURCES = daemon-io.c config-util.c daemon-client.c
include $(top_builddir)/make.tmpl
diff --git a/libdaemon/client/config-util.c b/libdaemon/client/config-util.c
new file mode 100644
index 0000000..2573139
--- /dev/null
+++ b/libdaemon/client/config-util.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dm-logging.h"
+#include "config-util.h"
+#include "libdevmapper.h"
+
+char *format_buffer_v(const char *head, va_list ap)
+{
+ char *buffer, *old;
+ char *next;
+ int keylen;
+
+ dm_asprintf(&buffer, "%s", head);
+ if (!buffer) goto fail;
+
+ while ((next = va_arg(ap, char *))) {
+ old = buffer;
+ if (!strchr(next, '=')) {
+ log_error(INTERNAL_ERROR "Bad format string at '%s'", next);
+ goto fail;
+ }
+ keylen = strchr(next, '=') - next;
+ if (strstr(next, "%d") || strstr(next, "%" PRId64)) {
+ int64_t value = va_arg(ap, int64_t);
+ dm_asprintf(&buffer, "%s%.*s= %" PRId64 "\n", buffer, keylen, next, value);
+ dm_free(old);
+ } else if (strstr(next, "%s")) {
+ char *value = va_arg(ap, char *);
+ dm_asprintf(&buffer, "%s%.*s= \"%s\"\n", buffer, keylen, next, value);
+ dm_free(old);
+ } else if (strstr(next, "%b")) {
+ char *block = va_arg(ap, char *);
+ if (!block)
+ continue;
+ dm_asprintf(&buffer, "%s%.*s%s", buffer, keylen, next, block);
+ dm_free(old);
+ } else {
+ dm_asprintf(&buffer, "%s%s", buffer, next);
+ dm_free(old);
+ }
+ if (!buffer) goto fail;
+ }
+
+ return buffer;
+fail:
+ dm_free(buffer);
+ return NULL;
+}
+
+char *format_buffer(const char *head, ...)
+{
+ va_list ap;
+ va_start(ap, head);
+ char *res = format_buffer_v(head, ap);
+ va_end(ap);
+ return res;
+}
+
+int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
+ const char *field, const char *flag, int want)
+{
+ struct dm_config_value *value = NULL, *pred = NULL;
+ struct dm_config_node *node = dm_config_find_node(parent->child, field);
+ struct dm_config_value *new;
+
+ if (node)
+ value = node->v;
+
+ while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) {
+ pred = value;
+ value = value->next;
+ }
+
+ if (value && want)
+ return 1;
+
+ if (!value && !want)
+ return 1;
+
+ if (value && !want) {
+ if (pred) {
+ pred->next = value->next;
+ } else if (value == node->v && value->next) {
+ node->v = value->next;
+ } else {
+ node->v->type = DM_CFG_EMPTY_ARRAY;
+ }
+ }
+
+ if (!value && want) {
+ if (!node) {
+ if (!(node = dm_config_create_node(cft, field)))
+ return 0;
+ node->sib = parent->child;
+ if (!(node->v = dm_config_create_value(cft)))
+ return 0;
+ node->v->type = DM_CFG_EMPTY_ARRAY;
+ node->parent = parent;
+ parent->child = node;
+ }
+ if (!(new = dm_config_create_value(cft))) {
+ /* FIXME error reporting */
+ return 0;
+ }
+ new->type = DM_CFG_STRING;
+ new->v.str = flag;
+ new->next = node->v;
+ node->v = new;
+ }
+
+ return 1;
+}
+
+static void chain_node(struct dm_config_node *cn,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ cn->parent = parent;
+ cn->sib = NULL;
+
+ if (parent && parent->child && !pre_sib) { /* find the last one */
+ pre_sib = parent->child;
+ while (pre_sib && pre_sib->sib)
+ pre_sib = pre_sib->sib;
+ }
+
+ if (parent && !parent->child)
+ parent->child = cn;
+ if (pre_sib) {
+ cn->sib = pre_sib->sib;
+ pre_sib->sib = cn;
+ }
+
+}
+
+struct dm_config_node *make_config_node(struct dm_config_tree *cft,
+ const char *key,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ struct dm_config_node *cn;
+
+ if (!(cn = dm_config_create_node(cft, key)))
+ return NULL;
+
+ cn->v = NULL;
+ cn->child = NULL;
+
+ chain_node(cn, parent, pre_sib);
+
+ return cn;
+}
+
+struct dm_config_node *make_text_node(struct dm_config_tree *cft,
+ const char *key,
+ const char *value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ struct dm_config_node *cn;
+
+ if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
+ !(cn->v = dm_config_create_value(cft)))
+ return NULL;
+
+ cn->v->type = DM_CFG_STRING;
+ cn->v->v.str = value;
+ return cn;
+}
+
+struct dm_config_node *make_int_node(struct dm_config_tree *cft,
+ const char *key,
+ int64_t value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib)
+{
+ struct dm_config_node *cn;
+
+ if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
+ !(cn->v = dm_config_create_value(cft)))
+ return NULL;
+
+ cn->v->type = DM_CFG_INT;
+ cn->v->v.i = value;
+ return cn;
+}
+
+struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ va_list ap)
+{
+ const char *next;
+ struct dm_config_node *first = NULL;
+
+ while ((next = va_arg(ap, char *))) {
+ struct dm_config_node *cn = NULL;
+ const char *fmt = strchr(next, '=');
+
+ if (!fmt) {
+ log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
+ return_NULL;
+ }
+ fmt += 2;
+
+ char *key = dm_pool_strdup(cft->mem, next);
+ *strchr(key, '=') = 0;
+
+ if (!strcmp(fmt, "%d") || !strcmp(fmt, "%" PRId64)) {
+ int64_t value = va_arg(ap, int64_t);
+ if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
+ return 0;
+ } else if (!strcmp(fmt, "%s")) {
+ char *value = va_arg(ap, char *);
+ if (!(cn = make_text_node(cft, key, value, parent, pre_sib)))
+ return 0;
+ } else if (!strcmp(fmt, "%t")) {
+ struct dm_config_tree *tree = va_arg(ap, struct dm_config_tree *);
+ cn = dm_config_clone_node(cft, tree->root, 1);
+ if (!cn)
+ return 0;
+ cn->key = key;
+ chain_node(cn, parent, pre_sib);
+ } else {
+ log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
+ return_NULL;
+ }
+ if (!first)
+ first = cn;
+ if (cn)
+ pre_sib = cn;
+ }
+
+ return first;
+}
+
+struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ ...)
+{
+ va_list ap;
+ va_start(ap, pre_sib);
+ struct dm_config_node *res = config_make_nodes_v(cft, parent, pre_sib, ap);
+ va_end(ap);
+ return res;
+}
+
+int buffer_rewrite(char **buf, const char *format, const char *string)
+{
+ char *old = *buf;
+ int r = dm_asprintf(buf, format, *buf, string);
+
+ dm_free(old);
+
+ return (r < 0) ? 0 : 1;
+}
+
+int buffer_line(const char *line, void *baton)
+{
+ char **buffer = baton;
+
+ if (*buffer) {
+ if (!buffer_rewrite(buffer, "%s\n%s", line))
+ return 0;
+ } else if (dm_asprintf(buffer, "%s\n", line) < 0)
+ return 0;
+
+ return 1;
+}
+
diff --git a/libdaemon/client/config-util.h b/libdaemon/client/config-util.h
new file mode 100644
index 0000000..ae5e556
--- /dev/null
+++ b/libdaemon/client/config-util.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_DAEMON_CONFIG_UTIL_H
+#define _LVM_DAEMON_CONFIG_UTIL_H
+
+#include "configure.h"
+#include "libdevmapper.h"
+
+#include <stdarg.h>
+
+char *format_buffer_v(const char *head, va_list ap);
+char *format_buffer(const char *head, ...);
+
+int buffer_line(const char *line, void *baton);
+int buffer_rewrite(char **buf, const char *format, const char *string);
+
+int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
+ const char *field, const char *flag, int want);
+
+struct dm_config_node *make_config_node(struct dm_config_tree *cft,
+ const char *key,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib);
+
+struct dm_config_node *make_text_node(struct dm_config_tree *cft,
+ const char *key,
+ const char *value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib);
+
+struct dm_config_node *make_int_node(struct dm_config_tree *cft,
+ const char *key,
+ int64_t value,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib);
+
+struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ va_list ap);
+struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
+ struct dm_config_node *parent,
+ struct dm_config_node *pre_sib,
+ ...);
+
+#endif /* _LVM_DAEMON_SHARED_H */
diff --git a/libdaemon/client/daemon-client.c b/libdaemon/client/daemon-client.c
index 2de970a..e34a2a0 100644
--- a/libdaemon/client/daemon-client.c
+++ b/libdaemon/client/daemon-client.c
@@ -12,8 +12,10 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "daemon-shared.h"
+#include "daemon-io.h"
+#include "config-util.h"
#include "daemon-client.h"
+#include "dm-logging.h"
#include <sys/un.h>
#include <sys/socket.h>
diff --git a/libdaemon/client/daemon-io.c b/libdaemon/client/daemon-io.c
new file mode 100644
index 0000000..4af9343
--- /dev/null
+++ b/libdaemon/client/daemon-io.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "daemon-io.h"
+#include "dm-logging.h"
+#include "libdevmapper.h"
+
+/*
+ * Read a single message from a (socket) filedescriptor. Messages are delimited
+ * by blank lines. This call will block until all of a message is received. The
+ * memory will be allocated from heap. Upon error, all memory is freed and the
+ * buffer pointer is set to NULL.
+ *
+ * See also write_buffer about blocking (read_buffer has identical behaviour).
+ */
+int read_buffer(int fd, char **buffer) {
+ int bytes = 0;
+ int buffersize = 32;
+ char *new;
+ *buffer = dm_malloc(buffersize + 1);
+
+ while (1) {
+ int result = read(fd, (*buffer) + bytes, buffersize - bytes);
+ if (result > 0) {
+ bytes += result;
+ if (!strncmp((*buffer) + bytes - 4, "\n##\n", 4)) {
+ *(*buffer + bytes - 4) = 0;
+ break; /* success, we have the full message now */
+ }
+ if (bytes == buffersize) {
+ buffersize += 1024;
+ if (!(new = realloc(*buffer, buffersize + 1)))
+ goto fail;
+ *buffer = new;
+ }
+ continue;
+ }
+ if (result == 0) {
+ errno = ECONNRESET;
+ goto fail; /* we should never encounter EOF here */
+ }
+ if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
+ goto fail;
+ /* TODO call select here if we encountered EAGAIN/EWOULDBLOCK/EINTR */
+ }
+ return 1;
+fail:
+ dm_free(*buffer);
+ *buffer = NULL;
+ return 0;
+}
+
+/*
+ * Write a buffer to a filedescriptor. Keep trying. Blocks (even on
+ * SOCK_NONBLOCK) until all of the write went through.
+ *
+ * TODO use select on EWOULDBLOCK/EAGAIN/EINTR to avoid useless spinning
+ */
+int write_buffer(int fd, const char *buffer, int length) {
+ static const char terminate[] = "\n##\n";
+ int done = 0;
+ int written = 0;
+write:
+ while (1) {
+ int result = write(fd, buffer + written, length - written);
+ if (result > 0)
+ written += result;
+ if (result < 0 && errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR)
+ return 0; /* too bad */
+ if (written == length) {
+ if (done)
+ return 1;
+ else
+ break; /* done */
+ }
+ }
+
+ buffer = terminate;
+ length = 4;
+ written = 0;
+ done = 1;
+ goto write;
+}
diff --git a/libdaemon/client/daemon-io.h b/libdaemon/client/daemon-io.h
new file mode 100644
index 0000000..e6e5f06
--- /dev/null
+++ b/libdaemon/client/daemon-io.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_DAEMON_IO_H
+#define _LVM_DAEMON_IO_H
+
+#include "configure.h"
+#include "libdevmapper.h"
+
+#define _REENTRANT
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+/* TODO function names */
+
+int read_buffer(int fd, char **buffer);
+int write_buffer(int fd, const char *buffer, int length);
+
+#endif /* _LVM_DAEMON_SHARED_H */
diff --git a/libdaemon/client/daemon-shared.c b/libdaemon/client/daemon-shared.c
deleted file mode 100644
index e6f17a0..0000000
--- a/libdaemon/client/daemon-shared.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2011-2012 Red Hat, Inc.
- *
- * This file is part of LVM2.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License v.2.1.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "dm-logging.h"
-#include "daemon-shared.h"
-#include "libdevmapper.h"
-
-/*
- * Read a single message from a (socket) filedescriptor. Messages are delimited
- * by blank lines. This call will block until all of a message is received. The
- * memory will be allocated from heap. Upon error, all memory is freed and the
- * buffer pointer is set to NULL.
- *
- * See also write_buffer about blocking (read_buffer has identical behaviour).
- */
-int read_buffer(int fd, char **buffer) {
- int bytes = 0;
- int buffersize = 32;
- char *new;
- *buffer = dm_malloc(buffersize + 1);
-
- while (1) {
- int result = read(fd, (*buffer) + bytes, buffersize - bytes);
- if (result > 0) {
- bytes += result;
- if (!strncmp((*buffer) + bytes - 4, "\n##\n", 4)) {
- *(*buffer + bytes - 4) = 0;
- break; /* success, we have the full message now */
- }
- if (bytes == buffersize) {
- buffersize += 1024;
- if (!(new = realloc(*buffer, buffersize + 1)))
- goto fail;
- *buffer = new;
- }
- continue;
- }
- if (result == 0) {
- errno = ECONNRESET;
- goto fail; /* we should never encounter EOF here */
- }
- if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
- goto fail;
- /* TODO call select here if we encountered EAGAIN/EWOULDBLOCK/EINTR */
- }
- return 1;
-fail:
- dm_free(*buffer);
- *buffer = NULL;
- return 0;
-}
-
-/*
- * Write a buffer to a filedescriptor. Keep trying. Blocks (even on
- * SOCK_NONBLOCK) until all of the write went through.
- *
- * TODO use select on EWOULDBLOCK/EAGAIN/EINTR to avoid useless spinning
- */
-int write_buffer(int fd, const char *buffer, int length) {
- static const char terminate[] = "\n##\n";
- int done = 0;
- int written = 0;
-write:
- while (1) {
- int result = write(fd, buffer + written, length - written);
- if (result > 0)
- written += result;
- if (result < 0 && errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR)
- return 0; /* too bad */
- if (written == length) {
- if (done)
- return 1;
- else
- break; /* done */
- }
- }
-
- buffer = terminate;
- length = 4;
- written = 0;
- done = 1;
- goto write;
-}
-
-char *format_buffer_v(const char *head, va_list ap)
-{
- char *buffer, *old;
- char *next;
- int keylen;
-
- dm_asprintf(&buffer, "%s", head);
- if (!buffer) goto fail;
-
- while ((next = va_arg(ap, char *))) {
- old = buffer;
- if (!strchr(next, '=')) {
- log_error(INTERNAL_ERROR "Bad format string at '%s'", next);
- goto fail;
- }
- keylen = strchr(next, '=') - next;
- if (strstr(next, "%d") || strstr(next, "%" PRId64)) {
- int64_t value = va_arg(ap, int64_t);
- dm_asprintf(&buffer, "%s%.*s= %" PRId64 "\n", buffer, keylen, next, value);
- dm_free(old);
- } else if (strstr(next, "%s")) {
- char *value = va_arg(ap, char *);
- dm_asprintf(&buffer, "%s%.*s= \"%s\"\n", buffer, keylen, next, value);
- dm_free(old);
- } else if (strstr(next, "%b")) {
- char *block = va_arg(ap, char *);
- if (!block)
- continue;
- dm_asprintf(&buffer, "%s%.*s%s", buffer, keylen, next, block);
- dm_free(old);
- } else {
- dm_asprintf(&buffer, "%s%s", buffer, next);
- dm_free(old);
- }
- if (!buffer) goto fail;
- }
-
- return buffer;
-fail:
- dm_free(buffer);
- return NULL;
-}
-
-char *format_buffer(const char *head, ...)
-{
- va_list ap;
- va_start(ap, head);
- char *res = format_buffer_v(head, ap);
- va_end(ap);
- return res;
-}
-
-int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
- const char *field, const char *flag, int want)
-{
- struct dm_config_value *value = NULL, *pred = NULL;
- struct dm_config_node *node = dm_config_find_node(parent->child, field);
- struct dm_config_value *new;
-
- if (node)
- value = node->v;
-
- while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) {
- pred = value;
- value = value->next;
- }
-
- if (value && want)
- return 1;
-
- if (!value && !want)
- return 1;
-
- if (value && !want) {
- if (pred) {
- pred->next = value->next;
- } else if (value == node->v && value->next) {
- node->v = value->next;
- } else {
- node->v->type = DM_CFG_EMPTY_ARRAY;
- }
- }
-
- if (!value && want) {
- if (!node) {
- if (!(node = dm_config_create_node(cft, field)))
- return 0;
- node->sib = parent->child;
- if (!(node->v = dm_config_create_value(cft)))
- return 0;
- node->v->type = DM_CFG_EMPTY_ARRAY;
- node->parent = parent;
- parent->child = node;
- }
- if (!(new = dm_config_create_value(cft))) {
- /* FIXME error reporting */
- return 0;
- }
- new->type = DM_CFG_STRING;
- new->v.str = flag;
- new->next = node->v;
- node->v = new;
- }
-
- return 1;
-}
-
-static void chain_node(struct dm_config_node *cn,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- cn->parent = parent;
- cn->sib = NULL;
-
- if (parent && parent->child && !pre_sib) { /* find the last one */
- pre_sib = parent->child;
- while (pre_sib && pre_sib->sib)
- pre_sib = pre_sib->sib;
- }
-
- if (parent && !parent->child)
- parent->child = cn;
- if (pre_sib) {
- cn->sib = pre_sib->sib;
- pre_sib->sib = cn;
- }
-
-}
-
-struct dm_config_node *make_config_node(struct dm_config_tree *cft,
- const char *key,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- struct dm_config_node *cn;
-
- if (!(cn = dm_config_create_node(cft, key)))
- return NULL;
-
- cn->v = NULL;
- cn->child = NULL;
-
- chain_node(cn, parent, pre_sib);
-
- return cn;
-}
-
-struct dm_config_node *make_text_node(struct dm_config_tree *cft,
- const char *key,
- const char *value,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- struct dm_config_node *cn;
-
- if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
- !(cn->v = dm_config_create_value(cft)))
- return NULL;
-
- cn->v->type = DM_CFG_STRING;
- cn->v->v.str = value;
- return cn;
-}
-
-struct dm_config_node *make_int_node(struct dm_config_tree *cft,
- const char *key,
- int64_t value,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib)
-{
- struct dm_config_node *cn;
-
- if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
- !(cn->v = dm_config_create_value(cft)))
- return NULL;
-
- cn->v->type = DM_CFG_INT;
- cn->v->v.i = value;
- return cn;
-}
-
-struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib,
- va_list ap)
-{
- const char *next;
- struct dm_config_node *first = NULL;
-
- while ((next = va_arg(ap, char *))) {
- struct dm_config_node *cn = NULL;
- const char *fmt = strchr(next, '=');
-
- if (!fmt) {
- log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
- return_NULL;
- }
- fmt += 2;
-
- char *key = dm_pool_strdup(cft->mem, next);
- *strchr(key, '=') = 0;
-
- if (!strcmp(fmt, "%d") || !strcmp(fmt, "%" PRId64)) {
- int64_t value = va_arg(ap, int64_t);
- if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
- return 0;
- } else if (!strcmp(fmt, "%s")) {
- char *value = va_arg(ap, char *);
- if (!(cn = make_text_node(cft, key, value, parent, pre_sib)))
- return 0;
- } else if (!strcmp(fmt, "%t")) {
- struct dm_config_tree *tree = va_arg(ap, struct dm_config_tree *);
- cn = dm_config_clone_node(cft, tree->root, 1);
- if (!cn)
- return 0;
- cn->key = key;
- chain_node(cn, parent, pre_sib);
- } else {
- log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
- return_NULL;
- }
- if (!first)
- first = cn;
- if (cn)
- pre_sib = cn;
- }
-
- return first;
-}
-
-struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib,
- ...)
-{
- va_list ap;
- va_start(ap, pre_sib);
- struct dm_config_node *res = config_make_nodes_v(cft, parent, pre_sib, ap);
- va_end(ap);
- return res;
-}
-
-int buffer_rewrite(char **buf, const char *format, const char *string)
-{
- char *old = *buf;
- int r = dm_asprintf(buf, format, *buf, string);
-
- dm_free(old);
-
- return (r < 0) ? 0 : 1;
-}
-
-int buffer_line(const char *line, void *baton)
-{
- char **buffer = baton;
-
- if (*buffer) {
- if (!buffer_rewrite(buffer, "%s\n%s", line))
- return 0;
- } else if (dm_asprintf(buffer, "%s\n", line) < 0)
- return 0;
-
- return 1;
-}
-
diff --git a/libdaemon/client/daemon-shared.h b/libdaemon/client/daemon-shared.h
deleted file mode 100644
index acb71c6..0000000
--- a/libdaemon/client/daemon-shared.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2011-2012 Red Hat, Inc.
- *
- * This file is part of LVM2.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License v.2.1.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _LVM_DAEMON_SHARED_H
-#define _LVM_DAEMON_SHARED_H
-
-#include "configure.h"
-#include "libdevmapper.h"
-
-#define _REENTRANT
-#define _GNU_SOURCE
-#define _FILE_OFFSET_BITS 64
-
-/* TODO function names */
-
-#include <stdarg.h>
-
-int read_buffer(int fd, char **buffer);
-int write_buffer(int fd, const char *buffer, int length);
-char *format_buffer_v(const char *head, va_list ap);
-char *format_buffer(const char *head, ...);
-
-int buffer_line(const char *line, void *baton);
-int buffer_rewrite(char **buf, const char *format, const char *string);
-
-int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
- const char *field, const char *flag, int want);
-
-struct dm_config_node *make_config_node(struct dm_config_tree *cft,
- const char *key,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib);
-
-struct dm_config_node *make_text_node(struct dm_config_tree *cft,
- const char *key,
- const char *value,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib);
-
-struct dm_config_node *make_int_node(struct dm_config_tree *cft,
- const char *key,
- int64_t value,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib);
-
-struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib,
- va_list ap);
-struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
- struct dm_config_node *parent,
- struct dm_config_node *pre_sib,
- ...);
-
-#endif /* _LVM_DAEMON_SHARED_H */
diff --git a/libdaemon/server/daemon-server.c b/libdaemon/server/daemon-server.c
index 50bf065..b15a7cc 100644
--- a/libdaemon/server/daemon-server.c
+++ b/libdaemon/server/daemon-server.c
@@ -10,7 +10,8 @@
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "daemon-shared.h"
+#include "daemon-io.h"
+#include "config-util.h"
#include "daemon-server.h"
#include "daemon-log.h"
11 years, 2 months
master - libdaemonclient: Use log_sys_error in place of perror.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=4ece923a4b8a38...
Commit: 4ece923a4b8a38fd794ac1cc83d887747db6edda
Parent: 7a2a1a7456be3adbfe5a3d034e122ea5e7cae6a0
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 26 13:11:13 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
libdaemonclient: Use log_sys_error in place of perror.
---
libdaemon/client/daemon-client.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/libdaemon/client/daemon-client.c b/libdaemon/client/daemon-client.c
index 39b082f..2de970a 100644
--- a/libdaemon/client/daemon-client.c
+++ b/libdaemon/client/daemon-client.c
@@ -60,7 +60,7 @@ error:
h.error = errno;
if (h.socket_fd >= 0)
if (close(h.socket_fd))
- perror("close");
+ log_sys_error("close", "daemon_open");
if (r.cft)
daemon_reply_destroy(r);
h.socket_fd = -1;
11 years, 2 months
master - libdaemonclient: Use dm_{malloc, free} in place of {malloc, free}.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7a2a1a7456be3a...
Commit: 7a2a1a7456be3adbfe5a3d034e122ea5e7cae6a0
Parent: 3124840185f9dc3e842c812e490a6f61ae040a2b
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 26 13:10:53 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
libdaemonclient: Use dm_{malloc,free} in place of {malloc,free}.
---
libdaemon/client/daemon-shared.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/libdaemon/client/daemon-shared.c b/libdaemon/client/daemon-shared.c
index 6a1cf05..e6f17a0 100644
--- a/libdaemon/client/daemon-shared.c
+++ b/libdaemon/client/daemon-shared.c
@@ -14,7 +14,6 @@
#include <errno.h>
#include <stdio.h>
-#include <malloc.h>
#include <string.h>
#include <unistd.h>
@@ -34,7 +33,7 @@ int read_buffer(int fd, char **buffer) {
int bytes = 0;
int buffersize = 32;
char *new;
- *buffer = malloc(buffersize + 1);
+ *buffer = dm_malloc(buffersize + 1);
while (1) {
int result = read(fd, (*buffer) + bytes, buffersize - bytes);
@@ -62,7 +61,7 @@ int read_buffer(int fd, char **buffer) {
}
return 1;
fail:
- free(*buffer);
+ dm_free(*buffer);
*buffer = NULL;
return 0;
}
11 years, 2 months
master - lvremove: Revert to allowing removal of partial LVs.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3124840185f9dc...
Commit: 3124840185f9dc3e842c812e490a6f61ae040a2b
Parent: 5f5832e318e43c86054a28a4c9f3003542513663
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 26 12:25:45 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvremove: Revert to allowing removal of partial LVs.
---
tools/lvremove.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/tools/lvremove.c b/tools/lvremove.c
index 2c5b317..0252149 100644
--- a/tools/lvremove.c
+++ b/tools/lvremove.c
@@ -26,12 +26,6 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
if (lv_is_cow(lv) && lv_is_virtual_origin(origin = origin_from_cow(lv)))
lv = origin;
- if (lv->status & PARTIAL_LV) {
- log_error("Not removing LV %s/%s because part or all of it is missing.",
- lv->vg->name, lv->name);
- return ECMD_FAILED;
- }
-
if (!lv_remove_with_dependencies(cmd, lv, arg_count(cmd, force_ARG), 0)) {
stack;
return ECMD_FAILED;
11 years, 2 months
master - lvremove: Ask before discarding data areas.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=5f5832e318e43c...
Commit: 5f5832e318e43c86054a28a4c9f3003542513663
Parent: f8e287cca21feda34ff261e449e8d5a89a9490e9
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 26 12:23:44 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvremove: Ask before discarding data areas.
---
lib/metadata/lv_manip.c | 29 ++++++++++++++++++++++-------
1 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 3702caf..6c62bb3 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3253,6 +3253,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
int format1_reload_required = 0;
int visible;
struct logical_volume *pool_lv = NULL;
+ int ask_discard;
vg = lv->vg;
@@ -3296,6 +3297,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
}
/* FIXME Ensure not referred to by another existing LVs */
+ ask_discard = find_config_tree_bool(cmd,
+ "devices/issue_discards", DEFAULT_ISSUE_DISCARDS);
if (lv_info(cmd, lv, 0, &info, 1, 0)) {
if (!lv_check_not_in_use(cmd, lv, &info))
@@ -3303,16 +3306,28 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
if ((force == PROMPT) &&
lv_is_visible(lv) &&
- lv_is_active(lv) &&
- yes_no_prompt("Do you really want to remove active "
- "%slogical volume %s? [y/n]: ",
- vg_is_clustered(vg) ? "clustered " : "",
- lv->name) == 'n') {
- log_error("Logical volume %s not removed", lv->name);
- return 0;
+ lv_is_active(lv)) {
+ if (yes_no_prompt("Do you really want to remove%s active "
+ "%slogical volume %s? [y/n]: ",
+ ask_discard ? " and DISCARD" : "",
+ vg_is_clustered(vg) ? "clustered " : "",
+ lv->name) == 'n') {
+ log_error("Logical volume %s not removed", lv->name);
+ return 0;
+ } else {
+ ask_discard = 0;
+ }
}
}
+ if ((force == PROMPT) && ask_discard &&
+ yes_no_prompt("Do you really want to remove and DISCARD "
+ "logical volume %s? [y/n]: ",
+ lv->name) == 'n') {
+ log_error("Logical volume %s not removed", lv->name);
+ return 0;
+ }
+
if (!archive(vg))
return 0;
11 years, 2 months
master - TEST: Workaround for lvmetad vs inconsistent metadata.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f8e287cca21fed...
Commit: f8e287cca21feda34ff261e449e8d5a89a9490e9
Parent: 9f96286c29897ba9ac5c7c2f167d0f33ebaa93d4
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Thu Sep 20 01:57:55 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
TEST: Workaround for lvmetad vs inconsistent metadata.
---
test/shell/inconsistent-metadata.sh | 1 +
test/shell/unlost-pv.sh | 12 ++++++++----
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/test/shell/inconsistent-metadata.sh b/test/shell/inconsistent-metadata.sh
index b5ef450..9f4ffd2 100644
--- a/test/shell/inconsistent-metadata.sh
+++ b/test/shell/inconsistent-metadata.sh
@@ -37,6 +37,7 @@ test -e LOCAL_LVMETAD && cache="--cache"
init
vgscan $cache 2>&1 | tee cmd.out
grep "Inconsistent metadata found for VG $vg" cmd.out
+test -e LOCAL_LVMETAD && vgrename $vg foo && vgrename foo $vg # trigger a write
vgscan $cache 2>&1 | tee cmd.out
not grep "Inconsistent metadata found for VG $vg" cmd.out
check
diff --git a/test/shell/unlost-pv.sh b/test/shell/unlost-pv.sh
index c7a1412..962fe22 100644
--- a/test/shell/unlost-pv.sh
+++ b/test/shell/unlost-pv.sh
@@ -15,26 +15,30 @@ check_() {
# vgscan needs --cache option for direct scan if lvmetad is used
test -e LOCAL_LVMETAD && cache="--cache"
vgscan $cache 2>&1 | tee vgscan.out
- grep "Inconsistent metadata found for VG $vg" vgscan.out
- vgscan $cache 2>&1 | tee vgscan.out
- not grep "Inconsistent metadata found for VG $vg" vgscan.out
+ $1 grep "Inconsistent metadata found for VG $vg" vgscan.out
}
aux prepare_vg 3
lvcreate -m 1 -l 1 -n mirror $vg
-lvchange -a n $vg/mirror
+lvchange -a n $vg
# try orphaning a missing PV (bz45867)
aux disable_dev "$dev1"
vgreduce --removemissing --force $vg
aux enable_dev "$dev1"
+
check_
+test -e LOCAL_LVMETAD && pvcreate -f "$dev1"
+check_ not
# try to just change metadata; we expect the new version (with MISSING_PV set
# on the reappeared volume) to be written out to the previously missing PV
vgextend $vg "$dev1"
+lvcreate -l 1 -n boo -a n --zero n $vg
aux disable_dev "$dev1"
lvremove $vg/mirror
aux enable_dev "$dev1"
check_
+test -e LOCAL_LVMETAD && lvremove $vg/boo # FIXME trigger a write :-(
+check_ not
11 years, 2 months
master - lvmetad: Initialise debug_config also if no -d is given.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9f96286c29897b...
Commit: 9f96286c29897ba9ac5c7c2f167d0f33ebaa93d4
Parent: 1ff2245c23247a1d3f9a03be66d3d186c824f03f
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Thu Sep 20 01:56:41 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvmetad: Initialise debug_config also if no -d is given.
---
daemons/lvmetad/lvmetad-core.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index f796e33..6c2303d 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -1043,6 +1043,7 @@ int main(int argc, char *argv[])
s.pidfile = LVMETAD_PIDFILE;
s.protocol = "lvmetad";
s.protocol_version = 1;
+ ls.debug_config = "";
// use getopt_long
while ((opt = getopt(argc, argv, "?fhVd:Rs:")) != EOF) {
11 years, 2 months
master - lvmetad: Give inconsistent metadata warnings in pvscan --cache.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1ff2245c23247a...
Commit: 1ff2245c23247a1d3f9a03be66d3d186c824f03f
Parent: c731bb1ee13565763cc1ac77ed1a01ccea0337ac
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 19 23:45:51 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvmetad: Give inconsistent metadata warnings in pvscan --cache.
---
daemons/lvmetad/lvmetad-core.c | 21 ++++++++++++++++-----
lib/cache/lvmetad.c | 5 +++++
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index c6cc3d9..f796e33 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -636,7 +636,7 @@ static int vg_remove_if_missing(lvmetad_state *s, const char *vgid)
* this function, so they can be safely destroyed after update_metadata returns
* (anything that might have been retained is copied). */
static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid,
- struct dm_config_node *metadata)
+ struct dm_config_node *metadata, int64_t *oldseq)
{
struct dm_config_tree *cft;
struct dm_config_tree *old;
@@ -665,6 +665,13 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid
filter_metadata(metadata); /* sanitize */
+ if (oldseq) {
+ if (old)
+ *oldseq = haveseq;
+ else
+ *oldseq = seq;
+ }
+
if (seq == haveseq) {
retval = 1;
if (compare_config(metadata, old->root))
@@ -786,6 +793,7 @@ static response pv_found(lvmetad_state *s, request r)
const char *old;
const char *pvid_dup;
int complete = 0, orphan = 0;
+ int64_t seqno = -1, seqno_old = -1;
if (!pvid)
return reply_fail("need PV UUID");
@@ -830,7 +838,7 @@ static response pv_found(lvmetad_state *s, request r)
if (daemon_request_int(r, "metadata/seqno", -1) < 0)
return reply_fail("need VG seqno");
- if (!update_metadata(s, vgname, vgid, metadata))
+ if (!update_metadata(s, vgname, vgid, metadata, &seqno_old))
return reply_fail("metadata update failed");
} else {
lock_pvid_to_vgid(s);
@@ -839,9 +847,10 @@ static response pv_found(lvmetad_state *s, request r)
}
if (vgid) {
- if ((cft = lock_vg(s, vgid)))
+ if ((cft = lock_vg(s, vgid))) {
complete = update_pv_status(s, cft, cft->root, 0);
- else if (!strcmp(vgid, "#orphan"))
+ seqno = dm_config_find_int(cft->root, "metadata/seqno", -1);
+ } else if (!strcmp(vgid, "#orphan"))
orphan = 1;
else {
unlock_vg(s, vgid);
@@ -854,6 +863,8 @@ static response pv_found(lvmetad_state *s, request r)
"status = %s", orphan ? "orphan" :
(complete ? "complete" : "partial"),
"vgid = %s", vgid ? vgid : "#orphan",
+ "seqno_before = %"PRId64, seqno_old,
+ "seqno_after = %"PRId64, seqno,
NULL);
}
@@ -872,7 +883,7 @@ static response vg_update(lvmetad_state *s, request r)
/* TODO defer metadata update here; add a separate vg_commit
* call; if client does not commit, die */
- if (!update_metadata(s, vgname, vgid, metadata))
+ if (!update_metadata(s, vgname, vgid, metadata, NULL))
return reply_fail("metadata update failed");
}
return daemon_reply_simple("OK", NULL);
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 8ac5732..24a6b16 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -720,6 +720,11 @@ int lvmetad_pv_found(struct id pvid, struct device *device, const struct format_
result = _lvmetad_handle_reply(reply, "update PV", uuid, NULL);
+ if (vg && result &&
+ (daemon_reply_int(reply, "seqno_after", -1) != vg->seqno ||
+ daemon_reply_int(reply, "seqno_after", -1) != daemon_reply_int(reply, "seqno_before", -1)))
+ log_warn("WARNING: Inconsistent metadata found for VG %s", vg->name);
+
if (result && handler) {
status = daemon_reply_str(reply, "status", "<missing>");
if (!strcmp(status, "partial"))
11 years, 2 months
master - lvmetad: Fix #845269: SEGV on corrupt lvmetad response.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c731bb1ee13565...
Commit: c731bb1ee13565763cc1ac77ed1a01ccea0337ac
Parent: d2d66634282459438210f1f9ba7e2e4c910e13ba
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Wed Sep 19 23:30:16 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Wed Sep 26 17:26:23 2012 +0200
lvmetad: Fix #845269: SEGV on corrupt lvmetad response.
---
lib/cache/lvmetad.c | 6 +++---
libdaemon/client/daemon-client.c | 2 ++
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index a7e3cd3..8ac5732 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -86,7 +86,7 @@ static int _token_update()
{
daemon_reply repl = _lvmetad_send("token_update", NULL);
- if (strcmp(daemon_reply_str(repl, "response", ""), "OK")) {
+ if (repl.error || strcmp(daemon_reply_str(repl, "response", ""), "OK")) {
daemon_reply_destroy(repl);
return 0;
}
@@ -118,7 +118,7 @@ retry:
daemon_request_destroy(req);
- if (!strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") && try < 2 && !test_mode()) {
+ if (!repl.error && !strcmp(daemon_reply_str(repl, "response", ""), "token_mismatch") && try < 2 && !test_mode()) {
future_token = _lvmetad_token;
_lvmetad_token = (char *) "update in progress";
if (!_token_update()) goto out;
@@ -298,7 +298,7 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd, const char *vgna
reply = _lvmetad_send("vg_lookup", "name = %s", vgname, NULL);
}
- if (!strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
+ if (!reply.error && !strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
if (!(top = dm_config_find_node(reply.cft->root, "metadata"))) {
log_error(INTERNAL_ERROR "metadata config node not found.");
diff --git a/libdaemon/client/daemon-client.c b/libdaemon/client/daemon-client.c
index 0ade329..39b082f 100644
--- a/libdaemon/client/daemon-client.c
+++ b/libdaemon/client/daemon-client.c
@@ -81,6 +81,8 @@ daemon_reply daemon_send(daemon_handle h, daemon_request rq)
if (read_buffer(h.socket_fd, &reply.buffer)) {
reply.cft = dm_config_from_string(reply.buffer);
+ if (!reply.cft)
+ reply.error = EPROTO;
} else
reply.error = errno;
11 years, 2 months