From 5bd7984820b32f2a5c4571255907f9bba0e3a8a5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Oct 2005 11:54:38 +0100 Subject: [PATCH 1/4] Remove bind_evtchn_to_irq/unbind_evtchn_from_irq from the evtchn kernel interface. Fix error path in bind_evtchn_to_irqhandler. Fix backend drivers to avoid double freeing IRQs. Signed-off-by: Keir Fraser --- .../arch/ia64/xen/drivers/evtchn_ia64.c | 6 ------ linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c | 10 +++++----- .../drivers/xen/blkback/interface.c | 12 ++++++++++-- .../drivers/xen/netback/interface.c | 17 ++++++++++------- linux-2.6-xen-sparse/include/asm-xen/evtchn.h | 8 -------- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c index e5c3a50f78..f6e6c9ee72 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c @@ -67,12 +67,6 @@ void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id) evtchns[evtchn].handler = NULL; } -void unbind_evtchn_from_irq(unsigned int evtchn) -{ - printk("unbind_evtchn_from_irq called... FIXME??\n"); - while(1); -} - irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 l1, l2; diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c index a709dd4198..6a85441f7f 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c @@ -296,7 +296,7 @@ void unbind_ipi_from_irq(int ipi) } EXPORT_SYMBOL(unbind_ipi_from_irq); -int bind_evtchn_to_irq(unsigned int evtchn) +static int bind_evtchn_to_irq(unsigned int evtchn) { int irq; @@ -314,9 +314,8 @@ int bind_evtchn_to_irq(unsigned int evtchn) return irq; } -EXPORT_SYMBOL(bind_evtchn_to_irq); -void unbind_evtchn_from_irq(unsigned int irq) +static void unbind_evtchn_from_irq(unsigned int irq) { evtchn_op_t op = { .cmd = EVTCHNOP_close }; int evtchn = irq_to_evtchn[irq]; @@ -333,7 +332,6 @@ void unbind_evtchn_from_irq(unsigned int irq) spin_unlock(&irq_mapping_update_lock); } -EXPORT_SYMBOL(unbind_evtchn_from_irq); int bind_evtchn_to_irqhandler( unsigned int evtchn, @@ -347,8 +345,10 @@ int bind_evtchn_to_irqhandler( irq = bind_evtchn_to_irq(evtchn); retval = request_irq(irq, handler, irqflags, devname, dev_id); - if (retval != 0) + if (retval != 0) { unbind_evtchn_from_irq(irq); + return retval; + } return irq; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index 458d6e9c36..ee1889a09a 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -74,6 +74,10 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) .u.bind_interdomain.remote_dom = blkif->domid, .u.bind_interdomain.remote_port = evtchn }; + /* Already connected through? */ + if (blkif->irq) + return 0; + if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL ) return -ENOMEM; @@ -107,8 +111,12 @@ static void free_blkif(void *arg) { blkif_t *blkif = (blkif_t *)arg; - if (blkif->irq) - unbind_evtchn_from_irqhandler(blkif->irq, blkif); + /* Already disconnected? */ + if (!blkif->irq) + return; + + unbind_evtchn_from_irqhandler(blkif->irq, blkif); + blkif->irq = 0; vbd_free(&blkif->vbd); diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index 3e4537c90f..43f516badf 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -183,6 +183,10 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, .u.bind_interdomain.remote_dom = netif->domid, .u.bind_interdomain.remote_port = evtchn }; + /* Already connected through? */ + if (netif->irq) + return 0; + netif->comms_area = alloc_vm_area(2*PAGE_SIZE); if (netif->comms_area == NULL) return -ENOMEM; @@ -227,13 +231,12 @@ static void free_netif_callback(void *arg) { netif_t *netif = (netif_t *)arg; - /* - * This can't be done in netif_disconnect() because at that point - * there may be outstanding requests in the network stack whose - * asynchronous responses must still be notified to the remote driver. - */ - if (netif->irq) - unbind_evtchn_from_irqhandler(netif->irq, netif); + /* Already disconnected? */ + if (!netif->irq) + return; + + unbind_evtchn_from_irqhandler(netif->irq, netif); + netif->irq = 0; unregister_netdev(netif->dev); diff --git a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h index c9feb34606..a38b8732a1 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h @@ -51,14 +51,6 @@ extern void unbind_virq_from_irq(int virq); extern int bind_ipi_to_irq(int ipi); extern void unbind_ipi_from_irq(int ipi); -/* - * Dynamically bind an event-channel port to Linux IRQ space. - * BIND: Returns IRQ or error. - * UNBIND: Takes IRQ to unbind from; automatically closes the event channel. - */ -extern int bind_evtchn_to_irq(unsigned int evtchn); -extern void unbind_evtchn_from_irq(unsigned int irq); - /* * Dynamically bind an event-channel port to an IRQ-like callback handler. * On some platforms this may not be implemented via the Linux IRQ subsystem. From 6f455ecab68654e5e448b610b094ccd35e38ec24 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Oct 2005 13:11:41 +0100 Subject: [PATCH 2/4] The hotplug agent sets the path now, but that's not as practical to do with udev rules. So instead, make sure that the path is set in the vif scripts themselves. Signed-off-by: Jeremy Katz --- tools/examples/vif-bridge | 1 + tools/examples/vif-nat | 2 +- tools/examples/vif-route | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/examples/vif-bridge b/tools/examples/vif-bridge index 2a3903a310..0f692d689f 100755 --- a/tools/examples/vif-bridge +++ b/tools/examples/vif-bridge @@ -33,6 +33,7 @@ # Exit if anything goes wrong set -e +export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH echo "*vif-bridge $*" >&2 diff --git a/tools/examples/vif-nat b/tools/examples/vif-nat index 00977f8819..f268fdcedc 100644 --- a/tools/examples/vif-nat +++ b/tools/examples/vif-nat @@ -22,7 +22,7 @@ # Exit if anything goes wrong set -e - +export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH echo "*vif-nat $*" >&2 # Operation name. diff --git a/tools/examples/vif-route b/tools/examples/vif-route index 2c0b2d1d3a..efb83881d2 100755 --- a/tools/examples/vif-route +++ b/tools/examples/vif-route @@ -23,7 +23,7 @@ # Exit if anything goes wrong set -e - +export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH echo "*vif-route $*" >&2 # Operation name. From 44e73911fe7a71dca0bae5c7b9994e5d9415d26c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Oct 2005 13:13:58 +0100 Subject: [PATCH 3/4] Move the block-phy and block-file handling into a common block script that gets called by the hotplug agent. Signed-off-by: Jeremy Katz --- tools/examples/Makefile | 3 +- tools/examples/block | 82 ++++++++++++++++++++++++++++++++ tools/examples/block-file | 31 ------------ tools/examples/block-phy | 30 ------------ tools/examples/xen-backend.agent | 10 +--- 5 files changed, 85 insertions(+), 71 deletions(-) create mode 100644 tools/examples/block delete mode 100755 tools/examples/block-file delete mode 100644 tools/examples/block-phy diff --git a/tools/examples/Makefile b/tools/examples/Makefile index 0f30fc021f..17d93453a1 100644 --- a/tools/examples/Makefile +++ b/tools/examples/Makefile @@ -22,8 +22,7 @@ XEN_SCRIPT_DIR = /etc/xen/scripts XEN_SCRIPTS = network-bridge vif-bridge XEN_SCRIPTS += network-route vif-route XEN_SCRIPTS += network-nat vif-nat -XEN_SCRIPTS += block-phy -XEN_SCRIPTS += block-file +XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd XEN_HOTPLUG_DIR = /etc/hotplug diff --git a/tools/examples/block b/tools/examples/block new file mode 100644 index 0000000000..4fec0d6597 --- /dev/null +++ b/tools/examples/block @@ -0,0 +1,82 @@ +#!/bin/sh + +set -e + +export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH + +expand_dev() { + local dev + case $1 in + /*) + dev=$1 + ;; + *) + dev=/dev/$1 + ;; + esac + echo -n $dev +} + +write_dev() { + local major + local minor + local pdev + + major=$(stat -L -c %t "$1") + minor=$(stat -L -c %T "$1") + pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) + xenstore-write "$XENBUS_PATH"/physical-device $pdev \ + "$XENBUS_PATH"/node $1 +} + +t=$(xenstore-read "$XENBUS_PATH"/type) + +case $1 in + bind) + p=$(xenstore-read "$XENBUS_PATH"/params) + case $t in + phy) + dev=$(expand_dev $p) + write_dev "$dev" + exit 0 + ;; + + file) + for dev in /dev/loop* ; do + echo "dev is $dev, p is $p" + if losetup $dev $p; then + write_dev "$dev" + exit 0 + fi + done + exit 1 + ;; + + *) + [ -x /etc/xen/scripts/block-"$t" ] && \ + /etc/xen/scripts/block-"$t" bind $p + ;; + esac + ;; + + unbind) + node=$(xenstore-read "$XENBUS_PATH"/node) + case $t in + phy) + exit 0 + ;; + + file) + losetup -d $node + exit 0 + ;; + + *) + [ -x /etc/xen/scripts/block-"$t" ] && \ + /etc/xen/scripts/block-"$t" unbind $node + ;; + + esac + ;; + +esac diff --git a/tools/examples/block-file b/tools/examples/block-file deleted file mode 100755 index 3270fa07ba..0000000000 --- a/tools/examples/block-file +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -# Usage: block_loop [bind file|unbind node] -# -# The file argument to the bind command is the file we are to bind to a -# loop device. -# -# The node argument to unbind is the name of the device node we are to -# unbind. - -set -e - -case $1 in - bind) - for dev in /dev/loop*; do - if losetup $dev $2; then - major=$(stat -L -c %t "$dev") - minor=$(stat -L -c %T "$dev") - pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) - xenstore-write "$XENBUS_PATH"/physical-device $pdev \ - "$XENBUS_PATH"/node $dev - exit 0 - fi - done - exit 1 - ;; - unbind) - losetup -d $2 - exit 0 - ;; -esac diff --git a/tools/examples/block-phy b/tools/examples/block-phy deleted file mode 100644 index a19a861bbe..0000000000 --- a/tools/examples/block-phy +++ /dev/null @@ -1,30 +0,0 @@ -#! /bin/sh - -set -e - -expand_dev() { - local dev - case $1 in - /*) - dev=$1 - ;; - *) - dev=/dev/$1 - ;; - esac - echo -n $dev -} - -case $1 in - bind) - dev=$(expand_dev $2) - major=$(stat -L -c %t "$dev") - minor=$(stat -L -c %T "$dev") - pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) - xenstore-write "$XENBUS_PATH"/physical-device $pdev \ - "$XENBUS_PATH"/node $dev - exit 0 - ;; - unbind) - ;; -esac diff --git a/tools/examples/xen-backend.agent b/tools/examples/xen-backend.agent index 91a5d0eb32..27af3359bf 100755 --- a/tools/examples/xen-backend.agent +++ b/tools/examples/xen-backend.agent @@ -11,20 +11,14 @@ case "$ACTION" in add) case "$XENBUS_TYPE" in vbd) - t=$(xenstore-read "$XENBUS_PATH"/type) - params=$(xenstore-read "$XENBUS_PATH"/params) - [ -x /etc/xen/scripts/block-"$t" ] && \ - /etc/xen/scripts/block-"$t" bind $params + /etc/xen/scripts/block bind ;; esac ;; remove) case "$XENBUS_TYPE" in vbd) - t=$(xenstore-read "$XENBUS_PATH"/type) - node=$(xenstore-read "$XENBUS_PATH"/node) - [ -x /etc/xen/scripts/block-"$t" ] && \ - /etc/xen/scripts/block-"$t" unbind $node + /etc/xen/scripts/block unbind ;; esac # remove device backend store entries From e3430966b875517990c942204afaad0dfac13510 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Oct 2005 13:15:52 +0100 Subject: [PATCH 4/4] Add udev rules that map similar to the hotplug agent. Based off of what Chris Bainbridge posted the end of last week but doing things as directly as possible. Signed-off-by: Jeremy Katz --- tools/examples/xen-backend.rules | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tools/examples/xen-backend.rules diff --git a/tools/examples/xen-backend.rules b/tools/examples/xen-backend.rules new file mode 100644 index 0000000000..3eb5a7d56a --- /dev/null +++ b/tools/examples/xen-backend.rules @@ -0,0 +1,4 @@ +SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ACTION=="add", RUN+="/etc/xen/scripts/block bind" +SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ACTION=="remove", RUN+="/etc/xen/scripts/block unbind" +SUBSYSTEM=="xen-backend", KERNEL=="vif*", ENV{PHYSDEVDRIVER}=="vif", ACTION=="online", RUN+="$env{script} up" +SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/usr/bin/xenstore-rm $env{XENBUS_PATH}"