summaryrefslogtreecommitdiffstats
path: root/daemons/clvmd/lvm-functions.c
diff options
context:
space:
mode:
authorChristine Caulfield <ccaulfie@redhat.com>2010-04-20 14:07:37 +0000
committerChristine Caulfield <ccaulfie@redhat.com>2010-04-20 14:07:37 +0000
commitc407d2bd11c6a8e364cfd6a5190bea7d7456db93 (patch)
tree0c913357163f6df3e9aff1f161f2c71848c49cc6 /daemons/clvmd/lvm-functions.c
parent49ada7a2c3f664aa2c3e17e2adf4abaf2a04d17d (diff)
downloadlvm2-c407d2bd11c6a8e364cfd6a5190bea7d7456db93.tar.gz
lvm2-c407d2bd11c6a8e364cfd6a5190bea7d7456db93.tar.xz
lvm2-c407d2bd11c6a8e364cfd6a5190bea7d7456db93.zip
Add -S command to clvmd, so it can restart itself and still
preserve exlusive LV locks.
Diffstat (limited to 'daemons/clvmd/lvm-functions.c')
-rw-r--r--daemons/clvmd/lvm-functions.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c
index aaafae08..bb77e971 100644
--- a/daemons/clvmd/lvm-functions.c
+++ b/daemons/clvmd/lvm-functions.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -103,7 +103,7 @@ static const char *decode_locking_cmd(unsigned char cmdl)
command = "LCK_VG";
break;
case LCK_LV:
- scope = "LV";
+ scope = "LV";
switch (cmdl & LCK_MASK) {
case LCK_LV_EXCLUSIVE & LCK_MASK:
command = "LCK_LV_EXCLUSIVE";
@@ -727,12 +727,36 @@ void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
}
/*
+ * Compare the uuid with the list of exclusive locks that clvmd
+ * held before it was restarted, so we can get the right kind
+ * of lock now we are restarting.
+ */
+static int was_ex_lock(char *uuid, char **argv)
+{
+ int optnum = 0;
+ char *opt = argv[optnum];
+
+ while (opt) {
+ if (strcmp(opt, "-E") == 0) {
+ opt = argv[++optnum];
+ if (opt && (strcmp(opt, uuid) == 0)) {
+ DEBUGLOG("Lock %s is exclusive\n", uuid);
+ return 1;
+ }
+ }
+ opt = argv[++optnum];
+ }
+ return 0;
+}
+
+/*
* Ideally, clvmd should be started before any LVs are active
* but this may not be the case...
* I suppose this also comes in handy if clvmd crashes, not that it would!
*/
-static void *get_initial_state()
+static void *get_initial_state(char **argv)
{
+ int lock_mode;
char lv[64], vg[64], flags[25], vg_flags[25];
char uuid[65];
char line[255];
@@ -768,8 +792,15 @@ static void *get_initial_state()
memcpy(&uuid[58], &lv[32], 6);
uuid[64] = '\0';
+ lock_mode = LKM_CRMODE;
+
+ /* Look for this lock in the list of EX locks
+ we were passed on the command-line */
+ if (was_ex_lock(uuid, argv))
+ lock_mode = LKM_EXMODE;
+
DEBUGLOG("getting initial lock for %s\n", uuid);
- hold_lock(uuid, LKM_CRMODE, LKF_NOQUEUE);
+ hold_lock(uuid, lock_mode, LKF_NOQUEUE);
}
}
}
@@ -848,8 +879,31 @@ void lvm_do_backup(const char *vgname)
pthread_mutex_unlock(&lvm_lock);
}
+struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
+{
+ struct lv_info *lvi;
+
+ *name = NULL;
+ if (!v)
+ v = dm_hash_get_first(lv_hash);
+
+ do {
+ if (v) {
+ lvi = dm_hash_get_data(lv_hash, v);
+ DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
+
+ if (lvi->lock_mode == LCK_EXCL) {
+ *name = dm_hash_get_key(lv_hash, v);
+ }
+ v = dm_hash_get_next(lv_hash, v);
+ }
+ } while (v && !*name);
+ DEBUGLOG("returning EXclusive UUID %s\n", *name);
+ return v;
+}
+
/* Called to initialise the LVM context of the daemon */
-int init_lvm(int using_gulm)
+int init_lvm(int using_gulm, char **argv)
{
if (!(cmd = create_toolcontext(1, NULL))) {
log_error("Failed to allocate command context");
@@ -874,7 +928,7 @@ int init_lvm(int using_gulm)
if (using_gulm)
drop_vg_locks();
- get_initial_state();
+ get_initial_state(argv);
/* Trap log messages so we can pass them back to the user */
init_log_fn(lvm2_log_fn);