diff options
author | David Teigland <teigland@redhat.com> | 2015-05-13 14:07:32 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2015-05-28 16:34:36 -0500 |
commit | 8ab724a00f5091ca09d473f56a3bc8037da99b53 (patch) | |
tree | 6736cc95924d89d11cc085fa3ebf676af24a39be | |
parent | 56cf94ad125f06787043a6f726d6381100994ded (diff) | |
download | lvm2-8ab724a00f5091ca09d473f56a3bc8037da99b53.tar.gz |
lib: use locks from lvmlockd
-rw-r--r-- | lib/commands/toolcontext.c | 31 | ||||
-rw-r--r-- | lib/commands/toolcontext.h | 8 | ||||
-rw-r--r-- | lib/config/config_settings.h | 23 | ||||
-rw-r--r-- | lib/config/defaults.h | 2 | ||||
-rw-r--r-- | lib/metadata/lv.c | 22 | ||||
-rw-r--r-- | lib/metadata/lv_manip.c | 121 | ||||
-rw-r--r-- | lib/metadata/metadata-exported.h | 15 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 86 | ||||
-rw-r--r-- | lib/metadata/raid_manip.c | 7 | ||||
-rw-r--r-- | lib/metadata/replicator_manip.c | 4 | ||||
-rw-r--r-- | lib/metadata/vg.c | 16 | ||||
-rw-r--r-- | lib/misc/lvm-globals.c | 5 | ||||
-rw-r--r-- | lib/misc/lvm-globals.h | 1 |
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); |