summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-05-13 14:07:32 -0500
committerDavid Teigland <teigland@redhat.com>2015-05-28 16:34:36 -0500
commit8ab724a00f5091ca09d473f56a3bc8037da99b53 (patch)
tree6736cc95924d89d11cc085fa3ebf676af24a39be
parent56cf94ad125f06787043a6f726d6381100994ded (diff)
downloadlvm2-8ab724a00f5091ca09d473f56a3bc8037da99b53.tar.gz
lib: use locks from lvmlockd
-rw-r--r--lib/commands/toolcontext.c31
-rw-r--r--lib/commands/toolcontext.h8
-rw-r--r--lib/config/config_settings.h23
-rw-r--r--lib/config/defaults.h2
-rw-r--r--lib/metadata/lv.c22
-rw-r--r--lib/metadata/lv_manip.c121
-rw-r--r--lib/metadata/metadata-exported.h15
-rw-r--r--lib/metadata/metadata.c86
-rw-r--r--lib/metadata/raid_manip.c7
-rw-r--r--lib/metadata/replicator_manip.c4
-rw-r--r--lib/metadata/vg.c16
-rw-r--r--lib/misc/lvm-globals.c5
-rw-r--r--lib/misc/lvm-globals.h1
13 files changed, 310 insertions, 31 deletions
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 47aa209d5..d84588600 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -29,6 +29,7 @@
#include "segtype.h"
#include "lvmcache.h"
#include "lvmetad.h"
+#include "lvmlockd.h"
#include "archiver.h"
#include "lvmpolld-client.h"
@@ -479,7 +480,10 @@ static int _process_config(struct cmd_context *cmd)
int64_t pv_min_kb;
const char *lvmetad_socket;
const char *lvmpolld_socket;
+ const char *lvmlockd_socket;
int udev_disabled = 0;
+ int locking_type;
+ int use_lvmlockd;
char sysfs_dir[PATH_MAX];
if (!_check_config(cmd))
@@ -656,6 +660,32 @@ static int _process_config(struct cmd_context *cmd)
lvmpolld_set_active(find_config_tree_bool(cmd, global_use_lvmpolld_CFG, NULL));
+ /*
+ * clvmd and lvmlockd cannot be used concurrently, it is
+ * one or the other.
+ * global/locking_type=3 is the clvmd configuration.
+ * global/use_lvmlockd=1 is the lvmlockd configuration.
+ *
+ * use_lvmlockd should be combined with locking_type 1 (local).
+ */
+
+ locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL);
+ use_lvmlockd = find_config_tree_bool(cmd, global_use_lvmlockd_CFG, NULL);
+
+ if (locking_type == 3 && use_lvmlockd) {
+ log_error("ERROR: configuration setting use_lvmlockd cannot be used with locking_type 3.");
+ return 0;
+ }
+
+ lvmlockd_disconnect();
+ lvmlockd_socket = getenv("LVM_LVMLOCKD_SOCKET");
+ if (!lvmlockd_socket)
+ lvmlockd_socket = DEFAULT_RUN_DIR "/lvmlockd.socket";
+
+ lvmlockd_set_socket(lvmlockd_socket);
+ lvmlockd_set_active(!!use_lvmlockd);
+ lvmlockd_init(cmd);
+
return 1;
}
@@ -2075,6 +2105,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
#endif
dm_free(cmd);
+ lvmlockd_disconnect();
lvmetad_release_token();
lvmetad_disconnect();
lvmpolld_disconnect();
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 28f5a2c3e..219de8b4d 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -100,6 +100,9 @@ struct cmd_context {
unsigned include_foreign_vgs:1;
unsigned include_active_foreign_vgs:1;
unsigned error_foreign_vgs:1;
+ unsigned lockd_vg_disable:1;
+ unsigned lockd_lv_disable:1;
+ unsigned lockd_vg_default_sh:1;
struct dev_types *dev_types;
@@ -142,6 +145,11 @@ struct cmd_context {
const char *report_list_item_separator;
int hosttags;
+ /* Locking */
+ const char *lock_gl_mode; /* gl mode, from --lock-gl */
+ const char *lock_vg_mode; /* vg mode, from --lock-vg */
+ const char *lock_lv_mode; /* lv mode, from --lock-lv */
+
const char *lib_dir; /* Cache value global/library_dir */
char system_dir[PATH_MAX];
char dev_dir[PATH_MAX];
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 885a2fa35..2c97b8fc8 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -830,6 +830,16 @@ cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL,
"LVM prints warnings and ignores lvmetad if this combination\n"
"is seen.\n")
+cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 120), NULL, 0, NULL,
+ "Use lvmlockd for locking among hosts using LVM on shared storage.\n")
+
+cfg(global_allow_override_lock_modes_CFG, "allow_override_lock_modes", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 120), NULL, 0, NULL,
+ "Allow command options to override normal locking.\n")
+
+cfg(global_read_only_lock_modes_CFG, "read_only_lock_modes", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 120), NULL, 0, NULL,
+ "Limit commands to actions that use read locks.\n"
+ "This disallows any actions that require a write (exclusive) lock.\n")
+
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
"The full path to the thin_check command.\n"
"LVM uses this command to check that a thin metadata\n"
@@ -1255,6 +1265,14 @@ cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, 0, CFG_TYPE_
"sometimes assist with data recovery.\n"
"The '--activationmode' option overrides this setting.\n")
+cfg_array(activation_lock_start_list_CFG, "lock_start_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY|CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 120), NULL, 0, NULL,
+ "Locking is started only for VGs selected by this list.\n"
+ "The rules are the same as those for LVs in volume_list.\n")
+
+cfg_array(activation_auto_lock_start_list_CFG, "auto_lock_start_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY|CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 120), NULL, 0, NULL,
+ "Locking is auto-started only for VGs selected by this list.\n"
+ "The rules are the same as those for LVs in auto_activation_volume_list.\n")
+
cfg(metadata_pvmetadatacopies_CFG, "pvmetadatacopies", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PVMETADATACOPIES, vsn(1, 0, 0), NULL, 0, NULL,
"Number of copies of metadata to store on each PV.\n"
"Possible options are: 0, 1, 2.\n"
@@ -1506,4 +1524,9 @@ cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG
"Use this only after consulting 'man lvmsystemid'\n"
"to be certain of correct usage and possible dangers.\n")
+cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 120), NULL, 0, NULL,
+ "The lvmlockd sanlock host_id.\n"
+ "This must be a unique among all hosts,\n"
+ "and must be between 1 and 2000.\n")
+
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 6793d0167..efe9544dd 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -221,4 +221,6 @@
#define DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD 100
#define DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT 20
+#define DEFAULT_CY_LOCK_TYPE "sanlock"
+
#endif /* _LVM_DEFAULTS_H */
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 10ce9063f..6316cd867 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -20,6 +20,7 @@
#include "toolcontext.h"
#include "segtype.h"
#include "str_list.h"
+#include "lvmlockd.h"
#include <time.h>
#include <sys/utsname.h>
@@ -911,6 +912,19 @@ static int _lv_is_exclusive(struct logical_volume *lv)
int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
enum activation_change activate, int needs_exclusive)
{
+ const char *ay_with_mode = NULL;
+
+ if (activate == CHANGE_ASY)
+ ay_with_mode = "sh";
+ if (activate == CHANGE_AEY)
+ ay_with_mode = "ex";
+
+ if (is_change_activating(activate) &&
+ !lockd_lv(cmd, lv, ay_with_mode, LDLV_PERSISTENT)) {
+ log_error("Failed to lock logical volume %s/%s", lv->vg->name, lv->name);
+ return 0;
+ }
+
switch (activate) {
case CHANGE_AN:
deactivate:
@@ -953,7 +967,9 @@ exclusive:
if (!activate_lv_excl(cmd, lv))
return_0;
break;
- default: /* CHANGE_AY */
+ case CHANGE_ASY:
+ case CHANGE_AY:
+ default:
if (needs_exclusive || _lv_is_exclusive(lv))
goto exclusive;
log_verbose("Activating logical volume \"%s\".", lv->name);
@@ -961,6 +977,10 @@ exclusive:
return_0;
}
+ if (!is_change_activating(activate) &&
+ !lockd_lv(cmd, lv, "un", LDLV_PERSISTENT))
+ log_error("Failed to unlock logical volume %s/%s", lv->vg->name, lv->name);
+
return 1;
}
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 1251a5d90..921bba93e 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -30,6 +30,7 @@
#include "lvm-exec.h"
#include "lvm-signal.h"
#include "memlock.h"
+#include "lvmlockd.h"
typedef enum {
PREFERRED,
@@ -1395,6 +1396,28 @@ int replace_lv_with_error_segment(struct logical_volume *lv)
return 1;
}
+int lv_refresh_suspend_resume(struct cmd_context *cmd, struct logical_volume *lv)
+{
+ if (!cmd->partial_activation && (lv->status & PARTIAL_LV)) {
+ log_error("Refusing refresh of partial LV %s."
+ " Use '--activationmode partial' to override.",
+ lv->name);
+ return 0;
+ }
+
+ if (!suspend_lv(cmd, lv)) {
+ log_error("Failed to suspend %s.", lv->name);
+ return 0;
+ }
+
+ if (!resume_lv(cmd, lv)) {
+ log_error("Failed to reactivate %s.", lv->name);
+ return 0;
+ }
+
+ return 1;
+}
+
/*
* Remove given number of extents from LV.
*/
@@ -4205,7 +4228,58 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
const char *new_name)
{
- return lv_rename_update(cmd, lv, new_name, 1);
+ struct volume_group *vg;
+ const char *old_name;
+ const char *old_args;
+ const char *new_args;
+ int is_active = 0;
+
+ if (!is_lockd_type(lv->lock_type))
+ return lv_rename_update(cmd, lv, new_name, 1);
+
+ /*
+ * When the LV has a lock_type, renaming takes more
+ * work because the LV name is a part of the lock
+ * name itself. This means creating and acquiring
+ * a new lock with the new name, then releasing and
+ * removing the lock with the old name.
+ */
+
+ vg = lv->vg;
+ old_name = lv->name;
+ old_args = lv->lock_args;
+ is_active = lv_is_active(lv);
+
+ /* Lock the old LV name. */
+ if (!lockd_lv_name(cmd, vg, old_name, old_args, "ex", is_active ? LDLV_PERSISTENT : 0))
+ return_0;
+
+ /* Create a lock for the new LV name. */
+ if (!lockd_init_lv_args(cmd, vg, new_name, lv->lock_type, &new_args)) {
+ log_error("Failed to init %s lock args for new LV", lv->lock_type);
+ return 0;
+ }
+
+ /* Lock the new LV name. */
+ if (is_active && !lockd_lv_name(cmd, vg, new_name, new_args, "ex", LDLV_PERSISTENT)) {
+ log_error("Failed to lock new LV name %s/%s.", vg->name, new_name);
+ return 0;
+ }
+
+ /* The new lock args need to be written in the metadata with the new name. */
+ lv->lock_args = new_args;
+
+ if (!lv_rename_update(cmd, lv, new_name, 1)) {
+ if (is_active)
+ lockd_lv_name(cmd, vg, new_name, new_args, "un", LDLV_PERSISTENT);
+ lockd_free_lv(cmd, vg, new_name, new_args);
+ return 0;
+ }
+
+ /* Unlock and free the lock on the old name. */
+ lockd_lv_name(cmd, vg, old_name, old_args, "un", is_active ? LDLV_PERSISTENT : 0);
+ lockd_free_lv(cmd, vg, old_name, old_args);
+ return 1;
}
/*
@@ -4566,7 +4640,9 @@ static int _lvresize_check_lv(struct cmd_context *cmd, struct logical_volume *lv
return 0;
}
- if (!lv_is_visible(lv) && !lv_is_thin_pool_metadata(lv)) {
+ /* FIXME: use a status flag instead of the name "lvmlock". */
+
+ if (!lv_is_visible(lv) && !lv_is_thin_pool_metadata(lv) && strcmp(lv->name, "lvmlock")) {
log_error("Can't resize internal logical volume %s", lv->name);
return 0;
}
@@ -5226,6 +5302,13 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
return 0;
}
+ /*
+ * 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, lv, "ex", 0))
+ return_0;
+
if (lp->sizeargs &&
!(lock_lv = _lvresize_volume(cmd, lv, lp, pvh)))
return_0;
@@ -5574,6 +5657,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
int format1_reload_required = 0;
int visible;
struct logical_volume *pool_lv = NULL;
+ struct logical_volume *lock_lv = lv;
struct lv_segment *cache_seg = NULL;
int ask_discard;
struct lv_list *lvl;
@@ -5620,14 +5704,19 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
log_error("Can't remove logical volume %s used by a pool.",
lv->name);
return 0;
- } else if (lv_is_thin_volume(lv))
+ } else if (lv_is_thin_volume(lv)) {
pool_lv = first_seg(lv)->pool_lv;
+ lock_lv = pool_lv;
+ }
if (lv_is_locked(lv)) {
log_error("Can't remove locked LV %s", lv->name);
return 0;
}
+ if (!lockd_lv(cmd, lock_lv, "ex", LDLV_PERSISTENT))
+ return_0;
+
/* FIXME Ensure not referred to by another existing LVs */
ask_discard = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL);
@@ -5802,6 +5891,10 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
backup(vg);
+ lockd_lv(cmd, lock_lv, "un", LDLV_PERSISTENT | LDLV_MODE_NOARG);
+ if (lv->lock_type)
+ lockd_free_lv(cmd, vg, lv->name, lv->lock_args);
+
if (!suppress_remove_message && visible)
log_print_unless_silent("Logical volume \"%s\" successfully removed", lv->name);
@@ -7184,6 +7277,25 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
lv->major, lv->minor);
}
+ /*
+ * lockd_init_lv clears lp lock_type if this LV does not use its own lock.
+ * TODO: use lockd_free_lv if lv_extend fails below.
+ */
+ if (lp->lock_type && !lockd_init_lv(vg->cmd, vg, lv->name, lp))
+ return_NULL;
+
+ if (lp->lock_type && !(lv->lock_type = dm_pool_strdup(cmd->mem, lp->lock_type))) {
+ log_error("Failed to allocate lock_type");
+ lockd_free_lv(vg->cmd, vg, lp->lv_name, lp->lock_args);
+ return NULL;
+ }
+
+ if (lp->lock_args && !(lv->lock_args = dm_pool_strdup(cmd->mem, lp->lock_args))) {
+ log_error("Failed to allocate lock_args");
+ lockd_free_lv(vg->cmd, vg, lp->lv_name, lp->lock_args);
+ return NULL;
+ }
+
dm_list_splice(&lv->tags, &lp->tags);
if (!lv_extend(lv, create_segtype,
@@ -7491,6 +7603,9 @@ deactivate_and_revert_new_lv:
}
revert_new_lv:
+ if (lp->lock_type)
+ lockd_free_lv(vg->cmd, vg, lp->lv_name, lp->lock_args);
+
/* FIXME Better to revert to backup of metadata? */
if (!lv_remove(lv) || !vg_write(vg) || !vg_commit(vg))
log_error("Manual intervention may be required to remove "
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0e52153e6..1fc46662c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -640,9 +640,9 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
* Return a handle to VG metadata.
*/
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
- const char *vgid, uint32_t flags);
+ const char *vgid, uint32_t flags, uint32_t lockd_state);
struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
- const char *vgid, uint32_t flags);
+ const char *vgid, uint32_t flags, uint32_t lockd_state);
/*
* Test validity of a VG handle.
@@ -685,6 +685,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name);
int vg_remove_mdas(struct volume_group *vg);
int vg_remove_check(struct volume_group *vg);
void vg_remove_pvs(struct volume_group *vg);
+int vg_remove_direct(struct volume_group *vg);
int vg_remove(struct volume_group *vg);
int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
const char *new_name);
@@ -738,6 +739,8 @@ int lv_empty(struct logical_volume *lv);
/* Empty an LV and add error segment */
int replace_lv_with_error_segment(struct logical_volume *lv);
+int lv_refresh_suspend_resume(struct cmd_context *cmd, struct logical_volume *lv);
+
/* Entry point for all LV extent allocations */
int lv_extend(struct logical_volume *lv,
const struct segment_type *segtype,
@@ -828,7 +831,8 @@ typedef enum activation_change {
CHANGE_AEY = 2, /* activate exclusively */
CHANGE_ALY = 3, /* activate locally */
CHANGE_ALN = 4, /* deactivate locally */
- CHANGE_AAY = 5 /* automatic activation */
+ CHANGE_AAY = 5, /* automatic activation */
+ CHANGE_ASY = 6 /* activate shared */
} activation_change_t;
/* Returns true, when change activates device */
@@ -866,6 +870,9 @@ struct lvcreate_params {
const char *origin_name; /* snap */
const char *pool_name; /* thin */
+ const char *lock_type;
+ const char *lock_args;
+
/* Keep args given by the user on command line */
/* FIXME: create some more universal solution here */
#define PASS_ARG_CHUNK_SIZE 0x01
@@ -1208,6 +1215,8 @@ struct vgcreate_params {
int clustered; /* FIXME: put this into a 'status' variable instead? */
uint32_t vgmetadatacopies;
const char *system_id;
+ const char *lock_type;
+ const char *lock_args;
};
int validate_major_minor(const struct cmd_context *cmd,
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 19741bac5..4b152dfe6 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -31,6 +31,7 @@
#include "locking.h"
#include "archiver.h"
#include "defaults.h"
+#include "lvmlockd.h"
#include <math.h>
#include <sys/param.h>
@@ -557,20 +558,14 @@ void vg_remove_pvs(struct volume_group *vg)
}
}
-int vg_remove(struct volume_group *vg)
+int vg_remove_direct(struct volume_group *vg)
{
struct physical_volume *pv;
struct pv_list *pvl;
int ret = 1;
- if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
- log_error("Can't get lock for orphan PVs");
- return 0;
- }
-
if (!vg_remove_mdas(vg)) {
log_error("vg_remove_mdas %s failed", vg->name);
- unlock_vg(vg->cmd, VG_ORPHANS);
return 0;
}
@@ -604,6 +599,8 @@ int vg_remove(struct volume_group *vg)
if (!lvmetad_vg_remove(vg))
stack;
+ lockd_vg_update(vg);
+
if (!backup_remove(vg->cmd, vg->name))
stack;
@@ -612,6 +609,20 @@ int vg_remove(struct volume_group *vg)
else
log_error("Volume group \"%s\" not properly removed", vg->name);
+ return ret;
+}
+
+int vg_remove(struct volume_group *vg)
+{
+ int ret;
+
+ if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
+ log_error("Can't get lock for orphan PVs");
+ return 0;
+ }
+
+ ret = vg_remove_direct(vg);
+
unlock_vg(vg->cmd, VG_ORPHANS);
return ret;
}
@@ -2972,6 +2983,8 @@ int vg_commit(struct volume_group *vg)
if ((vg->fid->fmt->features & FMT_PRECOMMIT) && !lvmetad_vg_update(vg))
return_0;
+ lockd_vg_update(vg);
+
cache_updated = _vg_commit_mdas(vg);
if (cache_updated) {
@@ -4496,18 +4509,47 @@ static int _access_vg_clustered(struct cmd_context *cmd, struct volume_group *vg
return 1;
}
-static int _access_vg_lock_type(struct cmd_context *cmd, struct volume_group *vg)
+static int _access_vg_lock_type(struct cmd_context *cmd, struct volume_group *vg,
+ uint32_t lockd_state)
{
if (!is_real_vg(vg->name))
return 1;
+ if (cmd->lockd_vg_disable)
+ return 1;
+
/*
- * Until lock_type support is added, reject any VG that has a lock_type.
+ * Local VG requires no lock from lvmlockd.
*/
- if (vg->lock_type && vg->lock_type[0] && strcmp(vg->lock_type, "none")) {
- log_error("Cannot access VG %s with unsupported lock_type %s.",
- vg->name, vg->lock_type);
- return 0;
+ if (!is_lockd_type(vg->lock_type))
+ return 1;
+
+ /*
+ * When lvmlockd is not running, only allow read access to the VG.
+ */
+ if (!lvmlockd_active()) {
+ if (lockd_state & LDST_EX) {
+ log_error("Cannot access VG %s which requires lvmlockd for lock_type %s.",
+ vg->name, vg->lock_type);
+ return 0;
+ } else {
+ log_warn("Reading VG %s without a lock.", vg->name);
+ return 1;
+ }
+ }
+
+ /*
+ * The lock failed. If the lock was ex, we cannot continue.
+ * If the lock was sh, we can allow reading.
+ */
+ if (lockd_state & LDST_FAIL) {
+ if (lockd_state & LDST_EX) {
+ log_error("Cannot access VG %s due to failed lock.", vg->name);
+ return 0;
+ } else {
+ log_warn("Reading VG %s without a lock.", vg->name);
+ return 1;
+ }
}
return 1;
@@ -4588,7 +4630,8 @@ static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
/*
* FIXME: move _vg_bad_status_bits() checks in here.
*/
-static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg, uint32_t *failure)
+static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg,
+ uint32_t lockd_state, uint32_t *failure)
{
if (!is_real_vg(vg->name)) {
/* Disallow use of LVM1 orphans when a host system ID is set. */
@@ -4604,7 +4647,7 @@ static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg
return 0;
}
- if (!_access_vg_lock_type(cmd, vg)) {
+ if (!_access_vg_lock_type(cmd, vg, lockd_state)) {
*failure |= FAILED_LOCK_TYPE;
return 0;
}
@@ -4630,7 +4673,8 @@ static int _vg_access_permitted(struct cmd_context *cmd, struct volume_group *vg
*/
static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const char *vg_name,
const char *vgid, uint32_t lock_flags,
- uint64_t status_flags, uint32_t misc_flags)
+ uint64_t status_flags, uint32_t misc_flags,
+ uint32_t lockd_state)
{
struct volume_group *vg = NULL;
int consistent = 1;
@@ -4676,7 +4720,7 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
goto bad;
}
- if (!_vg_access_permitted(cmd, vg, &failure))
+ if (!_vg_access_permitted(cmd, vg, lockd_state, &failure))
goto bad;
/* consistent == 0 when VG is not found, but failed == FAILED_NOTFOUND */
@@ -4752,7 +4796,7 @@ bad_no_unlock:
* *consistent = 1.
*/
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
- const char *vgid, uint32_t flags)
+ const char *vgid, uint32_t flags, uint32_t lockd_state)
{
uint64_t status = UINT64_C(0);
uint32_t lock_flags = LCK_VG_READ;
@@ -4765,7 +4809,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
if (flags & READ_ALLOW_EXPORTED)
status &= ~EXPORTED_VG;
- return _vg_lock_and_read(cmd, vg_name, vgid, lock_flags, status, flags);
+ return _vg_lock_and_read(cmd, vg_name, vgid, lock_flags, status, flags, lockd_state);
}
/*
@@ -4774,9 +4818,9 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
* request the new metadata to be written and committed).
*/
struct volume_group *vg_read_for_update(struct cmd_context *cmd, const char *vg_name,
- const char *vgid, uint32_t flags)
+ const char *vgid, uint32_t flags, uint32_t lockd_state)
{
- return vg_read(cmd, vg_name, vgid, flags | READ_FOR_UPDATE);
+ return vg_read(cmd, vg_name, vgid, flags | READ_FOR_UPDATE, lockd_state);
}
/*
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 64cfb3f13..f88381b4e 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -21,6 +21,7 @@
#include "activate.h"
#include "lv_alloc.h"
#include "lvm-string.h"
+#include "lvmlockd.h"
static int _lv_is_raid_with_tracking(const struct logical_volume *lv,
struct logical_volume **tracking)
@@ -1082,6 +1083,12 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
dm_list_init(&removal_list);
dm_list_init(&data_list);
+ if (is_lockd_type(lv->vg->lock_type)) {
+ log_error("Splitting raid image is not allowed with lock_type %s",
+ lv->vg->lock_type);
+ return 0;
+ }
+
if ((old_count - new_count) != 1) {
log_error("Unable to split more than one image from %s/%s",
lv->vg->name, lv->name);
diff --git a/lib/metadata/replicator_manip.c b/lib/metadata/replicator_manip.c
index 54dc75929..fc4bf5fa1 100644
--- a/lib/metadata/replicator_manip.c
+++ b/lib/metadata/replicator_manip.c
@@ -566,7 +566,7 @@ int cmd_vg_read(struct cmd_context *cmd, struct dm_list *cmd_vgs)
/* Iterate through alphabeticaly ordered cmd_vg list */
dm_list_iterate_items(cvl, cmd_vgs) {
- cvl->vg = vg_read(cmd, cvl->vg_name, cvl->vgid, cvl->flags);
+ cvl->vg = vg_read(cmd, cvl->vg_name, cvl->vgid, cvl->flags, 0);
if (vg_read_error(cvl->vg)) {
log_debug_metadata("Failed to vg_read %s", cvl->vg_name);
return 0;
@@ -644,7 +644,7 @@ int lv_read_replicator_vgs(const struct logical_volume *lv)
dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
if (!rsite->vg_name)
continue;
- vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
+ vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0, 0); // READ_WITHOUT_LOCK
if (vg_read_error(vg)) {
log_error("Unable to read volume group %s",
rsite->vg_name);
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index c9a7e9e1b..9d3cc8f85 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -20,6 +20,7 @@
#include "toolcontext.h"
#include "lvmcache.h"
#include "archiver.h"
+#include "lvmlockd.h"
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
const char *vg_name)
@@ -636,6 +637,19 @@ int vg_set_system_id(struct volume_group *vg, const char *system_id)
return 1;
}
+int vg_set_lock_type(struct volume_group *vg, const char *lock_type)
+{
+ if (!lock_type)
+ lock_type = "none";
+
+ if (!(vg->lock_type = dm_pool_strdup(vg->vgmem, lock_type))) {
+ log_error("vg_set_lock_type %s no mem", lock_type);
+ return 0;
+ }
+
+ return 1;
+}
+
char *vg_attr_dup(struct dm_pool *mem, const struct volume_group *vg)
{
char *repstr;
@@ -705,7 +719,7 @@ int vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
vg->extent_count -= pv_pe_count(pv);
orphan_vg = vg_read_for_update(cmd, vg->fid->fmt->orphan_vg_name,
- NULL, 0);
+ NULL, 0, 0);
if (vg_read_error(orphan_vg))
goto bad;
diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c
index 64557882a..4fa07792e 100644
--- a/lib/misc/lvm-globals.c
+++ b/lib/misc/lvm-globals.c
@@ -193,6 +193,11 @@ void set_cmd_name(const char *cmd)
_cmd_name[sizeof(_cmd_name) - 1] = '\0';
}
+const char *get_cmd_name(void)
+{
+ return _cmd_name;
+}
+
void set_sysfs_dir_path(const char *path)
{
strncpy(_sysfs_dir_path, path, sizeof(_sysfs_dir_path) - 1);
diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h
index b25f4aed0..8628a890a 100644
--- a/lib/misc/lvm-globals.h
+++ b/lib/misc/lvm-globals.h
@@ -51,6 +51,7 @@ void init_detect_internal_vg_cache_corruption(int detect);
void init_retry_deactivation(int retry);
void set_cmd_name(const char *cmd_name);
+const char *get_cmd_name(void);
void set_sysfs_dir_path(const char *path);
int test_mode(void);