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:
Stephan Kulow 2014-04-05 14:50:12 +00:00 committed by Git OBS Bridge
commit 4a044281f4
16 changed files with 1254 additions and 58 deletions

View 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
View 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}
};

View File

@ -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");

View 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;

View 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

View 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;

View 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

View 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, &params);
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;

View 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

View 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, &params);
+ 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, &params);
- /* 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;
}

View 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;

View File

@ -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

View File

@ -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)

View 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))

View 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))

View 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;