return ret;
}
+int lvmcache_vg_is_lockd_type(struct cmd_context *cmd, const char *vgname, const char *vgid)
+{
+ struct lvmcache_vginfo *vginfo;
+
+ if ((vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
+ return is_lockd_type(vginfo->lock_type);
+
+ return 0;
+}
+
/*
* Example of reading four devs in sequence from the same VG:
*
int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid);
+int lvmcache_vg_is_lockd_type(struct cmd_context *cmd, const char *vgname, const char *vgid);
+
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_arg);
* this result is passed into vg_read(). After vg_read() reads the VG,
* it checks if the VG lock_type (sanlock or dlm) requires a lock to be
* held, and if so, it verifies that the lock was correctly acquired by
- * looking at lockd_state. If vg_read() sees that the VG is a local VG,
- * i.e. lock_type is not sanlock or dlm, then no lock is required, and it
- * ignores lockd_state (which would indicate no lock was found.)
+ * looking at lockd_state.
+ *
+ * If vg_read() sees that the VG is a local VG, i.e. lock_type is not
+ * sanlock or dlm, then no lock is required, and it ignores lockd_state,
+ * which would indicate no lock was found.... although a newer
+ * optimization avoids calling lockd_vg() at all for local VGs
+ * by checking the lock_type in lvmcache saved by label_scan. In extremely
+ * rare case where the lock_type changes between label_scan and vg_read,
+ * the caller will go back and repeat lockd_vg()+vg_read().
*/
int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
struct logical_volume *lv_fast;
uint32_t lockd_state, error_flags;
uint64_t dirty;
+ int is_lockd;
int ret = 0;
idl = dm_list_item(dm_list_first(&lr->poll_idls), struct convert_poll_id_list);
id = idl->id;
+ is_lockd = lvmcache_vg_is_lockd_type(cmd, id->vg_name, NULL);
/*
* TODO: we should be able to save info about the dm device for this LV
lockd_state = 0;
error_flags = 0;
- if (!lockd_vg(cmd, id->vg_name, "ex", 0, &lockd_state)) {
+ if (is_lockd && !lockd_vg(cmd, id->vg_name, "ex", 0, &lockd_state)) {
log_error("Detaching writecache interrupted - locking VG failed.");
return 0;
}
if (!lv_writecache_is_clean(cmd, lv, &dirty)) {
unlock_and_release_vg(cmd, vg, vg->name);
- if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
stack;
log_print_unless_silent("Detaching writecache cleaning %llu blocks", (unsigned long long)dirty);
unlock_and_release_vg(cmd, vg, vg->name);
out_lockd:
- if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
stack;
return ret;
int finished = 0;
uint32_t lockd_state = 0;
uint32_t error_flags = 0;
+ int is_lockd;
int ret;
unsigned wait_before_testing = parms->wait_before_testing;
return 0;
}
+ is_lockd = lvmcache_vg_is_lockd_type(cmd, id->vg_name, NULL);
+
/*
* An ex VG lock is needed because the check can call finish_copy
* which writes the VG.
*/
- if (!lockd_vg(cmd, id->vg_name, "ex", 0, &lockd_state)) {
+ if (is_lockd && !lockd_vg(cmd, id->vg_name, "ex", 0, &lockd_state)) {
log_error("ABORTING: Can't lock VG for %s.", id->display_name);
return 0;
}
unlock_and_release_vg(cmd, vg, vg->name);
- if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
stack;
wait_before_testing = 1;
out:
if (vg)
unlock_and_release_vg(cmd, vg, vg->name);
- if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
stack;
return ret;
int ret;
int skip;
int notfound;
+ int is_lockd;
int process_all = 0;
int do_report_ret_code = 1;
vg_uuid = vgnl->vgid;
skip = 0;
notfound = 0;
+ is_lockd = lvmcache_vg_is_lockd_type(cmd, vg_name, vg_uuid);
uuid[0] = '\0';
if (is_orphan_vg(vg_name)) {
}
log_very_verbose("Processing VG %s %s", vg_name, uuid);
-
- if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
+do_lockd:
+ if (is_lockd && !lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
stack;
ret_max = ECMD_FAILED;
report_log_ret_code(ret_max);
if (skip || notfound)
goto endvg;
+ if (!is_lockd && vg_is_shared(vg)) {
+ /* The lock_type changed since label_scan, won't really occur in practice. */
+ log_debug("Repeat lock and read for local to shared vg");
+ unlock_and_release_vg(cmd, vg, vg_name);
+ is_lockd = 1;
+ goto do_lockd;
+ }
+
/* Process this VG? */
if ((process_all ||
(!dm_list_empty(arg_vgnames) && str_list_match_item(arg_vgnames, vg_name)) ||
unlock_vg(cmd, vg, vg_name);
endvg:
release_vg(vg);
- if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
log_set_report_object_name_and_id(NULL, NULL);
int ret;
int skip;
int notfound;
+ int is_lockd;
int do_report_ret_code = 1;
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_VG);
vg_uuid = vgnl->vgid;
skip = 0;
notfound = 0;
+ is_lockd = lvmcache_vg_is_lockd_type(cmd, vg_name, vg_uuid);
uuid[0] = '\0';
if (vg_uuid && !id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid)))
log_very_verbose("Processing VG %s %s", vg_name, vg_uuid ? uuid : "");
- if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
+do_lockd:
+ if (is_lockd && !lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
ret_max = ECMD_FAILED;
report_log_ret_code(ret_max);
continue;
if (skip || notfound)
goto endvg;
+ if (!is_lockd && vg_is_shared(vg)) {
+ /* The lock_type changed since label_scan, won't really occur in practice. */
+ log_debug("Repeat lock and read for local to shared vg");
+ unlock_and_release_vg(cmd, vg, vg_name);
+ is_lockd = 1;
+ goto do_lockd;
+ }
+
ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg, 0,
handle, check_single_lv, process_single_lv);
if (ret != ECMD_PROCESSED)
unlock_vg(cmd, vg, vg_name);
endvg:
release_vg(vg);
- if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
log_set_report_object_name_and_id(NULL, NULL);
}
int ret;
int skip;
int notfound;
+ int is_lockd;
int do_report_ret_code = 1;
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_VG);
vg_uuid = vgnl->vgid;
skip = 0;
notfound = 0;
+ is_lockd = lvmcache_vg_is_lockd_type(cmd, vg_name, vg_uuid);
uuid[0] = '\0';
if (is_orphan_vg(vg_name)) {
ret_max = ECMD_FAILED;
goto_out;
}
-
- if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
+do_lockd:
+ if (is_lockd && !lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
ret_max = ECMD_FAILED;
report_log_ret_code(ret_max);
continue;
if (notfound)
goto endvg;
+ if (vg && !is_lockd && vg_is_shared(vg)) {
+ /* The lock_type changed since label_scan, won't really occur in practice. */
+ log_debug("Repeat lock and read for local to shared vg");
+ unlock_and_release_vg(cmd, vg, vg_name);
+ is_lockd = 1;
+ goto do_lockd;
+ }
+
/*
* Don't call "continue" when skip is set, because we need to remove
* error_vg->pvs entries from devices list.
if (error_vg)
unlock_and_release_vg(cmd, error_vg, vg_name);
release_vg(vg);
- if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
+ if (is_lockd && !lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
/* Quit early when possible. */