From f45a4f9a5ecccab72f2c4bea8431e3fa5218c2896d8711bb59a6cc9a3d624aff Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 28 Mar 2014 14:57:40 +0000 Subject: [PATCH] Accepting request 227422 from home:deanraccoon:branches:Base:System forward-port several patches from sle11sp3.bnc#831518 OBS-URL: https://build.opensuse.org/request/show/227422 OBS-URL: https://build.opensuse.org/package/show/Base:System/lvm2?expand=0&rev=85 --- ...lvmd-avoid-logging-in-signal-handler.patch | 49 ++++ add_scm_support.patch | 24 ++ autoactivate-lvmetad-with-generator.patch | 40 --- avoid_reading_failed_dev_in_mirrored_log.diff | 144 ++++++++++ clmvd-fix-decriptor-leak-on-restart.patch | 28 ++ ...-way-deadlock-in-dead-client-cleanup.patch | 252 ++++++++++++++++++ ...e-up-down-handing-in-corosync-module.patch | 87 ++++++ device_is_usable_mem_leak.diff | 148 ++++++++++ display-dm-name-for-lv-name.diff | 55 ++++ ...read_from_mirrors_have_failed_devices.diff | 226 ++++++++++++++++ lvconvert-cluster-mirrored-disk-failed.patch | 34 +++ lvm2.changes | 25 ++ lvm2.spec | 64 +++-- ...ed_log_fixed_when_double_fault_occurs.diff | 59 ++++ pvmove_support_clustered_vg.diff | 50 ++++ suppress_format1_size_warning.diff | 27 ++ 16 files changed, 1254 insertions(+), 58 deletions(-) create mode 100644 0001-clvmd-avoid-logging-in-signal-handler.patch create mode 100644 add_scm_support.patch delete mode 100644 autoactivate-lvmetad-with-generator.patch create mode 100644 avoid_reading_failed_dev_in_mirrored_log.diff create mode 100644 clmvd-fix-decriptor-leak-on-restart.patch create mode 100644 clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch create mode 100644 clvmd-Fix-node-up-down-handing-in-corosync-module.patch create mode 100644 device_is_usable_mem_leak.diff create mode 100644 display-dm-name-for-lv-name.diff create mode 100644 do_not_read_from_mirrors_have_failed_devices.diff create mode 100644 lvconvert-cluster-mirrored-disk-failed.patch create mode 100644 mirrored_log_fixed_when_double_fault_occurs.diff create mode 100644 pvmove_support_clustered_vg.diff create mode 100644 suppress_format1_size_warning.diff diff --git a/0001-clvmd-avoid-logging-in-signal-handler.patch b/0001-clvmd-avoid-logging-in-signal-handler.patch new file mode 100644 index 0000000..b7c64bc --- /dev/null +++ b/0001-clvmd-avoid-logging-in-signal-handler.patch @@ -0,0 +1,49 @@ +From 5070ffbca7b16e4139b3da72bdff0c9add517351 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +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 + diff --git a/add_scm_support.patch b/add_scm_support.patch new file mode 100644 index 0000000..a9d849f --- /dev/null +++ b/add_scm_support.patch @@ -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 +--- + 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} + }; + diff --git a/autoactivate-lvmetad-with-generator.patch b/autoactivate-lvmetad-with-generator.patch deleted file mode 100644 index 0478077..0000000 --- a/autoactivate-lvmetad-with-generator.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Andrey Borzenkov -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 - ---- - 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"); diff --git a/avoid_reading_failed_dev_in_mirrored_log.diff b/avoid_reading_failed_dev_in_mirrored_log.diff new file mode 100644 index 0000000..3e41af8 --- /dev/null +++ b/avoid_reading_failed_dev_in_mirrored_log.diff @@ -0,0 +1,144 @@ +commit b248ba0a396d7fc9a459eea02cfdc70b33ce3441 +Author: Jonathan Brassow +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; + diff --git a/clmvd-fix-decriptor-leak-on-restart.patch b/clmvd-fix-decriptor-leak-on-restart.patch new file mode 100644 index 0000000..9398661 --- /dev/null +++ b/clmvd-fix-decriptor-leak-on-restart.patch @@ -0,0 +1,28 @@ +From 7b1315411f1de73801fd38f264ca507ae3807e53 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +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 + diff --git a/clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch b/clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch new file mode 100644 index 0000000..616d844 --- /dev/null +++ b/clvmd-Avoid-a-3-way-deadlock-in-dead-client-cleanup.patch @@ -0,0 +1,252 @@ +From 25bed9968155f43ef0b8832383ef711e7ae1685d Mon Sep 17 00:00:00 2001 +From: Petr Rockai +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; diff --git a/clvmd-Fix-node-up-down-handing-in-corosync-module.patch b/clvmd-Fix-node-up-down-handing-in-corosync-module.patch new file mode 100644 index 0000000..444f874 --- /dev/null +++ b/clvmd-Fix-node-up-down-handing-in-corosync-module.patch @@ -0,0 +1,87 @@ +From 431eda63cc0ebff7c62dacb313cabcffbda6573a Mon Sep 17 00:00:00 2001 +From: Christine Caulfield +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 +--- + 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; inodeid = 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 + diff --git a/device_is_usable_mem_leak.diff b/device_is_usable_mem_leak.diff new file mode 100644 index 0000000..dea541e --- /dev/null +++ b/device_is_usable_mem_leak.diff @@ -0,0 +1,148 @@ +commit ec49f07b0dc89720f4a74a1212e106990099d2d6 +Author: Zdenek Kabelac +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; diff --git a/display-dm-name-for-lv-name.diff b/display-dm-name-for-lv-name.diff new file mode 100644 index 0000000..490db77 --- /dev/null +++ b/display-dm-name-for-lv-name.diff @@ -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 + +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 diff --git a/do_not_read_from_mirrors_have_failed_devices.diff b/do_not_read_from_mirrors_have_failed_devices.diff new file mode 100644 index 0000000..f0c4f1a --- /dev/null +++ b/do_not_read_from_mirrors_have_failed_devices.diff @@ -0,0 +1,226 @@ +commit 9fd7ac7d035f0b2f8dcc3cb19935eb181816bd76 +Author: Jonathan Brassow +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; + } + diff --git a/lvconvert-cluster-mirrored-disk-failed.patch b/lvconvert-cluster-mirrored-disk-failed.patch new file mode 100644 index 0000000..a4884ba --- /dev/null +++ b/lvconvert-cluster-mirrored-disk-failed.patch @@ -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; + diff --git a/lvm2.changes b/lvm2.changes index 25d0e26..9fe42fa 100644 --- a/lvm2.changes +++ b/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 diff --git a/lvm2.spec b/lvm2.spec index 83bc436..281108e 100644 --- a/lvm2.spec +++ b/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) diff --git a/mirrored_log_fixed_when_double_fault_occurs.diff b/mirrored_log_fixed_when_double_fault_occurs.diff new file mode 100644 index 0000000..4ee325c --- /dev/null +++ b/mirrored_log_fixed_when_double_fault_occurs.diff @@ -0,0 +1,59 @@ +commit 54c73b7723713f43413584d59ca0bdd42c1d8241 +Author: Jonathan Brassow +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)) diff --git a/pvmove_support_clustered_vg.diff b/pvmove_support_clustered_vg.diff new file mode 100644 index 0000000..9911510 --- /dev/null +++ b/pvmove_support_clustered_vg.diff @@ -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)) diff --git a/suppress_format1_size_warning.diff b/suppress_format1_size_warning.diff new file mode 100644 index 0000000..c2346c4 --- /dev/null +++ b/suppress_format1_size_warning.diff @@ -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;