Change how event channels are allocated and used by the control

tools. /dev/xen/evtchn is now used by daemons to connect to
remote domains: the advantage is that the local ports are garbage
collected automatically if the daemon dies. xen no longer
constructs end-to-end event-channel port pairs -- it allocates an
unbound port in new domU and writes that port to xenstore. It is
then picked up by teh appropriate daemon which does interdomain bind
via /dev/xen/evtchn.

Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-10-06 16:07:52 +01:00
1 parent 0c6f366280
commit c804adf4b6
15 files changed
+330 -285

No files matched your search

+3 -3
View File
@@ -435,10 +435,10 @@ static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
u32 dom = DOMID_SELF, remote_dom;
int port = 0;
static char *kwd_list[] = { "remote_dom", "dom", "port", NULL };
static char *kwd_list[] = { "remote_dom", "dom", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
&remote_dom, &dom, &port) )
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
&remote_dom, &dom) )
return NULL;
if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 )
+3 -3
View File
@@ -126,8 +126,8 @@ def restore(xd, fd):
raise XendError(
"not a valid guest state file: pfn count out of range")
store_evtchn = dominfo.store_channel.port2
console_evtchn = dominfo.console_channel.port2
store_evtchn = dominfo.store_channel
console_evtchn = dominfo.console_channel
cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
str(dominfo.getDomid()), str(nr_pfns),
@@ -146,7 +146,7 @@ def restore(xd, fd):
dominfo.getDomainPath())
IntroduceDomain(dominfo.getDomid(),
store_mfn,
dominfo.store_channel.port1,
dominfo.store_channel,
dominfo.getDomainPath())
else:
m = re.match(r"^(console-mfn) (\d+)$", line)
+12 -59
View File
@@ -32,8 +32,6 @@ import errno
import xen.lowlevel.xc
from xen.util.blkif import blkdev_uname_to_file
from xen.xend.server import channel
from xen.xend import image
from xen.xend import scheduler
from xen.xend import sxp
@@ -785,32 +783,6 @@ class XendDomainInfo:
self.domid, self.info['name'])
def closeChannel(self, chan, entry):
"""Close the given channel, if set, and remove the given entry in the
store. Nothrow guarantee."""
if chan:
chan.close()
try:
self.removeDom(entry)
except:
log.exception('Removing entry %s failed', entry)
def closeStoreChannel(self):
"""Close the store channel, if any. Nothrow guarantee."""
self.closeChannel(self.store_channel, "store/port")
self.store_channel = None
def closeConsoleChannel(self):
"""Close the console channel, if any. Nothrow guarantee."""
self.closeChannel(self.console_channel, "console/port")
self.console_channel = None
## public:
def setConsoleRef(self, ref):
@@ -960,12 +932,8 @@ class XendDomainInfo:
sxpr.append(['up_time', str(up_time) ])
sxpr.append(['start_time', str(self.info['start_time']) ])
if self.store_channel:
sxpr.append(self.store_channel.sxpr())
if self.store_mfn:
sxpr.append(['store_mfn', self.store_mfn])
if self.console_channel:
sxpr.append(['console_channel', self.console_channel.sxpr()])
if self.console_mfn:
sxpr.append(['console_mfn', self.console_mfn])
@@ -1073,7 +1041,7 @@ class XendDomainInfo:
self.create_channel()
self.image.createImage()
IntroduceDomain(self.domid, self.store_mfn,
self.store_channel.port1, self.dompath)
self.store_channel, self.dompath)
## public:
@@ -1083,8 +1051,6 @@ class XendDomainInfo:
guarantee."""
self.release_devices()
self.closeStoreChannel()
self.closeConsoleChannel()
if self.image:
try:
@@ -1164,35 +1130,22 @@ class XendDomainInfo:
@param path under which port is stored in db
"""
port = 0
if path:
try:
port = int(self.readDom(path))
return int(self.readDom(path))
except:
# The port is not yet set, i.e. the channel has not yet been
# created.
pass
# Stale port information from above causes an Invalid Argument to be
# thrown by the eventChannel call below. To recover, we throw away
# port if it turns out to be bad, and just create a new channel.
# If creating a new channel with two new ports fails, then something
# else is going wrong, so we bail.
while True:
try:
ret = channel.eventChannel(0, self.domid, port1 = port,
port2 = 0)
break
except:
log.exception("Exception in eventChannel(0, %d, %d, %d)",
self.domid, port, 0)
if port == 0:
raise
else:
port = 0
log.error("Recovering from above exception.")
self.storeDom(path, ret.port1)
return ret
try:
port = xc.evtchn_alloc_unbound(dom=self.domid, remote_dom=0)
except:
log.exception("Exception in alloc_unbound(%d)", self.domid)
raise
self.storeDom(path, port)
return port
def create_channel(self):
"""Create the channels to the domain.
@@ -1419,11 +1372,11 @@ class XendDomainInfo:
def initStoreConnection(self):
ref = xc.init_store(self.store_channel.port2)
ref = xc.init_store(self.store_channel)
if ref and ref >= 0:
self.setStoreRef(ref)
try:
IntroduceDomain(self.domid, ref, self.store_channel.port1,
IntroduceDomain(self.domid, ref, self.store_channel,
self.dompath)
except RuntimeError, ex:
if ex.args[0] == errno.EISCONN:
+9 -12
View File
@@ -25,8 +25,6 @@ from xen.xend import sxp
from xen.xend.XendError import VmError
from xen.xend.XendLogging import log
from xen.xend.server import channel
xc = xen.lowlevel.xc.new()
@@ -168,11 +166,11 @@ class LinuxImageHandler(ImageHandler):
def buildDomain(self):
if self.vm.store_channel:
store_evtchn = self.vm.store_channel.port2
store_evtchn = self.vm.store_channel
else:
store_evtchn = 0
if self.vm.console_channel:
console_evtchn = self.vm.console_channel.port2
console_evtchn = self.vm.console_channel
else:
console_evtchn = 0
@@ -228,16 +226,17 @@ class VmxImageHandler(ImageHandler):
def buildDomain(self):
# Create an event channel
self.device_channel = channel.eventChannel(0, self.vm.getDomid())
log.info("VMX device model port: %d", self.device_channel.port2)
self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(),
remote_dom=0)
log.info("VMX device model port: %d", self.device_channel)
if self.vm.store_channel:
store_evtchn = self.vm.store_channel.port2
store_evtchn = self.vm.store_channel
else:
store_evtchn = 0
log.debug("dom = %d", self.vm.getDomid())
log.debug("image = %s", self.kernel)
log.debug("control_evtchn = %d", self.device_channel.port2)
log.debug("control_evtchn = %d", self.device_channel)
log.debug("store_evtchn = %d", store_evtchn)
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
log.debug("flags = %d", self.flags)
@@ -245,7 +244,7 @@ class VmxImageHandler(ImageHandler):
ret = xc.vmx_build(dom = self.vm.getDomid(),
image = self.kernel,
control_evtchn = self.device_channel.port2,
control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
flags = self.flags,
@@ -334,7 +333,7 @@ class VmxImageHandler(ImageHandler):
if len(vnc):
args = args + vnc
args = args + ([ "-d", "%d" % self.vm.getDomid(),
"-p", "%d" % self.device_channel.port1,
"-p", "%d" % self.device_channel,
"-m", "%s" % (self.vm.getMemoryTarget() / 1024)])
args = args + self.dmargs
env = dict(os.environ)
@@ -358,8 +357,6 @@ class VmxImageHandler(ImageHandler):
return vncconnect
def destroy(self):
if self.device_channel:
self.device_channel.close()
import signal
if not self.pid:
return
-76
View File
@@ -1,76 +0,0 @@
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
# Copyright (C) 2005 XenSource Ltd
#============================================================================
import xen.lowlevel.xc
from xen.xend.XendLogging import log
xc = xen.lowlevel.xc.new()
class EventChannel:
"""An event channel between domains.
"""
def __init__(self, dom1, dom2, port1, port2):
self.dom1 = dom1
self.dom2 = dom2
self.port1 = port1
self.port2 = port2
def close(self):
"""Close the event channel. Nothrow guarantee.
"""
def evtchn_close(dom, port):
try:
xc.evtchn_close(dom=dom, port=port)
except Exception:
log.exception("Exception closing event channel %d, %d.", dom,
port)
evtchn_close(self.dom1, self.port1)
evtchn_close(self.dom2, self.port2)
def sxpr(self):
return ['event-channel',
['dom1', self.dom1 ],
['port1', self.port1 ],
['dom2', self.dom2 ],
['port2', self.port2 ]
]
def __repr__(self):
return ("<EventChannel dom1:%d:%d dom2:%d:%d>"
% (self.dom1, self.port1, self.dom2, self.port2))
def eventChannel(dom1, dom2, port1 = 0, port2 = 0):
"""Create an event channel between domains.
@return EventChannel (None on error)
"""
v = xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2,
port1=port1, port2=port2)
if v and v.get('port1'):
return EventChannel(dom1, dom2, v['port1'], v['port2'])
else:
return None
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.