commit 31672ff60e405795cad70d6d7888ac011f5373ce Author: Christine Caulfield Date: Thu Oct 1 14:14:17 2009 +0000 Stop clvmd from automatically doing lock conversions. Now, if a lock is granted at one mode and an attempt to convert it wthout the LCK_CONVERT flag set then it will return errno=EBUSY. This fixes a pretty bad bug in which an LV could be activated exclusively on one node and lvchange -ay on another would convert it to shared! It might break some things in other areas, but I doubt it. Index: LVM2.2.02.39/daemons/clvmd/lvm-functions.c =================================================================== --- LVM2.2.02.39.orig/daemons/clvmd/lvm-functions.c 2010-01-15 18:45:15.000000000 +0800 +++ LVM2.2.02.39/daemons/clvmd/lvm-functions.c 2010-01-15 18:53:21.000000000 +0800 @@ -141,10 +141,11 @@ { static char buf[128]; - sprintf(buf, "0x%x (%s%s%s)", flags, + sprintf(buf, "0x%x (%s%s%s%s)", flags, flags & LCK_PARTIAL_MODE ? "PARTIAL " : "", flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC " : "", - flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : ""); + flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : "", + flags & LCK_CONVERT ? "CONVERT " : ""); return buf; } @@ -190,16 +191,26 @@ int saved_errno; struct lv_info *lvi; - flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */ + /* Mask off invalid options */ + flags &= LKF_NOQUEUE | LKF_CONVERT; pthread_mutex_lock(&lv_hash_lock); lvi = dm_hash_lookup(lv_hash, resource); pthread_mutex_unlock(&lv_hash_lock); + + if (lvi && lvi->lock_mode == mode) { + DEBUGLOG("hold_lock, lock mode %d already held\n", mode); + return 0; + } + + if (lvi && !(flags & LKF_CONVERT)) { + errno = EBUSY; + return -1; + } if (lvi) { /* Already exists - convert it */ status = - sync_lock(resource, mode, LKF_CONVERT | flags, - &lvi->lock_id); + sync_lock(resource, mode, flags, &lvi->lock_id); saved_errno = errno; if (!status) lvi->lock_mode = mode; @@ -215,7 +226,7 @@ return -1; lvi->lock_mode = mode; - status = sync_lock(resource, mode, flags, &lvi->lock_id); + status = sync_lock(resource, mode, flags & ~LKF_CONVERT, &lvi->lock_id); saved_errno = errno; if (status) { free(lvi); @@ -296,9 +307,13 @@ mode = LKM_EXMODE; } - /* Try to get the lock if it's a clustered volume group */ + /* Try to get the lock if it's a clustered volume group + * Use lock conversion only if requested, to prevent implicit conversion + * of exclusive lock to shared one during activation. + */ + if (lock_flags & LCK_CLUSTER_VG) { - status = hold_lock(resource, mode, LKF_NOQUEUE); + status = hold_lock(resource, mode, LKF_NOQUEUE | (lock_flags & LCK_CONVERT?LKF_CONVERT:0)); if (status) { /* Return an LVM-sensible error for this. * Forcing EIO makes the upper level return this text @@ -477,12 +492,13 @@ /* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the lock out on this node (because we are the node modifying the metadata) before suspending cluster-wide. + LKF_CONVERT is used always, local node is going to modify metadata */ if (command == LCK_LV_SUSPEND) { DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n", resource, decode_locking_cmd(command), decode_flags(lock_flags)); - if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE)) + if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE | LKF_CONVERT)) return errno; } return 0; @@ -514,7 +530,7 @@ return EIO; if (lvi.exists) { - if (hold_lock(resource, LKM_CRMODE, 0)) + if (hold_lock(resource, LKM_CRMODE, LKF_CONVERT)) return errno; } else { if (hold_unlock(resource)) Index: LVM2.2.02.39/lib/locking/locking.h =================================================================== --- LVM2.2.02.39.orig/lib/locking/locking.h 2008-05-10 03:26:58.000000000 +0800 +++ LVM2.2.02.39/lib/locking/locking.h 2010-01-15 18:45:15.000000000 +0800 @@ -86,6 +86,7 @@ #define LCK_PARTIAL_MODE 0x00000001U /* Running in partial mode */ #define LCK_MIRROR_NOSYNC_MODE 0x00000002U /* Mirrors don't require sync */ #define LCK_DMEVENTD_MONITOR_MODE 0x00000004U /* Register with dmeventd */ +#define LCK_CONVERT 0x00000008U /* Convert existing lock */ /* * Special cases of VG locks.