/* * VG locking is by VG name. * FIXME This should become VG uuid. */ static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t flags, lv_operation_t lv_op, struct logical_volume *lv) { uint32_t lck_type = flags & LCK_TYPE_MASK; uint32_t lck_scope = flags & LCK_SCOPE_MASK; int ret = 0; _block_signals(flags); _lock_memory(cmd, lv_op); assert(resource); if (!*resource) { log_error(INTERNAL_ERROR "Use of P_orphans is deprecated."); return 0; } if ((is_orphan_vg(resource) || is_global_vg(resource)) && (flags & LCK_CACHE)) { log_error(INTERNAL_ERROR "P_%s referenced", resource); return 0; } if (cmd->metadata_read_only && lck_type == LCK_WRITE && strcmp(resource, VG_GLOBAL)) { log_error("Operation prohibited while global/metadata_read_only is set."); return 0; } if ((ret = _locking.lock_resource(cmd, resource, flags, lv))) { if (lck_scope == LCK_VG && !(flags & LCK_CACHE)) { if (lck_type != LCK_UNLOCK) lvmcache_lock_vgname(resource, lck_type == LCK_READ); dev_reset_error_count(cmd); } _update_vg_lock_count(resource, flags); } else stack; /* If unlocking, always remove lock from lvmcache even if operation failed. */ if (lck_scope == LCK_VG && !(flags & LCK_CACHE) && lck_type == LCK_UNLOCK) { lvmcache_unlock_vgname(resource); if (!ret) _update_vg_lock_count(resource, flags); } _unlock_memory(cmd, lv_op); _unblock_signals(); return ret; }
int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags) #endif { char lockname[PATH_MAX]; int clvmd_cmd = 0; const char *lock_scope; const char *lock_type = ""; assert(strlen(resource) < sizeof(lockname)); assert(resource); switch (flags & LCK_SCOPE_MASK) { case LCK_VG: if (flags == LCK_VG_BACKUP) { log_very_verbose("Requesting backup of VG metadata for %s", resource); return _lock_for_cluster(cmd, CLVMD_CMD_VG_BACKUP, LCK_CLUSTER_VG, resource); } /* If the VG name is empty then lock the unused PVs */ if (is_orphan_vg(resource) || is_global_vg(resource) || (flags & LCK_CACHE)) dm_snprintf(lockname, sizeof(lockname), "P_%s", resource); else dm_snprintf(lockname, sizeof(lockname), "V_%s", resource); lock_scope = "VG"; clvmd_cmd = CLVMD_CMD_LOCK_VG; /* * Old clvmd does not expect LCK_HOLD which was already processed * in lock_vol, mask it for compatibility reasons. */ if (flags != LCK_VG_COMMIT && flags != LCK_VG_REVERT) flags &= ~LCK_HOLD; break; case LCK_LV: clvmd_cmd = CLVMD_CMD_LOCK_LV; strcpy(lockname, resource); lock_scope = "LV"; flags &= ~LCK_HOLD; /* Mask off HOLD flag */ break; default: log_error("Unrecognised lock scope: %d", flags & LCK_SCOPE_MASK); return 0; } switch(flags & LCK_TYPE_MASK) { case LCK_UNLOCK: lock_type = "UN"; break; case LCK_NULL: lock_type = "NL"; break; case LCK_READ: lock_type = "CR"; break; case LCK_PREAD: lock_type = "PR"; break; case LCK_WRITE: lock_type = "PW"; break; case LCK_EXCL: lock_type = "EX"; break; default: log_error("Unrecognised lock type: %u", flags & LCK_TYPE_MASK); return 0; } log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s) (0x%x)", lock_scope, lockname, lock_type, lock_scope, flags & LCK_NONBLOCK ? "|NONBLOCK" : "", flags & LCK_HOLD ? "|HOLD" : "", flags & LCK_LOCAL ? "|LOCAL" : "", flags & LCK_CLUSTER_VG ? "|CLUSTER" : "", flags & LCK_CACHE ? "|CACHE" : "", flags); /* Send a message to the cluster manager */ return _lock_for_cluster(cmd, clvmd_cmd, flags, lockname); }
static int _file_lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags, struct logical_volume *lv) { char lockfile[PATH_MAX]; unsigned origin_only = (flags & LCK_ORIGIN_ONLY) ? 1 : 0; unsigned revert = (flags & LCK_REVERT) ? 1 : 0; switch (flags & LCK_SCOPE_MASK) { case LCK_ACTIVATION: if (dm_snprintf(lockfile, sizeof(lockfile), "%s/A_%s", _lock_dir, resource + 1) < 0) { log_error("Too long locking filename %s/A_%s.", _lock_dir, resource + 1); return 0; } if (!lock_file(lockfile, flags)) return_0; break; case LCK_VG: /* Skip cache refresh for VG_GLOBAL - the caller handles it */ if (strcmp(resource, VG_GLOBAL)) lvmcache_drop_metadata(resource, 0); if (!strcmp(resource, VG_SYNC_NAMES)) fs_unlock(); /* LCK_CACHE does not require a real lock */ if (flags & LCK_CACHE) break; if (is_orphan_vg(resource) || is_global_vg(resource)) { if (dm_snprintf(lockfile, sizeof(lockfile), "%s/P_%s", _lock_dir, resource + 1) < 0) { log_error("Too long locking filename %s/P_%s.", _lock_dir, resource + 1); return 0; } } else if (dm_snprintf(lockfile, sizeof(lockfile), "%s/V_%s", _lock_dir, resource) < 0) { log_error("Too long locking filename %s/V_%s.", _lock_dir, resource); return 0; } if (!lock_file(lockfile, flags)) return_0; break; case LCK_LV: switch (flags & LCK_TYPE_MASK) { case LCK_UNLOCK: log_very_verbose("Unlocking LV %s%s%s", resource, origin_only ? " without snapshots" : "", revert ? " (reverting)" : ""); if (!lv_resume_if_active(cmd, resource, origin_only, 0, revert, lv_ondisk(lv))) return 0; break; case LCK_NULL: log_very_verbose("Locking LV %s (NL)", resource); if (!lv_deactivate(cmd, resource, lv_ondisk(lv))) return 0; break; case LCK_READ: log_very_verbose("Locking LV %s (R)", resource); if (!lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv))) return 0; break; case LCK_PREAD: log_very_verbose("Locking LV %s (PR) - ignored", resource); break; case LCK_WRITE: log_very_verbose("Locking LV %s (W)%s", resource, origin_only ? " without snapshots" : ""); if (!lv_suspend_if_active(cmd, resource, origin_only, 0, lv_ondisk(lv), lv)) return 0; break; case LCK_EXCL: log_very_verbose("Locking LV %s (EX)", resource); if (!lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv))) return 0; break; default: break; } break; default: log_error("Unrecognised lock scope: %d", flags & LCK_SCOPE_MASK); return 0; } return 1; }