Accepting request 229047 from Base:System
Automatic submission by obs-autosubmit OBS-URL: https://build.opensuse.org/request/show/229047 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/lvm2?expand=0&rev=65
This commit is contained in:
commit
4a044281f4
49
0001-clvmd-avoid-logging-in-signal-handler.patch
Normal file
49
0001-clvmd-avoid-logging-in-signal-handler.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 5070ffbca7b16e4139b3da72bdff0c9add517351 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Wed, 17 Apr 2013 23:16:30 +0200
|
||||
Subject: [PATCH] clvmd: avoid logging in signal handler
|
||||
|
||||
debuglog in the main thread.
|
||||
---
|
||||
daemons/clvmd/clvmd.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c
|
||||
index c649bbe..a64bd54 100644
|
||||
--- a/daemons/clvmd/clvmd.c
|
||||
+++ b/daemons/clvmd/clvmd.c
|
||||
@@ -874,6 +874,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
int saved_errno = errno;
|
||||
|
||||
reread_config = 0;
|
||||
+ DEBUGLOG("got SIGHUP\n");
|
||||
if (clops->reread_config)
|
||||
clops->reread_config();
|
||||
errno = saved_errno;
|
||||
@@ -982,6 +983,8 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
|
||||
closedown:
|
||||
clops->cluster_closedown();
|
||||
+ if (quit)
|
||||
+ DEBUGLOG("SIGTERM received\n");
|
||||
}
|
||||
|
||||
static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
|
||||
@@ -2253,14 +2256,12 @@ static void sigusr2_handler(int sig)
|
||||
|
||||
static void sigterm_handler(int sig)
|
||||
{
|
||||
- DEBUGLOG("SIGTERM received\n");
|
||||
quit = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static void sighup_handler(int sig)
|
||||
{
|
||||
- DEBUGLOG("got SIGHUP\n");
|
||||
reread_config = 1;
|
||||
}
|
||||
|
||||
--
|
||||
1.8.4.5
|
||||
|
24
add_scm_support.patch
Normal file
24
add_scm_support.patch
Normal file
@ -0,0 +1,24 @@
|
||||
filters: add scm devices
|
||||
|
||||
Fix this:
|
||||
pvcreate /dev/scma
|
||||
Device /dev/scma not found (or ignored by filtering).
|
||||
|
||||
Upstream via:
|
||||
9602e68 filters: add scm devices
|
||||
|
||||
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
|
||||
---
|
||||
lib/filters/device-types.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/lib/filters/device-types.h
|
||||
+++ b/lib/filters/device-types.h
|
||||
@@ -56,5 +56,6 @@ static const device_info_t _device_info[
|
||||
{"blkext", 1}, /* Extended device partitions */
|
||||
{"fio", 16}, /* Fusion */
|
||||
{"mtip32xx", 16}, /* Micron PCIe SSDs */
|
||||
+ {"scm", 8}, /* Storage Class Memory (IBM S/390) */
|
||||
{"", 0}
|
||||
};
|
||||
|
@ -1,40 +0,0 @@
|
||||
From: Andrey Borzenkov <arvidjaar@gmail.com>
|
||||
Subject: [PATCH] activate lvmetad in generator if use_lvmetad=1
|
||||
|
||||
This avoids unbootable system if user changes use_lvmetad but forgets
|
||||
to enable lvmetad.
|
||||
|
||||
Ref: https://bugzilla.novell.com/show_bug.cgi?id=862076
|
||||
|
||||
Signed-off-by: Andrey Borzenkov <arvidjaar@gmail.com>
|
||||
|
||||
---
|
||||
scripts/lvm2_activation_generator_systemd_red_hat.c | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
Index: LVM2.2.02.98/scripts/lvm2_activation_generator_systemd_red_hat.c
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/scripts/lvm2_activation_generator_systemd_red_hat.c
|
||||
+++ LVM2.2.02.98/scripts/lvm2_activation_generator_systemd_red_hat.c
|
||||
@@ -153,15 +153,15 @@ int main(int argc, char *argv[])
|
||||
r = EXIT_FAILURE; goto out;
|
||||
}
|
||||
|
||||
+ dir = argc > 1 ? argv[1] : DEFAULT_UNIT_DIR;
|
||||
+
|
||||
/* If lvmetad used, rely on autoactivation instead of direct activation. */
|
||||
if (lvm_uses_lvmetad()) {
|
||||
kmsg("LVM: Logical Volume autoactivation enabled.\n");
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- dir = argc > 1 ? argv[1] : DEFAULT_UNIT_DIR;
|
||||
-
|
||||
- if (!generate_unit(dir, 1) || !generate_unit(dir, 0))
|
||||
+ if (dm_snprintf(unit_path, PATH_MAX, "%s/%s", "/usr/lib/systemd/system", "lvm2-lvmetad.socket") < 0 ||
|
||||
+ !register_unit_with_target (dir, "lvm2-lvmetad.socket", "sockets.target"))
|
||||
+ r = EXIT_FAILURE;
|
||||
+ } else if (!generate_unit(dir, 1) || !generate_unit(dir, 0))
|
||||
r = EXIT_FAILURE;
|
||||
out:
|
||||
kmsg("LVM: Activation generator %s.\n", r ? "failed" : "successfully completed");
|
144
avoid_reading_failed_dev_in_mirrored_log.diff
Normal file
144
avoid_reading_failed_dev_in_mirrored_log.diff
Normal file
@ -0,0 +1,144 @@
|
||||
commit b248ba0a396d7fc9a459eea02cfdc70b33ce3441
|
||||
Author: Jonathan Brassow <jbrassow@redhat.com>
|
||||
Date: 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.
|
||||
|
||||
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;
|
||||
|
28
clmvd-fix-decriptor-leak-on-restart.patch
Normal file
28
clmvd-fix-decriptor-leak-on-restart.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 7b1315411f1de73801fd38f264ca507ae3807e53 Mon Sep 17 00:00:00 2001
|
||||
From: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Tue, 6 Aug 2013 16:07:50 +0200
|
||||
Subject: [PATCH] clmvd: fix decriptor leak on restart
|
||||
|
||||
Do not leave descriptor used for dup2() openned.
|
||||
---
|
||||
daemons/clvmd/clvmd.c | 4 ++++
|
||||
2 files changed, 5 insertions(+)
|
||||
|
||||
diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c
|
||||
index f05776f..eaa75ca 100644
|
||||
--- a/daemons/clvmd/clvmd.c
|
||||
+++ b/daemons/clvmd/clvmd.c
|
||||
@@ -1085,6 +1085,10 @@ static void be_daemon(int timeout)
|
||||
log_error("Error setting terminal FDs to /dev/null: %m");
|
||||
exit(5);
|
||||
}
|
||||
+ if ((devnull > STDERR_FILENO) && close(devnull)) {
|
||||
+ log_sys_error("close", "/dev/null");
|
||||
+ exit(7);
|
||||
+ }
|
||||
if (chdir("/")) {
|
||||
log_error("Error setting current directory to /: %m");
|
||||
exit(6);
|
||||
--
|
||||
1.8.4.5
|
||||
|
252
clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch
Normal file
252
clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch
Normal file
@ -0,0 +1,252 @@
|
||||
From 25bed9968155f43ef0b8832383ef711e7ae1685d Mon Sep 17 00:00:00 2001
|
||||
From: Petr Rockai <prockai@redhat.com>
|
||||
Date: Mon, 9 Sep 2013 00:01:44 +0200
|
||||
Subject: [PATCH] clvmd: Avoid a 3-way deadlock in dead-client cleanup.
|
||||
|
||||
---
|
||||
daemons/clvmd/clvmd.c | 177 +++++++++++++++++++++++++++-----------------------
|
||||
daemons/clvmd/clvmd.h | 1 +
|
||||
2 files changed, 96 insertions(+), 82 deletions(-)
|
||||
|
||||
Index: LVM2.2.02.98/daemons/clvmd/clvmd.c
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/daemons/clvmd/clvmd.c 2014-03-18 16:14:07.237654914 +0800
|
||||
+++ LVM2.2.02.98/daemons/clvmd/clvmd.c 2014-03-18 16:14:07.272654866 +0800
|
||||
@@ -120,6 +120,7 @@ static void *pre_and_post_thread(void *a
|
||||
static int send_message(void *buf, int msglen, const char *csid, int fd,
|
||||
const char *errtext);
|
||||
static int read_from_local_sock(struct local_client *thisfd);
|
||||
+static int cleanup_zombie(struct local_client *thisfd);
|
||||
static int process_local_command(struct clvm_header *msg, int msglen,
|
||||
struct local_client *client,
|
||||
unsigned short xid);
|
||||
@@ -694,6 +695,7 @@ static int local_rendezvous_callback(str
|
||||
newfd->bits.localsock.sent_out = FALSE;
|
||||
newfd->bits.localsock.threadid = 0;
|
||||
newfd->bits.localsock.finished = 0;
|
||||
+ newfd->bits.localsock.cleanup_needed = 0;
|
||||
newfd->bits.localsock.pipe_client = NULL;
|
||||
newfd->bits.localsock.private = NULL;
|
||||
newfd->bits.localsock.all_success = 1;
|
||||
@@ -884,7 +886,7 @@ static void main_loop(int local_sock, in
|
||||
for (thisfd = &local_client_head; thisfd != NULL;
|
||||
thisfd = thisfd->next) {
|
||||
|
||||
- if (thisfd->removeme) {
|
||||
+ if (thisfd->removeme && !cleanup_zombie(thisfd)) {
|
||||
struct local_client *free_fd;
|
||||
lastfd->next = thisfd->next;
|
||||
free_fd = thisfd;
|
||||
@@ -911,7 +913,6 @@ static void main_loop(int local_sock, in
|
||||
|
||||
/* Got error or EOF: Remove it from the list safely */
|
||||
if (ret <= 0) {
|
||||
- struct local_client *free_fd;
|
||||
int type = thisfd->type;
|
||||
|
||||
/* If the cluster socket shuts down, so do we */
|
||||
@@ -921,12 +922,7 @@ static void main_loop(int local_sock, in
|
||||
|
||||
DEBUGLOG("ret == %d, errno = %d. removing client\n",
|
||||
ret, errno);
|
||||
- lastfd->next = thisfd->next;
|
||||
- free_fd = thisfd;
|
||||
- safe_close(&(free_fd->fd));
|
||||
-
|
||||
- /* Queue cleanup, this also frees the client struct */
|
||||
- add_to_lvmqueue(free_fd, NULL, 0, NULL);
|
||||
+ thisfd->removeme = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1089,6 +1085,95 @@ static void be_daemon(int timeout)
|
||||
|
||||
}
|
||||
|
||||
+static int cleanup_zombie(struct local_client *thisfd)
|
||||
+{
|
||||
+ int *status;
|
||||
+
|
||||
+ if (thisfd->type != LOCAL_SOCK)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!thisfd->bits.localsock.cleanup_needed)
|
||||
+ return 0;
|
||||
+
|
||||
+ DEBUGLOG("EOF on local socket: inprogress=%d\n",
|
||||
+ thisfd->bits.localsock.in_progress);
|
||||
+
|
||||
+ thisfd->bits.localsock.finished = 1;
|
||||
+
|
||||
+ /* If the client went away in mid command then tidy up */
|
||||
+ if (thisfd->bits.localsock.in_progress) {
|
||||
+ pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
|
||||
+ if (pthread_mutex_trylock(&thisfd->bits.localsock.mutex))
|
||||
+ goto bail;
|
||||
+ thisfd->bits.localsock.state = POST_COMMAND;
|
||||
+ pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
+ pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
|
||||
+
|
||||
+ /* Free any unsent buffers */
|
||||
+ free_reply(thisfd);
|
||||
+ }
|
||||
+
|
||||
+ /* Kill the subthread & free resources */
|
||||
+ if (thisfd->bits.localsock.threadid) {
|
||||
+ DEBUGLOG("Waiting for child thread\n");
|
||||
+ pthread_mutex_lock(&thisfd->bits.localsock.mutex);
|
||||
+ thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
+ pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
+ pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
|
||||
+
|
||||
+ if ((errno = pthread_join(thisfd->bits.localsock.threadid,
|
||||
+ (void **) &status)))
|
||||
+ log_sys_error("pthread_join", "");
|
||||
+
|
||||
+ DEBUGLOG("Joined child thread\n");
|
||||
+
|
||||
+ thisfd->bits.localsock.threadid = 0;
|
||||
+ pthread_cond_destroy(&thisfd->bits.localsock.cond);
|
||||
+ pthread_mutex_destroy(&thisfd->bits.localsock.mutex);
|
||||
+
|
||||
+ /* Remove the pipe client */
|
||||
+ if (thisfd->bits.localsock.pipe_client != NULL) {
|
||||
+ struct local_client *newfd;
|
||||
+ struct local_client *lastfd = NULL;
|
||||
+ struct local_client *free_fd = NULL;
|
||||
+
|
||||
+ (void) close(thisfd->bits.localsock.pipe_client->fd); /* Close pipe */
|
||||
+ (void) close(thisfd->bits.localsock.pipe);
|
||||
+
|
||||
+ /* Remove pipe client */
|
||||
+ for (newfd = &local_client_head; newfd != NULL;
|
||||
+ newfd = newfd->next) {
|
||||
+ if (thisfd->bits.localsock.
|
||||
+ pipe_client == newfd) {
|
||||
+ thisfd->bits.localsock.
|
||||
+ pipe_client = NULL;
|
||||
+
|
||||
+ lastfd->next = newfd->next;
|
||||
+ free_fd = newfd;
|
||||
+ newfd->next = lastfd;
|
||||
+ free(free_fd);
|
||||
+ break;
|
||||
+ }
|
||||
+ lastfd = newfd;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Free the command buffer */
|
||||
+ free(thisfd->bits.localsock.cmd);
|
||||
+
|
||||
+ /* Clear out the cross-link */
|
||||
+ if (thisfd->bits.localsock.pipe_client != NULL)
|
||||
+ thisfd->bits.localsock.pipe_client->bits.pipe.client =
|
||||
+ NULL;
|
||||
+
|
||||
+ safe_close(&(thisfd->fd));
|
||||
+ thisfd->bits.localsock.cleanup_needed = 0;
|
||||
+ return 0;
|
||||
+bail:
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/* Called when we have a read from the local socket.
|
||||
was in the main loop but it's grown up and is a big girl now */
|
||||
static int read_from_local_sock(struct local_client *thisfd)
|
||||
@@ -1106,80 +1191,8 @@ static int read_from_local_sock(struct l
|
||||
|
||||
/* EOF or error on socket */
|
||||
if (len <= 0) {
|
||||
- int *status;
|
||||
-
|
||||
- DEBUGLOG("EOF on local socket: inprogress=%d\n",
|
||||
- thisfd->bits.localsock.in_progress);
|
||||
-
|
||||
- thisfd->bits.localsock.finished = 1;
|
||||
-
|
||||
- /* If the client went away in mid command then tidy up */
|
||||
- if (thisfd->bits.localsock.in_progress) {
|
||||
- pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
|
||||
- pthread_mutex_lock(&thisfd->bits.localsock.mutex);
|
||||
- thisfd->bits.localsock.state = POST_COMMAND;
|
||||
- pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
- pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
|
||||
-
|
||||
- /* Free any unsent buffers */
|
||||
- free_reply(thisfd);
|
||||
- }
|
||||
-
|
||||
- /* Kill the subthread & free resources */
|
||||
- if (thisfd->bits.localsock.threadid) {
|
||||
- DEBUGLOG("Waiting for child thread\n");
|
||||
- pthread_mutex_lock(&thisfd->bits.localsock.mutex);
|
||||
- thisfd->bits.localsock.state = PRE_COMMAND;
|
||||
- pthread_cond_signal(&thisfd->bits.localsock.cond);
|
||||
- pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
|
||||
-
|
||||
- if ((errno = pthread_join(thisfd->bits.localsock.threadid,
|
||||
- (void **) &status)))
|
||||
- log_sys_error("pthread_join", "");
|
||||
-
|
||||
- DEBUGLOG("Joined child thread\n");
|
||||
-
|
||||
- thisfd->bits.localsock.threadid = 0;
|
||||
- pthread_cond_destroy(&thisfd->bits.localsock.cond);
|
||||
- pthread_mutex_destroy(&thisfd->bits.localsock.mutex);
|
||||
-
|
||||
- /* Remove the pipe client */
|
||||
- if (thisfd->bits.localsock.pipe_client != NULL) {
|
||||
- struct local_client *newfd;
|
||||
- struct local_client *lastfd = NULL;
|
||||
- struct local_client *free_fd = NULL;
|
||||
-
|
||||
- (void) close(thisfd->bits.localsock.pipe_client->fd); /* Close pipe */
|
||||
- (void) close(thisfd->bits.localsock.pipe);
|
||||
-
|
||||
- /* Remove pipe client */
|
||||
- for (newfd = &local_client_head; newfd != NULL;
|
||||
- newfd = newfd->next) {
|
||||
- if (thisfd->bits.localsock.
|
||||
- pipe_client == newfd) {
|
||||
- thisfd->bits.localsock.
|
||||
- pipe_client = NULL;
|
||||
-
|
||||
- lastfd->next = newfd->next;
|
||||
- free_fd = newfd;
|
||||
- newfd->next = lastfd;
|
||||
- free(free_fd);
|
||||
- break;
|
||||
- }
|
||||
- lastfd = newfd;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Free the command buffer */
|
||||
- free(thisfd->bits.localsock.cmd);
|
||||
-
|
||||
- /* Clear out the cross-link */
|
||||
- if (thisfd->bits.localsock.pipe_client != NULL)
|
||||
- thisfd->bits.localsock.pipe_client->bits.pipe.client =
|
||||
- NULL;
|
||||
-
|
||||
- safe_close(&(thisfd->fd));
|
||||
+ thisfd->bits.localsock.cleanup_needed = 1;
|
||||
+ cleanup_zombie(thisfd); /* we ignore errors here */
|
||||
return 0;
|
||||
} else {
|
||||
int comms_pipe[2];
|
||||
Index: LVM2.2.02.98/daemons/clvmd/clvmd.h
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/daemons/clvmd/clvmd.h 2012-10-15 22:24:58.000000000 +0800
|
||||
+++ LVM2.2.02.98/daemons/clvmd/clvmd.h 2014-03-18 16:14:07.272654866 +0800
|
||||
@@ -53,6 +53,7 @@ struct localsock_bits {
|
||||
int finished; /* Flag to tell subthread to exit */
|
||||
int all_success; /* Set to 0 if any node (or the pre_command)
|
||||
failed */
|
||||
+ int cleanup_needed; /* helper for cleanup_zombie */
|
||||
struct local_client *pipe_client;
|
||||
pthread_t threadid;
|
||||
enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
|
87
clvmd-Fix-node-up-down-handing-in-corosync-module.patch
Normal file
87
clvmd-Fix-node-up-down-handing-in-corosync-module.patch
Normal file
@ -0,0 +1,87 @@
|
||||
From 431eda63cc0ebff7c62dacb313cabcffbda6573a Mon Sep 17 00:00:00 2001
|
||||
From: Christine Caulfield <ccaulfie@redhat.com>
|
||||
Date: Mon, 23 Sep 2013 13:23:00 +0100
|
||||
Subject: [PATCH] clvmd: Fix node up/down handing in corosync module
|
||||
|
||||
The corosync cluster interface for clvmd did not correctly
|
||||
deal with node up/down events so that when a node was removed
|
||||
from the cluster clvmd would prevent remote operations
|
||||
from happening, as it thought the node was up but not
|
||||
running clvmd.
|
||||
|
||||
This patch fixes that code by simplifying the case to node
|
||||
being up or down - which was the original intention
|
||||
and is supported by pacemaker and CPG in the higher layers.
|
||||
|
||||
Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
|
||||
---
|
||||
daemons/clvmd/clvmd-corosync.c | 31 ++++---------------------------
|
||||
2 files changed, 5 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/daemons/clvmd/clvmd-corosync.c b/daemons/clvmd/clvmd-corosync.c
|
||||
index d85ec1e..9092c8a 100644
|
||||
--- a/daemons/clvmd/clvmd-corosync.c
|
||||
+++ b/daemons/clvmd/clvmd-corosync.c
|
||||
@@ -89,7 +89,7 @@ quorum_callbacks_t quorum_callbacks = {
|
||||
|
||||
struct node_info
|
||||
{
|
||||
- enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
+ enum {NODE_DOWN, NODE_CLVMD} state;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
@@ -255,26 +255,6 @@ static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
- for (i=0; i<member_list_entries; i++) {
|
||||
- if (member_list[i].nodeid == 0) continue;
|
||||
- ninfo = dm_hash_lookup_binary(node_hash,
|
||||
- (char *)&member_list[i].nodeid,
|
||||
- COROSYNC_CSID_LEN);
|
||||
- if (!ninfo) {
|
||||
- ninfo = malloc(sizeof(struct node_info));
|
||||
- if (!ninfo) {
|
||||
- break;
|
||||
- }
|
||||
- else {
|
||||
- ninfo->nodeid = member_list[i].nodeid;
|
||||
- dm_hash_insert_binary(node_hash,
|
||||
- (char *)&ninfo->nodeid,
|
||||
- COROSYNC_CSID_LEN, ninfo);
|
||||
- }
|
||||
- }
|
||||
- ninfo->state = NODE_CLVMD;
|
||||
- }
|
||||
-
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
@@ -440,7 +420,6 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
- int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
@@ -452,12 +431,10 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||
ninfo->state);
|
||||
|
||||
- if (ninfo->state != NODE_DOWN)
|
||||
- callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
- if (ninfo->state != NODE_CLVMD)
|
||||
- somedown = -1;
|
||||
+ if (ninfo->state == NODE_CLVMD)
|
||||
+ callback(master_client, csid, 1);
|
||||
}
|
||||
- return somedown;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
--
|
||||
1.8.4.5
|
||||
|
148
device_is_usable_mem_leak.diff
Normal file
148
device_is_usable_mem_leak.diff
Normal file
@ -0,0 +1,148 @@
|
||||
commit ec49f07b0dc89720f4a74a1212e106990099d2d6
|
||||
Author: Zdenek Kabelac <zkabelac@redhat.com>
|
||||
Date: Thu Dec 6 23:37:21 2012 +0100
|
||||
|
||||
mirrors: fix leak in device_is_usable mirror check
|
||||
|
||||
Function _ignore_blocked_mirror_devices was not release
|
||||
allocated strings images_health and log_health.
|
||||
|
||||
In error paths it was also not releasing dm_task structure.
|
||||
|
||||
Swaped return code of _ignore_blocked_mirror_devices and
|
||||
use 1 as success.
|
||||
|
||||
In _parse_mirror_status use log_error if memory allocation
|
||||
fails and few more errors so they are no going unnoticed
|
||||
as debug messages.
|
||||
|
||||
On error path always clear return values and free strings.
|
||||
|
||||
For dev_create_file use cache mem pool to avoid memleak.
|
||||
|
||||
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
|
||||
index 40f719e..3f74c2d 100644
|
||||
--- a/lib/activate/dev_manager.c
|
||||
+++ b/lib/activate/dev_manager.c
|
||||
@@ -158,6 +158,10 @@ static int _parse_mirror_status(char *mirror_status_str,
|
||||
char **args, **log_args;
|
||||
unsigned num_devs, log_argc;
|
||||
|
||||
+ *images_health = NULL;
|
||||
+ *log_health = NULL;
|
||||
+ *log_dev = 0;
|
||||
+
|
||||
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 */
|
||||
@@ -176,19 +180,31 @@ static int _parse_mirror_status(char *mirror_status_str,
|
||||
log_argc, 0, log_args) < log_argc)
|
||||
return_0;
|
||||
|
||||
- *log_health = NULL;
|
||||
- *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;
|
||||
+ if (!(*log_health = dm_strdup(log_args[2]))) {
|
||||
+ log_error("Allocation of log string failed.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (sscanf(log_args[1], "%d:%d", &major, &minor) != 2) {
|
||||
+ log_error("Parsing of log's major minor failed.");
|
||||
+ goto out;
|
||||
+ }
|
||||
*log_dev = MKDEV((dev_t)major, minor);
|
||||
}
|
||||
- if (!(*images_health = dm_strdup(args[2 + num_devs])))
|
||||
- return_0;
|
||||
+
|
||||
+ if (!(*images_health = dm_strdup(args[2 + num_devs]))) {
|
||||
+ log_error("Allocation of images string failed.");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
return 1;
|
||||
+
|
||||
+out:
|
||||
+ dm_free(*log_health);
|
||||
+ *log_health = NULL;
|
||||
+ *log_dev = 0;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -227,11 +243,12 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
uint64_t s,l;
|
||||
char *params, *target_type = NULL;
|
||||
void *next = NULL;
|
||||
- struct dm_task *dmt;
|
||||
+ struct dm_task *dmt = NULL;
|
||||
+ int r = 0;
|
||||
|
||||
if (!_parse_mirror_status(mirror_status_str,
|
||||
&images_health, &log_dev, &log_health))
|
||||
- goto_out;
|
||||
+ return_0;
|
||||
|
||||
for (i = 0; images_health[i]; i++)
|
||||
if (images_health[i] != 'A') {
|
||||
@@ -254,7 +271,7 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
(int)MINOR(log_dev)) < 0)
|
||||
goto_out;
|
||||
|
||||
- if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 1)))
|
||||
+ if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 0)))
|
||||
goto_out;
|
||||
|
||||
tmp_dev->dev = log_dev;
|
||||
@@ -263,8 +280,10 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
- if (!check_for_blocking)
|
||||
- return 0;
|
||||
+ if (!check_for_blocking) {
|
||||
+ r = 1;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* We avoid another system call if we can, but if a device is
|
||||
@@ -293,16 +312,19 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
strstr(params, "handle_errors")) {
|
||||
log_debug("%s: I/O blocked to mirror device",
|
||||
dev_name(dev));
|
||||
- return 1;
|
||||
+ goto out;
|
||||
}
|
||||
}
|
||||
} while (next);
|
||||
- dm_task_destroy(dmt);
|
||||
-
|
||||
- return 0;
|
||||
|
||||
+ r = 1;
|
||||
out:
|
||||
- return 1;
|
||||
+ if (dmt)
|
||||
+ dm_task_destroy(dmt);
|
||||
+ dm_free(log_health);
|
||||
+ dm_free(images_health);
|
||||
+
|
||||
+ return r;
|
||||
}
|
||||
|
||||
int device_is_usable(struct device *dev)
|
||||
@@ -356,7 +378,7 @@ int device_is_usable(struct device *dev)
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (target_type && !strcmp(target_type, "mirror") &&
|
||||
- _ignore_blocked_mirror_devices(dev, start, length, params)) {
|
||||
+ !_ignore_blocked_mirror_devices(dev, start, length, params)) {
|
||||
log_debug("%s: Mirror device %s not usable.",
|
||||
dev_name(dev), name);
|
||||
goto out;
|
55
display-dm-name-for-lv-name.diff
Normal file
55
display-dm-name-for-lv-name.diff
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
lib/config/defaults.h | 1 +
|
||||
lib/display/display.c | 14 ++++++++++----
|
||||
lib/display/display.h | 1 +
|
||||
3 files changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
Index: LVM2.2.02.98/lib/display/display.c
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/lib/display/display.c 2012-10-15 22:24:58.000000000 +0800
|
||||
+++ LVM2.2.02.98/lib/display/display.c 2014-03-20 12:24:55.761578040 +0800
|
||||
@@ -535,10 +535,16 @@ int lvdisplay_full(struct cmd_context *c
|
||||
lv->vg->cmd->dev_dir, lv->vg->name, lv->name);
|
||||
else if (lv_is_visible(lv)) {
|
||||
/* Thin pool does not have /dev/vg/name link */
|
||||
- if (!lv_is_thin_pool(lv))
|
||||
- log_print("LV Path %s%s/%s",
|
||||
- lv->vg->cmd->dev_dir,
|
||||
- lv->vg->name, lv->name);
|
||||
+ if (!lv_is_thin_pool(lv)) {
|
||||
+ if (find_config_tree_bool(cmd, "global/display_dm_name_for_lv_name",
|
||||
+ DEFAULT_DISPLAY_DM_NAME_FOR_LV_NAME)) {
|
||||
+ log_print("LV Path %smapper/%s-%s", lv->vg->cmd->dev_dir,
|
||||
+ lv->vg->name, lv->name);
|
||||
+ } else {
|
||||
+ log_print("LV Path %s%s/%s", lv->vg->cmd->dev_dir,
|
||||
+ lv->vg->name, lv->name);
|
||||
+ }
|
||||
+ }
|
||||
log_print("LV Name %s", lv->name);
|
||||
} else
|
||||
log_print("Internal LV Name %s", lv->name);
|
||||
Index: LVM2.2.02.98/lib/display/display.h
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/lib/display/display.h 2014-03-20 12:24:30.403397837 +0800
|
||||
+++ LVM2.2.02.98/lib/display/display.h 2014-03-20 12:24:55.761578040 +0800
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "metadata-exported.h"
|
||||
#include "locking.h"
|
||||
+#include "defaults.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
Index: LVM2.2.02.98/lib/config/defaults.h
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/lib/config/defaults.h 2014-03-20 12:24:30.403397837 +0800
|
||||
+++ LVM2.2.02.98/lib/config/defaults.h 2014-03-20 12:25:27.958815335 +0800
|
||||
@@ -31,6 +31,7 @@
|
||||
#define DEFAULT_PROC_DIR "/proc"
|
||||
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
|
||||
#define DEFAULT_SYSFS_SCAN 1
|
||||
+#define DEFAULT_DISPLAY_DM_NAME_FOR_LV_NAME 0
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
|
||||
#define DEFAULT_MULTIPATH_COMPONENT_DETECTION 1
|
226
do_not_read_from_mirrors_have_failed_devices.diff
Normal file
226
do_not_read_from_mirrors_have_failed_devices.diff
Normal file
@ -0,0 +1,226 @@
|
||||
commit 9fd7ac7d035f0b2f8dcc3cb19935eb181816bd76
|
||||
Author: Jonathan Brassow <jbrassow@redhat.com>
|
||||
Date: 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.)
|
||||
|
||||
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;
|
||||
}
|
||||
|
34
lvconvert-cluster-mirrored-disk-failed.patch
Normal file
34
lvconvert-cluster-mirrored-disk-failed.patch
Normal file
@ -0,0 +1,34 @@
|
||||
Index: LVM2.2.02.98/daemons/clvmd/lvm-functions.c
|
||||
===================================================================
|
||||
--- LVM2.2.02.98.orig/daemons/clvmd/lvm-functions.c
|
||||
+++ LVM2.2.02.98/daemons/clvmd/lvm-functions.c
|
||||
@@ -418,11 +418,13 @@ static int do_resume_lv(char *resource,
|
||||
int oldmode, origin_only, exclusive, revert;
|
||||
|
||||
/* Is it open ? */
|
||||
+ /*
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_resume_lv, lock not already held\n");
|
||||
- return 0; /* We don't need to do anything */
|
||||
+ return 0;
|
||||
}
|
||||
+ */
|
||||
origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
|
||||
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
||||
revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
|
||||
@@ -442,11 +444,13 @@ static int do_suspend_lv(char *resource,
|
||||
unsigned exclusive;
|
||||
|
||||
/* Is it open ? */
|
||||
+ /*
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_suspend_lv, lock not already held\n");
|
||||
- return 0; /* Not active, so it's OK */
|
||||
+ return 0;
|
||||
}
|
||||
+ */
|
||||
|
||||
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
||||
|
25
lvm2.changes
25
lvm2.changes
@ -1,3 +1,28 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Mar 25 09:08:16 UTC 2014 - dmzhang@suse.com
|
||||
|
||||
- backport more patches from slesp3(bnc#831518)
|
||||
scm support:
|
||||
add_scm_support.patch
|
||||
mirrored log fix:
|
||||
do_not_read_from_mirrors_have_failed_devices.diff
|
||||
avoid_reading_failed_dev_in_mirrored_log.diff
|
||||
mirrored_log_fixed_when_double_fault_occurs.diff
|
||||
device_is_usable_mem_leak.diff
|
||||
clvmd:
|
||||
clmvd-fix-decriptor-leak-on-restart.patch
|
||||
clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch
|
||||
clvmd-Fix-node-up-down-handing-in-corosync-module.patch
|
||||
0001-clvmd-avoid-logging-in-signal-handler.patch
|
||||
fate#314367, missing patch
|
||||
lvconvert-cluster-mirrored-disk-failed.patch
|
||||
other fix:
|
||||
pvmove_support_clustered_vg.diff
|
||||
suppress_format1_size_warning.diff
|
||||
display-dm-name-for-lv-name.diff
|
||||
no longer needed patches:
|
||||
autoactivate-lvmetad-with-generator.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Feb 20 16:23:21 UTC 2014 - arvidjaar@gmail.com
|
||||
|
||||
|
64
lvm2.spec
64
lvm2.spec
@ -25,6 +25,7 @@ BuildRequires: libdlm-devel
|
||||
BuildRequires: libselinux-devel
|
||||
BuildRequires: libudev-devel
|
||||
BuildRequires: readline-devel
|
||||
BuildRequires: systemd-rpm-macros
|
||||
BuildRequires: pkgconfig(udev)
|
||||
Requires: device-mapper >= 1.02.25
|
||||
Provides: lvm
|
||||
@ -37,17 +38,11 @@ Group: System/Base
|
||||
Source: ftp://sources.redhat.com/pub/%{name}/LVM2.%{version}.tgz
|
||||
Source42: ftp://sources.redhat.com/pub/%{name}/LVM2.%{version}.tgz.asc
|
||||
Source1: lvm.conf
|
||||
#Source2: boot.lvm
|
||||
Source4: mkinitrd-lvm2-setup.sh
|
||||
Source5: mkinitrd-lvm2-boot.sh
|
||||
#Source6: 64-lvm2.rules
|
||||
#Source7: collect_lvm
|
||||
Source8: clvmd.ocf
|
||||
Source10: cmirrord.ocf
|
||||
#Source12: mkinitrd-devmapper-setup.sh
|
||||
#Source13: mkinitrd-devmapper-boot.sh
|
||||
Source14: baselibs.conf
|
||||
#Source15: lvm2-activation.service
|
||||
Source16: csm-converter.tar.gz
|
||||
|
||||
Patch: improve_probing.diff
|
||||
@ -60,6 +55,9 @@ Patch13: pipe_buff-definition.diff
|
||||
|
||||
Patch20: support-drbd-filter.diff
|
||||
Patch22: handle_extended_devt.diff
|
||||
#suse
|
||||
Patch23: display-dm-name-for-lv-name.diff
|
||||
|
||||
Patch66: device-mapper-type_punning.diff
|
||||
Patch67: lvm-path.patch
|
||||
|
||||
@ -67,24 +65,41 @@ Patch67: lvm-path.patch
|
||||
Patch68: make-mirror-legs-on-different-tag-pvs.patch
|
||||
Patch69: improve-mirror-legs-on-different-tag-pvs.patch
|
||||
|
||||
#fate#314367
|
||||
Patch70: cluster_support_mirrord_log.diff
|
||||
|
||||
#upstream
|
||||
Patch71: make_raid1_default.diff
|
||||
#suppress warning
|
||||
Patch72: suppress_locking_failer_message.patch
|
||||
#upstream
|
||||
Patch73: remove-fedora-systemd.patch
|
||||
|
||||
#bnc#862076
|
||||
Patch74: autoactivate-lvmetad-with-generator.patch
|
||||
|
||||
#fate#315092
|
||||
Patch75: cmirrord_improvment_performance.patch
|
||||
|
||||
#bnc#862076
|
||||
Patch76: 0001-lvmetad-Init-lazily-to-avoid-socket-access-on-config.patch
|
||||
|
||||
#fate#314367
|
||||
Patch77: cluster_support_mirrord_log.diff
|
||||
Patch78: lvconvert-cluster-mirrored-disk-failed.patch
|
||||
|
||||
Patch79: add_scm_support.patch
|
||||
|
||||
#upstream backport
|
||||
Patch80: do_not_read_from_mirrors_have_failed_devices.diff
|
||||
Patch81: avoid_reading_failed_dev_in_mirrored_log.diff
|
||||
Patch82: mirrored_log_fixed_when_double_fault_occurs.diff
|
||||
Patch83: device_is_usable_mem_leak.diff
|
||||
|
||||
#forward-port from sle11
|
||||
Patch84: suppress_format1_size_warning.diff
|
||||
Patch85: pvmove_support_clustered_vg.diff
|
||||
|
||||
#upstream
|
||||
Patch86: clmvd-fix-decriptor-leak-on-restart.patch
|
||||
Patch87: clvmd-Fix-node-up-down-handing-in-corosync-module.patch
|
||||
Patch88: clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch
|
||||
Patch89: 0001-clvmd-avoid-logging-in-signal-handler.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
# Not a real replacement but we drop evms
|
||||
Provides: evms = 2.5.5
|
||||
@ -115,17 +130,29 @@ Volume Manager.
|
||||
%patch13 -p1
|
||||
%patch20 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch66 -p1
|
||||
%patch67 -p1
|
||||
%patch68 -p1
|
||||
%patch69 -p1
|
||||
%patch70 -p1
|
||||
%patch71 -p1
|
||||
%patch72 -p1
|
||||
%patch73 -p1
|
||||
%patch74 -p1
|
||||
%patch75 -p1
|
||||
%patch76 -p1
|
||||
%patch77 -p1
|
||||
%patch78 -p1
|
||||
%patch79 -p1
|
||||
%patch80 -p1
|
||||
%patch81 -p1
|
||||
%patch82 -p1
|
||||
%patch83 -p1
|
||||
%patch84 -p1
|
||||
%patch85 -p1
|
||||
%patch86 -p1
|
||||
%patch87 -p1
|
||||
%patch88 -p1
|
||||
%patch89 -p1
|
||||
|
||||
%build
|
||||
#set path so that thin_check can be found
|
||||
@ -221,17 +248,18 @@ mv README.csm-converter ..
|
||||
popd
|
||||
|
||||
%post
|
||||
%service_add_post blk-availability.service lvm2-monitor.service lvm2-lvmetad.socket
|
||||
/usr/bin/systemctl enable lvm2-lvmetad.socket
|
||||
[ -x /sbin/mkinitrd ] && /sbin/mkinitrd
|
||||
/sbin/ldconfig
|
||||
[ -x /sbin/mkinitrd ] && /sbin/mkinitrd
|
||||
%service_add_post blk-availability.service lvm2-monitor.service
|
||||
%service_add_post lvm2-lvmetad.socket
|
||||
|
||||
%preun
|
||||
%service_del_preun blk-availability.service lvm2-monitor.service lvm2-lvmetad.service lvm2-lvmetad.socket
|
||||
|
||||
%postun
|
||||
[ -x /sbin/mkinitrd ] && /sbin/mkinitrd
|
||||
/sbin/ldconfig
|
||||
[ -x /sbin/mkinitrd ] && /sbin/mkinitrd
|
||||
%service_del_postun lvm2-lvmetad.service
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
|
59
mirrored_log_fixed_when_double_fault_occurs.diff
Normal file
59
mirrored_log_fixed_when_double_fault_occurs.diff
Normal file
@ -0,0 +1,59 @@
|
||||
commit 54c73b7723713f43413584d59ca0bdd42c1d8241
|
||||
Author: Jonathan Brassow <jbrassow@redhat.com>
|
||||
Date: Wed Nov 14 14:58:47 2012 -0600
|
||||
|
||||
mirror: Mirrored log should be fixed before mirror when double fault occurs
|
||||
|
||||
This patch is intended to fix bug 825323 - FS turns read-only during a double
|
||||
fault of a mirror leg and mirrored log's leg at the same time. It only
|
||||
affects a 2-way mirror with a mirrored log. 3+-way mirrors and mirrors
|
||||
without a mirrored log are not affected.
|
||||
|
||||
The problem resulted from the fact that the top level mirror was not
|
||||
using 'noflush' when suspending before its "down-convert". When a
|
||||
mirror image fails, the bios are queue until a suspend is recieved. If
|
||||
it is a 'noflush' suspend, the bios can be safely requeued in the DM
|
||||
core. If 'noflush' is not used, the bios must be pushed through the
|
||||
target and if a device is failed for a mirror, that means issuing an
|
||||
error. When an error is received by a file system, it results in it
|
||||
turning read-only (depending on the FS).
|
||||
|
||||
Part of the problem was is due to the nature of the stacking involved in
|
||||
using a mirror as a mirror's log. When an image in each fail, the top
|
||||
level mirror stalls because it is waiting for a log flush. The other
|
||||
stalls waiting for corrective action. When the repair command is issued,
|
||||
the entire stacked arrangement is collapsed to a linear LV. The log
|
||||
flush then fails (somewhat uncleanly) and the top-level mirror is suspended
|
||||
without 'noflush' because it is a linear device.
|
||||
|
||||
This patch allows the log to be repaired first, which in turn allows the
|
||||
top-level mirror's log flush to complete cleanly. The top-level mirror
|
||||
is then secondarily reduced to a linear device - at which time this mirror
|
||||
is suspended properly with 'noflush'.
|
||||
|
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
|
||||
index f23fc4b..27d8181 100644
|
||||
--- a/tools/lvconvert.c
|
||||
+++ b/tools/lvconvert.c
|
||||
@@ -1341,10 +1341,6 @@ int mirror_remove_missing(struct cmd_context *cmd,
|
||||
if (!(failed_pvs = _failed_pv_list(lv->vg)))
|
||||
return_0;
|
||||
|
||||
- /* No point in keeping a log if the result is not a mirror */
|
||||
- if (_failed_mirrors_count(lv) + 1 >= lv_mirror_count(lv))
|
||||
- log_count = 0;
|
||||
-
|
||||
if (force && _failed_mirrors_count(lv) == lv_mirror_count(lv)) {
|
||||
log_error("No usable images left in %s.", lv->name);
|
||||
return lv_remove_with_dependencies(cmd, lv, DONT_PROMPT, 0);
|
||||
@@ -1363,8 +1359,8 @@ int mirror_remove_missing(struct cmd_context *cmd,
|
||||
_is_partial_lv, NULL, 0))
|
||||
return 0;
|
||||
|
||||
- if (!_lv_update_log_type(cmd, NULL, lv, failed_pvs,
|
||||
- log_count))
|
||||
+ if (lv_is_mirrored(lv) &&
|
||||
+ !_lv_update_log_type(cmd, NULL, lv, failed_pvs, log_count))
|
||||
return 0;
|
||||
|
||||
if (!_reload_lv(cmd, lv->vg, lv))
|
50
pvmove_support_clustered_vg.diff
Normal file
50
pvmove_support_clustered_vg.diff
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
lib/activate/activate.c | 30 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
--- LVM2.2.02.98.orig/lib/activate/activate.c
|
||||
+++ LVM2.2.02.98/lib/activate/activate.c
|
||||
@@ -569,6 +569,26 @@ int module_present(struct cmd_context *c
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* 0 on not running, 1 on running */
|
||||
+static int check_cmirrord()
|
||||
+{
|
||||
+ int fd;
|
||||
+ int ret = 0;
|
||||
+ struct flock lock;
|
||||
+ if (( fd = open("/var/run/cmirrord.pid", O_WRONLY)) >= 0)
|
||||
+ {
|
||||
+ lock.l_type = F_WRLCK;
|
||||
+ lock.l_start = 0;
|
||||
+ lock.l_whence = SEEK_SET;
|
||||
+ lock.l_len = 0;
|
||||
+ if (fcntl(fd, F_SETLK, &lock) < 0) {
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+ close(fd);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe)
|
||||
{
|
||||
@@ -577,6 +597,16 @@ int target_present(struct cmd_context *c
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
+ if (!strncmp(target_name, "log-userspace", 13)) {
|
||||
+ /*
|
||||
+ When the target_name is log-userspace, it also means
|
||||
+ we need cmirrord daemon running. It doesn't work alone.
|
||||
+ */
|
||||
+ if (!check_cmirrord())
|
||||
+ log_error("cmirrord is required, but not running now.");
|
||||
+ return_0;
|
||||
+ }
|
||||
+
|
||||
#ifdef MODPROBE_CMD
|
||||
if (use_modprobe) {
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
27
suppress_format1_size_warning.diff
Normal file
27
suppress_format1_size_warning.diff
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
lib/format1/import-export.c | 2 +-
|
||||
lib/format_text/import_vsn1.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- LVM2.2.02.98.orig/lib/format1/import-export.c
|
||||
+++ LVM2.2.02.98/lib/format1/import-export.c
|
||||
@@ -104,7 +104,7 @@ int import_pv(const struct format_type *
|
||||
log_error("%s: Couldn't get size.", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
- log_verbose("Fixing up missing format1 size (%s) "
|
||||
+ log_debug("Fixing up missing format1 size (%s) "
|
||||
"for PV %s", display_size(fmt->cmd, pv->size),
|
||||
pv_dev_name(pv));
|
||||
if (vg) {
|
||||
--- LVM2.2.02.98.orig/lib/format_text/import_vsn1.c
|
||||
+++ LVM2.2.02.98/lib/format_text/import_vsn1.c
|
||||
@@ -262,7 +262,7 @@ static int _read_pv(struct format_instan
|
||||
log_error("%s: Couldn't get size.", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
- log_verbose("Fixing up missing size (%s) "
|
||||
+ log_debug("Fixing up missing size (%s) "
|
||||
"for PV %s", display_size(fid->fmt->cmd, pv->size),
|
||||
pv_dev_name(pv));
|
||||
size = pv->pe_count * (uint64_t) vg->extent_size + pv->pe_start;
|
Loading…
Reference in New Issue
Block a user