From 959a8703937f01161988221940d189acc4f7a796 Mon Sep 17 00:00:00 2001
From: Federico Simoncelli <fsimonce@redhat.com>
Date: Sun, 13 Jan 2013 16:21:55 +0200
Subject: [PATCH 17/22] udev: Race fix- load and trigger dev rule
The rule file is generated, yet not synch-loaded in memory, so a VM with
a direct lun fails to start.
This patch reloads the rules before triggering using the new private
udev functions - udevReloadRules() in supervdsmServer.py .
Also added a check in appropriateDevice() (hsm.py) to make sure the
mapping is indeed there.
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=891300
Change-Id: If3b2008a3d9df2dcaf54190721c2dd9764338627
Signed-off-by: Lee Yarwood <lyarwood@redhat.com>
Signed-off-by: Vered Volansky <vvolansk@redhat.com>
Signed-off-by: Federico Simoncelli <fsimonce@redhat.com>
Reviewed-on: http://gerrit.ovirt.org/11410
Reviewed-by: Allon Mureinik <amureini@redhat.com>
---
vdsm/storage/hsm.py | 7 +++++++
vdsm/supervdsmServer.py | 31 +++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index efb2749..62e9f74 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -67,6 +67,7 @@ import mount
import dispatcher
import supervdsm
import storageServer
+from vdsm import utils
GUID = "guid"
NAME = "name"
@@ -87,6 +88,8 @@ SECTOR_SIZE = 512
STORAGE_CONNECTION_DIR = os.path.join(constants.P_VDSM_RUN, "connections/")
+QEMU_READABLE_TIMEOUT = 30
+
def public(f=None, **kwargs):
if f is None:
@@ -2925,6 +2928,10 @@ class HSM:
"""
supervdsm.getProxy().appropriateDevice(guid, thiefId)
supervdsm.getProxy().udevTrigger(guid)
+ devPath = devicemapper.DMPATH_FORMAT % guid
+ utils.retry(partial(fileUtils.validateQemuReadable, devPath),
+ expectedException=OSError,
+ timeout=QEMU_READABLE_TIMEOUT)
@public
def inappropriateDevices(self, thiefId):
diff --git a/vdsm/supervdsmServer.py b/vdsm/supervdsmServer.py
index dc89218..833e91f 100755
--- a/vdsm/supervdsmServer.py
+++ b/vdsm/supervdsmServer.py
@@ -89,6 +89,10 @@ LOG_CONF_PATH = "/etc/vdsm/logger.conf"
class _SuperVdsm(object):
+ UDEV_WITH_RELOAD_VERSION = 181
+
+ log = logging.getLogger("SuperVdsm.ServerCallback")
+
@logDecorator
def ping(self, *args, **kwargs):
# This method exists for testing purposes
@@ -226,6 +230,7 @@ class _SuperVdsm(object):
@logDecorator
def udevTrigger(self, guid):
+ self.__udevReloadRules(guid)
cmd = [EXT_UDEVADM, 'trigger', '--verbose', '--action', 'change',
'--property-match=DM_NAME=%s' % guid]
rc, out, err = misc.execCmd(cmd, sudo=False)
@@ -304,6 +309,32 @@ class _SuperVdsm(object):
def removeFs(self, path):
return mkimage.removeFs(path)
+ def __udevReloadRules(self, guid):
+ if self.__udevOperationReload():
+ reload = "--reload"
+ else:
+ reload = "--reload-rules"
+ cmd = [EXT_UDEVADM, 'control', reload]
+ rc, out, err = misc.execCmd(cmd, sudo=False)
+ if rc:
+ self.log.error("Udevadm reload-rules command failed rc=%s, "
+ "out=\"%s\", err=\"%s\"", rc, out, err)
+ raise OSError(errno.EINVAL, "Could not reload-rules for device "
+ "%s" % guid)
+
+ @utils.memoized
+ def __udevVersion(self):
+ cmd = [EXT_UDEVADM, '--version']
+ rc, out, err = misc.execCmd(cmd, sudo=False)
+ if rc:
+ self.log.error("Udevadm version command failed rc=%s, "
+ " out=\"%s\", err=\"%s\"", rc, out, err)
+ raise RuntimeError("Could not get udev version number")
+ return int(out[0])
+
+ def __udevOperationReload(self):
+ return self.__udevVersion() > self.UDEV_WITH_RELOAD_VERSION
+
def __pokeParent(parentPid, address, log):
try:
--
1.8.1