[dm-devel] [PATCH] multipath-tools: prevent unexpected swapping of underlying LUNs
Jun'ichi Nomura
j-nomura at ce.jp.nec.com
Fri Aug 17 08:40:39 UTC 2012
When you want to rename a multipath device
but the new alias is already used by other multipath device,
multipath-tools mistakenly reload a table for the original multipath device
to the other multipath device.
That could lead to very bad result, such as I/O error and data corruption.
This patch checks such a condition and gives up renaming with error log.
For example, suppose you have following 'bindings' file:
# cat /etc/multipath/bindings
mpatha 212140084abcd0000
mpathb 212150084abcd0000
and a logical volume 'VG/LV0' on top of mpathb,
which is on top of /dev/sde(8:64) and /dev/sdk(8:160):
# dmsetup ls --tree
mpatha (253:1)
├─ (8:144)
└─ (8:48)
VG-LV0 (253:2)
└─mpathb (253:0)
├─ (8:160)
└─ (8:64)
Then you decide to swap their names and change the 'bindings' as follows:
# cat /etc/multipath/bindings
mpathb 212140084abcd0000
mpatha 212150084abcd0000
you'll get this after 'service multipathd reload':
# dmsetup ls --tree
mpatha (253:1)
├─ (8:160)
└─ (8:64)
VG-LV0 (253:2)
└─mpathb (253:0)
├─ (8:144)
└─ (8:48)
Now you suddenly have 'VG/LV0' on top of /dev/sdd(8:48) and /dev/sdj(8:144),
that is obviously wrong and will corrupt data if you write to 'VG/LV0'.
diff -urpN multipath-tools.orig/libmultipath/configure.c multipath-tools.new/libmultipath/configure.c
--- multipath-tools.orig/libmultipath/configure.c 2012-07-19 15:17:40.368622358 +0900
+++ multipath-tools.new/libmultipath/configure.c 2012-08-17 17:11:07.691898774 +0900
@@ -150,12 +150,12 @@ static void
select_action (struct multipath * mpp, vector curmp, int force_reload)
{
struct multipath * cmpp;
+ struct multipath * cmpp_by_name;
- cmpp = find_mp_by_alias(curmp, mpp->alias);
-
- if (!cmpp) {
- cmpp = find_mp_by_wwid(curmp, mpp->wwid);
+ cmpp = find_mp_by_wwid(curmp, mpp->wwid);
+ cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
+ if (!cmpp_by_name) {
if (cmpp) {
condlog(2, "%s: rename %s to %s", mpp->wwid,
cmpp->alias, mpp->alias);
@@ -169,17 +169,25 @@ select_action (struct multipath * mpp, v
return;
}
- if (!find_mp_by_wwid(curmp, mpp->wwid)) {
- condlog(2, "%s: remove (wwid changed)", cmpp->alias);
+ if (!cmpp) {
+ condlog(2, "%s: remove (wwid changed)", mpp->alias);
dm_flush_map(mpp->alias);
- strncpy(cmpp->wwid, mpp->wwid, WWID_SIZE);
- drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
+ strncpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE);
+ drop_multipath(curmp, cmpp_by_name->wwid, KEEP_PATHS);
mpp->action = ACT_CREATE;
condlog(3, "%s: set ACT_CREATE (map wwid change)",
mpp->alias);
return;
}
+ if (cmpp != cmpp_by_name) {
+ condlog(2, "%s: unable to rename %s to %s (%s is used by %s)",
+ mpp->wwid, cmpp->alias, mpp->alias,
+ mpp->alias, cmpp_by_name->wwid);
+ mpp->action = ACT_NOTHING;
+ return;
+ }
+
if (pathcount(mpp, PATH_UP) == 0) {
mpp->action = ACT_NOTHING;
condlog(3, "%s: set ACT_NOTHING (no usable path)",
More information about the dm-devel
mailing list