master - systemd: various updates and fixes
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=360c569ce8f0bf...
Commit: 360c569ce8f0bfe936d59ca91de2716958550524
Parent: 09d77d0c9455a42bfe7c1c55ac64475fb349b1d6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Oct 30 20:36:49 2012 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue Oct 30 20:55:50 2012 +0100
systemd: various updates and fixes
Don't use lvmetad in lvm2-monitor.service ExecStop to avoid a systemd issue.
- a systemd design issue while processing dependencies
with socket-based activation that ends up with a hang
- https://bugzilla.redhat.com/show_bug.cgi?id=843587
(also tracker bug https://bugzilla.redhat.com/show_bug.cgi?id=871527)
- not using lvmetad in this case is just a workaround, once the bug
above is resolved, we should enable the lvmetad in that specific case
Remove dependency on fedora-storage-init.service in lvm2 systemd units.
- fedora-storage-init.service and fedora-storage-init-late.service is
going to be separated into respective units that belong to each block
device subsystem:
- mpath + mdraid activated via udev solely
- dmraid with its own dmraid-activation.service unit
- lvm2 with the lvm2-activation-generator to generate the
activation units runtime if lvmetad disabled
(global/use_lvmetad=0 set in lvm.conf) and activation done
via udev+lvmetad if lvmetad enabled (global/use_lvmetad=1 set
in lvm.conf)
Depend on lvm2-lvmetad.socket in lvm2-monitor.service systemd unit.
- as lvm2-monitor uses lvmetad if lvmetad is enabled
---
WHATS_NEW | 3 +++
scripts/lvm2_monitoring_systemd_red_hat.service.in | 7 ++++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 4b71402..a3f8142 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,8 @@
Version 2.02.99 -
===================================
+ Don't use lvmetad in lvm2-monitor.service ExecStop to avoid a systemd issue.
+ Remove dependency on fedora-storage-init.service in lvm2 systemd units.
+ Depend on lvm2-lvmetad.socket in lvm2-monitor.service systemd unit.
Hardcode use_lvmetad=0 if cluster locking used and issue a warning msg.
Avoid reading mirrors with failed devices in its mirrored log.
Avoid reading from mirrors that have failed devices if they block I/O.
diff --git a/scripts/lvm2_monitoring_systemd_red_hat.service.in b/scripts/lvm2_monitoring_systemd_red_hat.service.in
index 6c4c55f..e6b4814 100644
--- a/scripts/lvm2_monitoring_systemd_red_hat.service.in
+++ b/scripts/lvm2_monitoring_systemd_red_hat.service.in
@@ -1,8 +1,8 @@
[Unit]
Description=Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
Documentation=man:dmeventd(8) man:lvcreate(8) man:lvchange(8) man:vgchange(8)
-Requires=dm-event.socket
-After=dm-event.socket fedora-storage-init.service fedora-storage-init-late.service lvm2-activation.service lvm2-lvmetad.service
+Requires=dm-event.socket lvm2-lvmetad.socket
+After=dm-event.socket lvm2-lvmetad.socket lvm2-lvmetad.service
Before=local-fs.target
DefaultDependencies=no
Conflicts=shutdown.target
@@ -11,7 +11,8 @@ Conflicts=shutdown.target
Type=oneshot
Environment=LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1
ExecStart=@sbindir@/lvm vgchange --monitor y
-ExecStop=@sbindir@/lvm vgchange --monitor n
+# The lvmetad must be disabled here, it needs https://bugzilla.redhat.com/show_bug.cgi?id=843587 to be resolved first.
+ExecStop="@sbindir@/lvm vgchange --monitor n --config 'global{use_lvmetad=0}'"
RemainAfterExit=yes
[Install]
11 years, 1 month
master - test: Check that overriding use_lvmetad with --config works.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=09d77d0c9455a4...
Commit: 09d77d0c9455a42bfe7c1c55ac64475fb349b1d6
Parent: 983f0b46f2de85b8de0e2d7f8afbdf53f132a87a
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Tue Oct 30 09:16:15 2012 +0100
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Tue Oct 30 09:16:15 2012 +0100
test: Check that overriding use_lvmetad with --config works.
---
test/shell/lvmetad-override.sh | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/test/shell/lvmetad-override.sh b/test/shell/lvmetad-override.sh
new file mode 100644
index 0000000..3fb281a
--- /dev/null
+++ b/test/shell/lvmetad-override.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+#
+# 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 General Public License v.2.
+#
+# You should have received a copy of the GNU 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
+
+. lib/test
+
+test -e LOCAL_LVMETAD || skip
+aux prepare_pvs 2
+
+vgcreate $vg1 $dev1 $dev2
+lvchange -ay $vg1 2>&1 | not grep "Failed to connect"
+kill $(cat LOCAL_LVMETAD)
+lvchange -ay $vg1 2>&1 | grep "Failed to connect"
+lvchange -ay $vg1 --sysinit 2>&1 | not grep "Failed to connect"
+lvchange -ay $vg1 --config 'global { use_lvmetad = 0 }' 2>&1 | not grep "Failed to connect"
+aux lvmconf "global/use_lvmetad = 0"
+lvchange -ay $vg1 --config 'global { use_lvmetad = 1 }' 2>&1 | grep "Failed to connect"
+
11 years, 1 month
master - lvmetad: Init lazily, to avoid socket access on config overrides.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=983f0b46f2de85...
Commit: 983f0b46f2de85b8de0e2d7f8afbdf53f132a87a
Parent: 7c59199d4932d7edcd2919d6d45ec4baac590e2e
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Mon Oct 29 21:39:46 2012 +0100
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Tue Oct 30 09:15:47 2012 +0100
lvmetad: Init lazily, to avoid socket access on config overrides.
---
lib/cache/lvmetad.c | 28 ++++++++++++++++++++++------
1 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 6a374ac..72e07fd 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -33,7 +33,8 @@ static struct cmd_context *_lvmetad_cmd = NULL;
void lvmetad_disconnect(void)
{
- daemon_close(_lvmetad);
+ if (_lvmetad_connected)
+ daemon_close(_lvmetad);
_lvmetad_connected = 0;
_lvmetad_cmd = NULL;
}
@@ -41,19 +42,25 @@ void lvmetad_disconnect(void)
void lvmetad_init(struct cmd_context *cmd)
{
if (!_lvmetad_use && !access(LVMETAD_PIDFILE, F_OK))
- log_warn("WARNING: lvmetad is running but disabled. Restart lvmetad before enabling it!");
+ log_warn("WARNING: lvmetad is running but disabled."
+ " Restart lvmetad before enabling it!");
+ _lvmetad_cmd = cmd;
+}
+
+static void _lvmetad_connect()
+{
if (_lvmetad_use && _lvmetad_socket && !_lvmetad_connected) {
assert(_lvmetad_socket);
_lvmetad = lvmetad_open(_lvmetad_socket);
- if (_lvmetad.socket_fd >= 0 && !_lvmetad.error) {
+ if (_lvmetad.socket_fd >= 0 && !_lvmetad.error)
_lvmetad_connected = 1;
- _lvmetad_cmd = cmd;
- }
}
}
void lvmetad_warning(void)
{
+ if (!_lvmetad_connected)
+ _lvmetad_connect();
if (_lvmetad_use && (_lvmetad.socket_fd < 0 || _lvmetad.error))
log_warn("WARNING: Failed to connect to lvmetad: %s. Falling back to internal scanning.",
strerror(_lvmetad.error));
@@ -61,7 +68,11 @@ void lvmetad_warning(void)
int lvmetad_active(void)
{
- return _lvmetad_use && _lvmetad_connected;
+ if (!_lvmetad_use)
+ return 0;
+ if (!_lvmetad_connected)
+ _lvmetad_connect();
+ return _lvmetad_connected;
}
void lvmetad_set_active(int active)
@@ -873,6 +884,11 @@ int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler)
char *future_token;
int was_silent;
+ if (!lvmetad_active()) {
+ log_error("Cannot proceed since lvmetad is not active.");
+ return 0;
+ }
+
if (!(iter = dev_iter_create(cmd->lvmetad_filter, 1))) {
log_error("dev_iter creation failed");
return 0;
11 years, 1 month
master - lvmetad: warn only if use_lvmetad=1 and locking_type=3
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7c59199d4932d7...
Commit: 7c59199d4932d7edcd2919d6d45ec4baac590e2e
Parent: bbff143d54b890f3b9c91b302f0322469ba56ef6
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Oct 29 16:20:35 2012 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Oct 29 16:20:35 2012 +0100
lvmetad: warn only if use_lvmetad=1 and locking_type=3
---
lib/commands/toolcontext.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 8da96e4..aec4df3 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -413,13 +413,15 @@ static int _process_config(struct cmd_context *cmd)
lvmetad_set_socket(lvmetad_socket);
cn = find_config_tree_node(cmd, "devices/global_filter");
lvmetad_set_token(cn ? cn->v : NULL);
- if (find_config_tree_int(cmd, "global/locking_type", 1) != 3)
- lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
- else {
+
+ if (find_config_tree_int(cmd, "global/locking_type", 1) == 3 &&
+ find_config_tree_int(cmd, "global/use_lvmetad", 0)) {
log_warn("WARNING: configuration setting use_lvmetad overriden to 0 due to locking_type 3. "
"Clustered environment not supported by lvmetad yet.");
lvmetad_set_active(0);
- }
+ } else
+ lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
+
lvmetad_init(cmd);
return 1;
11 years, 1 month
master - python-lvm: Memory leaks & seg. fault fixes
by tasleson
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=bbff143d54b890...
Commit: bbff143d54b890f3b9c91b302f0322469ba56ef6
Parent: 291909ecafbf5594c145516c19c2ce87c874ffb1
Author: Tony Asleson <tasleson(a)redhat.com>
AuthorDate: Thu Oct 25 17:31:11 2012 -0500
Committer: Tony Asleson <tasleson(a)redhat.com>
CommitterDate: Thu Oct 25 18:09:10 2012 -0500
python-lvm: Memory leaks & seg. fault fixes
Issues found (thus far) in unit test developemnt for python bindings.
Added Py_DECREF(ptr) in liblvm_lvm_vg_open & liblvm_lvm_vg_create
in error paths so that we correctly clean up memory.
Added a call to lvm_vg_close when we remove a vg. The code was
clearing out the vg pointer which prevented us from actually
calling lvm_vg_close in the close path.
liblvm_lvm_vg_create_lv_linear was not initializing
lvobj->parent_vgobj and if lvm_vg_create_lv_linear failed
we went through liblvm_lv_dealloc on clean up and tried to
Py_DECREF an invalid pointer.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
python/liblvm.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/python/liblvm.c b/python/liblvm.c
index 4da2999..831493e 100644
--- a/python/liblvm.c
+++ b/python/liblvm.c
@@ -309,6 +309,7 @@ liblvm_lvm_vg_open(PyObject *self, PyObject *args)
if ((vgobj->vg = lvm_vg_open(libh, vgname, mode, 0))== NULL) {
PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(vgobj);
return NULL;
}
@@ -332,6 +333,7 @@ liblvm_lvm_vg_create(PyObject *self, PyObject *args)
if ((vgobj->vg = lvm_vg_create(libh, vgname))== NULL) {
PyErr_SetObject(LibLVMError, liblvm_get_last_error());
+ Py_DECREF(vgobj);
return NULL;
}
@@ -401,6 +403,10 @@ liblvm_lvm_vg_remove(vgobject *self)
if (lvm_vg_write(self->vg) == -1)
goto error;
+ /* Not much you can do with a vg that is removed so close it */
+ if (lvm_vg_close(self->vg) == -1)
+ goto error;
+
self->vg = NULL;
Py_INCREF(Py_None);
@@ -872,6 +878,9 @@ liblvm_lvm_vg_create_lv_linear(vgobject *self, PyObject *args)
if ((lvobj = PyObject_New(lvobject, &LibLVMlvType)) == NULL)
return NULL;
+ /* Initialize the parent ptr in case lv create fails and we dealloc lvobj */
+ lvobj->parent_vgobj = NULL;
+
if ((lvobj->lv = lvm_vg_create_lv_linear(self->vg, vgname, size)) == NULL) {
PyErr_SetObject(LibLVMError, liblvm_get_last_error());
Py_DECREF(lvobj);
@@ -887,7 +896,9 @@ liblvm_lvm_vg_create_lv_linear(vgobject *self, PyObject *args)
static void
liblvm_lv_dealloc(lvobject *self)
{
- Py_DECREF(self->parent_vgobj);
+ /* We can dealloc an object that didn't get fully created */
+ if (self->parent_vgobj)
+ Py_DECREF(self->parent_vgobj);
PyObject_Del(self);
}
11 years, 1 month
master - WHATS_NEW: latest changes under libdm 1.02.78
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=291909ecafbf55...
Commit: 291909ecafbf5594c145516c19c2ce87c874ffb1
Parent: 10492b238d25d85b9aab3eb851bedd1937146e39
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Oct 25 16:29:35 2012 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Oct 25 16:29:35 2012 +0200
WHATS_NEW: latest changes under libdm 1.02.78
---
WHATS_NEW_DM | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 7c636f0..3f8d9c9 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,6 +1,9 @@
-Version 1.02.77 - 15th October 2012
+Version 1.02.78 -
===================================
Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled.
+
+Version 1.02.77 - 15th October 2012
+===================================
Support unmount of thin volumes from pool above thin pool threshold.
Update man page to reflect that dm UUIDs are being mangled as well.
Apply 'dmsetup mangle' for dm UUIDs besides dm names.
11 years, 1 month
master - lvmetad: whats_new + more explanation for previous commit
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=10492b238d25d8...
Commit: 10492b238d25d85b9aab3eb851bedd1937146e39
Parent: 2fdd0840d5adb1ff492cd09da79f7a2c5290fd2a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Oct 25 14:47:45 2012 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Oct 25 14:47:45 2012 +0200
lvmetad: whats_new + more explanation for previous commit
---
WHATS_NEW | 1 +
lib/commands/toolcontext.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index b883bde..4b71402 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Hardcode use_lvmetad=0 if cluster locking used and issue a warning msg.
Avoid reading mirrors with failed devices in its mirrored log.
Avoid reading from mirrors that have failed devices if they block I/O.
Change lvs heading Copy% to Cpy%Sync and print RAID4/5/6 sync% there too.
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 1dd23bf..8da96e4 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -416,7 +416,8 @@ static int _process_config(struct cmd_context *cmd)
if (find_config_tree_int(cmd, "global/locking_type", 1) != 3)
lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
else {
- log_warn("WARNING: use_lvmetad overriden to 0 due to locking_type 3");
+ log_warn("WARNING: configuration setting use_lvmetad overriden to 0 due to locking_type 3. "
+ "Clustered environment not supported by lvmetad yet.");
lvmetad_set_active(0);
}
lvmetad_init(cmd);
11 years, 1 month
master - lvmetad: Disable and warn when locking_type is 3.
by Petr Rockai
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2fdd0840d5adb1...
Commit: 2fdd0840d5adb1ff492cd09da79f7a2c5290fd2a
Parent: b248ba0a396d7fc9a459eea02cfdc70b33ce3441
Author: Petr Rockai <prockai(a)redhat.com>
AuthorDate: Thu Oct 25 14:30:03 2012 +0200
Committer: Petr Rockai <prockai(a)redhat.com>
CommitterDate: Thu Oct 25 14:31:08 2012 +0200
lvmetad: Disable and warn when locking_type is 3.
---
lib/commands/toolcontext.c | 7 ++++++-
test/shell/lvmetad-no-cluster.sh | 19 +++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index d72b0c0..1dd23bf 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -413,7 +413,12 @@ static int _process_config(struct cmd_context *cmd)
lvmetad_set_socket(lvmetad_socket);
cn = find_config_tree_node(cmd, "devices/global_filter");
lvmetad_set_token(cn ? cn->v : NULL);
- lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
+ if (find_config_tree_int(cmd, "global/locking_type", 1) != 3)
+ lvmetad_set_active(find_config_tree_int(cmd, "global/use_lvmetad", 0));
+ else {
+ log_warn("WARNING: use_lvmetad overriden to 0 due to locking_type 3");
+ lvmetad_set_active(0);
+ }
lvmetad_init(cmd);
return 1;
diff --git a/test/shell/lvmetad-no-cluster.sh b/test/shell/lvmetad-no-cluster.sh
new file mode 100644
index 0000000..db68e77
--- /dev/null
+++ b/test/shell/lvmetad-no-cluster.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+#
+# 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 General Public License v.2.
+#
+# You should have received a copy of the GNU 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
+
+. lib/test
+
+test -e LOCAL_CLVMD || skip
+aux prepare_vg 2
+aux prepare_lvmetad
+vgs -vv 2> errs
+cat errs
+grep 'use_lvmetad' errs
11 years, 1 month
master - mirror: Avoid reading mirrors with failed devices in mirrored log
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b248ba0a396d7f...
Commit: b248ba0a396d7fc9a459eea02cfdc70b33ce3441
Parent: 9fd7ac7d035f0b2f8dcc3cb19935eb181816bd76
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Thu Oct 25 00:42:45 2012 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Thu Oct 25 00:42:45 2012 -0500
mirror: Avoid reading mirrors with failed devices in mirrored log
Commit 9fd7ac7d035f0b2f8dcc3cb19935eb181816bd76 did not handle mirrors
that contained mirrored logs. This is because the status line of the
mirror does not give an indication of the health of the mirrored log,
as you can see here:
[root@bp-01 lvm2]# dmsetup status vg-lv vg-lv_mlog
vg-lv: 0 409600 mirror 2 253:6 253:7 400/400 1 AA 3 disk 253:5 A
vg-lv_mlog: 0 8192 mirror 2 253:3 253:4 7/8 1 AD 1 core
Thus, the possibility for LVM commands to hang still persists when mirror
have mirrored logs. I discovered this while performing some testing that
does polling with 'pvs' while doing I/O and killing devices. The 'pvs'
managed to get between the mirrored log device failure and the attempt
by dmeventd to repair it. The result was a very nasty block in LVM
commands that is very difficult to remove - even for someone who knows
what is going on. Thus, it is absolutely essential that the log of a
mirror be recursively checked for mirror devices which may be failed
as well.
Despite what the code comment says in the aforementioned commit...
+ * _mirrored_transient_status(). FIXME: It is unable to handle mirrors
+ * with mirrored logs because it does not have a way to get the status of
+ * the mirror that forms the log, which could be blocked.
... it is possible to get the status of the log because the log device
major/minor is given to us by the status output of the top-level mirror.
We can use that to query the log device for any DM status and see if it
is a mirror that needs to be bypassed. This patch does just that and is
now able to avoid reading from mirrors that have failed devices in a
mirrored log.
---
WHATS_NEW | 1 +
lib/activate/dev_manager.c | 54 +++++++++++++++++++++++++++++++-------------
2 files changed, 39 insertions(+), 16 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index db776c0..b883bde 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Avoid reading mirrors with failed devices in its mirrored log.
Avoid reading from mirrors that have failed devices if they block I/O.
Change lvs heading Copy% to Cpy%Sync and print RAID4/5/6 sync% there too.
Fix clvmd support for option -d and properly use its argument.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 6cc57d0..40f719e 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -139,6 +139,7 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
* _parse_mirror_status
* @mirror_status_string
* @image_health: return for allocated copy of image health characters
+ * @log_device: return for 'dev_t' of log device
* @log_health: NULL if corelog, otherwise alloc'ed log health char
*
* This function takes the mirror status string, breaks it up and returns
@@ -149,8 +150,10 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
* Returns: 1 on success, 0 on failure
*/
static int _parse_mirror_status(char *mirror_status_str,
- char **images_health, char **log_health)
+ char **images_health,
+ dev_t *log_dev, char **log_health)
{
+ int major, minor;
char *p = NULL;
char **args, **log_args;
unsigned num_devs, log_argc;
@@ -174,10 +177,14 @@ static int _parse_mirror_status(char *mirror_status_str,
return_0;
*log_health = NULL;
- if (!strcmp(log_args[0], "disk") &&
- !(*log_health = dm_strdup(log_args[2])))
- return_0;
-
+ *log_dev = 0;
+ if (!strcmp(log_args[0], "disk")) {
+ if (!(*log_health = dm_strdup(log_args[2])))
+ return_0;
+ if (sscanf(log_args[1], "%d:%d", &major, &minor) != 2)
+ return_0;
+ *log_dev = MKDEV((dev_t)major, minor);
+ }
if (!(*images_health = dm_strdup(args[2 + num_devs])))
return_0;
@@ -199,9 +206,7 @@ static int _parse_mirror_status(char *mirror_status_str,
* attempting to read a mirror, a circular dependency would be created.)
*
* This function is a slimmed-down version of lib/mirror/mirrored.c:
- * _mirrored_transient_status(). FIXME: It is unable to handle mirrors
- * with mirrored logs because it does not have a way to get the status of
- * the mirror that forms the log, which could be blocked.
+ * _mirrored_transient_status().
*
* If a failed device is detected in the status string, then it must be
* determined if 'block_on_error' or 'handle_errors' was used when
@@ -217,23 +222,17 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
char *mirror_status_str)
{
unsigned i, check_for_blocking = 0;
+ dev_t log_dev;
char *images_health, *log_health;
-
uint64_t s,l;
char *params, *target_type = NULL;
void *next = NULL;
struct dm_task *dmt;
if (!_parse_mirror_status(mirror_status_str,
- &images_health, &log_health))
+ &images_health, &log_dev, &log_health))
goto_out;
- if (log_health && (log_health[0] != 'A')) {
- log_debug("%s: Mirror log device marked as failed",
- dev_name(dev));
- check_for_blocking = 1;
- }
-
for (i = 0; images_health[i]; i++)
if (images_health[i] != 'A') {
log_debug("%s: Mirror image %d marked as failed",
@@ -241,6 +240,29 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
check_for_blocking = 1;
}
+ if (!check_for_blocking && log_dev) {
+ if (log_health[0] != 'A') {
+ log_debug("%s: Mirror log device marked as failed",
+ dev_name(dev));
+ check_for_blocking = 1;
+ } else {
+ struct device *tmp_dev;
+ char buf[16];
+
+ if (dm_snprintf(buf, sizeof(buf), "%d:%d",
+ (int)MAJOR(log_dev),
+ (int)MINOR(log_dev)) < 0)
+ goto_out;
+
+ if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 1)))
+ goto_out;
+
+ tmp_dev->dev = log_dev;
+ if (!device_is_usable(tmp_dev))
+ goto_out;
+ }
+ }
+
if (!check_for_blocking)
return 0;
11 years, 1 month
master - mirror: Avoid reading from mirrors that have failed devices
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9fd7ac7d035f0b...
Commit: 9fd7ac7d035f0b2f8dcc3cb19935eb181816bd76
Parent: b873fc54baf12891158017cd732e01a7f19b3ac3
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Tue Oct 23 23:10:33 2012 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Tue Oct 23 23:10:33 2012 -0500
mirror: Avoid reading from mirrors that have failed devices
Addresses: rhbz855398 (Allow VGs to be built on cluster mirrors),
and other issues.
The LVM code attempts to avoid reading labels from devices that are
suspended to try to avoid situations that may cause the commands to
block indefinitely. When scanning devices, 'ignore_suspended_devices'
can be set so the code (lib/activate/dev_manager.c:device_is_usable())
checks any DM devices it finds and avoids them if they are suspended.
The mirror target has an additional mechanism that can cause I/O to
be blocked. If a device in a mirror fails, all I/O will be blocked
by the kernel until a new table (a linear target or a mirror with
replacement devices) is loaded. The mirror indicates that this condition
has happened by marking a 'D' for the faulty device in its status
output. This condition must also be checked by 'device_is_usable()' to
avoid the possibility of blocking LVM commands indefinitely due to an
attempt to read the blocked mirror for labels.
Until now, mirrors were avoided if the 'ignore_suspended_devices'
condition was set. This check seemed to suggest, "if we are concerned
about suspended devices, then let's ignore mirrors altogether just
in case". This is insufficient and doesn't solve any problems. All
devices that are suspended are already avoided if
'ignore_suspended_devices' is set; and if a mirror is blocking because
of an error condition, it will block the LVM command regardless of the
setting of that variable.
Rather than avoiding mirrors whenever 'ignore_suspended_devices' is
set, this patch causes mirrors to be avoided whenever they are blocking
due to an error. (As mentioned above, the case where a DM device is
suspended is already covered.) This solves a number of issues that weren't
handled before. For example, pvcreate (or any command that does a
pv_read or vg_read, which eventually call device_is_usable()) will be
protected from blocked mirrors regardless of how
'ignore_suspended_devices' is set. Additionally, a mirror that is
neither suspended nor blocking is /allowed/ to be read regardless
of how 'ignore_suspended_devices' is set. (The latter point being the
source of the fix for rhbz855398.)
---
WHATS_NEW | 1 +
lib/activate/dev_manager.c | 160 ++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 155 insertions(+), 6 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index ffbf4ef..db776c0 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Avoid reading from mirrors that have failed devices if they block I/O.
Change lvs heading Copy% to Cpy%Sync and print RAID4/5/6 sync% there too.
Fix clvmd support for option -d and properly use its argument.
Support use of option --yes for lvchange --persistent.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 31c1c27..6cc57d0 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -135,6 +135,154 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
return r;
}
+/*
+ * _parse_mirror_status
+ * @mirror_status_string
+ * @image_health: return for allocated copy of image health characters
+ * @log_health: NULL if corelog, otherwise alloc'ed log health char
+ *
+ * This function takes the mirror status string, breaks it up and returns
+ * its components. For now, we only return the health characters. This
+ * is an internal function. If there are more things we want to return
+ * later, we can do that then.
+ *
+ * Returns: 1 on success, 0 on failure
+ */
+static int _parse_mirror_status(char *mirror_status_str,
+ char **images_health, char **log_health)
+{
+ char *p = NULL;
+ char **args, **log_args;
+ unsigned num_devs, log_argc;
+
+ if (!dm_split_words(mirror_status_str, 1, 0, &p) ||
+ !(num_devs = (unsigned) atoi(p)))
+ /* On errors, we must assume the mirror is to be avoided */
+ return_0;
+
+ p += strlen(p) + 1;
+ args = alloca((num_devs + 5) * sizeof(char *));
+
+ if ((unsigned)dm_split_words(p, num_devs + 4, 0, args) < num_devs + 4)
+ return_0;
+
+ log_argc = (unsigned) atoi(args[3 + num_devs]);
+ log_args = alloca(log_argc * sizeof(char *));
+
+ if ((unsigned)dm_split_words(args[3 + num_devs] + strlen(args[3 + num_devs]) + 1,
+ log_argc, 0, log_args) < log_argc)
+ return_0;
+
+ *log_health = NULL;
+ if (!strcmp(log_args[0], "disk") &&
+ !(*log_health = dm_strdup(log_args[2])))
+ return_0;
+
+ if (!(*images_health = dm_strdup(args[2 + num_devs])))
+ return_0;
+
+ return 1;
+}
+
+/*
+ * ignore_blocked_mirror_devices
+ * @dev
+ * @start
+ * @length
+ * @mirror_status_str
+ *
+ * When a DM 'mirror' target is created with 'block_on_error' or
+ * 'handle_errors', it will block I/O if there is a device failure
+ * until the mirror is reconfigured. Thus, LVM should never attempt
+ * to read labels from a mirror that has a failed device. (LVM
+ * commands are issued to repair mirrors; and if LVM is blocked
+ * attempting to read a mirror, a circular dependency would be created.)
+ *
+ * This function is a slimmed-down version of lib/mirror/mirrored.c:
+ * _mirrored_transient_status(). FIXME: It is unable to handle mirrors
+ * with mirrored logs because it does not have a way to get the status of
+ * the mirror that forms the log, which could be blocked.
+ *
+ * If a failed device is detected in the status string, then it must be
+ * determined if 'block_on_error' or 'handle_errors' was used when
+ * creating the mirror. This info can only be determined from the mirror
+ * table. The 'dev', 'start', 'length' trio allow us to correlate the
+ * 'mirror_status_str' with the correct device table in order to check
+ * for blocking.
+ *
+ * Returns: 1 if mirror should be ignored, 0 if safe to use
+ */
+static int _ignore_blocked_mirror_devices(struct device *dev,
+ uint64_t start, uint64_t length,
+ char *mirror_status_str)
+{
+ unsigned i, check_for_blocking = 0;
+ char *images_health, *log_health;
+
+ uint64_t s,l;
+ char *params, *target_type = NULL;
+ void *next = NULL;
+ struct dm_task *dmt;
+
+ if (!_parse_mirror_status(mirror_status_str,
+ &images_health, &log_health))
+ goto_out;
+
+ if (log_health && (log_health[0] != 'A')) {
+ log_debug("%s: Mirror log device marked as failed",
+ dev_name(dev));
+ check_for_blocking = 1;
+ }
+
+ for (i = 0; images_health[i]; i++)
+ if (images_health[i] != 'A') {
+ log_debug("%s: Mirror image %d marked as failed",
+ dev_name(dev), i);
+ check_for_blocking = 1;
+ }
+
+ if (!check_for_blocking)
+ return 0;
+
+ /*
+ * We avoid another system call if we can, but if a device is
+ * dead, we have no choice but to look up the table too.
+ */
+ if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+ goto_out;
+
+ if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
+ goto_out;
+
+ if (activation_checks() && !dm_task_enable_checks(dmt))
+ goto_out;
+
+ if (!dm_task_run(dmt))
+ goto_out;
+
+ do {
+ next = dm_get_next_target(dmt, next, &s, &l,
+ &target_type, ¶ms);
+ if ((s == start) && (l == length)) {
+ if (strcmp(target_type, "mirror"))
+ goto_out;
+
+ if (strstr(params, "block_on_error") ||
+ strstr(params, "handle_errors")) {
+ log_debug("%s: I/O blocked to mirror device",
+ dev_name(dev));
+ return 1;
+ }
+ }
+ } while (next);
+ dm_task_destroy(dmt);
+
+ return 0;
+
+out:
+ return 1;
+}
+
int device_is_usable(struct device *dev)
{
struct dm_task *dmt;
@@ -180,15 +328,15 @@ int device_is_usable(struct device *dev)
goto out;
}
- /* FIXME Also check for mirror block_on_error and mpath no paths */
- /* For now, we exclude all mirrors */
-
+ /* FIXME Also check for mpath no paths */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, ¶ms);
- /* Skip if target type doesn't match */
- if (target_type && !strcmp(target_type, "mirror") && ignore_suspended_devices()) {
- log_debug("%s: Mirror device %s not usable.", dev_name(dev), name);
+
+ if (target_type && !strcmp(target_type, "mirror") &&
+ _ignore_blocked_mirror_devices(dev, start, length, params)) {
+ log_debug("%s: Mirror device %s not usable.",
+ dev_name(dev), name);
goto out;
}
11 years, 1 month