summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2019-03-19 14:38:38 -0500
committerDavid Teigland <teigland@redhat.com>2019-03-21 12:38:20 -0500
commitd369de8399e14e82fb1ea45e7977d917411fbc21 (patch)
tree9691d2d77f64278a7586d830e7e35995574d1db3
parent9b4926aaff7f8644c8492cd68ab0b7079416ef3a (diff)
downloadlvm2-d369de8399e14e82fb1ea45e7977d917411fbc21.tar.gz
lvextend: allow on LV active with a shared lock
Detect when a shared lock exists, don't require the normal exclusive lock, and allow the lvextend.
-rw-r--r--daemons/lvmlockd/lvmlockd-core.c5
-rw-r--r--daemons/lvmlockd/lvmlockd-internal.h1
-rw-r--r--lib/locking/lvmlockd.c17
-rw-r--r--lib/locking/lvmlockd.h2
-rw-r--r--lib/metadata/lv_manip.c2
5 files changed, 25 insertions, 2 deletions
diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c
index 40a2f21b6..da3de54a8 100644
--- a/daemons/lvmlockd/lvmlockd-core.c
+++ b/daemons/lvmlockd/lvmlockd-core.c
@@ -1816,9 +1816,9 @@ static void res_process(struct lockspace *ls, struct resource *r,
add_client_result(act);
} else {
/* persistent lock is sh, transient request is ex */
- /* FIXME: can we remove this case? do a convert here? */
log_debug("res_process %s existing persistent lock new transient", r->name);
r->last_client_id = act->client_id;
+ act->flags |= LD_AF_SH_EXISTS;
act->result = -EEXIST;
list_del(&act->list);
add_client_result(act);
@@ -3661,6 +3661,9 @@ static int client_send_result(struct client *cl, struct action *act)
if ((act->flags & LD_AF_WARN_GL_REMOVED) || gl_vg_removed)
strcat(result_flags, "WARN_GL_REMOVED,");
+ if (act->flags & LD_AF_SH_EXISTS)
+ strcat(result_flags, "SH_EXISTS,");
+
if (act->op == LD_OP_INIT) {
/*
* init is a special case where lock args need
diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h
index f0fa85fbc..50015f10f 100644
--- a/daemons/lvmlockd/lvmlockd-internal.h
+++ b/daemons/lvmlockd/lvmlockd-internal.h
@@ -106,6 +106,7 @@ struct client {
#define LD_AF_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000
+#define LD_AF_SH_EXISTS 0x00100000
/*
* Number of times to repeat a lock request after
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index a1436898c..bc6e66f3b 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -118,6 +118,9 @@ static void _flags_str_to_lockd_flags(const char *flags_str, uint32_t *lockd_fla
if (strstr(flags_str, "WARN_GL_REMOVED"))
*lockd_flags |= LD_RF_WARN_GL_REMOVED;
+
+ if (strstr(flags_str, "SH_EXISTS"))
+ *lockd_flags |= LD_RF_SH_EXISTS;
}
/*
@@ -2205,6 +2208,20 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
* LV with an ex LV lock when the LV is already active with a
* sh LV lock.
*/
+
+ /*
+ * Special case to allow lvextend under gfs2.
+ *
+ * FIXME: verify the LV actually holds gfs2/ocfs2 which we know
+ * allow this (other users of the LV may not.)
+ */
+ if (lockd_flags & LD_RF_SH_EXISTS) {
+ if (flags & LDLV_EXTEND) {
+ log_warn("WARNING: extending LV with a shared lock, other hosts may require LV refresh.");
+ return 1;
+ }
+ }
+
log_error("LV is already locked with incompatible mode: %s/%s", vg->name, lv_name);
return 0;
}
diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h
index e5ae331b8..53d077e3f 100644
--- a/lib/locking/lvmlockd.h
+++ b/lib/locking/lvmlockd.h
@@ -22,6 +22,7 @@
/* lockd_lv flags */
#define LDLV_MODE_NO_SH 0x00000001
#define LDLV_PERSISTENT 0x00000002
+#define LDLV_EXTEND 0x00000004
/* lvmlockd result flags */
#define LD_RF_NO_LOCKSPACES 0x00000001
@@ -29,6 +30,7 @@
#define LD_RF_WARN_GL_REMOVED 0x00000004
#define LD_RF_DUP_GL_LS 0x00000008
#define LD_RF_NO_LM 0x00000010
+#define LD_RF_SH_EXISTS 0x00000020
/* lockd_state flags */
#define LDST_EX 0x00000001
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index e128336b6..c21a0f960 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5762,7 +5762,7 @@ int lv_resize(struct logical_volume *lv,
* If the LV is locked from activation, this lock call is a no-op.
* Otherwise, this acquires a transient lock on the lv (not PERSISTENT).
*/
- if (!lockd_lv(cmd, lock_lv, "ex", 0))
+ if (!lockd_lv(cmd, lock_lv, "ex", (lp->resize == LV_EXTEND) ? LDLV_EXTEND : 0))
return_0;
if (!archive(vg))